📄 pengpenggamedlg.cpp
字号:
// pengpengGameDlg.cpp : implementation file
//
#include "stdafx.h"
#include "pengpengGame.h"
#include "pengpengGameDlg.h"
#include "GetNameDlg.h"
#include <mmsystem.h>
//#include <vfw.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
extern CPengpengGameApp theApp;
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPengpengGameDlg dialog
CPengpengGameDlg::CPengpengGameDlg(CWnd* pParent /*=NULL*/)
: CDialog(CPengpengGameDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CPengpengGameDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CPengpengGameDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPengpengGameDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPengpengGameDlg, CDialog)
//{{AFX_MSG_MAP(CPengpengGameDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_ERASEBKGND()
ON_WM_LBUTTONDOWN()
ON_WM_TIMER()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPengpengGameDlg message handlers
BOOL CPengpengGameDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// PlayMidi("F:\\梦里水乡.mid");
//装入图片资源
CBitmap bmBack,bmBallan,bmBallhei,bmScore,bmButtonsys;
bmBack.LoadBitmap(IDB_BACK);
bmBallan.LoadBitmap(IDB_BALLAN);
bmBallhei.LoadBitmap(IDB_BALLHEI);
bmScore.LoadBitmap(IDB_SCORE);
bmButtonsys.LoadBitmap(IDB_BUTTONSYS);
//初始化DC
CClientDC dc(this);
m_dcBack.CreateCompatibleDC(&dc);
m_dcBallAn.CreateCompatibleDC(&dc);
m_dcBallHei.CreateCompatibleDC(&dc);
m_dcScore.CreateCompatibleDC(&dc);
m_dcButtonSys.CreateCompatibleDC(&dc);
//把图片放到对应的DC
m_dcBack.SelectObject(&bmBack);
m_dcBallAn.SelectObject(&bmBallan);
m_dcBallHei.SelectObject(&bmBallhei);
m_dcScore.SelectObject(&bmScore);
m_dcButtonSys.SelectObject(&bmButtonsys);
//释放
bmBack.DeleteObject();
bmBallan.DeleteObject();
bmBallhei.DeleteObject();
bmScore.DeleteObject();
bmButtonsys.DeleteObject();
//调整窗口大小及位置改窗口标题
CRect rt1,rt2;
GetWindowRect(&rt1);
GetClientRect(&rt2);
int cx=rt1.right-rt1.left-(rt2.right-rt2.left);
int cy=rt1.bottom-rt1.top-(rt2.bottom-rt2.top);
MoveWindow(0,0,539+cx,485+cy);
CenterWindow();
SetWindowText("搞怪PKLANG");
srand(time(NULL));//初始化随机发生器
//打开用于记录前五名的信息文件
CFile fHero;
int i;
PK_Hero da;
if(fHero.Open("Hero.dat",CFile::modeRead)==0)//找不到文件就新建一个
{
//随便几个名字和分数
char *name[]={"鏒ぢ箆麖ぜ蔆","PKLANG's GF[Nancy]","PKLANG's GF[XiaoQian]","PKLANG's GF[Wenwen]","PKLANG's GF[Dandan]"};
int score[5]={885,750,640,620,520};
fHero.Open("Hero.dat",CFile::modeCreate|CFile::modeWrite);
for(i=0;i<5;i++)
{
strcpy(da.Name,name[i]);
da.Score=score[i];
fHero.Write(&da,sizeof(PK_Hero));
m_arrHero.Add(da);
}
fHero.Close();
}
else//找到就读出来放进m_arrHero链表里
{
for(i=0;i<5;i++)
{
fHero.Read(&da,sizeof(PK_Hero));
m_arrHero.Add(da);
}
fHero.Close();
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
//设置6个按钮的矩形位置
m_rtSelect[0].SetRect(476,0,504,32);
m_rtSelect[1].SetRect(508,0,540,32);
m_rtSelect[2].SetRect(409,246,495,246+33);
m_rtSelect[3].SetRect(409,286,495,286+33);
m_rtSelect[4].SetRect(409,326,495,326+33);
m_rtSelect[5].SetRect(395,374,530,420);
m_nButtonSelect=-1;//鼠标不在任何一个按钮
m_nSelected=-1; //还没有选中球子
ReStart();//初始化游戏
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
//////////////////////////////////////////////////////////////////////
// 在OnPaint()里重画各个小球以及分数
//
//
/////////////////////////////////////////////////////////////////////
void CPengpengGameDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x+100, y, m_hIcon);
}
else
{
CDialog::OnPaint();
CClientDC ddc(this);
//重画各个球子
for(int i=0;i<81;i++)
if(m_Ball[i]!=-1)
{
if(i%2)
ddc.BitBlt(20+(i%9)*40+2,60+i/9*40+2,36,38,&m_dcBallHei,2,m_Ball[i]*40,SRCCOPY);
else
ddc.BitBlt(20+(i%9)*40+2,60+i/9*40+2,36,38,&m_dcBallAn,2,m_Ball[i]*40,SRCCOPY);
}
//重画下一要出现的球子
for( i=0;i<3;i++)
ddc.BitBlt(400+i*40+2,94,36,38,&m_dcBallHei,2,m_NextBall[i]*40,SRCCOPY);
//重画玩家当前分数
DisplayScore(&ddc,410,188,m_nScore);
//重画最高分数的姓名和分数
int oldMode=ddc.SetBkMode(TRANSPARENT);//设置透明背景
int oldColor=ddc.SetTextColor(RGB(255,10,10));//文字颜色
ddc.DrawText(m_arrHero.GetAt(0).Name,CRect(280,458,420,475),DT_CENTER|DT_VCENTER);
DisplayScore(&ddc,430,458,m_arrHero.GetAt(0).Score);
ddc.SetBkMode(oldMode);
ddc.SetTextColor(oldColor);
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CPengpengGameDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
//////////////////////////////////////////////////////////////////////
// 重载OnEraseBkgnd设置窗口的背景图片
//
//
/////////////////////////////////////////////////////////////////////
BOOL CPengpengGameDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
pDC->BitBlt(0,0,539,485,&m_dcBack,0,0,SRCCOPY);
pDC->SetBkMode(TRANSPARENT);
CFont *ft=GetFont();
pDC->SelectObject(ft);
pDC->TextOut(10,3,"送给 鏒ぢ箆麖ぜ蔆 ");
return TRUE;//CDialog::OnEraseBkgnd(pDC);
}
//////////////////////////////////////////////////////////////////////
// 重载OnLButtonDown处理鼠标单击时
//
//
/////////////////////////////////////////////////////////////////////
void CPengpengGameDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
//如果鼠标在6个按钮其中一个时
if(m_nButtonSelect!=-1)
ClickVirtualButton();
else
if(point.y<20)//如果横坐标<20时就给它认为是单击在标题栏上,用于移动窗口
PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x,point.y));
//重要部分:单击在棋盘上时
if( point.x>20 && point.x<380 && point.y>60 && point.y<420)
{
CUIntArray ar,arrgood;
int i,j,ret[3],old,pos;
CRect rt;
CClientDC dc(this);
pos=(point.x-20)/40+(point.y-60)/40*9; //换算成一维数组的坐标
if( m_nSelected!=-1)//如果已经选定了一个球子
{
if(pos==m_nSelected)return; //不处理重复原来的
if( m_Ball[pos]==-1 )//如果点的位置是空的
{
if(BFSPathBest(m_nSelected,pos,&ar))//如果两个点是可以连通
{
old=m_Ball[m_nSelected];//保存原来选中的位置
m_Ball[m_nSelected]=-1;//把原来选中的设置为空
KillTimer(1313);//关闭闪烁效果
PlayMySound(IDR_F4);//播放移动效果声音
//这个循环是两个点前移动过去的视觉效果
for( i=ar.GetSize()-1;i>0;i-- )
{
rt.SetRect(20+ar.GetAt(i)%9*40,60+ar.GetAt(i)/9*40,20+ar.GetAt(i)%9*40+40,60+ar.GetAt(i)/9*40+40);
RedrawWindow(rt);
if(ar.GetAt(i-1)%2)
dc.BitBlt(20+(ar.GetAt(i-1)%9)*40+2,60+ar.GetAt(i-1)/9*40+2,36,38,&m_dcBallHei,2,old*40,SRCCOPY);
else
dc.BitBlt(20+(ar.GetAt(i-1)%9)*40+2,60+ar.GetAt(i-1)/9*40+2,36,38,&m_dcBallAn,2,old*40,SRCCOPY);
Sleep(100);//延时时间,想快就改为更小的时间
}
m_Ball[pos]=old;//交换位置信息
m_nSelected=-1;//设置没有球子选中状态
//判断刚才移过去的位置是否满足削球子的条件
//for循环是要判断上下,左右,左斜,右斜等四个方向的
for(j=0;j<4;j++)
if(FindSuccLine(pos,j,&arrgood))
{
FlashTheCheak(&dc,&arrgood);//如果满足就执行闪烁效果
return; //记得要返回了
}
//没有满足削球时就生成三个球子
for( i=0;i<3;i++)
{
ret[i]=RandFindAt();//ret数组保存随机来的位置
m_Ball[ret[i]]=m_NextBall[i];//设置新三个位置的球子信息
m_NextBall[i]=rand()%8;//随机下次要出现的球子信息
if(ret[i]==-1)//如果已经没有足够位置了
{
//如果得分已经超第五名了
if(m_nScore>m_arrHero.GetAt(4).Score)
{
//输入大名对话框
CGetNameDlg nameDlg;
if(nameDlg.DoModal()==IDOK)//确认保存
SaveHero(nameDlg.m_strName);
}
else//不然呵呵!
AfxMessageBox("HAHA!玩完了!");
ReStart();//重新游戏
RedrawWindow();//重画窗口
return;
}
}
PlayMySound(IDR_C0);//播放新生球子的欢乐声音
//判断刚才移过去的位置是否满足削球子的条件
//I循环是要判断上下,左右,左斜,右斜等四个方向的
for( i=1;i<4;i++ )
{
for( j=0;j<3;j++)
{
if(ret[j]%2)
dc.BitBlt(20+(ret[j]%9)*40+2,60+ret[j]/9*40+2,36,38,&m_dcBallHei,2+(rand()%5+1)*40,m_Ball[ret[j]]*40,SRCCOPY);
else
dc.BitBlt(20+(ret[j]%9)*40+2,60+ret[j]/9*40+2,36,38,&m_dcBallAn,2+(rand()%5+1)*40,m_Ball[ret[j]]*40,SRCCOPY);
}
Sleep(200);
}
rt.SetRect(400,94,400+120,94+40);
RedrawWindow(rt);
//判断刚才移过去的位置是否满足削球子的条件
//j循环是要判断上下,左右,左斜,右斜等四个方向的
for(i=0;i<3;i++)//I循环是有三个球子
{
for(j=0;j<4;j++)
if(FindSuccLine(ret[i],j,&arrgood))
{
FlashTheCheak(&dc,&arrgood);//跟上面效果一样
break;
//MessageBox("good Line");
}
}
}//BFSPathBest(m_nSelected,pos,&ar)
else//两点没有连通时播放警告声音
{
PlayMySound(IDR_J0);
}
}//m_Ball[pos]==-1 )
else//这是当前单击位置是有球子时且已经有选中球子时
{
rt.SetRect(20+m_nSelected%9*40,60+m_nSelected/9*40,20+m_nSelected%9*40+38,60+m_nSelected/9*40+38);
RedrawWindow(rt);
PlayMySound(IDR_D2);//播放点中的声音
m_nSelected=pos;//交换选中位置
}
}//m_nSelected!=-1)
else if(m_Ball[pos]!=-1)//是开始有选中时
{
PlayMySound(IDR_D2);//播放点中的声音
m_nSelected=pos;//交换选中位置
SetTimer(1313,300,NULL);//用定时器来动画左看看右看看下看看上看看的效果
SendMessage(WM_TIMER,1313);//给我马上动作
}
}//if inRect(...
CDialog::OnLButtonDown(nFlags, point);
}
//////////////////////////////////////////////////////////////////////
// 重要:判断两点是否连通
// 这里采用广度优先搜索法(BFS)来查找两个点是否连通
// 以及经过的最短路径
// 其中from来开始点,to为到达点,arrSave保存经过的位置
// 如果能通就返回TRUE,不然返回FALSE
/////////////////////////////////////////////////////////////////////
BOOL CPengpengGameDlg::BFSPathBest(int from, int to, CUIntArray *arrSave)
{
int i,head; //队列头
int tail; //队列尾
int data[81]; //队列数组
int pnt[81]; //保存父结点位置
int bcheck[81]; //记录是否已经走过 0没有 1已经走过
for( i=0;i<81;i++)
bcheck[i]=0; //初始都没有走过
//初始队列
head=0;
tail=1;
data[0]=from;
pnt[0]=0;
while(1)
{
//判断上下左右是否有路通
//从上搜索
if( (data[head]-9)>=0 && //没有越界
m_Ball[data[head]-9]==-1 && //且位置是空的
bcheck[data[head]-9]==0) //且还没有走过
{
data[tail]=data[head]-9; //满足了保存进队列尾去
pnt[data[tail]]=data[head]; //保存父结点位置
if(data[tail]==to)break; //如果已经到达目标了就退出循环
bcheck[data[tail]]=1; //设置已经走过标志
tail++; //队列尾加一个
}
//以下方法基本一样,只是方向不同
//从下搜索
if( (data[head]+9)<81 && m_Ball[data[head]+9]==-1 && bcheck[data[head]+9]==0)
{
data[tail]=data[head]+9;
pnt[data[tail]]=data[head];
if(data[tail]==to)break;
bcheck[data[head]+9]=1;
tail++;
}
//从左搜索
if( ((data[head])%9)>0 && m_Ball[data[head]-1]==-1 && bcheck[data[head]-1]==0)
{
data[tail]=data[head]-1;
pnt[data[tail]]=data[head];
if(data[tail]==to)break;
bcheck[data[head]-1]=1;
tail++;
}
//从右搜索
if( ((data[head])%9)<8 && m_Ball[data[head]+1]==-1 && bcheck[data[head]+1]==0)
{
data[tail]=data[head]+1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -