用了一个星期,终于把扫雷做的差不多了,其中遇到很多很多问题,但慢慢解决了,确实挺令人高兴,也许这就是编程的魅力所在吧。
下面记录扫雷的主要几个算法:
一:布雷
1 void CMineButton::Reset(CWnd* pParent)//参考与小张上传中的程序,,对butto进行初始化
2 {
3
4 CMINEMFCApp *app = (CMINEMFCApp *)AfxGetApp();
5
6 app->m_pParent = pParent;
7
8 int nI;
9
10 for(nI=0;nI<100;nI++)
11 {
12 if (app->m_aLandMine[nI]!=NULL)
13 delete app->m_aLandMine[nI];
14 }
15 for(nI=0;nI<100;nI++)
16 {
17
18 app->m_aLandMine[nI] = new CMineButton;
19
20 }
21
22
23 int nCurMines=0;
24 int nCurMine;
25 int curi = 0;
26 srand( (unsigned)time( NULL ));
27
28 while(nCurMines<10)
29 {
30 nCurMine=rand()%(100);//获取10个雷的分布
31 (app->m_theRealMine[curi]) = nCurMine;
32 if(app->m_aLandMine[nCurMine]->GetMineNum() != -1)//该写法的作用是初始化10个雷周围button的雷的数量
33 {
34 app->m_aLandMine[nCurMine]->SetMineNum(-1);
35 int nMineRound,nMineRound1;
36 //right;
37 nMineRound = app->m_aLandMine[nCurMine]->GetRight(nCurMine);
38 if(nMineRound>=0)
39 {
40 if (app->m_aLandMine[nMineRound]->GetMineNum() != -1)
41 ++(*app->m_aLandMine[nMineRound]);
42 //right top
43 nMineRound1 = (app->m_aLandMine[nMineRound]->GetTop(nMineRound));
44 if(nMineRound1>=0 && app->m_aLandMine[nMineRound1]->GetMineNum() != -1)
45 {
46 ++(*app->m_aLandMine[nMineRound1]);
47 }
48 //right bottom
49 nMineRound1 = app->m_aLandMine[nMineRound]->GetBot(nMineRound);
50 if(nMineRound1>=0 && app->m_aLandMine[nMineRound1]->GetMineNum() != -1)
51 {
52 ++(*app->m_aLandMine[nMineRound1]);
53 }
54 }
55 //left
56 nMineRound = app->m_aLandMine[nCurMine]->GetLeft(nCurMine);
57 if(nMineRound>=0)
58 {
59 if(app->m_aLandMine[nMineRound]->GetMineNum() != -1)
60 ++(*app->m_aLandMine[nMineRound]);
61
62 //Left top
63 nMineRound1 = app->m_aLandMine[nMineRound]->GetTop(nMineRound);
64 if(nMineRound1>=0 && app->m_aLandMine[nMineRound1]->GetMineNum() != -1)
65 {
66 ++(*app->m_aLandMine[nMineRound1]);
67 }
68
69 //Left bottom
70 nMineRound1 = app->m_aLandMine[nMineRound]->GetBot(nMineRound);
71 if(nMineRound1>=0 && app->m_aLandMine[nMineRound1]->GetMineNum() !=分公司的72 {
73 ++(*app->m_aLandMine[nMineRound1]);
74 }
75 }
76 //Top
77 nMineRound = app->m_aLandMine[nCurMine]->GetTop(nCurMine);
78 if(nMineRound>=0 && app->m_aLandMine[nMineRound]->GetMineNum() != -1)
79 {
80 ++(*app->m_aLandMine[nMineRound]);
81 }
82
83 //Bottom
84 nMineRound = app->m_aLandMine[nCurMine]->GetBot(nCurMine);
85 if(nMineRound>=0 && app->m_aLandMine[nMineRound]->GetMineNum() != -1)
86 {
87 ++(*app->m_aLandMine[nMineRound]);
88 }
89 nCurMines++;
90 curi ++ ;
91 }
92 }
93 }
二:空白雷区的实现
BOOL CMINEMFCDlg::RecordMine(int nCurMine)//也是根据另一个程序打开空白的周围的算法,,是一个循环队列的使用
{
CMINEMFCApp *app = (CMINEMFCApp *)AfxGetApp();
int nRoundMine,nRoundMine1;
int aMine[500];
int nTop=0,nTail=0;
aMine[nTop++] = nCurMine;
while(nTop!=nTail)
{
int nCurrent=aMine[nTail];
nTail = (nTail+1)%500;
switch((app->m_aLandMine[nCurrent])->OpenMine(nCurrent))
{
case 0: // Mine number is zero
nRoundMine = (app->m_aLandMine[nCurrent])->GetLeft(nCurrent);
if(nRoundMine!=-1)
{
aMine[nTop] = nRoundMine;
nTop = (nTop+1)%500;
nRoundMine1 = (app->m_aLandMine[nCurrent])->GetTop(nRoundMine);
if(nRoundMine1!=-1)
{
aMine[nTop] = nRoundMine1;
nTop = (nTop+1)%500;
nRoundMine1 = (app->m_aLandMine[nCurrent])->GetTop(nRoundMine);
}
nRoundMine1 = (app->m_aLandMine[nCurrent])->GetBot(nRoundMine);
if(nRoundMine1!=-1)
{
aMine[nTop] = nRoundMine1;
nTop = (nTop+1)%500;
nRoundMine1 = (app->m_aLandMine[nCurrent])->GetTop(nRoundMine);
}
}
nRoundMine = (app->m_aLandMine[nCurrent])->GetRight(nCurrent);
if(nRoundMine!=-1)
{
aMine[nTop] = nRoundMine;
nTop = (nTop+1)%500;
nRoundMine1 = (app->m_aLandMine[nCurrent])->GetTop(nRoundMine);
if(nRoundMine1!=-1)
{
aMine[nTop] = nRoundMine1;
nTop = (nTop+1)%500;
nRoundMine1 = (app->m_aLandMine[nCurrent])->GetTop(nRoundMine);
}
nRoundMine1 = (app->m_aLandMine[nCurrent])->GetBot(nRoundMine);
if(nRoundMine1!=-1)
{
aMine[nTop] = nRoundMine1;
nTop = (nTop+1)%500;
nRoundMine1 = (app->m_aLandMine[nCurrent])->GetTop(nRoundMine);
}
}
nRoundMine = (app->m_aLandMine[nCurrent])->GetTop(nCurrent);
if(nRoundMine!=-1)
{
aMine[nTop] = nRoundMine;
nTop = (nTop+1)%500;
}
nRoundMine = (app->m_aLandMine[nCurrent])->GetBot(nCurrent);
if(nRoundMine!=-1)
{
aMine[nTop] = nRoundMine;
nTop = (nTop+1)%500;
}
break;
case 1:
break;
case -1:
return FALSE; // fail
}
}
return TRUE;
}
下面讲讲自己遇到的一些困难和新get的技能吧:
1,invalidate函数
Invalidate()之后:(MFC的,顺便了)
OnPaint()->OnPrepareDC()->OnDraw()
所以只是刷新在OnPaint()和OnDraw()函数中的绘图语句。其它地方没有影响。
Invalidate标记一个需要重绘的无效区域,并不意味着调用该函数后就立刻进行重绘。类似于PostMessage(WM_PAINT),需要处理到WM_PAINT消息时才真正重绘。以为您Invalidate之后还有其他的语句正在执行,程序没有机会去处理WM_PAINT消息,但当函数执行完毕后,消息处理才得以进行。
Invalidate只是放一个WM_PAINT消息在队列里,不做别的,所以只有当当前函数返回后,进入消息循环,取出WM_PAINT,才执行PAINT,所以不管Invalidate放哪里,都是最后的。
其实我遇到了就是把drawbutton放在了onpaint里面,导致其不断的刷新。。。。
invalidateRect是通过消息来调用OnPaint
RedrawWindow除了有InvalidateRect的效果,还会立即调用一次OnPaint(不经过消息队列,类似 UpdateWindow),这个redrawwindow会立即调用ONpaint。
2.
这个一般都是lib库没有设置好而导致的。。
3,
这个比较多,,发一个网址吧http://blog.csdn.net/xjkstar/article/details/6922259。
3
//声明:
SetWindowPos(
hWnd: HWND; {窗口句柄}
hWndInsertAfter: HWND; {窗口的 Z 顺序}
X, Y: Integer; {位置}
cx, cy: Integer; {大小}
uFlags: UINT {选项}
): BOOL;
//hWndInsertAfter 参数可选值:
HWND_TOP = 0; {在前面}
HWND_BOTTOM = 1; {在后面}
HWND_TOPMOST = HWND(-1); {在前面, 位于任何顶部窗口的前面}
HWND_NOTOPMOST = HWND(-2); {在前面, 位于其他顶部窗口的后面}
//uFlags 参数可选值:
SWP_NOSIZE = 1; {忽略 cx、cy, 保持大小}
SWP_NOMOVE = 2; {忽略 X、Y, 不改变位置}
SWP_NOZORDER = 4; {忽略 hWndInsertAfter, 保持 Z 顺序}
SWP_NOREDRAW = 8; {不重绘}
SWP_NOACTIVATE = $10; {不激活}
SWP_FRAMECHANGED = $20; {强制发送 WM_NCCALCSIZE 消息, 一般只是在改变大小时才发送此消息}
SWP_SHOWWINDOW = $40; {显示窗口}
SWP_HIDEWINDOW = $80; {隐藏窗口}
SWP_NOCOPYBITS = $100; {丢弃客户区}
SWP_NOOWNERZORDER = $200; {忽略 hWndInsertAfter, 不改变 Z 序列的所有者}
SWP_NOSENDCHANGING = $400; {不发出 WM_WINDOWPOSCHANGING 消息}
SWP_DRAWFRAME = SWP_FRAMECHANGED; {画边框}
SWP_NOREPOSITION = SWP_NOOWNERZORDER;{}
SWP_DEFERERASE = $2000; {防止产生 WM_SYNCPAINT 消息}
SWP_ASYNCWINDOWPOS = $4000; {若调用进程不拥有窗口, 系统会向拥有窗口的线程发出需求}
//举例: procedure TForm1.Button1Click(Sender: TObject); begin SetWindowPos(Handle, HWND_TOPMOST, 0,0, 100,200, SWP_SHOWWINDOW); end;
4,在鼠标右击响应函数中这样来写
BOOL CMINEMFCDlg::PreTranslateMessage(MSG* pMsg) //对于右击鼠标的响应
{
// TODO: Add your specialized code here and/or call the base class
CMINEMFCApp *app = (CMINEMFCApp *)AfxGetApp();
CClientDC dc(this);
CFont font;
font.CreateFont(20, 15, 0, 0, FW_SEMIBOLD,
FALSE, FALSE, FALSE, 0, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN, _T("新宋体"));
CFont *pOldFont=dc.SelectObject(&font);
dc.SetBkColor(RGB(237,237,237));
if(pMsg->message==WM_RBUTTONDOWN)//鼠标点击右键
{
CRect rc;
CPoint ptCursor;
::GetCursorPos(&ptCursor);//获取鼠标的位置信息
int pos;
for(pos=159;pos<259;pos++)
{
GetDlgItem(pos)-> GetWindowRect(&rc);//获取控件的位置信息
if(PtInRect(&rc,ptCursor))//右键点击位置在某一个控件上
{
CMineButtonVisual* pMineButton = (CMineButtonVisual*)GetDlgItem(pos);
if(pMineButton->rButClickedFlags == 0)
{
SetDlgItemText(pos,"☆");
pMineButton->rButClickedFlags = (pMineButton->rButClickedFlags +1)%3;
m_recordRealMine[m_recordRealMineFlags] = pos;
m_recordRealMineFlags ++ ;
CString str;
str.Format("剩余雷数:%d",(10-m_recordRealMineFlags));
GetDlgItem(IDC_STATIC_MINENUM)->SetWindowText(str);
}
else if(pMineButton->rButClickedFlags == 1)
{
SetDlgItemText(pos,"?");
pMineButton->rButClickedFlags =(pMineButton->rButClickedFlags +1)%3;
m_recordRealMineFlags -- ;
CString str;
str.Format("剩余雷数:%d",(10-m_recordRealMineFlags));
GetDlgItem(IDC_STATIC_MINENUM)->SetWindowText(str);
}
else
{
SetDlgItemText(pos," ");
pMineButton->rButClickedFlags = (pMineButton->rButClickedFlags +1)%3;
}
//m_minenum--;
//if(flg[pos-1000]==1)
//mine[0]--;
}
}
if(m_recordRealMineFlags == 10)
{
int curflags = 0;
for(int curj = 0;curj<m_recordRealMineFlags;curj++)
for(int curi = 0;curi<10;curi++)
{
if (m_recordRealMine[curi] == (app->m_theRealMine[curj]+159))
{
curflags ++ ;
break;
}
}
if(curflags == 10)
{
MessageBox("恭喜你!!!扫雷成功!!你碉堡了!!!");
bFail = 1;
}
}
// GetDlgItem(1100)-> GetWindowRect(&rc);//获取开始按钮的位置信息
/*if(PtInRect(&rc,ptCursor))//右键点击位置在某一个控件上
{
for(int i=1;i<=mine[0];i++)
{
SetDlgItemText(mine[i]+1000,"*");
}
}*/
}
return CDialog::PreTranslateMessage(pMsg);
}
5.ON_CONTROL_RANGE(BN_CLICKED, IDC_BUTTON1, IDC_BUTTON10, OnButtonClicked)的使用。
6.创建一个指针,,delete掉。
for(int curi = 0; curi < 100 ;curi++)
{
if(m_btn[curi]->m_hWnd != 0)
{
delete m_btn[curi];
m_btn[curi] = new CMineButtonVisual;
}
}
7.定时器的用法
settimer(1,1000,null)
ontimer()则响应。
killtimer则销毁settimer
最后附一张截图,,纪念一下自己写的第一个游戏。
原文:http://www.cnblogs.com/fuzhenzhen/p/3618342.html