4、着法名称显示(程序辅助)
每当下棋方(用户或是计算机)走一步棋,我们就在棋盘旁边的一个列表框控件(List Box)中按照中国象棋关于着法描述的规范要求显示出该着法的名称。如:红炮二平五、黑马8进7此类。为了获得该着法名称,我们写了一个六百余行的函数。其功能就是将被移动的棋子类型以及走法的起点坐标、终点坐标这些信息转换成中国象棋所规范的着法名称。由于该函数主要涉及的是中国象棋关于着法表示的规范要求,故在此我们不对其具体实现做额外的解释。这里我们主要讨论的是如何对列表框控件(List Box)进行操作,以显示或删除着法名称。 MFC为我们提供了一个CListBox类,使用该类的成员函数我们可以非常容易地实现在List Box中添加与删除“项(item)”。 首先,我们先要定义一个指向该类的对象的指针: CListBox* pLB; 然后,在进行程序初始化(对话框的初始化)时,我们使用如下语句来让该指针与对话框中的List Box控件建立起联系来(即让该指针指向对话框中的List Box控件)。 pLB = (CListBox*)GetDlgItem(IDC_LISTCCHESS); 其中IDC_LISTCCHESS是所要建立关联的控件的ID号。 之后,我们便可调用成员函数pLB->AddString(str);来向List Box控件中添加显示字符串,str即为所要添加的字符串。 当列表框中的项的数目超过列表框的显示范围时,列表框会自动添加垂直滚动条(前提是其VerticalScrollbar属性要为True——该属性默认即为True)。但是显示的内容依然是最早加进来的项。也就是说,垂直滚动条不会自动向下滚。为了能让列表框中始终能自动显示出最新的着法名称(所谓自动,即不需用户去手动地滚动垂直滚动条来查看最新的着法名称),我们可以使用pLB->PostMessage(WM_VSCROLL,SB_BOTTOM,0);语句来发送一个让垂直滚动条处于最底端的消息,使得列表框自动滚动垂直滚动条以显示最新的着法名称。 当我们想要从列表框中删除项时,我们可以使用pLB->DeleteString(n);参数n指明了要删除的行数。最早加入列表框中的项记为第0行,以后逐次递增。若要删除最后一行内容(在悔棋功能中需要用到这一操作),则可以使用pLB->DeleteString(pLB->GetCount()-1);其中pLB->GetCount()返回的是列表框中的项的数目,减一之后正好是最后一项的行号。
5、悔棋、还原(程序辅助)
悔棋和还原是棋类软件中较为基本的功能。要实现悔棋和还原功能,首先我们要明确哪些信息应当被保存以供悔棋和还原所使用。 在我们的程序中保存了如下信息: 棋局表示中所定义的棋盘数组; 各棋子的贴图位置。 这里需要特别说明的是通常象棋程序处于程序效率的考虑并不保存所有棋子的信息,而只是保存之前一步的走棋信息。此后当悔棋的时候,需要撤销着法;还原的时候,需要执行着法。然而,我们在编写自己的程序时一来考虑到程序的可读性和不易出错性,二来考虑到对当今的计算机的配置来说这点开销基本上不会对程序的效率产生什么影响。因此索性保存了全部棋子的信息。 根据所要保存的数据我们定义了如下基本结构类型: typedef struct{ BYTE CChessBoard[9][10]; POINT ptChess[32]; } CCChess; // 供悔棋、还原保存用的信息结构 并随之定义了两个队列以供悔棋和还原所用: vector<CCChess> vBackQueue; //悔棋保存队列 vector<CCChess> vForwardQueue;//还原保存队列 在对弈过程中,每一回合我们都将棋局信息(这里指前面所说的需要保存的信息)保存至vBackQueue队列,以供悔棋所用。同时,若vForwardQueue不为空的话,我们还将清空它。因为还原功能是与悔棋功能相对应的,只有当产生了悔棋功能之后,还原功能才会被激活。一个回合的结束意味着前一次操作没有悔棋功能的产生,因此还原队列也应被清空。 在悔棋中我们主要完成了以下任务: 下棋回合数减一; 将当前局面信息保存至vForwardQueue队列,以供还原所用; 从vBackQueue队列中取出上一回合的棋局信息,恢复到当前局面,然后将其从vBackQueue队列中剔除掉; 将显示着法名称的列表框中的本回合的着法名称保存到一个着法名称队列(我们将其定义为vector<CString> vNameQueue;),以供还原所用。然后从列表框中删除它。 而在还原中我们所做的刚好和悔棋相反: 下棋回合数加一; 将当前局面信息保存至vBackQueue队列,以供悔棋所用; 从vForwardQueue队列中取出最近一次悔棋前的棋局信息,恢复到当前局面,然后将其从vForwardQueue队列中剔除; 从着法名称队列vNameQueue中取出最近一次存入的着法名称(两项,因为每回合会产生两步着法),将其重新显示到列表框中。然后将其从vNameQueue中剔除。 以上便是悔棋和还原功能所完成的具体操作,其代码分别写入悔棋和还原按钮(Button)的BN_CLICKED事件处理函数中。
四、总 结
下面简单地总结一下。 首先,在指导老师的热心帮助下,小组成员协同工作最终顺利实现了程序。整个程序近6000行代码,内容涉及人工智能的基本理论以及开发MFC应用程序的一些基础知识。无论是从程序难度上讲还是从程序规模上讲都是我们之前所未遇到过的。该程序的顺利完成为我们积累了相当可观的运用理论知识解决实际问题的经验。特别是当程序运行过程中发现错误的时候,找出问题所在并解决问题更是一个积累经验,提高实际编程能力的过程。得益于此次编写该中国象棋对弈程序,我们对人工智能有了一个初步的认识——这为我们以后选择进一步学习或研究的方向也提供了一定的参考价值。此外,我们还实践了用MFC编写基本的Windows应用程序,为今后从事开发Windows应用程序也起到了一定的入门帮助作用。 然而,我们的程序也存在着几点遗憾: 第一、由于我们对使用MFC编写Windows程序的不熟悉,导致我们在界面及附属功能部分花费了大量的时间和精力。因而没能够对计算机下棋引擎部分作更深一步的挖掘和研究。对于诸如位棋盘(BitBoard)、置换表(H
首页 上一页 3 4 5 6 7 下一页 尾页 6/7/7