C++扫雷Word文档下载推荐.docx
- 文档编号:21339281
- 上传时间:2023-01-29
- 格式:DOCX
- 页数:25
- 大小:795.63KB
C++扫雷Word文档下载推荐.docx
《C++扫雷Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《C++扫雷Word文档下载推荐.docx(25页珍藏版)》请在冰豆网上搜索。
位图:
下图(图2-1)。
图2-1
按扭位图30*30IDB_BITMAP1、IDB_BITMAP2、IDB_BITMAP3、IDB_BITMAP4
雷区位图14*14ID号按下图依次为:
IDB_BITMAP5……IDB_BITMAP16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
icon
3.3.
变量函数
定义新类:
对于雷,我们是单独定义一个类,这样有利于程序的操作。
classLeiMine
{
public:
//显示哪一个位图
intweitu;
bitmap
//这个位置相应的值
intshumu;
index
};
并有如下规定(图2-2):
图2-2
视图类变量:
接着是在View类添加变量和函数:
//剩下雷数
intleftnum;
//雷数
intleinum;
minenum
//结束
intjieshu;
endflag
//计时
shortsecond;
//开始计时
intsecondstart;
//位图数组
CBitmapm_Bitmap[12];
//按扭位图数组
CBitmapm_anniu[4];
button
//雷区行数
intm_RowCount;
row
//雷区列数
intm_ColCount;
line
//最大雷区
Leilei[50][50];
Minemine
//这个位置周围雷数为0
voidleizero();
//计时器函数
afx_msgvoidOnTimer(UINTnIDEvent);
//鼠标按下左键
afx_msgvoidOnLButtonDown(UINTnFlags,CPointpoint);
//鼠标按下右键
afx_msgvoidOnRButtonDown(UINTnFlags,CPointpoint);
//初始化函数
afx_msgintOnCreate(LPCREATESTRUCTlpCreateStruct);
//鼠标左键松开
afx_msgvoidOnLButtonUp(UINTnFlags,CPointpoint);
4.4.
具体实现
删去状态栏和工具栏:
开始执行程序,就能见到一个有状态栏和工具栏的大的单文档,与上图不同,所以我们第一步就是整理框架:
打开下面函数,把里面的一些语句去掉。
如下所示:
intCMainFrame:
:
OnCreate(LPCREATESTRUCTlpCreateStruct)
if(CFrameWnd:
OnCreate(lpCreateStruct)==-1)
return-1;
/*if(!
m_wndToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP
|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||
!
m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("
Failedtocreatetoolbar\n"
);
//failtocreate
}
if(!
m_wndStatusBar.Create(this)||
m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
Failedtocreatestatusbar\n"
//TODO:
Deletethesethreelinesifyoudon'
twantthetoolbarto
//bedockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&
m_wndToolBar);
*/
return0;
}
设置窗口大小:
运行附加的代码,还能看到扫雷游戏的框架是不能调大小的,而且总是显示在最前面,这又是怎么实现的呢?
在下面函数里添加语句,你能说出前三句是什么意思吗?
注释已经被我去掉了,如果不知道,不如按一下F1。
BOOLCMainFrame:
PreCreateWindow(CREATESTRUCT&
cs)
if(!
CFrameWnd:
PreCreateWindow(cs))
returnFALSE;
ModifytheWindowclassorstylesherebymodifying
//theCREATESTRUCTcs
cs.dwExStyle=cs.dwExStyle|WS_EX_TOPMOST;
//
cs.style=WS_SYSMENU|WS_OVERLAPPED|WS_MINIMIZEBOX;
//;
//设置窗口大小:
400*340
cs.cx=400;
cs.cy=340;
returnTRUE;
构造函数:
由于构造函数是程序运行时就执行的,所以,除了对变量赋值之外,我们还可以把游戏的核心结构即内部数组赋值:
先是把全部格子的位图和雷数赋值为0,然后调用随机函数按指定雷数赋值为-1,最后把不是雷的格子的雷数赋值为相应的值。
CMy2_1View:
CMy2_1View()
addconstructioncodehere
for(intii=0;
ii<
16;
ii++)
m_Bitmap[ii].LoadBitmap(IDB_BITMAP14+ii);
for(intjj=0;
jj<
4;
jj++)
m_anniu[jj].LoadBitmap(IDB_ANNIU1+jj);
//计时
second=0;
//1时开始计时
secondstart=0;
//行数
m_RowCount=25;
//列数
m_ColCount=16;
leinum=80;
//剩余雷数
leftnum=leinum;
//jieshu=1时停止
jieshu=0;
intaa=0;
//初始化为0
for(inti=0;
i<
m_RowCount;
i++)
for(intj=0;
j<
m_ColCount;
j++)
{
lei[i][j].shumu=0;
lei[i][j].weitu=0;
}
//获取当前时间
CTimetime=GetCurrentTime();
ints;
//获取秒数
s=time.GetSecond();
//设置40个雷
do
//以当前秒数为产生随机算法
intk=(rand()*s)%m_RowCount;
intl=(rand()*s)%m_ColCount;
//为了避免一个位置同时算两个雷
//只允许当前位置不是雷时赋值为雷
if(lei[k][l].shumu!
=-1)
lei[k][l].shumu=-1;
aa++;
}while(aa!
=leinum);
//给方格赋值,计算雷数
for(inta=0;
a<
a++)
for(intb=0;
b<
b++)
if(lei[a][b].shumu==0)
{
for(intc=a-1;
c<
a+2;
c++)
for(intd=b-1;
d<
b+2;
d++)
if(c>
=0&
&
m_RowCount&
d>
m_ColCount)
if(lei[c][d].shumu==-1)
lei[a][b].shumu++;
}
}
界面函数:
现在,可以开始画界面了。
如下函数:
很明显,前面部分是用画的方法画出整个界面,但是,后面for循环显示的位图并不是现在画界面的内容,为什么要写呢?
这是为了用户框重画的需要,当我们的游戏玩了一半后最小化,或是把部分窗口移出屏幕,或是执行了新的应用程序覆盖了原来的程序时,必须重画。
我们调用重画函数,它都要重新执行OnDraw(CDC*pDC)函数,那么,此时它就必须把已经显示出来的位图也显示出来。
而开始时雷区位图是不可见的,并不影响界面的初始化。
voidCMy2_1View:
OnDraw(CDC*pDC)
CMy2_1Doc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
adddrawcodefornativedatahere
//画背景
CBrushmybrush1;
mybrush1.CreateSolidBrush(RGB(192,192,192));
CRectmyrect1(0,0,1200,800);
pDC->
FillRect(myrect1,&
mybrush1);
//画黑框
CBrushmybrush;
mybrush.CreateSolidBrush(RGB(0,0,0));
CRectmyrect(20,10,70,40);
FillRect(myrect,&
mybrush);
CRectmyrect2(325,10,375,40);
FillRect(myrect2,&
CPenmypen;
CPen*myoldPen;
mypen.CreatePen(PS_SOLID,2,RGB(255,255,255));
myoldPen=pDC->
SelectObject(&
mypen);
//画黑框的白线
pDC->
MoveTo(20,40);
LineTo(70,40);
LineTo(70,10);
MoveTo(325,40);
LineTo(375,40);
LineTo(375,10);
//画雷区边线
//左上角是白线,右下角是黑线,以显示立体感
pDC->
MoveTo(10+i*15,50+j*15+14);
LineTo(10+i*15,50+j*15);
LineTo(10+i*15+14,50+j*15);
SelectObject(myoldPen);
CPenmypen2;
CPen*myoldPen2;
mypen2.CreatePen(PS_SOLID,1,RGB(0,0,0));
myoldPen2=pDC->
mypen2);
for(intjj=0;
MoveTo(10+ii*15,50+jj*15+14);
LineTo(10+ii*15+14,50+jj*15+14);
LineTo(10+ii*15+14,50+jj*15);
SelectObject(myoldPen2);
CDCDc;
if(Dc.CreateCompatibleDC(pDC)==FALSE)
AfxMessageBox("
Can'
tcreateDC"
//显示按钮
Dc.SelectObject(m_anniu[0]);
BitBlt(180,10,160,160,&
Dc,0,0,SRCCOPY);
//判断显示什么位图
//weitu=1已按下的数字区
//weitu=2显示旗
//weitu=3显示问号
if(lei[a][b].weitu==1)
{
Dc.SelectObject(m_Bitmap[lei[a][b].shumu]);
pDC->
BitBlt(a*15+10,b*15+50,160,160,&
}
if(lei[a][b].weitu==2)
Dc.SelectObject(m_Bitmap[9]);
if(lei[a][b].weitu==3)
Dc.SelectObject(m_Bitmap[10]);
//结束
if(jieshu==1&
lei[a][b].shumu==-1)
Dc.SelectObject(m_Bitmap[11]);
Dc.SelectObject(m_anniu[3]);
//显示黑框里的数字
intnOldDC=pDC->
SaveDC();
SetTextColor(RGB(255,0,0));
SetBkColor(RGB(0,0,0));
CFontfont;
if(0==font.CreatePointFont(160,"
ComicSansMS"
))
AfxMessageBox("
tCreateFont"
font);
CStringstr;
//利用判断显示位数,不够三位前面加0
if(leftnum<
10)
str.Format("
00%d"
leftnum);
else
0%d"
TextOut(25,10,str);
if(second<
10)
second);
elseif(second<
100)
str.Format("
second);
else
%d"
TextOut(330,10,str);
RestoreDC(nOldDC);
运行一下,外观已经出来了,只是还不能玩。
那我们就来添加一些功能函数,使它可以玩。
当然,如果你对程序已经有一定的经验的话,你就会指出上面的函数太长了。
这并不太符合我们编程的要求。
我们编程有一个讲究,就是尽量使函数的代码少,一般为一页左右,便于查看。
那么,我们可以把上面的函数细分为几个小函数,然后在这个函数里面分别调用。
按下鼠标左键:
用if语句判断,如果在按钮上面,则显示按钮按下位图;
如果在扫雷区,先把按钮位图改为张口位图,再判断按下的是否是雷,是就结束,重画,以显示所有的雷;
否则,重画相应格子以显示数字。
voidCMy2_1View:
OnLButtonDown(UINTnFlags,CPointpoint)
Addyourmessagehandlercodehereand/orcalldefault
//获取指针pdc
CDC*pDC=GetDC();
CDCDc;
//显示按下按钮
if(point.x>
180&
point.x<
210&
point.y>
10&
point.y<
40)
Dc.SelectObject(m_anniu[3]);
if((point.x>
=10)&
(point.x<
=385)&
(point.y>
=50)&
(point.y<
=290))
{
if(jieshu==1)
return;
//显示张口按钮
Dc.SelectObject(m_anniu[1]);
//secondstart为1时计时有效
secondstart=1;
//鼠标坐标转换为数组坐标
inta=(point.x-10)/15;
intb=(point.y-50)/15;
if(lei[a][b].weitu==0||lei[a][b].weitu==3)
if(lei[a][b].shumu==-1)
jieshu=1;
//结束时,释放Timer
KillTimer
(1);
//重画,因为这次重画将显示全部的雷,
//不能用部分重画
Invalidate();
else
lei[a][b].weitu=1;
CRectrect;
rect.left=a*15+10;
rect.right=a*15+25;
rect.top=b*15+50;
rect.bottom=b*15+65;
InvalidateRect(&
rect);
}
}CView:
OnLButtonDown(nFlags,point);
如果你现在运行的话,你会发现按下按钮时并不还原,这就涉及到鼠标函数:
OnLButtonUp(UINTnFlags,CPointpoint)
松开鼠标左键:
松开左键时,显示按钮没有按下的位图;
再判断,如果结束,就要显示失败的位图;
另外,如果是在按钮上松开按钮,即表示我们已经按下了重新开始的按钮,必须调用重新开始函数OnStart()。
由于OnStart()函数是与菜单里的开始共有的,此处先保留不说,若有必要运行,可以先去掉最后两行。
OnLButtonUp(UINTnFlags,CPointpoint)
Addyourmessagehandlercodehereand/orcalldefault
CDCDc;
if(jieshu==1)
//显示按扭位图
Dc.SelectObject(m_anniu[2]);
}
//如果按下的是按扭,重新开始
point.y
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C+ 扫雷
![提示](https://static.bdocx.com/images/bang_tan.gif)