[问题描述]
实现一个简单的二人对战五子棋游戏,自动判断胜负。同时记录每一步的思考时间及落点位置。并且在每次对弈时,能给对弈者的应招提供某些启发式信息。
[基本要求]
在界面上显示必要的功能部分,其余的大部分都放在菜单里。对于这种棋类游戏,计时和计分功能一般是必不可少的部分,相应的还有玩家水平的显示、最高纪录的显示等等。
[供参考的数据结构和算法]
数据结构只需一个二维数组。对于整型数组Cell[x][y],x记录了单击时鼠标位置的横坐标,y记录了单击时鼠标位置的纵坐标,而单元0、1、2分别表示未被选中、由玩家A选中、由玩家B选中。相应的,新游戏实际就是利用循环将整个数组赋值为0,而玩家输赢的判断则是分别向左、右、上、下、左上、左下、右上、右下的搜索。如果相邻5个数组单元值都相同且不为零,则做出相应玩家获胜的判断。
[活动建议]
可以尝试实现人机对战。此时,对于机器的每步的走法,需要考虑目前形势下的可选的最佳走法,这涉及到启发式搜索算法。
问题分析
根据问题的描述写出五子棋游戏.
系统分析
本软件有选择人人对战的功能同人机对战的功能,能判断输赢,可以计算胜负的局数,可以计算行了多少个棋子.
1,局数whitewin,blackwin
2,已行棋子iwhite,iblack
3,人人对战tag=0,人机对战tag=1
4,判断输赢IsWin()
5,人工智能DoAI()
程序设计
1 利用CDocument里面的内容来包含数据,利用CView里的内容来显示
2 利用OnLButtonDown来显示图形并更改数据
3 在CDocument内SetPoint()调用OnAI()来设置新的由电脑得出得数据点,其中OnAI的算法是分左右,上下,左上右下,左下右上四个方案来选择,而SetPoint()则是利用从五个点到一个点来选择,当五个点的时候先行,当四个点的时候其次………….如此类推,直到一个点为止.
4 FindFir()寻找第一个数据,减少空间树
5 FindLast()寻找最后一个数据
6 CView中init()用来初始化图形,并且利用OnDraw()来画出来
7 利用LButtonDown()来画图形
8 DrawWhite用来画白棋
9 DrawBlack用来画黑棋
10 当判断胜利的时候调用IsWin(),如果胜利则初始化图形OnDraw()
11 OnFileNew2()新建棋盘
一些主要算法(已经简化一些不必要的部分)
void CFiveView::OnLButtonDown(UINT nFlags, CPoint point)
{
if( ((point.x<25) || (point.x>(MAXX+1)*25))
||((point.y<25) || (point.y>(MAXY+1)*25)))//看看那里不可以下棋
MessageBox("此处不能下棋");
if((point.x >= (i+1)*25) && (point.x < (i+2)*25)
&& (point.y >= (j+1)*25) && (point.y < (j+2)*25))
{
if(pDoc->Cell[i][j]!=0)
MessageBox("此处不能下棋");
if(pDoc->blacknum <= pDoc->whitenum)//行黑棋
{
DrawBlack(pDC);
}
else//行白棋
{
DrawWhite(pDC);
}
}
bool CFiveDoc::IsWin(int i,int j)//胜利条件
{
if(!((i-5<0) && (i+5>MAXX)))//减少搜索空间
for(tempi=0 ; tempi<5 ; tempi++)//向左右
{
for(tempj=0 ; tempj<5 ; tempj++)
{
if((Cell[i][j] == Cell[i-tempi+tempj][j]) != 0)
k++;
}
if(k==5) return true;
k=0;
}
CPoint CFiveDoc::SetPoint()
{
if((nowpoint.x==-1)&&(nowpoint.y==-1))
{
pnow.x = 7;
pnow.y = 8;
return pnow;
}
if((pnow = DoAI(pfir,plast,5,2,true)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
if((pnow = DoAI(pfir,plast,4,2,false)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
if((pnow = DoAI(pfir,plast,5,3,true)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
if((pnow = DoAI(pfir,plast,4,3,false)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
if((pnow = DoAI(pfir,plast,4,2,true)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
if((pnow = DoAI(pfir,plast,3,2,false)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
if((pnow = DoAI(pfir,plast,4,3,true)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
if((pnow = DoAI(pfir,plast,3,3,false)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
if((pnow = DoAI(pfir,plast,3,2,true)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
if((pnow = DoAI(pfir,plast,2,2,false)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
if((pnow = DoAI(pfir,plast,3,3,true)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
if((pnow = DoAI(pfir,plast,2,3,false)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
if((pnow = DoAI(pfir,plast,1,2,false)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
if((pnow = DoAI(pfir,plast,1,3,false)) != nopoint)
if((pnow.x<MAXX) && (pnow.y<MAXY))
return pnow;
return pnow;
}
CPoint CFiveDoc::DoAI(CPoint pfir , CPoint plast , int length , int color , bool havefree)
//pfir是第一个数,plast是最后一个数,length 是要搜索的长度,color是黑白,havefree是中间有否空白
{
for(i=0 ; i<MAXX ; i++)//上下搜索
for(j=0 ; j<MAXY ; j++)
{
if(j+length<MAXY)
{
for(tempj=0 ; tempj<length ; tempj++)
{
if(Cell[i][j+tempj] == color)
m++;
else if(Cell[i][j+tempj] == 0)
{
pblank.x = i;
pblank.y = j+tempj;
}}
if((m==length)&&(!havefree))
{
if(Cell[i][j-1]==0)
{
pnow.x = i;
pnow.y = j-1;
return pnow;
}
if(Cell[i][j+tempj+1]==0)
{
pnow.x = i;
pnow.y = j+tempj+1;
return pnow;
}}
if((m==length-1) && (havefree)//有空格
&& (pblank.y>j-1) && (pblank.y<j+tempj+1))
{
pnow = pblank;
return pnow;
}
}
m=0;
}
}
数据传递流程:
OnFileNew2()
|
OnLButtonDown()->pDoc->nowpoint
|
CDocument::SetPoint()->Cell[][],nowpoint
|
FindFir()->pfir
|
FirdLast()->plast
|
OnAI()->pnow
|
Draw()
|
IsWin()->nowi,nowj—N return
|--Y
OnDraw()
|
Init()
软件测试:
黑盒测试__利用一边玩游戏一边测试.
白盒测试__检查过里面的数据,开始因为没有初始化,而造成得出来的数据错误