您的位置:首页 > 其它

回溯算法--三连游戏(人机对战)

2017-08-24 16:47 555 查看
  程序的核心部分在于计算机如何选择下棋的位置。采用的策略叫作极小极大策略。通过一个赋值函数来给一个位置的“好坏”定值。能使计算机获胜的位置得到值+1;平局得到0;使计算机输棋的位置得到值-1。通过考察盘面就能够确定输赢的位置叫作终端位置。

  如果一个位置不是终端位置,那么该位置的值通过递归假设双方最优棋步而确定。这叫做极小极大策略,因为下棋的一方(人)试图极小化这个位置的值,而另一方(计算机)却要使它的值达到极大。

  采用数组下标1-9代表九个格子,随机生成一个数来确定先手。如果计算机先手,因为此时盘面处于平局,计算机总会选择第一个位置,所以随机生成一个位置给计算机。

头文件

#include <vector>
using namespace std;
class TicTacToe
{
public:

static const int COMP=1;
static const int HUMAN=-1;

TicTacToe():board(10){}

bool fullBoard()
{
for(int i=1;i<=9;++i)
{
if(board[i]==0)
return false;
}
return true;
}
bool isEmpty(int i)
{
if(board[i]==0)
return true;
else
return false;
}

void place(int i,int player)
{
board[i]=player;
}

void unplace(int i)
{
board[i]=0;
}

bool immediateWin(int & bestMove,int player);

int findCompMove(int & bestMove);
int findHumanMove(int & bestMove);

void setChessPiece(int location,int player);

void showBoard();

bool check(int i);

private:

static const int DRAW=0;
static const int COMP_WIN=1;
static const int COMP_LOSS=-1;

vector<int> board;

};


cpp文件

#include "TicTacToe.hpp"

#include <iostream>
bool TicTacToe::immediateWin(int & bestMove,int player)
{
for(int i=1;i<=9;++i)
{
if(isEmpty(i))
{
bool flag=false;
place(i, player);
if(i==1)
{
if(
(board[i]==board[i+1]&&board[i]==board[i+2])
||(board[i]==board[i+3]&&board[i]==board[i+6])
||(board[i]==board[i+4]&&board[i]==board[i+8])
)
{
flag=true;
}

}
if(i==2)
{
if(
(board[i]==board[i+1]&&board[i]==board[i-1])
||(board[i]==board[i+3]&&board[i]==board[i+6])
)
{
flag=true;
}
}
if(i==3)
{
if(
(board[i]==board[i-1]&&board[i]==board[i-2])
||(board[i]==board[i+3]&&board[i]==board[i+6])
||(board[i]==board[i+2]&&board[i]==board[i+4])
)
{
flag=true;
}

}
if(i==4)
{
if(
(board[i]==board[i+3]&&board[i]==board[i-3])
||(board[i]==board[i+2]&&board[i]==board[i+1])
)
{
flag=true;
}

}
if(i==5)
{
if(
(board[i]==board[i+3]&&board[i]==board[i-3])
||(board[i]==board[i-1]&&board[i]==board[i+1])
||(board[i]==board[i-4]&&board[i]==board[i+4])
||(board[i]==board[i-2]&&board[i]==board[i+2])
)
{
flag=true;
}

}
if(i==6)
{
if(
(board[i]==board[i-1]&&board[i]==board[i-2])
||(board[i]==board[i+3]&&board[i]==board[i-3])
)
{
flag=true;
}

}
if(i==7)
{
if(
(board[i]==board[i+1]&&board[i]==board[i+2])
||(board[i]==board[i-6]&&board[i]==board[i-3])
||(board[i]==board[i-2]&&board[i]==board[i-4])
)
{
flag=true;                }

}
if(i==8)
{
if(
(board[i]==board[i+1]&&board[i]==board[i-1])
||(board[i]==board[i-6]&&board[i]==board[i-3])
)
{
flag=true;
}

}
if(i==9)
{
if(
(board[i]==board[i-1]&&board[i]==board[i-2])
||(board[i]==board[i-6]&&board[i]==board[i-3])
||(board[i]==board[i-8]&&board[i]==board[i-4])
)
{
flag=true;                }

}

unplace(i);
if(flag)
{
bestMove=i;
return true;
}

}
}

return false;
}

int TicTacToe::findCompMove(int & bestMove)
{
int i,responseValue;
int dc;                 //do not care
int value;

if(fullBoard())
value=DRAW;

else
{
if(immediateWin(bestMove, COMP))
return COMP_WIN;
else
{
value=COMP_LOSS;bestMove=1;

for(i=1;i<=9;++i)
{
if(isEmpty(i))
{
place(i, COMP);
responseValue=findHumanMove(dc);
unplace(i);
if(responseValue>value)
{
value=responseValue;
bestMove=i;
}
}
}
}
}
return value;

}
int TicTacToe::findHumanMove(int & bestMove)
{
int i,responseValue;
int dc;
int value;

if(fullBoard())
value=DRAW;

else
{
if(immediateWin(bestMove, HUMAN))
return COMP_LOSS;
else
{
value=COMP_WIN;bestMove=1;

for(i=1;i<=9;++i)
{
if(isEmpty(i))
{
place(i, HUMAN);
responseValue=findCompMove(dc);
unplace(i);
if(responseValue<value)
{
value=responseValue;
bestMove=i;
}
}
}
}
}
return value;

}

