[转载] 中国象棋软件-引擎实现(七)测试程序

之前我们已经讲了实现一个中国象棋软件的所有要素,本篇我们只是粗略地建一个工程再添加一点文件使得我们能看到程序的运行情况如何。

在界面完成之前,我先建了一个Win32控制台项目(学生朋友们对这个最熟悉也最容易理解)。根据前面所讲的我们已经有了CChessDef.h CChessMove.h CChessSearch.h HistoryHeuristic.h SortMove.h CChessEvaluate.h六个文件。将这六个文件加入工程后,再向工程里加入scCChess.h和scCChess.cpp两个文件。定义如下:

scCChess.cpp

// scCChess.cpp

#include "scCChess.h"

int main()
{
  cout << "***********************************************************" << endl
       << "**    中国象棋对弈软件引擎" << endl
       << "**           by sun428" << endl
       << "***********************************************************" << endl;

  InitGame();
  StartGame();

  return 0;
}

// end of scCChess.cpp

scCChess.h

// scCChess.h

#include < stdio.h>
#include < stdlib.h>
#include < time.h>
#include < iostream>
using namespace std;

#include "CChessMove.h"
#include "CChessSearch.h"

#define OK    1
#define Error  0

/////////////////// Data Define ///////////////////////////////////////////////

CCHESSMOVE cmMove;

int nNumOfStep;  

////////////////////// Type Define ////////////////////////////////////////////

typedef int Status;

////////////////////// Function Prototype /////////////////////////////////////

// 初始化游戏(进行一些基本参数的设定)
Status InitGame( int fComputerSide = BLACK, int nUserSetMaxSearchDepth = 4 );

// 开始游戏
Status StartGame();

// 使用开局库
inline CCHESSMOVE UseLibrary();

///////////////////// Programmer-Defined function /////////////////////////////

Status InitGame(  int fComputerSide, int nUserSetMaxSearchDepth )
{

  srand( (unsigned)time( NULL ) );

  if( fComputerSide == RED )
  {
    //
  }

  nMaxSearchDepth =  nUserSetMaxSearchDepth ;

  nNumOfStep =0;

  return OK;
}

Status StartGame()
{
  char fx,fy,tx,ty;

  while( 1 )
  {
    cin >> fx >> fy >> tx >> ty ;
    cmMove.ptFrom.x = fx - '0';
    cmMove.ptFrom.y = fy - '0';
    cmMove.ptTo.x = tx - '0';
    cmMove.ptTo.y = ty - '0';

    DoMove( & cmMove );
    nNumOfStep++;

    if( nNumOfStep == 1 )
    {//第一步查开局库
      cmMove =UseLibrary();
      if( cmMove.ptFrom.x != -1 )
      {
        DoMove( &cmMove );
      }
      else
      {
        cmMove = SearchAGoodMove();
      }
    }
    else
    {
      cmMove = SearchAGoodMove();
    }

    printf( "%d%d %d%dn", cmMove.ptFrom.x, cmMove.ptFrom.y,
          cmMove.ptTo.x, cmMove.ptTo.y );
  }
  return OK;
}

