机器博弈:tic-tac-toe游戏

下面是我写的一个tic-tac-toe的简单游戏。

 

我主要的思路是使用极大极小的搜索策略。并且体会到博弈程序的好坏很大程度上取决于局面评估函数的好坏。

因为机器方希望在所有下一步可以下子的集合中,选择最优的步法。这是就需要就局面进行评估,需要附加一些知识,而局面的评估值可以是所有这些知识评估的结果之和。

 

评估函数和程序对局面的搜索速度是成反比的。

 

 

我的程序中评估函数比较弱。

 

主要有二个类:

 

~~~~~~~~~~~~~~~~~~~~Map.h~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`

 

#ifndef MAP_H
#define MAP_H

#include<iostream>
#include<cstring>
#define MAX_DEPTH 2
using namespace std;

class Map{
public :

 Map(){
  
  
 }
 
 //the computer try to make best movement
 int makeBestMove(Player& computer){
  
  int bestValue = minMaxSearch(MAX_DEPTH , computer.type );
  cout<<"Computer (x,y):"<< bestMove.x <<" "<<bestMove.y<<endl;
  makeMove(computer.type , bestMove.x , bestMove.y );
  return 0;
 }
 
 //check wether the board is all occupied
 bool isAllOccupied(){
  
  bool result = true  ;
  for(int i=1;i<=boardSize; i++){
   
   for(int j=1 ; j<=boardSize ; j++){
    
    if( '0' ==  board[i][j]){
     result = false ;
     return result ;
    }
     
   }
  }
  return result ;
 }
 
 //decide wether one side has won
 bool isHuamanOrComputerWin(const int& side){
  
  
  bool win = false ;
  char flag = (side == 1)? 'c' :'h';
  
  int i;
  
  for( i=1 ; i<=boardSize ; i++){       //行
   
   if( flag== board[i][0] && flag == board[i][1] && flag == board[i][2] ){
    
    win = true ;
    return win ;
   }
    
  }
  
  for (i =1 ; i<=boardSize ; i++){      //列
   
   if( flag == board[0][i] && flag == board[1][i] && flag == board[2][i] ){
    
    win = true ;
    return win;
   }
   
  }
  
  if( ((board[1][1] == board[2][2]) && (board[1][1] == board[3][3])) ||
   ((board[3][1] == board[2][2]) &&  (board[3][1] == board[1][3])) )
  {
    
    win = true ;
    return win ;
  }       
  
  return win ;
 }
 
 // 1:computer -1:human 'c': computer 'h':human
 bool makeMove(const int& side,const int& x,const int& y ){
  
  if( x<=0 || x >=4 || y<=0 || y>=4 || board[x][y] != '0')
   return false ;
   
  board[x][y]= (1 == side )?  'c' : 'h' ;
  return true ;
 } 
 //umake previous movement
 bool unmakeMove(const int& x,const int& y){
  
  if( x<=0 || x >=4 || y<=0 || y>=4 || board[x][y] == '0')
   return false ;
   
  board[x][y] = '0';
  return true ;
 }
 
 //print the board
 void printBoard(){
  
  for( int i=1 ; i<= boardSize ; i++){
   for(int j=1 ; j<= boardSize ; j++){
    
    cout<<board[i][j]<<" ";
   }   
   cout<<endl;
  }
 }
 
 //max-min search strategy
 int minMaxSearch(int depth , int side ){
  
  int value,best;
  Move moveArray[9];        //保存可下子的位置
   
  if( 1== side )
   best = INT_MIN ;
  if( -1 == side )
   best = INT_MAX ;
  
  if( 0 == depth  ){
   
   return evaluateMap();
  }
  
  int num = genAllMove(moveArray) ;
  
  for(int i=0; i<num ; i++){
   
   makeMove(side, moveArray[i].x , moveArray[i].y );
   value = minMaxSearch(depth -1 ,-1 * side );
   unmakeMove(moveArray[i].x , moveArray[i].y );
   
   if( 1 == side ){
    
    if( value > best){
     
     best = value ;
     if( MAX_DEPTH == depth )
      bestMove = moveArray[i];
    
    }
   }
   
   if( -1 == side ){
    
    if( value < best  ){
     
     best = value ;
     if(MAX_DEPTH == depth )
      bestMove = moveArray[i];
    }    
   }
   
  }
  
  return best ;          //返回走棋方的最优值
  
 }
 
private:

 
 
 static char board[4][4];
 enum { boardSize=3 };
 
 typedef struct move{
  int x;
  int y;
 }Move ;
 
 Move bestMove;          //最佳的下子位置
 
 int  genAllMove(Move* array){      //这里Move的定义要放在对Move的引用之前
  
  int moveNum = 0;
  
  for(int i=1 ; i<=boardSize ; i++){
   
   for(int j=1 ; j<=boardSize ;j++){
    
    if( '0' == board[i][j]){
     
     array[moveNum].x= i;
     array[moveNum].y = j;
     moveNum ++;
    }
   }
  }
  
  return moveNum;
 }
 
 int evaluateMap(){
  
  char boardCopy[4][4];
  memcpy( boardCopy , board , sizeof(board));   //对原来的board进行备份
  int comp=0,human=0;
  
  for( int i=1 ;i<=boardSize ; i++){
   
   for(int j=1 ; j<=boardSize ; j++){
    
    if( 'c' == board[i][j]){
     
     comp +=util(i,j,'c');
    }
    
    if( 'h' == board[i][j] ){
     
     human += util(i,j,'h');
    }
   }
  }
  
  memcpy( board , boardCopy , sizeof(boardCopy));  //还原原来的board
  
  return comp - human ;
  
 }
 

 int util(int x,int y,char c){
  
  
  int score= 0 , i , j ;
  
  for(int k=0; k<8 ; k++) {
   
   i = x+ dir[k][0] ;      //2连子
   j = y+ dir[k][1] ;
   
   if( i<=0 || i>=4 || j<=0 || j>=4 || c != board[i][j] )
    continue;
      
   score +=4 ;
   
   i = i+ dir[k][0] ;      //朝相同方向再测试
   j = j+ dir[k][1] ;
   
   if( i<=0 || i>=4 || j<=0 || j>=4 || c != board[i][j] )
    continue;
   
   score -= 4; 
   score += 16  ;

  }
  
  board[x][y] = '0' ;
  
  if( 0 == score )
   return 1 ;
  else
   return score ;
  
 }
 

 const static int dir[8][2];
};

#endif

char Map::board[4][4]={
 
 '0','0','0','0',
 '0','0','0','0',
 '0','0','0','0',
 '0','0','0','0'
};

const int Map::dir[8][2]={ {0 ,-1},{-1,0},{ 0 , 1} ,{ 1,0},{-1,-1},{-1,1},{1,-1},{1,1} };

 

 

 

~~~~~~~~~~~~~~~~~~~~~~~Player.h~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

 

#ifndef PLAYER_H
#define PLAYER_H

class Player{
 
public:
 Player(int t):type(t){
    
 }
public:
 
 int posx;     //记录player当前的位置
 int posy;
 int type;
};
#endif

~~~~~~~~~~~~~~~~~~~~~~~主程序~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

#include<iostream>
#include "Player.h"
#include "Map.h"
#define NOT !
using namespace std;

Player computer(1),human(-1);     // 1对应computer -1对应human
Map map;

int main(){
 
 cout<<"tic-tac-toe Game!"<<endl<<endl;
 
 cout<<"Computer make first step...." <<endl;
 computer.posx = 2;
 computer.posy = 2;
 map.makeMove(computer.type,computer.posx,computer.posy);
 map.printBoard();
 
 bool moveCorrectFlag = true ;
 
 //start the game
 while( NOT map.isAllOccupied() ){
  
  cout<<"make step (x,y):";
  cin>>human.posx>>human.posy ;
  moveCorrectFlag = map.makeMove(human.type , human.posx ,human.posy );
  if( false == moveCorrectFlag ){
   
   cout<<"invalid move.. try again!"<<endl;
   continue ;
  }
  
  else{
   
   map.printBoard();
   if( map.isHuamanOrComputerWin(human.type)){  //if human win
    
    cout<<"You Win!"<<endl;
    return 0;
   }
   else{
    
    map.makeBestMove(computer) ;
    map.printBoard();
    if( map.isHuamanOrComputerWin(computer.type) ){
     
     cout<<"You Lost!"<<endl;
     return 0;
    }
   }
  }
 }
 
 cout<<"A Draw ... The Game Ends!"<<endl;
 
 return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值