推荐下载C++五子棋人机对战游戏设计Word下载.docx
- 文档编号:16314304
- 上传时间:2022-11-22
- 格式:DOCX
- 页数:25
- 大小:23.22KB
推荐下载C++五子棋人机对战游戏设计Word下载.docx
《推荐下载C++五子棋人机对战游戏设计Word下载.docx》由会员分享,可在线阅读,更多相关《推荐下载C++五子棋人机对战游戏设计Word下载.docx(25页珍藏版)》请在冰豆网上搜索。
CPointbpointcan4,//这个位置空,它旁边有四个黑棋
wpointcan4,//这个位置空,它旁边有四个白棋
bpointcan3,//这个位置空,它的旁边有三个黑棋
wpointcan3,//这个位置空,它的旁边有三个白棋
bpointcan2,//这个位置空,它的旁边有两个黑棋
wpointcan2,//这个位置空,它的旁边有两个白棋
bpointcan1;
//不是以上情况,这个位置空
在得到最大值和方向上寻找落棋点,其中i、j表示搜索起点,n表示方向
voidsearchcandown1(inti,intj,intn);
voidsearchcandown2(inti,intj,intn);
voidsearchcandown3(inti,intj,intn);
voidsearchcandown4(inti,intj,intn);
计算最大值及方向CPointmaxnum(inta,intb,intc,intd);
最好落棋点voidbestputdown(inti,intj);
计算机下棋voidcomputerdown();
在位置point放下棋子voidputdown(CPointpoint);
人对机菜单afx_msgvoidOnCpmputer();
3.2.框架的搭建
新建工程,选择单文档,在Step4of6中先中WindowsSockets复选框
4.算法分析与设计
1游戏界面的设计
由于游戏的棋盘大小是一定的,不能改变大小的,是应该符合要求的。
用如下函数设置窗口大小:
BOOLCMainFrame:
:
PreCreateWindow(CREATESTRUCT&cs)
{
if(!
CFrameWnd:
PreCreateWindow(cs))
returnFALSE;
//TODO:
ModifytheWindowclassorstylesherebymodifying
//theCREATESTRUCTcs
cs.dwExStyle=cs。
dwExStyle|WS_EX_TOPMOST;
//
cs.style=WS_SYSMENU|WS_OVERLAPPED|WS_MINIMIZEBOX;
//;
//设置窗口大小:
400*340
cs。
cx=450;
cy=500;
returnTRUE;
}
画棋盘:
在OnDraw(CDC*pDC)函数中画棋盘,由于在游戏过程中有可能重画棋盘,而那时棋盘上面有棋子,所以,我们在这个函数里面必须有画棋子的语句。
在此用数组的做为1表示白棋,-1表示黑棋.
voidCMy3_1View:
:
OnDraw(CDC*pDC)
CMy3_1Doc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//画背景
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);
MoveTo(40+i*20,40);
pDC—〉LineTo(40+i*20,400);
}
//重画时显示存在的棋子
CDCDc;
if(Dc.CreateCompatibleDC(pDC)==FALSE)
AfxMessageBox(”Can'
tcreateDC"
);
for(intn=0;
n<
n++)
for(intm=0;
m〈19;
m++)
if(wzq[n][m]==1)
{
//显示白棋
Dc。
SelectObject(m_bmwhite);
BitBlt(n*20+32,m*20+32,160,160,&
Dc,0,0,SRCCOPY);
}
elseif(wzq[n][m]==—1)
{
//显示黑棋
Dc.SelectObject(m_bmblack);
BitBlt(n*20+32,m*20+32,160,160,&
Dc,0,0,SRCCOPY);
棋盘的效果如图
5.核心算法
在完成界面设计后,就开始展开游戏核心的设计,该部分主要包括计算机搜索最佳落棋位置,游戏胜利判断的实现。
5.1搜索最佳落棋位置
计算机是怎样下棋?
这就是定位的问题了.即搜索棋盘,找出一个最佳点,放下黑棋。
我们实现的方法是:
全盘搜索,并把搜索到的位置,保存在变量。
由于有多种情况,我们定义变量如下:
CPointbpointcan4,//这个位置空,它旁边有四个黑棋
wpointcan4,//这个位置空,它旁边有四个白棋
bpointcan3,//这个位置空,它的旁边有三个黑棋
wpointcan3,//这个位置空,它的旁边有三个白棋
bpointcan2,//这个位置空,它的旁边有两个黑棋
wpointcan2,//这个位置空,它的旁边有两个白棋
bpointcan1;
并在搜索之前都赋值为(—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;
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!
putdown(bpointcan3);
elseif(wpointcan3.x!
putdown(wpointcan3);
elseif(bpointcan2.x!
putdown(bpointcan2);
elseif(wpointcan2。
putdown(wpointcan2);
else
putdown(bpointcan1);
}
上面又有两个新函数,分别定义为空函数,如下:
搜索最佳位置voidbestputdown(inti,intj);
放下黑棋voidputdown(CPointpoint);
现在,对上面两个空函数进行定义
在指定位置下棋:
由于putdown(CPointpoint)函数的原理非常简单,我们先说明如下:
//黑棋下
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;
y=point。
y*20+30;
over(overpoint);
colorwhite=true;
搜索最佳落棋点:
现在还有voidbestputdown(inti,intj)函数没有定义.它的实现原理是:
在四个方向上,各自计算那个方向上棋子的状态,利用原来定义的白棋为1,黑棋为—1的思想,让同个方向上的五个棋子的值相加,取绝对值并赋值给为这个方向定义的局部变量num[i].
如果几个棋子是同色的,无论黑白,它的绝对值必然大,而对于几个棋子中有黑棋和白棋的,其值必然相加而抵消变小。
所以我们可以利用这种方法来寻找旁边有多个同色棋子的空位置(前面已经具体说明)。
在每一个棋盘位置,计算以它为起点的四个方向(横、竖、撇、捺),再比较这四个方向中哪个值最大,然后在这个方向上寻找落棋点。
//检查四个方向,各算出五个棋子的和并赋值
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]"
|"
if(j<
a=a+wzq[i][j+k];
num[1]=abs(a);
///////////////////////////////num[2]”\"
if(i〈15&
&j〈15)
k<
5;
a=a+wzq[i+k][j+k];
num[2]=abs(a);
//////////////////////////////num[3]”/"
a=0;
if((i〉4)&&(j<
15))
for(k=0;
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。
break;
case2:
searchcandown2(i,j,numbig.x);
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;
y=a;
point.x=1;
point.y=b;
if(c>
point。
y)
x=2;
point.y=c;
if(d〉point。
point.x=3;
y=d;
returnpoint;
而另外的四个函数,有其相似性,分别介绍如下:
voidsearchcandown4(inti,intj,intn)函数:
如果最大值是四,它必然有一个空位置;
可以这样计算,如果第一个是空,那我们把它赋值给相应变量;
否则,先找那个空位置,然后判断第一个棋子的颜色,并赋相应的值。
//由于相似,下面代码只解释第一个方向
//有四个同色棋
searchcandown4(inti,intj,intn)
intk;
/////////////////////////////num[0]"
—-”
if(n==0)
//如果第一个是空
if(wzq[i][j]==0)
//如果下面有白棋
if(wzq[i+1][j]==1)
//下面位置可以下棋,已经有四个白棋
wpointcan4.x=i;
wpointcan4.y=j;
break;
//下面位置可以下棋,已经有四个黑棋
bpointcan4.x=i;
bpointcan4。
y=j;
//如果找到下棋位置,一定能找到!
elseif(wzq[i+k][j]==0)
//如果第一个是白棋
if(wzq[j][j]==1)
wpointcan4。
x=i+k;
//否则第一个是黑棋
bpointcan4.y=j;
break;
////////////////////////////num[1]”|”
if(n==1)
5;
if(wzq[i][j]==0)
if(wzq[i][j+1]==1)
x=i;
y=j;
x=i;
elseif(wzq[i][j+k]==0)
if(wzq[i][j]==1)
wpointcan4.y=j+k;
y=j+k;
}
///////////////////////////////num[2]"
\"
if(n==2)
if(wzq[i][j]==0)
if(wzq[i+1][j+1]==1)
wpointcan4.x=i;
elseif(wzq[i+k][j+k]==0)
if(wzq[i][j]==1)
wpointcan4.x=i+k;
x=i+k;
y=j+k;
//////////////////////////////num[3]”/”
if(n==3)
if(wzq[i-1][j+1]==1)
elseif(wzq[i-k][j+k]==0)
if(wzq[i][j]==1)
wpointcan4.x=i—k;
bpointcan4.x=i—k;
bpointcan4.y=j+k;
voidsearchcandown3(inti,intj,intn)函数:
如果最大值是三,它有两种情况,一种是三个同色和两个空;
一种是四个同色和一个异色。
前一种必定能找到一个空位置,赋值;
后一种必定找不到空位置,不赋值.所以我们的想法很简单,先找到空位置,证明有三个同色,这对于玩五子棋来说三个同色是很重要的,再判断是哪种颜色,赋相应的值。
voidsearchcandown2(inti,intj,intn)函数:
如果最大值是二,也有两种情况:
一种是有两个同色和三个空位置;
一种是有三个同色和一个异色和一个空位置,并且只算三个同色不连在一起的情况(因为如果有三个连续的情况,重全盘搜索的角度看,必然会被另外的情况所代替)。
分两种算法:
一种是有一个空位置,一种是有三个空位置。
前者先找到空位置,再判断它下面两个是否同色,同色则赋值给相应变量,异色则不赋值,因为意义不大;
后者只要找到一个空位置就行了.
voidsearchcandown1(inti,intj,intn)函数:
最后的一个函数是searchcandown1(inti,intj,intn),这是为了预防用的,如果以上情况不发生,这个函数就是为了处理这种情况。
这里就说明了为什么我们要添加vspoint的原因了,它保存了上次白棋下棋的位置,而我们在没有办法的情况下,在白棋旁边随便找个位置就可以了。
//如果五个位置的和是一
searchca
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 推荐 下载 C+ 五子棋 人机 游戏 设计