MFCC++五子棋课程设计报告.docx
- 文档编号:4453683
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:31
- 大小:98.88KB
MFCC++五子棋课程设计报告.docx
《MFCC++五子棋课程设计报告.docx》由会员分享,可在线阅读,更多相关《MFCC++五子棋课程设计报告.docx(31页珍藏版)》请在冰豆网上搜索。
MFCC++五子棋课程设计报告
课程设计成绩
考勤成绩(%)
指导老师评语
报告及程序成绩(%)
总评成绩
指导老师签名:
《windows程序设计》
课程设计报告
学院(系):
计算机科学与技术系
班级:
计专2班
学生姓名:
梁剑学号**********
指导教师:
时间:
从2010年1月18日到2010年1月22日
摘要
1.能够利用所学的基本知识,设计一个简单的五子棋序,具有以下功能:
①数据结构的设计;五子棋棋盘的绘制。
②人机下棋时,计算机下棋算法的设计。
③人机下棋时,判断任一方获胜的算法的设计。
关键字:
MFC编程,Windows程序
目录
项目一:
五子棋
五子棋
1设计目的与要求
1.1设计目的
1、进一步掌握利用VisualC++进行程序设计的能力;
2、进一步理解和运用面向对象程序设计的思想和方法;
3、初步掌握开发一个小型实用系统的基本方法;
4、学会调试一个较长程序的基本方法;
5、理解Windows程序的运行过程;
1.2设计内容
能够利用所学的基本知识,设计一个简单的学生信息管理应用程序,具有以下功能:
①数据结构的设计;五子棋棋盘的绘制。
②人机下棋时,计算机下棋算法的设计。
③人机下棋时,判断任一方获胜的算法的设计。
1.3设计要求
整个程序使用winsocket函数做网络数据收发,基于UDP协议。
可以直接使用WindowsAPI编程(SDK编程),也可以使用MFC编程。
本课程设计中我们使用的是MFC编程。
其具体的设计要求如下所述:
2设计环境或器材、原理与说明
2.1设计环境与器材
因为选择使用MFC编程Windows环境与MicrosoftVisualC++6.0编译环境;
2.2原理与说明
首先利用mfc建立单文档窗口,在窗口上画19*19的表格,把每个表格点的信息存在二维数组wzq[19][19]中。
白棋为1,黑棋为-1,这样当要测是否结束时只要查看4个方向的绝对值是否等于5,就可以判定输赢了
如图:
3.1设计过程及程序代码
3.11界面设计:
图3-2五子棋界面设计
打开应用程序时游戏会自动开始。
显示表格代码:
CMyDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//TODO:
adddrawcodefornativedatahere
CBrushmybrush1;
mybrush1.CreateSolidBrush(RGB(192,192,192));
CRectmyrect1(0,0,1200,800);
pDC->FillRect(myrect1,&mybrush1);
//画棋盘框线
CPenmypen;
CPen*myoldPen;
mypen.CreatePen(PS_SOLID,1,RGB(0,0,0));
myoldPen=pDC->SelectObject(&mypen);
for(inti=0;i<19;i++)
{
pDC->MoveTo(40,40+i*20);
pDC->LineTo(400,40+i*20);
pDC->MoveTo(40+i*20,40);
pDC->LineTo(40+i*20,400);
}
//重画时显示存在的棋子
CDCDc;
if(Dc.CreateCompatibleDC(pDC)==FALSE)
AfxMessageBox("Can'tcreateDC");
for(intn=0;n<19;n++)
for(intm=0;m<19;m++)
if(wzq[n][m]==1
{
//显示白棋
Dc.SelectObject(m_bmwhite);pDC->BitBlt(n*20+32,m*20+32,160,160,&Dc,0,0,SRCCOPY);
}
elseif(wzq[n][m]==-1)
{
//显示黑棋
Dc.SelectObject(m_bmblack);pDC->BitBlt(n*20+32,m*20+32,160,160,&Dc,0,0,SRCCOPY);
}
3.1.2人下棋设计
涉及到OnLButtonDown(UINTnFlags,CPointpoint)和OnLButtonUp(UINTnFlags,CPointpoint)两个函数了。
要用哪一个或用两个?
用Down函数时是在鼠标按下时放下棋子,可是,要是我们按下后意识到按错了怎么办;那就改用Up函数,表示当鼠标键松开时放下棋子。
这样子当鼠标点下并放开时界面上会显示相应的棋子。
并调用over函数判断输赢。
代码如下:
voidCMy3_1View:
:
OnLButtonUp(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
CDC*pDC=GetDC();
CDCDc;
if(Dc.CreateCompatibleDC(pDC)==FALSE)
AfxMessageBox("Can'tcreateDC");
//是否在棋盘内
if(point.x>30&&point.x<410&&point.y>30&&point.y<410)
{
intpx=(point.x-30)/20;
intpy=(point.y-30)/20;
//是否已经有棋子
if(colorwhite&&wzq[px][py]==0)
{
Dc.SelectObject(m_bmwhite);
pDC->BitBlt(px*20+32,py*20+32,160,160,&Dc,0,0,SRCCOPY);
//表示存在白棋
wzq[px][py]=1;
//检查是否结束
over(point);
//换黑棋下
colorwhite=false;
}
elseif(wzq[px][py]==0)
{
Dc.SelectObject(m_bmblack);
pDC->BitBlt(px*20+32,py*20+32,160,160,&Dc,0,0,SRCCOPY);
wzq[px][py]=-1;
over(point);
colorwhite=true;
}
}
CView:
:
OnLButtonUp(nFlags,point);
}
3.1.3电脑下棋:
计算机要下棋?
就要定位。
即搜索棋盘,找出一个最佳点,放下黑棋。
实现的方法是:
全盘搜索,并把搜索到的位置,保存在变量。
由于有多种情况,我们定义变量如下:
CPointbpointcan4,//这个位置空,它旁边有四个黑棋
wpointcan4,//这个位置空,它旁边有四个白棋
bpointcan3,//这个位置空,它的旁边有三个黑棋
wpointcan3,//这个位置空,它的旁边有三个白棋
bpointcan2,//这个位置空,它的旁边有两个黑棋
wpointcan2,//这个位置空,它的旁边有两个白棋
bpointcan1;//不是以上情况,这个位置空
3.1.4搜索最优下棋点
并在搜索之前都赋值为(-1,-1),然后,进行搜索,并把相应的值保存在相应变量里面,而如果前面已经对变量赋值,我们依然赋值,用新值代替旧值。
注意:
我们只保存最后一个值,这样的一个好处是,避免了每次都从左上角开始,并且它的随机性比随机函数还随机。
全盘搜索完之后,由于上面的变量中至少有一个已经被赋值,即不是(-1,-1),我们可以采用多数优先的方法,让已经有多个同色棋子的位置先下棋。
其原理是,如果已经有四个黑棋,计算机再下一个黑棋就赢了;否则,如果人已经有四个白棋,那么计算机就必须放下一个黑棋,阻止白棋下一步赢;如果已经有三个黑棋,再下一个黑棋,变成四个;否则,如果已经有三个白棋,下一个黑棋,破坏它;两个棋子的同理;否则,在刚才白棋下的地方,顺便找一个位置,下棋。
computerdown()函数如下:
//轮到计算机下棋
voidCMy3_1View:
:
computerdown()
{
//把各种情形赋值为如下
bpointcan4=(-1,-1);
wpointcan4=(-1,-1);
bpointcan3=(-1,-1);
wpointcan3=(-1,-1);
bpointcan2=(-1,-1);
wpointcan2=(-1,-1);
bpointcan1=(-1,-1);
//搜索最好的落棋点
for(inti=0;i<19;i++)
for(intj=0;j<19;j++)
bestputdown(i,j);
//判断放在哪里
//棋多的位置优先
//黑白一样多时黑先
//不是-1就表示已经被赋值!
if(bpointcan4.x!
=-1)
{
putdown(bpointcan4);
return;
}
elseif(wpointcan4.x!
=-1)
{
putdown(wpointcan4);
return;
}
elseif(bpointcan3.x!
=-1)
{
putdown(bpointcan3);
return;
}
elseif(wpointcan3.x!
=-1)
{
putdown(wpointcan3);
return;
}
elseif(bpointcan2.x!
=-1)
{
putdown(bpointcan2);
return;
}
elseif(wpointcan2.x!
=-1)
{
putdown(wpointcan2);
return;
}
else
{
putdown(bpointcan1);
return;
}
}
上面又有两个新函数,分别定义为空函数,如下:
//搜索最佳位置
voidbestputdown(inti,intj);
//放下黑棋
voidputdown(CPointpoint);
现在,我们就必须对上面两个空函数进行定义了。
在指定位置下棋:
由于putdown(CPointpoint)函数的原理非常简单,我们先说明如下:
//黑棋下
voidCMy3_1View:
:
putdown(CPointpoint)
{
CDC*pDC=GetDC();
CDCDc;
if(Dc.CreateCompatibleDC(pDC)==FALSE)
AfxMessageBox("Can'tcreateDC");
Dc.SelectObject(m_bmblack);
pDC->BitBlt(point.x*20+32,point.y*20+32,160,160,&Dc,0,0,SRCCOPY);
wzq[point.x][point.y]=-1;
//由于原来我们检查是否结束时用的是鼠标点下的坐标,而现在
//putdown(CPointpoint)函数用的是数组棋盘的坐标,所以必须转换
CPointoverpoint;
overpoint.x=point.x*20+30;
overpoint.y=point.y*20+30;
over(overpoint);
colorwhite=true;
}
搜索最佳落棋点:
现在就剩下voidbestputdown(inti,intj)函数没有定义了(虽然前面的变量函数已经说明了,当时我们这里是用程序扩展的思路进行的,故如此说明)。
它的实现原理是:
在四个方向上,各自计算那个方向上棋子的状态,我们的思路是利用原来定义的白棋为1,黑棋为-1,的思想,让同个方向上的五个棋子的值相加,取绝对值并赋值给为这个方向定义的局部变量num[i]。
为什么要用五个棋子的值相加呢?
因为,如果几个棋子是同色的,无论黑白,它的绝对值必然大,而对于几个棋子中有黑棋和白棋的,其值必然相加而抵消变小。
所以我们可以利用这种方法来寻找旁边有多个同色棋子的空位置(前面已经具体说明)。
在每一个棋盘位置,计算以它为起点的四个方向(横、竖、撇、捺),再比较这四个方向中哪个值最大,然后在这个方向上寻找落棋点。
//检查四个方向,各算出五个棋子的和并赋值
voidCMy3_1View:
:
bestputdown(inti,intj)
{
//四个方向的值
intnum[4];
inta,k;
///////////////////////////////num[0]-->
a=0;
if(i<15)
for(k=0;k<5;k++)
a=a+wzq[i+k][j];
num[0]=abs(a);
//////////////////////////////num[1]"|"
a=0;
if(j<15)
for(k=0;k<5;k++)
a=a+wzq[i][j+k];
num[1]=abs(a);
///////////////////////////////num[2]"\"
a=0;
if(i<15&&j<15)
for(k=0;k<5;k++)
a=a+wzq[i+k][j+k];
num[2]=abs(a);
//////////////////////////////num[3]"/"
a=0;
if((i>4)&&(j<15))
for(k=0;k<5;k++)
a=a+wzq[i-k][j+k];
num[3]=abs(a);
//比较哪个方向同色棋最多
//由于我们搜索落棋点时用到最大值和方向,我们可以定义一个Cpoint类变量,//让它返回两个值。
可以说,这也是一种巧妙的想法,因为这样你就不用去写//内联函数了
CPointnumbig;
//numbig.x表示方向
//numbig.y表示最大值
numbig=maxnum(num[0],num[1],num[2],num[3]);
//在得到最大值和方向上寻找落棋点
switch(numbig.y)
{
case4:
searchcandown4(i,j,numbig.x);break;
case3:
searchcandown3(i,j,numbig.x);break;
case2:
searchcandown2(i,j,numbig.x);break;
default:
searchcandown1(i,j,numbig.x);
}
}
同样的方法,我们必须为上面还没有定义的函数添加空函数。
//其中i、j表示搜索起点,n表示方向
voidsearchcandown1(inti,intj,intn);
voidsearchcandown2(inti,intj,intn);
voidsearchcandown3(inti,intj,intn);
voidsearchcandown4(inti,intj,intn);
CPointmaxnum(inta,intb,intc,intd);
最大值函数的实现:
现在先介绍CPointmaxnum(inta,intb,intc,intd)函数,它只是四个整数的比较:
CPointCMy3_1View:
:
maxnum(inta,intb,intc,intd)
{
//point.x为方向值
//point.y为最大值
CPointpoint;
if(a>=b)
{
point.x=0;
point.y=a;
}
else
{
point.x=1;
point.y=b;
}
if(c>point.y)
{
point.x=2;
point.y=c;
}
if(d>point.y)
{
point.x=3;
point.y=d;
}
returnpoint;
}
而另外的四个函数,有其相似性,分别介绍如下:
voidsearchcandown4(inti,intj,intn)函数:
如果最大值是四,它必然有一个空位置;我们可以这样计算,如果第一个是空,那我们把它赋值给相应变量;否则,先找那个空位置,然后判断第一个棋子的颜色,并赋相应的值。
//由于相似,下面代码只解释第一个方向
//有四个同色棋
voidCMy3_1View:
:
searchcandown4(inti,intj,intn)
{
intk;
/////////////////////////////num[0]"--"
if(n==0)
for(k=0;k<5;k++)
//如果第一个是空
if(wzq[i][j]==0)
{
//如果下面有白棋
if(wzq[i+1][j]==1)
{
//下面位置可以下棋,已经有四个白棋
wpointcan4.x=i;
wpointcan4.y=j;
break;
}
else
{
//下面位置可以下棋,已经有四个黑棋
bpointcan4.x=i;
bpointcan4.y=j;
break;
}
}
//如果找到下棋位置,一定能找到!
elseif(wzq[i+k][j]==0)
{
//如果第一个是白棋
if(wzq[j][j]==1)
{
wpointcan4.x=i+k;
wpointcan4.y=j;
break;
}
//否则第一个是黑棋
else
{
bpointcan4.x=i+k;
bpointcan4.y=j;
break;
}
}
////////////////////////////num[1]"|"
if(n==1)
for(k=0;k<5;k++)
{
if(wzq[i][j]==0)
if(wzq[i][j+1]==1)
{
wpointcan4.x=i;
wpointcan4.y=j;
break;
}
else
{
bpointcan4.x=i;
bpointcan4.y=j;
break;
}
elseif(wzq[i][j+k]==0)
{
if(wzq[i][j]==1)
{
wpointcan4.x=i;
wpointcan4.y=j+k;
break;
}
else
{
bpointcan4.x=i;
bpointcan4.y=j+k;
break;
}
}
}
///////////////////////////////num[2]"\"
if(n==2)
for(k=0;k<5;k++)
{
if(wzq[i][j]==0)
if(wzq[i+1][j+1]==1)
{
wpointcan4.x=i;
wpointcan4.y=j;
break;
}
else
{
bpointcan4.x=i;
bpointcan4.y=j;
break;
}
elseif(wzq[i+k][j+k]==0)
{
if(wzq[i][j]==1)
{
wpointcan4.x=i+k;
wpointcan4.y=j+k;
break;
}
else
{
bpointcan4.x=i+k;
bpointcan4.y=j+k;
break;
}
}
}
//////////////////////////////num[3]"/"
if(n==3)
for(k=0;k<5;k++)
{
if(wzq[i][j]==0)
if(wzq[i-1][j+1]==1)
{
wpointcan4.x=i;
wpointcan4.y=j;
break;
}
else
{
bpointcan4.x=i;
bpointcan4.y=j;
break;
}
elseif(wzq[i-k][j+k]==0)
{
if(wzq[i][j]==1)
{
wpointcan4.x=i-k;
wpointcan4.y=j+k;
break;
}
else
{
bpointcan4.x=i-k;
bpointcan4.y=j+k;
break;
}
}
}
}
voidsearchcandown3(inti,intj,intn)函数:
如果最大值是三,它有两种情况,一种是三个同色和两个空;一种是四个同色和一个异色。
前一种必定能找到一个空位置,赋值;后一种必定找不到空位置,不赋值。
所以我们的想法很简单,先找到空位置,证明有三个同色,这对于玩五子棋来说三个同色是很重要的,再判断是哪种颜色,赋相应的值。
//最多有三个同色
voidCMy3_1View:
:
searchca
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MFCC 五子棋 课程设计 报告