VCMFC单机和网络版五子棋_第1页
VCMFC单机和网络版五子棋_第2页
VCMFC单机和网络版五子棋_第3页
VCMFC单机和网络版五子棋_第4页
VCMFC单机和网络版五子棋_第5页
已阅读5页,还剩27页未读 继续免费阅读

下载本文档

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

文档简介

1、 五子棋 五子棋是一种很受人们喜爱的游戏,它的规则简单,但玩法变化多端,富有趣味性,适合人们消遣。这里我们就来设计一个五子棋游戏。  (一) (一)   人对人游戏        1. 1.    游戏实现 人对人游戏,其实只是对游戏规则的实现,我们只是利用五子棋游戏的规则来编程,至于真正的游戏实现计算机的“智能”算法,我们将在后面讲述。五子棋的规则很简单:1,判断是否能放下棋子(是否已经有了棋子);2,判断是哪种颜色下棋;3,判断是否

2、已经结束(是谁赢?)。 这些规则,我们将用相应的函数来实现。其它,我们还将介绍其它一些功能的实现。如鼠标的更换,工具栏和状态栏的编辑,类与类之间的相互调用。 新建工程3_1,选择单文档,在Step 4 of 6中先中Windows Sockets复选框。如下图:  图3-1-1     2. 2.    资源编辑 由于我们这个程序出现的关于资源编辑的内容太多,我们具体介绍如下:见下图3-1-2,我们需要添加的有: 图3-1-2  黑白位图Bitmap以表示棋盘上面的

3、棋子:IDB_BLACK IDB_WHITE黑白鼠标Cursor以替换当前鼠标:IDC_CURSOR1黑棋子IDC_CURSOR2白棋子 说明:由于下棋时我们必须把鼠标热点设置在中间,点击下图(图3-1-3)最右边按扭,然后把鼠标移动到图像中你想设置为热点的地方,按下鼠标左键。 图3-1-3 黑白图标Icon以显示在状态栏供以提示:IDI_BLACKIDI_WHITE  说明: 由于我们的图标支持256色,按下下图(图3-1-4)最右边按扭,选择Device里面显示的选项。  图3-1-4 菜单以供操作:开始:ID_START保存:ID_SAV

4、E打开:ID_OPEN工具栏:如上图所示。说明:工具栏一般都是根据菜单选项而产生的,它的ID一般都能从菜单的ID 中找到。 3. 3.    变量函数 首先,为了实现状态栏的应用,我们必须更改它的变量: 在MainFrm.h文件里面,把CStatusBar m_wndStatusBar 为public 接着是在3_1View.h文件里面添加变量函数:   /两个鼠标 HCURSOR hcursorwhite;HCURSOR hcursorblack; /棋盘数组int wzq1919; / colorwhite T

5、RUE时白棋下,否则黑棋下bool colorwhite; /棋子位图CBitmap m_bmblack;CBitmap m_bmwhite; /保存文件void Save();/检查是否结束void over(CPoint point);/鼠标操作afx_msg void OnLButtonUp(UINT nFlags, CPoint point);/鼠标图形更换afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);/菜单的开始afx_msg void OnStart();/菜单的保存afx_msg vo

6、id OnSave();/菜单的打开afx_msg void OnOpen();       4. 4.    具体实现 棋盘大小设置: 由于我们的游戏的棋盘大小是一定的,不能改变大小的,是应该符合要求的。在如下函数添加设置窗口大小的语句: BOOL CMainFrame:PreCreateWindow(CREATESTRUCT& cs)if( !CFrameWnd:PreCreateWindow(cs) )return FALSE;/ TODO: Modi

7、fy the Window class or styles here by modifying/ the CREATESTRUCT cscs.dwExStyle=cs.dwExStyle|WS_EX_TOPMOST;/cs.style=WS_SYSMENU|WS_OVERLAPPED|WS_MINIMIZEBOX;/; /设置窗口大小:400*340cs.cx=450;cs.cy=500; return TRUE; 初始化变量: 在构造函数里添加初始代码: CMy3_1View:CMy3_1View()/ TODO: add construction code h