// 使用开局库
inline CCHESSMOVE UseLibrary()
{
  CCHESSMOVE cmMove;
  cmMove.ptFrom.x  = -1;  //用于以后判断是否在开局库中找到了应着

  //srand( (unsigned)time( NULL ) );

  if( CChessBoard[4][2] == RED_P )//当头炮
  {
    if( CChessBoard[1][2] == 0 )//左炮
    {
      cmMove.ptFrom.x = 1;
      cmMove.ptFrom.y  = 9;
      cmMove.ptTo.x  = 2;
      cmMove.ptTo.y  = 7;
    }
    else            //右炮
    {
      cmMove.ptFrom.x = 7;
      cmMove.ptFrom.y  = 9;
      cmMove.ptTo.x  = 6;
      cmMove.ptTo.y  = 7;
    }
  }
  else if( CChessBoard[2][2] == RED_P )//炮
  {
    cmMove.ptFrom.x = 7;  //当头炮
    cmMove.ptFrom.y  = 7;
    cmMove.ptTo.x  = 4;
    cmMove.ptTo.y  = 7;
  }
  else if( CChessBoard[6][2] == RED_P )//炮
  {
    cmMove.ptFrom.x = 1;  //当头炮
    cmMove.ptFrom.y  = 7;
    cmMove.ptTo.x  = 4;
    cmMove.ptTo.y  = 7;
  }
  else if( CChessBoard[3][2] == RED_P )//炮
  {
    if( CChessBoard[1][2] == 0 )
    {
      cmMove.ptFrom.x = 7;  //当头炮
      cmMove.ptFrom.y  = 7;
      cmMove.ptTo.x  = 4;
      cmMove.ptTo.y  = 7;
    }
    else
    {
      switch( rand()%3 )
      {
      case 0:
      case 1:
        cmMove.ptFrom.x = 7;  //当头炮
        cmMove.ptFrom.y  = 7;
        cmMove.ptTo.x  = 4;
        cmMove.ptTo.y  = 7;
        break;

      case 2:
        cmMove.ptFrom.x = 6;  //卒
        cmMove.ptFrom.y  = 6;
        cmMove.ptTo.x  = 6;
        cmMove.ptTo.y  = 5;
        break;
      }
    }
  }
  else if( CChessBoard[5][2] == RED_P )//炮
  {
    if( CChessBoard[7][2] == 0 )
    {
      cmMove.ptFrom.x = 1;  //当头炮
      cmMove.ptFrom.y  = 7;
      cmMove.ptTo.x  = 4;
      cmMove.ptTo.y  = 7;
    }
    else
    {
      switch( rand()%3 )
      {
      case 0:
      case 1:
        cmMove.ptFrom.x = 1;  //当头炮
        cmMove.ptFrom.y  = 7;
        cmMove.ptTo.x  = 4;
        cmMove.ptTo.y  = 7;
        break;

      case 2:
        cmMove.ptFrom.x = 2;  //卒
        cmMove.ptFrom.y  = 6;
        cmMove.ptTo.x  = 2;
        cmMove.ptTo.y  = 5;
        break;
      }
    }
  }
  else if( CChessBoard[4][2] == RED_X )//飞象
  {
    switch( rand()%8 )
    {
    case 0:
    case 1:
    case 2:
      cmMove.ptFrom.x = 7;  //跳马
      cmMove.ptFrom.y  = 9;
      cmMove.ptTo.x  = 6;
      cmMove.ptTo.y  = 7;
      break;

    case 3:
    case 4:
    case 5:
      cmMove.ptFrom.x = 6;  //飞象
      cmMove.ptFrom.y  = 9;
      cmMove.ptTo.x  = 4;
      cmMove.ptTo.y  = 7;
      break;

    case 6:
    case 7:
      cmMove.ptFrom.x = 1;  //炮支士角
      cmMove.ptFrom.y  = 7;
      cmMove.ptTo.x  = 5;
      cmMove.ptTo.y  = 7;
      break;

    }
  }
  else if( CChessBoard[2][2] == RED_M )//跳马
  {
    cmMove.ptFrom.x = 2;  //走卒
    cmMove.ptFrom.y  = 6;
    cmMove.ptTo.x  = 2;
    cmMove.ptTo.y  = 5;
  }
  else if( CChessBoard[6][2] == RED_M )//跳马
  {
    cmMove.ptFrom.x = 6;  //走卒
    cmMove.ptFrom.y  = 6;
    cmMove.ptTo.x  = 6;
    cmMove.ptTo.y  = 5;
  }
  else if( CChessBoard[2][4] == RED_B )//走卒
  {
    switch( rand()%3 )
    {
    case 0:
    case 1:
      cmMove.ptFrom.x = 1;  //炮顶
      cmMove.ptFrom.y  = 7;
      cmMove.ptTo.x  = 2;
      cmMove.ptTo.y  = 7;
      break;

    case 2:
      cmMove.ptFrom.x = 2;  //飞象
      cmMove.ptFrom.y  = 9;
      cmMove.ptTo.x  = 4;
      cmMove.ptTo.y  = 7;
      break;
    }
  }
  else if( CChessBoard[6][4] == RED_B )//走卒
  {
    switch( rand()%3 )
    {
    case 0:
    case 1:
      cmMove.ptFrom.x = 7;  //炮顶
      cmMove.ptFrom.y  = 7;
      cmMove.ptTo.x  = 6;
      cmMove.ptTo.y  = 7;
      break;

    case 2:
      cmMove.ptFrom.x = 6;  //飞象
      cmMove.ptFrom.y  = 9;
      cmMove.ptTo.x  = 4;
      cmMove.ptTo.y  = 7;
      break;
    }
  }

  return cmMove;
}

// end of scCChess.h

两个文件其实都很简单,就是用户输入下棋的起点坐标和终点坐标,电脑再返回一个起点坐标和终点坐标,如此反复来进行对弈。关于坐标的定义依然是按下图所示(同棋局表示中所讲的一样)。

qipan.gif

例如,第一步你要走一步当头炮,你就可以输入1242或是7242。之后电脑会返回它的走法。

如果你觉得电脑下棋太慢你可以通过修改

// 初始化游戏(进行一些基本参数的设定)
Status InitGame( int fComputerSide = BLACK, int nUserSetMaxSearchDepth = 4 );

中nUserSetMaxSearchDepth = 4处的值来设定搜索深度。值越小电脑下棋速度越快(当然从理论上讲水平也越差)。

这两个文件写得都很简单,既没有结束判断也没有用户下棋的合法性检查。目的只是大概地测试一下电脑的下棋情况。由于电脑第一步棋下得不好,所以我给它加了一个简陋的“开局库”而使得代码有点长。这一部分的程序没有什么难点,就不再累述了。各位网友也可以自己另写界面来测试程序。说到这儿顺便提一句,我们科技小组所写的界面也已经初步完成了。过一段时间我把界面的主体代码也贴上来,让大家可以更方便地测试程序: )

至此,本站的“中国象棋软件-引擎实现”系列就全部结束了。简单地总结一下。
首先,这个程序是我目前所写的程序中代码最长、难度也最大的一个。通过不断查找资料学习、写程序、修改程序,直至最终顺利完成程序。我体会到了无比的喜悦及成就感(这种喜悦与成就感完全冲淡了写程序的辛苦)。我很高兴自己从最初对象棋软件的一无所知到了后来能亲手实现了一个象棋软件。

再者,写本程序我最大的一个遗憾就是没有用上面向对象的思想,虽然在学校里学过了C++,但很遗憾没能将其用之于实践。通篇程序没有一个类,大量的全局变量实在让我也有点不太好意思把程序贴到网上来——这也反映了我对面向对象的认识还有很大的欠缺,今后还需努力学习……

最后,我把程序贴到网上的目的是想让同我一样热爱编程但暂为菜鸟的学生朋友有一个了解象棋软件的具体实现的机会。由于本人着实很菜,程序中难免有多多少少的不佳之处(比如刚刚所说的没用面向对象等等)。对此,一来希望不要误导、影响各位学弟学妹,二来还请大虾们不要见笑、多多指教。

好了,大概就讲这么多了。对于程序中有什么欠妥的地方还望各位朋友多多赐教。同时再次感谢广大网友的支持,谢谢!

posted @ 2017-01-06 22:21  Yao,Mane  阅读(714)  评论(0编辑  收藏  举报