计算机应用 | 古代文学 | 市场营销 | 生命科学 | 交通物流 | 财务管理 | 历史学 | 毕业 | 哲学 | 政治 | 财税 | 经济 | 金融 | 审计 | 法学 | 护理学 | 国际经济与贸易
计算机软件 | 新闻传播 | 电子商务 | 土木工程 | 临床医学 | 旅游管理 | 建筑学 | 文学 | 化学 | 数学 | 物理 | 地理 | 理工 | 生命 | 文化 | 企业管理 | 电子信息工程
计算机网络 | 语言文学 | 信息安全 | 工程力学 | 工商管理 | 经济管理 | 计算机 | 机电 | 材料 | 医学 | 药学 | 会计 | 硕士 | 法律 | MBA
现当代文学 | 英美文学 | 通讯工程 | 网络工程 | 行政管理 | 公共管理 | 自动化 | 艺术 | 音乐 | 舞蹈 | 美术 | 本科 | 教育 | 英语 |

免费vc中国象棋软件(一)毕业论文(5)

2013-06-30 01:00
导读:CPoint point) { } 当用户在窗口客户区按下鼠标左键时,程序就会调用OnLButtonDown(UINT nFlags, CPoint point)函数来进行响应。其中第二个参数CPoint point是我们在本程序
CPoint point)
 {
 }
 当用户在窗口客户区按下鼠标左键时,程序就会调用OnLButtonDown(UINT nFlags, CPoint point)函数来进行响应。其中第二个参数CPoint point是我们在本程序中所要用到的,它给出了当鼠标左键被按下时,鼠标指针的位置坐标。我们可以通过这一信息来得知用户的走法。
 在OnLButtonDown函数里我们处理如下两种操作:
 1、如果用户点击鼠标的位置落在己方的棋子上,表示用户选中了该棋子,下一步将移动该子进行走棋(也可能用户下一步将会选择己方另外的棋子,总之这一操作会记录下用户所选的将要走的棋子)。
 2、如果之前用户已经选过了棋子,那么这一次的点击(如果不是另选本方的其它棋子的话)表达了用户的一次走棋过程。在收到用户传达的走棋信息后,我们先判断该着法是否合法(是否符合中国象棋的游戏规则),如果合法,则执行之。紧接着我们调用引擎的搜索函数计算出计算机对用户着法的应着,然后执行该应着。
 如此,在OnLButtonDown函数里,我们实现了人与机器的对弈(当然每走一步棋,也还需要绘图函数来显示棋盘局面的更新)。
 
 以上三部分并非界面程序的全部,而仅仅是与我们的程序密切相关的部分。此外还有其它部分对程序同样必不可少,但这些部分主要由MFC自动生成,无需人为改动,故在此不多做介绍。

2、多线程(程序辅助)

 最初,我们的程序中没有给计算机的“思考”另外开辟新的线程。而仅仅是简单地按照如下顺序编写代码:
    用户走棋 —〉计算机思考并走棋
 按这种方式编写的程序似乎毫无问题,程序运行一切正常。
 然而,在我们给程序加入计时功能(后面将会在讲到其实现)后,程序出现了异常:对用户方的计时功能完全正确,而对电脑方的计时功能却根本不起作用!后来,经指导老师点拨,我们找到了问题的所在以及相应的解决方案——由于程序在进行搜索时会占用大量的CPU时间,因而阻塞了位于同一线程内的计时器,使之无法正常工作。解决方案就是另外开一个线程,让搜索与计时器分处两个线程。

(科教范文网http://fw.ΝsΕΑc.com编辑)


 启动一个新的线程的方法非常简单,只需调用API函数AfxBeginThread即可,函数原型:
CWinThread* AfxBeginThread(
      AFX_THREADPROC pfnThreadProc,
      LPVOID pParam,
      int nPriority = THREAD_PRIORITY_NORMAL,
      UINT nStackSize = 0,
      DWORD dwCreateFlags = 0,
      LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
       );[ 该函数原型的描述摘自Visual Studio .NET MSDN 版权所有 1987-2002 Microsoft Corporation]
 该函数启动一个新的线程并返回一个指向该新线程对象的指针,然后新的线程与启动该新线程的线程同时运行。该函数的第一个参数AFX_THREADPROC pfnThreadProc指定了线程函数。线程函数的内容即为新线程所要执行的内容,线程函数执行完毕,新线程结束(自动销毁)。
 线程函数必须被定义为全局函数,其返回值类型必须是UINT,必须有一个LPVOID类型的参数。我们可以把调用引擎部分的搜索函数的代码以及完成走棋动作的代码放入我们所定义的思考线程内,如下:
 UINT ThinkingThread(LPVOID pParam)
 {
  //计算机思考并走棋
 }
 然后,我们只要将原先调搜索函数并完成走棋的代码代之以调用AfxBeginThread来启动新线程即可。这样一来,我们就实现了程序的多线程,计算机方的计时器不能正常工作的问题也就随之解决了。

3、计时器(程序辅助)

 我们要给程序添加计时功能(分别记录下棋双方的“思考时间”),可以使用SetTimer函数、KillTimer函数以及OnTimer函数,SetTimer函数可写成如下:
 SetTimer(1,1000,NULL); 内容来自www.nseac.com
 其中第一个参数指明了计时器的ID(可以在同一个程序中建立多个计时器,用计时器ID来区别它们)。第二个参数给出了产生WM_TIMER消息的时间间隔,单位是毫秒。
 当不想再继续使用该计时器时,可以通过调用函数KillTimer(计时器ID)来销毁计时器。如销毁上面所设的计时器可以写作如下:
 KillTimer(1);
 OnTimer函数是WM_TIMER消息的消息响应函数,通俗地讲即每过SetTimer函数中指定的时间间隔,程序就调用一次OnTimer函数。它只有一个参数,即计时器的ID——当一个程序中有多个计时器时,OnTimer函数可以通过识别不同的计时器ID号来完成不同的操作。
 这样要给程序增加对双方下棋时间的计时功能,可以按如下流程编写程序:
 0 - 棋局正式开始,红方先行;
 1 - SetTimer(1,1000,NULL);
 2 - 红方思考;
 3 - 红方走棋;
 4 - KillTimer(1);
 5 - SetTimer(2,1000,NULL);
 6 - 黑方思考;
 7 - 黑方走棋;
 8 - KillTimer(2);
 9 - 跳转至1,重复走棋过程
 
 OnTimer函数则按如下编写代码:
 OnTimer(计时器ID)
 {
  if 计时器ID == 1 then 红方计时+1;
  if 计时器ID == 2 then 黑方计时+1;
 }
 
 当然,上面的流程及伪码仅仅说明编写象棋计时器大体思想,实际情况要比这复杂的多。在我们的实际的程序中还涉及了线程间的通信(因为我们把计算机方的思考和走棋的过程放在了另一个线程之内),时间的刷新显示,分、秒、时的进位换算等等。而且为了提高计时精度,我们还将SetTimer函数的第二个参数设为了100,即每0.1秒做一次计时(有时

上一篇:免费vc++网上寻呼QICQ源代码(附带论文)(一) 下一篇:没有了