8、ere/Load鼠标图像和棋子位图hcursorblack=AfxGetApp()->LoadCursor(IDC_CURSOR1);hcursorwhite=AfxGetApp()->LoadCursor(IDC_CURSOR2);m_bmwhite.LoadBitmap(IDB_WHITE);m_bmblack.LoadBitmap(IDB_BLACK);/清理棋盘 /数组值为0表示没有棋子for(int i=0;i<19;i+)for(int j=0;j<19;j+)wzqij=0;/白棋先下 colorwhite=true; 画棋盘: 在On

9、Draw(CDC* pDC)函数中画棋盘,由于在游戏过程中有可能重画棋盘,而那时棋盘上面有棋子,所以,我们在这个函数里面必须有画棋子的语句。我们用数组的做为1表示白棋,-1表示黑棋。 void CMy3_1View:OnDraw(CDC* pDC)CMy3_1Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);/ TODO: add draw code for native data here/画背景 CBrush mybrush1; mybrush1.CreateSolidBrush(RGB(192,192,192); CRect myrect

10、1(0,0,1200,800); pDC->FillRect(myrect1,&mybrush1);/画棋盘框线CPen mypen;CPen*myoldPen;mypen.CreatePen(PS_SOLID,1,RGB(0,0,0); myoldPen=pDC->SelectObject(&mypen); for(int i=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,40

11、0); /重画时显示存在的棋子CDC Dc;if(Dc.CreateCompatibleDC(pDC)=FALSE) AfxMessageBox("Can't create DC");for(int n=0;n<19;n+)for(int m=0;m<19;m+)if(wzqnm=1)/显示白棋Dc.SelectObject(m_bmwhite);pDC->BitBlt(n*20+32,m*20+32,160,160,&Dc,0,0,SRCCOPY);else if(wzqnm=-1)/显示黑棋Dc.SelectObject(m_bmbla

12、ck);pDC->BitBlt(n*20+32,m*20+32,160,160,&Dc,0,0,SRCCOPY); 设置鼠标: 棋盘画好了,接下来就是下棋了。但鼠标并没有像我们上面说的那样变成白棋,加函数如下: BOOL CMy3_1View:OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) / TODO: Add your message handler code here and/or call defaultif(nHitTest=HTCLIENT)/白棋下,显示白棋鼠标if(colorw

13、hite) /调用主框架里面的状态栏CMainFrame*pFrm=(CMainFrame*)AfxGetApp()->m_pMainWnd;CStatusBar*pStatus=&pFrm->m_wndStatusBar;if(pStatus)pStatus->GetStatusBarCtrl().SetIcon(0,AfxGetApp()->LoadIcon(IDI_WHITE);pStatus->SetPaneText(0,"白棋下");SetCursor(hcursorwhite);/显示黑棋鼠标elseSetCursor(hc

14、ursorblack);CMainFrame*pFrm=(CMainFrame*)AfxGetApp()->m_pMainWnd;CStatusBar*pStatus=&pFrm->m_wndStatusBar;if(pStatus)/显示图像pStatus->GetStatusBarCtrl().SetIcon(0,AfxGetApp()->LoadIcon(IDI_BLACK);/显示文字pStatus->SetPaneText(0,"黑棋下");return 1;return CView:OnSetCursor(pWnd, nHi

15、tTest, message); 现在运行程序,怎样,鼠标变成白棋了,而且下面的状态栏也能够显示鼠标状态了,真是一举两得。可是,又该怎样把棋子放在棋盘上呢? 下棋操作: 这就涉及到OnLButtonDown(UINT nFlags, CPoint point)和OnLButtonUp(UINT nFlags, CPoint point)两个函数了。要用哪一个或用两个?用Down函数时是在鼠标按下时放下棋子,可是,要是我们按下后意识到按错了怎么办;那就改用Up函数,表示当鼠标键松开时放下棋子。OK!添加函数如下: void CMy3_1View:OnLBu

16、ttonUp(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/or call defaultCDC *pDC=GetDC();CDC Dc;if(Dc.CreateCompatibleDC(pDC)=FALSE) AfxMessageBox("Can't create DC"); /是否在棋盘内 if(point.x>30&&point.x<410&&point.y>30&&point.y<410

17、)int px=(point.x-30)/20;int py=(point.y-30)/20;/是否已经有棋子if(colorwhite&&wzqpxpy=0)Dc.SelectObject(m_bmwhite);pDC->BitBlt(px*20+32,py*20+32,160,160,&Dc,0,0,SRCCOPY);/表示存在白棋wzqpxpy=1;/检查是否结束over(point);/换黑棋下colorwhite=false;else if(wzqpxpy=0)Dc.SelectObject(m_bmblack); pDC->BitBlt(px*2

18、0+32,py*20+32,160,160,&Dc,0,0,SRCCOPY);wzqpxpy=-1;over(point);colorwhite=true;CView:OnLButtonUp(nFlags, point); 由上面可以看出,当鼠标键松开时判断,如果那个位置没有棋子,则放下,并把棋盘数组赋相应的值:1 或-1。 是否结束: 接着是用一个over()函数判断是否结束,是则结束并重新开始;否则,接着把鼠标变成对方棋子,表示对方下棋。那over()函数又是怎样的呢? 此函数是利用刚下棋的位置为中心,检查它各个方向上的连续五个棋子是否同色,是则结束并

19、重新开始。然而,我们又是怎样判断一个方向上的五个棋子的同色的?这就涉及地为什么我要把五子棋数组赋值为1和-1的问题。因为这样有一个好处:利用连续五个棋子的值相加,如果它们的值的绝对值等于5,则说明是同色。当然,这只是这样赋值的一点作用,真正的作用将在后面介绍。添加如下: void CMy3_1View:over(CPoint point)/获取鼠标指向数组位置,即中心位置int x=(point.x-30)/20;int y=(point.y-30)/20;/计算开始判断的坐标 xx,yyint xx,yy; if(x<4)xx=0;elsexx=x-4;if(y<4)y

20、y=0;elseyy=y-4;int i,j,a;/横向判断for(i=xx;i<15;i+) a=0;for(j=i;j<i+5;j+)a=a+wzqjy;/五个都是白棋 if(a=5)AfxMessageBox("白棋胜!");/重新开始OnStart();return;/五个都是黑棋if(a=-5)AfxMessageBox("黑棋胜!");OnStart();return;/竖向判断for(i=yy;i<15;i+) a=0;for(j=i;j<i+5;j+)a=a+wzqxj; if(a=5)AfxMessageBox(

21、"白棋胜!");OnStart();return;if(a=-5)AfxMessageBox("黑棋胜!");OnStart();return;/向右下角/判断起点位置if(x<y)if(xx=0)yy=y-x;elseif(yy=0)xx=x-y;/参数over=1时退出循环int over=0;doa=0;for(i=0;i<5;i+)if(xx+i)<19|(yy+i)<19)a=a+wzqxx+iyy+i;if(a=5)AfxMessageBox("白棋胜!");OnStart();return;if(

22、a=-5)AfxMessageBox("黑棋胜!");OnStart();return;/到了边界elseover=1; xx+=1;yy+=1;while(over=0); /向左下角 if(y>(18-x)if(x>13)yy=y-(18-x);xx=18;elseyy=y-4;xx=x+4;elseif(y<5)xx=x+y;yy=0;elseyy=y-4;xx=x+4; over=0;doa=0;for(i=0;i<5;i+)if(xx-i)>=0|(yy+i)<19)a=a+wzqxx-iyy+i;if(a=5)AfxMessa

23、geBox("白棋胜!");OnStart();return;if(a=-5)AfxMessageBox("黑棋胜!");OnStart();return;/到了边界elseover=1; xx-=1;yy+=1;while(over=0);  现在,我们的人对人游戏就完成了。下面介绍附加内容。 5. 5.    附加内容 理论上,这个游戏并无须保存,因为它确实太小了。事实上,这个游戏有保存的功能,由于我们学习的需要。这个游戏的保存,与其说是学习文件的保存,不如说是我们学习字符串的操作。另外,这

24、个附加的内容并不是为了当前的学习而添加的,而是为了后面的学习和应用而铺垫的。 保存文件: 保存文件函数是一个菜单选项。它的作用就是保存当前游戏的状态。首先,我们应该为我们自己的文件定义一个后缀名:.wzq;接着是打开保存文件的公共对话框,如果确定,则表示保存,那么就先获取文件名,然后按照一定的顺序保存各个点的数组的值,最后保存当前是哪种颜色下棋。 void CMy3_1View:OnSave() / TODO: Add your command handler code here/设置保存的文件,后缀名wzqCFileDialog dlg(FALSE,"wzq&q

25、uot;,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"(*.WZQ)|*.wzq|All Files|*.*|",this);/如果公共类对话框为确定if(dlg.DoModal()=IDOK) /获取文件名dlg.GetFileName();/否则,退出elsereturn;/字符串变量CString str;int i,j;  CStdioFile file;/如果有问题,退出if(file.Open(dlg.GetFileName(),CFile:modeCreate|CFile:modeWrite|CFile:ty

26、peText)=0)AfxMessageBox("save error!");return;/循环把棋盘数组的值写进文件for(i=0;i<19;i+)for(j=0;j<19;j+)if(wzqij=-1)file.WriteString("-1n");if(wzqij=0)file.WriteString("0n");if(wzqij=1)file.WriteString("1n");/保存当前下棋颜色if(colorwhite=true)file.WriteString("1n"

27、;);elsefile.WriteString("0n");/关闭文件 file.Close(); 读取文件: 读文件就是把我们以前保存的文件打开,读取当前打开文件的内容,并给数组赋值使和文件内容相同,然后可以继续进行游戏。 /与保存文件相反void CMy3_1View:OnOpen() / TODO: Add your command handler code hereCFileDialog dlg(TRUE,"wzq",NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"(*

28、.WZQ)|*.wzq|All Files|*.*|",this);if(dlg.DoModal()=IDOK) dlg.GetFileName();elsereturn;  CString str;int i,j,m; CStdioFile file;if(file.Open(dlg.GetFileName(),CFile:modeRead)=0)AfxMessageBox("save error!");return;CArchive ar(&file,CArchive:load); for(i=0;i<19

29、;i+)for(j=0;j<19;j+)ar.ReadString(str);sscanf(str,"%d",&m);if(m=-1)wzqij=-1;if(m=0)wzqij=0;if(m=1)wzqij=1;ar.ReadString(str);sscanf(str,"%d",&m);if(m=1)colorwhite=true;elsecolorwhite=false;file.Close();ar.Close(); Invalidate(false);   6. 6. 

30、60;  小结  当然,这样的程序,你只要玩一两次就会厌了,因为下棋时要找一个伴。那么,我们是否该编一个人对机的游戏呢?请看下面!      (二) (二)   人对机游戏      1、 1、    游戏实现 先看上图,玩过五子棋的人一眼就能看出这才是一场真正的战斗!(至少它不允许你随便下棋。)那么,我们该如何实现?其实,只是在原来的基础上,把其中一个人用计算机代替而已。也就是说,我们只要在原来的基础上,加上计算机的下棋算法

31、就好了。而计算机下棋的算法,正是一个程序的重点和难点。这里先介绍一下:计算机是没有头脑的,但是,计算机必须下棋。那么,它该怎么办呢?我们必须自己编程序,“教”计算机下棋。然而,我们是否只是让计算机随便在棋盘上面放一颗棋子呢?事情并不是这么简单。计算机要下的那个位置,必定是它认为最好的!当然,这里的最好是程序员给予计算机的,是计算机算法的体现。最好的位置,人都难以保证!但是,计算机可以。这正是计算机能够在我们这个社会迅速发展的一个重要原因。当然,计算机的可以是建立在人的程序的基础上的。计算机的会是依奈于它的速度,人所不能及的速度。上面说过,为什么要把数组的值赋值为1和-1,而不是0,1或者其它的

32、数字呢?这里就涉及到数字的妙用。前面说了,五个连续棋子的值相加,如果绝对值是五,则不是五个棋子同色,应该结束游戏。那么,如果绝对值不是五呢?它就没有意义了吗?不是!不但不是,而是它有着更重要的意义。它关系到我们这个程序的几乎全部的算法。下面细说(数字是表示绝对值的): 4:表示五个棋子中有一个空位置和四个同色的棋子。3:表示五个棋子中有两个空位置和三个同色的棋子;也表示五个棋子中有四个同色棋子和一个异色棋子。注意:此时没有空位置,可以不考虑。2:表示五个棋子中有三个空位置和两个同色棋子;也表示五个棋子中一个空位置和三个同色棋子和一个异色棋子;1、0:由于出现1和0的机会太少(除了开始

33、的时候),我们不必多加考虑。但是,因为刚才对方下棋的对方必定有一定的危险,我们只需要在刚刚下棋的附近找一个空位置下棋就可以了。说明: 1、 上面之所以把空位置这个词语放在前面,因为我们注重的是通过检查,出一个可以下棋的空位置,然后下棋。 2、 为了方便说明,我们在说明用了绝对值。而事实上正负还是有区别的。正表示白棋占多数,负表示黑棋占多数。而由于我们的这个算法是针对于计算机的,而我们又让计算机为黑棋,所以我们的后面的算法还是有一定区别的。我们必须把它们分开,而且这样规定:绝对值大表示危险性大(这是很容易理解的);而当出现绝对值相同的正负两个值时,我们必须这样做,在值为负(表示黑棋一方)的那个位

34、置下棋,以保证黑棋一方的优先性。 下面,就让我们在怎样对程序的扩展方法的介绍过程中实现人对机游戏。 先把3_1的文件夹复制一个,改为3_2。以后就用它来扩展。   2、 2、    资源编辑 从上面图中,我们可以看到,工具栏变了。因此我们也可以想到菜单也应该变了。它们的修改如下: 修改菜单: 删除菜单项 开始:ID_START添加菜单项 人对人游戏:ID_PLAYER人对机游戏:ID_CPMPUTER 修改工具栏: 删除原来的按扭对应ID:ID_START添加两个新

35、按扭对应ID:ID_PLAYER ID_CPMPUTER  3、 3、    变量和函数 在view类中添加变量函数如下: /保存vscomputer时白棋位置CPoint vspoint;/是人与人游戏?是人与机游戏?int vscomputer; CPoint bpointcan4,/这个位置空,它旁边有四个黑棋wpointcan4,/这个位置空,它旁边有四个白棋bpointcan3,/这个位置空,它的旁边有三个黑棋wpointcan3,/这个位置空,它的旁边有三个白棋bpointcan2,/这个位置空,它的旁

36、边有两个黑棋wpointcan2,/这个位置空,它的旁边有两个白棋bpointcan1;/不是以上情况,这个位置空 /在得到最大值和方向上寻找落棋点(具体见后面介绍)/其中i、j表示搜索起点,n表示方向void searchcandown1(int i,int j,int n);void searchcandown2(int i,int j,int n);void searchcandown3(int i,int j,int n);void searchcandown4(int i,int j,int n);/计算最大值及方向CPoint maxnum(int a,int b,int

37、 c,int d);/最好落棋点void bestputdown(int i,int j);/计算机下棋void computerdown();/在位置point放下棋子void putdown(CPoint point);/人对人菜单afx_msg void OnPlayer();/人对机菜单afx_msg void OnCpmputer();  4、 4、    具体实现  下面,我们朝着程序扩充的思路,来实现我们的游戏。 菜单函数: 添加了菜单项,我们必须添加一个变量vscomputer,赋值为1,

38、并约定:/vscomputer:2表示人对人,1表示人对机 void CMy3_1View:OnPlayer() / TODO: Add your command handler code herevscomputer=2;OnStart(); void CMy3_1View:OnCpmputer() / TODO: Add your command handler code herevscomputer=1;OnStart(); 其中,我们只是添加一个变量,而仍然利用原来的开始函数。虽然我们的菜单项已经删除了,但它的函数还在,我们应该加以利用。 人变成

39、计算机: 下面,我们就必须把游戏双方中的一方改为计算机。我们把黑棋改为计算机,因为一般情况计算机比人强,应让人先下。当然,要是人赢了,就必须让计算机先下了,在将在以后的算法中体现。由于下棋只是在OnLButtonUp(UINT nFlags, CPoint point)函数中,我们把它改为如下: void CMy3_1View:OnLButtonUp(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/or call defaultCDC *pDC=GetDC();CDC Dc;

40、if(Dc.CreateCompatibleDC(pDC)=FALSE) AfxMessageBox("Can't create DC"); /显示棋子/人对机if(vscomputer=1)if(point.x>30&&point.x<410&&point.y>30&&point.y<410)int px=(point.x-30)/20;int py=(point.y-30)/20;if(colorwhite&&wzqpxpy=0) Dc.SelectObject(m_bmwh

41、ite);pDC->BitBlt(px*20+32,py*20+32,160,160,&Dc,0,0,SRCCOPY);wzqpxpy=1;over(point);colorwhite=false;/保存白棋位置vspoint=point;/计算机下棋computerdown(); /人对人if(vscomputer=2)if(point.x>30&&point.x<410&&point.y>30&&point.y<410)int px=(point.x-30)/20;int py=(point.y-30)/

42、20;if(colorwhite&&wzqpxpy=0)Dc.SelectObject(m_bmwhite);pDC->BitBlt(px*20+32,py*20+32,160,160,&Dc,0,0,SRCCOPY);wzqpxpy=1;over(point);colorwhite=false;else if(wzqpxpy=0)Dc.SelectObject(m_bmblack); pDC->BitBlt(px*20+32,py*20+32,160,160,&Dc,0,0,SRCCOPY);wzqpxpy=-1;over(point);color

43、white=true;CView:OnLButtonUp(nFlags, point);由上面可知,我们对人对机游戏的方法是采用:人下完了之后,检查是否胜利,是则结束游戏,重新开始,并改为黑棋(即计算机)先下;如果人没有胜利,也改为计算机下。而对于计算机怎么下棋,我们只是用了一个函数computerdown()表示。但是现在我们并不能运行程序,因为有一个没有定义的函数,怎么办呢? l l       程序扩展思想:添加一个空函数! 仔细看程序的话,你还会发现一个变量Cpoint vspoint,这是后来添加的它的用

44、处是保存刚才白棋下的位置,有利于黑棋下棋时的定位。接着,我们的主要问题就是实现computerdown()函数,让计算机能够自动下棋! 计算机下棋: 计算机是怎样下棋?这就是定位的问题了。即搜索棋盘,找出一个最佳点,放下黑棋。我们实现的方法是:全盘搜索,并把搜索到的位置,保存在变量。由于有多种情况,我们定义变量如下:CPoint bpointcan4,/这个位置空,它旁边有四个黑棋wpointcan4,/这个位置空,它旁边有四个白棋bpointcan3,/这个位置空,它的旁边有三个黑棋wpointcan3,/这个位置空,它的旁边有三个白棋bpointcan2,/这个位置空,

45、它的旁边有两个黑棋wpointcan2,/这个位置空,它的旁边有两个白棋bpointcan1;/不是以上情况,这个位置空并在搜索之前都赋值为(-1,-1),然后,进行搜索,并把相应的值保存在相应变量里面,而如果前面已经对变量赋值,我们依然赋值,用新值代替旧值。注意:我们只保存最后一个值,这样的一个好处是,避免了每次都从左上角开始,并且它的随机性比随机函数还随机。全盘搜索完之后,由于上面的变量中至少有一个已经被赋值,即不是(-1,-1),我们可以采用多数优先的方法,让已经有多个同色棋子的位置先下棋。其原理是,如果已经有四个黑棋,计算机再下一个黑棋就赢了;否则,如果人已经有四个白棋,那么计算机就必

46、须放下一个黑棋,阻止白棋下一步赢;如果已经有三个黑棋,再下一个黑棋,变成四个;否则,如果已经有三个白棋,下一个黑棋,破坏它;两个棋子的同理;否则,在刚才白棋下的地方,顺便找一个位置,下棋。computerdown()函数如下: /轮到计算机下棋void CMy3_1View:computerdown()/把各种情形赋值为如下bpointcan4=(-1,-1);wpointcan4=(-1,-1);bpointcan3=(-1,-1);wpointcan3=(-1,-1);bpointcan2=(-1,-1);wpointcan2=(-1,-1);bpointcan1=(-1,-1)

47、; /搜索最好的落棋点for(int i=0;i<19;i+)for(int j=0;j<19;j+)bestputdown(i,j);/判断放在哪里/棋多的位置优先/黑白一样多时黑先 /不是-1就表示已经被赋值!if(bpointcan4.x!=-1)putdown(bpointcan4);return;else if(wpointcan4.x!=-1)putdown(wpointcan4);return;else if(bpointcan3.x!=-1)putdown(bpointcan3);return;else if(wpointcan3.x!=-1)putdown(wpo

48、intcan3);return;else if(bpointcan2.x!=-1) putdown(bpointcan2);return;else if(wpointcan2.x!=-1)putdown(wpointcan2);return;else putdown(bpointcan1);return;上面又有两个新函数,分别定义为空函数,如下: /搜索最佳位置void bestputdown(int i,int j);/放下黑棋void putdown(CPoint point);现在,我们就必须对上面两个空函数进行定义了。 在指定位置下棋: 由于putdown(CPo

49、int point)函数的原理非常简单,我们先说明如下:  /黑棋下void CMy3_1View:putdown(CPoint point)CDC *pDC=GetDC();CDC Dc;if(Dc.CreateCompatibleDC(pDC)=FALSE) AfxMessageBox("Can't create DC");Dc.SelectObject(m_bmblack); pDC->BitBlt(point.x*20+32,point.y*20+32,160,160,&Dc,0,0,SRCCOPY); wzqpoint.xpoint

50、.y=-1;/由于原来我们检查是否结束时用的是鼠标点下的坐标,而现在/putdown(CPoint point)函数用的是数组棋盘的坐标,所以必须转换CPoint overpoint;overpoint.x=point.x*20+30;overpoint.y=point.y*20+30;over(overpoint);colorwhite=true;  搜索最佳落棋点: 现在就剩下void bestputdown(int i,int j)函数没有定义了(虽然前面的变量函数已经说明了,当时我们这里是用程序扩展的思路进行的,故如此说明)。它的实现原理是:在四个方向上,各自计算那

51、个方向上棋子的状态,我们的思路是利用原来定义的白棋为1,黑棋为-1,的思想,让同个方向上的五个棋子的值相加,取绝对值并赋值给为这个方向定义的局部变量numi。 为什么要用五个棋子的值相加呢?因为,如果几个棋子是同色的,无论黑白,它的绝对值必然大,而对于几个棋子中有黑棋和白棋的,其值必然相加而抵消变小。所以我们可以利用这种方法来寻找旁边有多个同色棋子的空位置(前面已经具体说明)。在每一个棋盘位置,计算以它为起点的四个方向(横、竖、撇、捺),再比较这四个方向中哪个值最大,然后在这个方向上寻找落棋点。我们添加函数如下: /检查四个方向,各算出五个棋子的和并赋值void CMy3_1View:bestputdown(int i,int j) /四个方向的值int num4;int a,k; / num0 ->a=0; if(i<15)for(k=0;k<5;k+)a=a+wzqi

温馨提示

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

评论

0/150

提交评论