五子棋人机对战设计任务书.docx_第1页
五子棋人机对战设计任务书.docx_第2页
五子棋人机对战设计任务书.docx_第3页
五子棋人机对战设计任务书.docx_第4页
五子棋人机对战设计任务书.docx_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

五子棋人机对战设计任务书目录1.系统需求分析12.总体设计13.详细设计24.系统调试45.使用说明56.编程体会67.源程序清单71. 系统需求分析五子棋是我国古代传统的黑白棋种之一,又称作连珠棋。五子棋游戏首先需要棋盘,并绘制棋子,若希望人机对战还要为计算机设置一定的算法,以使其能够自动判断落棋的位置,此外,还需要有一定的判断系统来判定胜负,还有悔棋功能。综上,五子棋人机对战游戏需要提供以下功能:(1) 使用图形界面,绘制棋盘,并能够提供虚拟棋盘来作为计算机运算的依据。(2) 判断玩家的落子位置,并相应的画出对应颜色的棋子,判断落子位置时误差要很小。另外,需要记录玩家的落子情况。(3) 通过运算判定电脑的落子位置,如防范玩家连成五子,或进攻使自己连成五子取得胜利,并相应的显示对应颜色的棋子。另外,需要记录电脑的落子情况。(4) 根据规则判断出胜负,先连成五子者获得胜利,并显示出胜利的一方,之后可以按任意键再来一局。(5) 当玩家落棋出现重大失误时,可进行悔棋,清除棋子。2. 总体设计五子棋人机对战游戏包括四个方面的功能,分别是绘制棋盘和棋子等图形化显示功能,获取玩家落子功能,计算并判断得到电脑落子位置的功能以及判断胜负的功能。图形化显示功能方面,运用easyx图形库进行图形的绘制,可以进行背景色的设置,线条的绘制,文字的显示和字体的设置。通过initgraph初始化界面,设置坐标,用setbkcolor函数设置背景色,用settextcolor函数设置文本颜色,用settextstyle函数设置文本字体,用outtextxy函数显示文字,用line和fillcircle函数进行棋盘的绘制,用fillcircle函数进行棋子的绘制。通过HWND句柄可以弹出选项框。建立二维数组作为虚拟棋盘。玩家落子方面,首先需要判断鼠标所点击的位置,然后需要在链表上建立新的节点,在虚拟棋盘上设置玩家落子,并在棋盘上绘制出玩家的棋子。电脑落子方面,需要遍历所有位置,分别对玩家在该处落子和电脑在该处落子进行评分,找出玩家或电脑落子评分最高的位置作为落子的位置,在虚拟棋盘上落子,并在棋盘上绘制出电脑的棋子。判定胜负功能方面,在玩家及电脑每次落子之后,都通过调用判定函数来判断某一方是否连成五子,若一方胜利,显示游戏结果,跳出当前棋局的循环,并按任意键重新布置棋盘,开始新的一局。悔棋方面,需要沿着链表的结构进行前一步棋子的清除。设置棋盘模块显示界面,绘制棋盘,设置虚拟棋盘五子棋人机对战游戏判断模块判断某一方是否连成五子,显示结果电脑落子模块判定最佳落子处,建立链表新节点玩家落子模块玩家落子捕捉,建立链表的新节点悔棋模块清除原棋子五子棋游戏中的功能模块图:3. 详细设计chessboard(棋盘类)piece(棋子类)piece_playerpiece_computerplayer_listcomputer_list五子棋人机对战程序中的类的层次图为:五子棋人机对战游戏中各功能模块的实现:开始界面布置棋盘玩家落子电脑落子判定胜负悔棋布置棋盘功能绘制15*15棋盘设置虚拟棋盘1.布置棋盘模块玩家落子功能捕捉鼠标信息建立新的链表节点设置与绘制棋子2.玩家落子模块3.电脑落子模块电脑落子功能运算判断最佳落子位置建立新的链表节点设置与绘制棋子4.判定胜负模块判定胜负功能判定是否连为五子显示结果,清空缓存,跳出循环5.悔棋模块悔棋功能清除玩家棋子清除电脑棋子五子棋人机对战游戏中六个类的UML图:chessboard(棋盘类)public: chessboard()initboard()piece(棋子基类)public: piece()virtual piece()int getx()int gety()virtual void print()const=0protected: int xint ypiece_player(玩家棋子类)piece_computer(电脑棋子类)public: piece_player()piece_player(int,int)virtual void print()virtual piece_playerpublic: piece_computer()piece_computer(int,int)virtual void print()virtual piece_computerpublic: piece_player *p_nextpublic: piece_computer *c_nextplayer_list(玩家链表类)computer_list(电脑链表类)public: player_list()player_list()bool insert(int,int)bool Delete(int a1616)public: computer_list()computer_list()bool insert(int,int)bool delete(int a1616)protected: piece_player *p_headprotected: piece_computer *c_head4. 系统调试由于使用了图形界面,很多功能的调试只能在程序基本编译完成后进行。对于棋盘等方面的调试,我是先将程序写为两个玩家的对战进行调试,开始的错误主要是语法错误,例如两次声明全局数组extern int a1616,却没有对其进行定义,导致了LNK2001错误。另外的一个错误是电脑自动先下时,未将数组坐标转化为图形界面上的坐标,使得棋子所在的位置与其应当出现的位置出现了较大的偏差。接下来的调试主要是算法方面的调试。开始时,电脑下棋会出现一些致命的错误,例如:玩家执白旗,电脑执黑棋,玩家已在c8,d9,e10连成三珠,但电脑下棋时去选择了f4的位置,而不是b7或f11来堵住玩家,从而导致电脑输下此局,根据这个情况,我判断是f4左上方三颗棋子影响了电脑的判断,另外d4到f4处还可形成进攻,因而修改程序的过程中,我增大了连成三珠且两边没有另一方棋子堵住情况的权重。经过修改,电脑下棋便不再犯这样的低级错误,但不得不说,电脑下棋的方式也变得比之前保守。此外,之前还出现过电脑没有注意边界,而依然在边界处下棋企图连成三子的情况,为此,我在程序中另加了判断语句,若连接的棋子数目小于5且一边已到达边界,则不在边界处着棋,另外如果对方棋子已在距边界小于等于五的距离处将该方向堵住,也扣除一定的权重。经过上述的处理,最佳落棋处的分数会比那些受限制的落棋处的分数高,而不是因为可能的分数相同而造成电脑判断的失误。在进行悔棋功能的调试时,我先是处理了循环结构造成的问题,然后在棋盘上清除棋子图案的程序经过了两三次的修改,终于使得棋子的图案完全被清除。此外在悔棋直到没有棋子时,刚开始的时候程序会发生崩溃,原因是我没有添加头指针是否为空的判断,添加该判断后,棋盘上没有棋子时不再发生变化。5. 使用说明启动游戏后,首先会进入开始界面。此时按任意键(指键盘)即可进入游戏。进入游戏后首先需要选择是否让电脑先下,另外,游戏中永远是玩家执白棋,电脑执黑棋,游戏中没有禁手的规则。游戏的窗口大小不能改变,故高度较小、屏幕较小的电脑需要调节分辨率来显示全部的棋盘,否则可能有一部分棋盘(一半是棋盘的最下方)在屏幕中无法显示。若想要棋盘显示完全,请保证屏幕的竖直方向像素至少为800,水平方向的像素至少为900.点击确定电脑先下,点击取消则玩家先下。电脑先下时,会自动选择天元的位置。玩家获得胜利或电脑胜利时时,棋盘的上方会出现玩家胜利或玩家失利的的信息。此时按任意键(键盘)可以重新布置棋盘,开始新的一局。请注意,下棋时鼠标是有一定的点击范围的,起一定要点击到交点的中央区域附近,否则程序不会认为玩家已下棋,也不会在玩家认为自己下过棋的地方显示棋子,故一定要点击准确,下棋前一定要三思,点击一定要准确。此外,游戏设置了悔棋功能,点击右键即可悔棋。若希望结束游戏,直接点击右上方的关闭按钮关闭程序即可退出游戏。此外,游戏编译通过是建立在有easyx C+图形库的基础上。故而没有安装easyx图形库的情况下,头文件graphics.h中是没有相关函数的,会使编译不通过。程序在VS2008下编译成功。6. 编程体会这是我第一次应用图形界面编程,通过这个游戏程序的编写,我初步了解了MFC,easyx等图形化编程的工具,并初步学会使用easyx C+图形库进行编程。除了图形界面编程,此程序中还应用了构造函数的重载,类的继承与抽象基类,动态内存分配与链表结构的建立等知识。这个程序中包含六个类,其中玩家棋子类与电脑棋子类属性与方法相似,通过棋子基类进行派生,各个类的功能分配等方面比我之前的编程也更加明晰。使用链表结构使得每一步棋间都通过链表进行了关联,既贴合实际,也是程序进一步完善的需要。通过链表的结构,每一步棋都可以追溯到上一步棋,通过为玩家和电脑双方各建立一个链表,方便了悔棋功能的设置。使用链表的同时还进行内存的动态分配,每一次添加棋子都通过调用list类的添加函数,使得主程序更加简洁。判断胜负与对电脑应该下的位置进行打分通过两个函数实现。判断胜负的函数较简单,只需对当前所下位置处各个方向的连珠情况进行比较,返回游戏是否结束或某一方获胜的结果即可。难点在于计算机下棋算法的设计,在给计算机下棋的位置进行评估时,需要考虑四个方向,还需考虑一些其他的情况,想得越周到便意味着计算机算法越完善,同时还需要由不同的方面根据不同的情况对某一位置赋予不同的分数,分数的确定也是一个困难所在。在我的算法中,更多的考虑的是如何让电脑避免失败,同时也有一定的进攻能力。对每一位置程序都会对电脑下在该处和玩家下在该处同时进行评分,然后选择分数最高处,这样玩家最有威胁的位置和电脑最有威胁的位置都在程序的考虑之内。在这个评分函数中,取的是四个方向中的最大值,这样的设置虽然在一定程度上能够实现不同方向上的综合考虑(在某一方向评分已经较高的情况下还有另一方向评分更高,当然是一个好位置),但是还不足,因为有些位置落棋后可能对多个方向都有好处,此时仅仅取其中的最高值当然是不够的,可以在函数中增加其他方向加分的功能,但这对分数权重的分配和细节考虑上无疑有更高的要求,否则可能会导致多方向的小利战胜了某一方向上的大利,直接影响电脑的输赢。这是我的程序还需完善的地方。总之,这个程序满足了五子棋人机对战游戏的基本要求,同时也可以被改编为双人对战游戏。游戏还有添加功能的空间,算法也可以更加完善。以此作为我应用程序编程、电脑算法及图形界面编程的初步尝试。7. 源程序清单1 chessboard.h文件#include#include#includeusing namespace std;class chessboardpublic:chessboard(); /开始界面void initboard(); /布置棋盘;2 chessboard.cpp文件#includechessboard.hchessboard:chessboard() /开始界面initgraph(900,800); /初始化为横向个点,纵向个点setbkcolor(WHITE);cleardevice();settextcolor(RED);settextstyle(60, 0, _T(楷体);outtextxy(220, 100, _T(五子棋人机对战);settextstyle(30, 0, _T(宋体);outtextxy(300,300,_T(按任意键开始游戏);getch();void chessboard:initboard()int i;initgraph(900,800);setbkcolor(BROWN);cleardevice(); /清除屏幕和图形缓冲区settextcolor(RED);settextstyle(120, 0, _T(隶书);outtextxy(780, 80, _T(五);outtextxy(780, 200, _T(子);outtextxy(780, 320, _T(棋);settextstyle(30,0, _T(楷体);outtextxy(780,500,_T(按右键);outtextxy(800,530,_T(悔棋);for(i=50;i=750;i=i+50) /绘制棋盘setlinecolor(BLACK);line(50,i,750,i);line(i,50,i,750);setfillcolor(BLACK); /绘制天元和星fillcircle(200,200,4);fillcircle(200,600,4);fillcircle(600,200,4);fillcircle(600,600,4);fillcircle(400,400,4);3 piece.h文件#include#includeusing namespace std;class piece /棋子基类public:piece();virtual piece();int getx();int gety();virtual void print() const=0; /绘制棋子函数protected:int x; /棋盘上的坐标int y;class piece_player:public piece /玩家棋子类public:piece_player();piece_player(int,int);virtual piece_player();virtual void print() const; /绘制玩家棋子函数piece_player *p_next; /链表结构;class piece_computer:public piece /电脑棋子类public:piece_computer();piece_computer(int,int);virtual piece_computer();virtual void print() const; /绘制电脑棋子piece_computer *c_next;class player_list /玩家棋子链表public:player_list();player_list();bool insert(int,int); /插入节点函数bool Delete(int a1616);protected:piece_player *p_head;class computer_list /电脑棋子链表public:computer_list();computer_list();bool insert(int,int); /插入节点函数bool Delete(int a1616);protected:piece_computer *c_head;extern int judge(int,int,int,int a16); /判定胜负函数extern int score(int,int,int,int a16); /打分函数4 FiveChess.cpp文件#includepiece.hpiece:piece()x=0;y=0;piece:piece()int piece:getx()return x;int piece:gety()return y;piece_player:piece_player()x=0;y=0;piece_player:piece_player(int a, int b)x=a;y=b;p_next=NULL;piece_player:piece_player()void piece_player:print() constsetfillcolor(WHITE); /画一个白色的棋子fillcircle(x,y,20);piece_computer:piece_computer()x=0;y=0;piece_computer:piece_computer(int a, int b)x=a;y=b;c_next=NULL;piece_computer:piece_computer()void piece_computer:print() constsetfillcolor(BLACK); /画一个黑色的棋子fillcircle(x,y,20);player_list:player_list()p_head=NULL;player_list:player_list()piece_player *p=p_head; /链表析构函数,直到所有节点都被清除for(;p!=NULL;)p_head=p-p_next;delete p;p=p_head;bool player_list:insert(int a, int b) /插入新的节点piece_player *ptemp=new piece_player(a,b);if(ptemp=NULL)return false;ptemp-p_next=p_head;p_head=ptemp;ptemp-print();return true;bool player_list:Delete(int a1616)int x,y;if(p_head=NULL)return false;piece_player *p;x=p_head-getx();y=p_head-gety();ax/50y/50=0;setfillcolor(BROWN);fillcircle(x,y,20);setcolor(BROWN);circle(x,y,20);setcolor(BLACK);line(x-20,y,x+20,y);line(x,y-20,x,y+20);p=p_head-p_next;delete p_head;p_head=p;return true;computer_list:computer_list()c_head=NULL;computer_list:computer_list()piece_computer *p=c_head;for(;p!=NULL;)c_head=p-c_next;delete p;p=c_head;bool computer_list:insert(int a, int b)piece_computer *ctemp=new piece_computer(a,b);if(ctemp=NULL)return false;ctemp-c_next=c_head;c_head=ctemp;ctemp-print();return true;bool computer_list:Delete(int a1616)int x,y;if(c_head=NULL)return false;piece_computer *p;x=c_head-getx();y=c_head-gety();ax/50y/50=0;setfillcolor(BROWN);fillcircle(x,y,20);setcolor(BROWN);circle(x,y,20);setcolor(BLACK);line(x-20,y,x+20,y);line(x,y-20,x,y+20);p=c_head-c_next;delete c_head;c_head=p;return true;extern int a1616;extern int judge(int x,int y,int s,int a16)int i,j; /坐标int p,q; /记录连珠数int vertical,horizon,rincline,lincline; /记录四个方向的连珠数for(i=x,p=0;(ix+5)&(ix-5)&(i0);i-)if(aiy!=s)break;elseq+;horizon=p+q;for(j=y,p=0;(jy+5)&(jy-5)&(j0);j-)if(axj!=s)break;elseq+;vertical=p+q;for(i=x,j=y,p=0;(ix+5)&(jy+5)&(i16)&(jx-5)&(jy-5)&(i0)&(j0);i-,j-)if(aij!=s)break;elseq+;rincline=p+q;for(i=x,j=y,p=0;(ix-5)&(j0)&(j16);i-,j+) /左斜方向连珠数if(aij!=s)break;elsep+;for(i=x+1,j=y-1,q=0;(iy-5)&(i0);i+,j-)if(aij!=s)break;elseq+;lincline=p+q;if(vertical=5)|(horizon=5)|(rincline=5)|(lincline=5) /判断某一方是否胜利if(s=1)return 1;else if(s=2)return 2;else return 0;else return 0;extern int score (int m,int n,int s,int a16) /打分函数int i1,j1,i2,j2; /坐标记录int i;intp=0,q=0; /计算连子数intscore4=0,0,0,0; /记录四个方向的一串连子的两头的情况,是否被另一方堵上intx=0; /分数intvertical,horizon,lincline,rincline; /四个方向的连子数for(i1=m;(i1m+5)&(i116);i1+)if(ai1n!=s)if(ai1n=0)score0+;else if(i1m-5)&(i20);i2-)if(ai2n!=s)if(ai2n=0)score0+;else if(i2=10) /棋盘大小限制score0=0;break;elseq+;horizon=p+q;if(horizon=4)&(ai2n=0)&(ai1n=0) /防止四连珠或形成四连珠if(s=2)score3+=3;score3+=2;for(j1=n,p=0;(j1n+5)&(j116);j1+)if(amj1!=s)if(amj1=0)score1+;else if(j1n-5)&(j20);j2-)if(amj2!=s)if(amj2=0)score1+;else if(j2=10)score1-;break;elseq+;vertical=p+q;if(vertical=4)&(amj2=0)&(amj1=0)if(s=2)score1+=3;score1+=2;for(i1=m,j1=n,p=0;(i116)&(i1m+5)&(j116);i1+,j1+)if(ai1j1!=s)if(ai1j1=0) /score2+;else if(i10)&(i2m-5)&(j20);i2-,j2-)if(ai2j2!=s)if(ai2j2=0)score2+;else if(i2=10)score2-;break;elseq+;rincline=p+q;if(rincline=4)&(ai2j2=0)&(ai1j1=0)if(s=2)score2+=3;score2+=2;for(i1=m,j1=n,p=0;(i10)&(i1m-5)&(j116);i1-,j1+)if(ai1j1!=s)if(ai1j1=0)score3+;else if(j1=5)score3-;break;elsep+;for(i2=m+1,j2=n-1,q=0;(i216)&(i20);i2+,j2-)if(ai2j2!=s)if(ai2j2=0)score3+;else if(j2=10)score3-;break;elseq+;lincline=p+q;if(lincline=4)&(ai2j2=0)&(ai1j1=0)if(s=2)score3+=3;score3+=2;if(horizon4|vertical4|lincline4|rincline4)x=100;elsefor(i=0;i4;i+)if(scoreix)x=vertical+score1;if(lincline+score2x)x=lincline+score2;if(rincline+score3x)x=rincline+score3;return x; /返回最大的分数5 main.cpp文件#includechessboard.h#includepiece.hint a1616; /15*15棋盘,只用至的数组int main()chessboard board1;MOUSEMSG m;int i,j; /棋盘数组坐标bool p=0; /记录player是否下过int score_player1616,score_computer1616; /判断电脑的落子处int score_max; /记录打分的最大值int max_x,max_y; /记录打分最大值的坐标int x;while(1)board1.initboard();player_list *player=new player_list; /建立玩家链表computer_list *computer=new computer_list; /建立电脑链表 for(i=1;i16;i+) /初始化棋盘,代表没有棋子,代表player,代表computerfor(j=1;jinsert(i*50,j*50); /点击确定,电脑先下while(1)while(p=0)m=GetMouseMsg(); /获取玩家落子位置switch(m.uMsg)case WM_LBUTTO

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论