[轉載] 中國象棋軟件-引擎實現(七)測試程序

以前咱們已經講了實現一箇中國象棋軟件的全部要素,本篇咱們只是粗略地建一個工程再添加一點文件使得咱們能看到程序的運行狀況如何。ios

在界面完成以前,我先建了一個Win32控制檯項目(學生朋友們對這個最熟悉也最容易理解)。根據前面所講的咱們已經有了CChessDef.h CChessMove.h CChessSearch.h HistoryHeuristic.h SortMove.h CChessEvaluate.h六個文件。將這六個文件加入工程後,再向工程里加入scCChess.h和scCChess.cpp兩個文件。定義以下:編程

scCChess.cppide

// 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。以後電腦會返回它的走法。lua

若是你以爲電腦下棋太慢你能夠經過修改spa

// 初始化遊戲(進行一些基本參數的設定)
Status InitGame( int fComputerSide = BLACK, int nUserSetMaxSearchDepth = 4 );

中nUserSetMaxSearchDepth = 4處的值來設定搜索深度。值越小電腦下棋速度越快(固然從理論上講水平也越差)。.net

這兩個文件寫得都很簡單,既沒有結束判斷也沒有用戶下棋的合法性檢查。目的只是大概地測試一下電腦的下棋狀況。因爲電腦第一步棋下得很差,因此我給它加了一個簡陋的「開局庫」而使得代碼有點長。這一部分的程序沒有什麼難點,就再也不累述了。各位網友也能夠本身另寫界面來測試程序。說到這兒順便提一句,咱們科技小組所寫的界面也已經初步完成了。過一段時間我把界面的主體代碼也貼上來,讓你們能夠更方便地測試程序: )對象

至此,本站的「中國象棋軟件-引擎實現」系列就所有結束了。簡單地總結一下。
首先,這個程序是我目前所寫的程序中代碼最長、難度也最大的一個。經過不斷查找資料學習、寫程序、修改程序,直至最終順利完成程序。我體會到了無比的喜悅及成就感(這種喜悅與成就感徹底沖淡了寫程序的辛苦)。我很高興本身從最初對象棋軟件的一無所知到了後來能親手實現了一個象棋軟件。遊戲

再者,寫本程序我最大的一個遺憾就是沒有用上面向對象的思想,雖然在學校裏學過了C++,但很遺憾沒能將其用之於實踐。通篇程序沒有一個類,大量的全局變量實在讓我也有點不太好意思把程序貼到網上來——這也反映了我對面向對象的認識還有很大的欠缺,從此還需努力學習……

最後,我把程序貼到網上的目的是想讓同我同樣熱愛編程但暫爲菜鳥的學生朋友有一個瞭解象棋軟件的具體實現的機會。因爲本人着實很菜,程序中不免有多多少少的不佳之處(好比剛剛所說的沒用面向對象等等)。對此,一來但願不要誤導、影響各位學弟學妹,二來還請大蝦們不要見笑、多多指教。

好了,大概就講這麼多了。對於程序中有什麼欠妥的地方還望各位朋友多多賜教。同時再次感謝廣大網友的支持,謝謝!

相關文章
相關標籤/搜索