void TicTacToe::showBoard()
{
for(int i=0;i<20;++i)
cout<<"\n";
vector<string> out(10);
for(int i=1;i<=9;++i)
{
if(board[i]==0)
out[i]=' ';
else if(board[i]==-1)
{
out[i]="Ο";
}
else
{
out[i]="Χ";
}
}

cout<<"________________"<<endl;
cout<<"| "<<out[1]<<"  | "<<out[2]<<"  | "<<out[3]<<"  |"<<endl;
cout<<"|    |    |    |"<<endl;
cout<<"|—-——|—-——|—-——|"<<endl;
cout<<"| "<<out[4]<<"  | "<<out[5]<<"  | "<<out[6]<<"  |"<<endl;
cout<<"|    |    |    |"<<endl;
cout<<"|——-—|—-——|—-——|"<<endl;
cout<<"|    |    |    |"<<endl;
cout<<"| "<<out[7]<<"  | "<<out[8]<<"  | "<<out[9]<<"  |"<<endl;
cout<<"|____|____|____|"<<endl;

}

bool TicTacToe::check(int i)
{
if(i==1)
{
if(
(board[i]==board[i+1]&&board[i]==board[i+2])
||(board[i]==board[i+3]&&board[i]==board[i+6])
||(board[i]==board[i+4]&&board[i]==board[i+8])
)
{

return true;
}

}
if(i==2)
{
if(
(board[i]==board[i+1]&&board[i]==board[i-1])
||(board[i]==board[i+3]&&board[i]==board[i+6])
)
{

return true;
}

}
if(i==3)
{
if(
(board[i]==board[i-1]&&board[i]==board[i-2])
||(board[i]==board[i+3]&&board[i]==board[i+6])
||(board[i]==board[i+2]&&board[i]==board[i+4])
)
{

return true;
}

}
if(i==4)
{
if(
(board[i]==board[i+3]&&board[i]==board[i-3])
||(board[i]==board[i+2]&&board[i]==board[i+1])
)
{

return true;
}

}
if(i==5)
{
if(
(board[i]==board[i+3]&&board[i]==board[i-3])
||(board[i]==board[i-1]&&board[i]==board[i+1])
||(board[i]==board[i-4]&&board[i]==board[i+4])
||(board[i]==board[i-2]&&board[i]==board[i+2])
)
{

return true;
}

}
if(i==6)
{
if(
(board[i]==board[i-1]&&board[i]==board[i-2])
||(board[i]==board[i+3]&&board[i]==board[i-3])
)
{

return true;
}

}
if(i==7)
{
if(
(board[i]==board[i+1]&&board[i]==board[i+2])
||(board[i]==board[i-6]&&board[i]==board[i-3])
||(board[i]==board[i-2]&&board[i]==board[i-4])
)
{

return true;
}

}
if(i==8)
{
if(
(board[i]==board[i+1]&&board[i]==board[i-1])
||(board[i]==board[i-6]&&board[i]==board[i-3])
)
{

return true;
}

}
if(i==9)
{
if(
(board[i]==board[i-1]&&board[i]==board[i-2])
||(board[i]==board[i-6]&&board[i]==board[i-3])
||(board[i]==board[i-8]&&board[i]==board[i-4])
)
{

return true;
}

}
return false;
}

void TicTacToe::setChessPiece(int location,int player)
{
if(location>0&&location<10&&isEmpty(location))
{
board[location]=player;
}
else
{
cout<<"try again";
cin>>location;
setChessPiece(location, player);
}
}


main.cpp

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "TicTacToe.hpp"
using namespace std;
int main()
{
TicTacToe board;
board.showBoard();
int move;

srand((unsigned)time(NULL));
bool turn=rand()%2;             //决定先手

if(turn==0)
{
sleep(1.5);
move=rand()%9+1;            //随机选择一个位置
board.setChessPiece(move, board.COMP);
board.showBoard();
turn=1;
}
else
{
cout<<"Human First";
}
while (1)
{
if(turn)
{
cin>>move;

board.setChessPiece(move, board.HUMAN);
turn=0;
}
else
{
sleep(1.5);
board.findCompMove(move);
board.setChessPiece(move, board.COMP);
turn=1;
}

board.showBoard();

if(board.check(move))
{
if(!turn)
cout<<"human win"<<endl<<endl;
else
cout<<"computer win"<<endl<<endl;
return 0;
}
if(board.fullBoard())
{
cout<<"draw"<<endl<<endl;
return 0;

}

}
return 0;
}


结果



















内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: