(not exactly big blue or Watson, but fun nonetheless)
#include <iostream>
#include <string>
#include <vector>
using namespace std;
bool isWin(vector<vector<int> > board, int playerNum){
int size = board.size();
//check verticals
for(int row=0; row<size; row++){
bool win = 1;
for(int col=0, player=board[row][col]; col<size; col++){
if(player!=playerNum || player!=board[row][col]) {
win = 0;
break;
}
}
if(win==1) return 1;
}
//check horizontals
for(int col=0; col<size; col++){
bool win = 1;
for(int row=0, player=board[row][col]; row<size; row++){
if(player!=playerNum || player!=board[row][col]) {
win = 0;
break;
}
}
if(win==1) return 1;
}
//check forward diagonal
bool win = 1;
for(int diag=0, player=board[diag][diag]; diag<size; diag++){
if(player!=playerNum || player!=board[diag][diag]){
win=0;
break;
}
}
if(win==1) return 1;
//check backward diagonal
win =1;
for(int diag=0, player=board[diag][size-diag-1]; diag<size; diag++){
if(player!=playerNum || player!=board[diag][size-diag-1u]){
win=0;
break;
}
}
if(win==1) return 1;
return 0;
}
//print the gui
void printBoard(vector<vector<int> > board){
unsigned int size = board.size();
for(unsigned int row=0; row<size; row++){
for(unsigned int col=0; col<size; col++){
string mark = " ";
if(board[row][col]==1){
mark = "X";
}
else if (board[row][col]==2){
mark = "O";
}
cout << mark;
if(col==(size-1)) cout<<endl;
else cout<<" | ";
}
if(row!=size-1) cout << " ---------";
cout<<endl;
}
}
//generate a vector of possible board configurations
vector<vector<vector <int > > > getAllPossibleMoves(vector<vector<int > > board, unsigned int player){
vector<vector<vector <int > > > allPossibleMoves;
unsigned int size = board.size();
for(unsigned int row=0; row<size; row++){
for(unsigned int col=0; col<size; col++){
if(board[row][col] == 0){
board[row][col] = player;
allPossibleMoves.push_back(board);
board[row][col] = 0;
}
}
}
return allPossibleMoves;
}
//return 1 if board is full, otherwise 0
bool boardFull(vector<vector<int> > board){
unsigned int size = board.size();
for(unsigned int row=0; row<size; row++){
for(unsigned int col=0; col<size; col++){
if(board[row][col]==0) {return 0;}
}
}
return 1;
}
int nextBestMoveSub(vector<vector<int> > board, bool isNextMove){
if((isNextMove==1) && isWin(board,1) ){
return 2;
}
isNextMove = 0; //no longer the next move, have to play more moves
if(isWin(board,1)) return 1;//if this move wins return win
//return draw if board is full
if(boardFull(board))return 0;
vector<vector<vector<int> > > allOpponentsPossibleMoves = getAllPossibleMoves(board,2);
unsigned int opponentsMoves = allOpponentsPossibleMoves.size();
//check if opponent won, if he did, this move is sure lose.
for(unsigned int opponentMove=0; opponentMove<opponentsMoves; opponentMove++){
if(isWin(allOpponentsPossibleMoves[opponentMove],2)) return -1;
}
int outcome = 1;
//check if any of my future moves would result in a win.
for(unsigned int opponentMove=0; opponentMove<opponentsMoves; opponentMove++){
vector<vector<vector<int> > > allMyPossibleMoves = getAllPossibleMoves(allOpponentsPossibleMoves[opponentMove],1);
unsigned int myMoves = allMyPossibleMoves.size();
int myBest = -1;
//for each of my possible moves, check for the best possible outcome
for(unsigned int myMove=0; myMove<myMoves; myMove++){
int winLoseDraw = nextBestMoveSub(allMyPossibleMoves[myMove], isNextMove);
myBest = (winLoseDraw>=myBest)?winLoseDraw:myBest;
}
//for each of the opponents move, check for the worst possible outcome
outcome = (myBest<=outcome)?myBest:outcome;
}
return outcome;
}
vector<vector<int> > nextBestMove(vector<vector<int> > board){
vector<vector<int> > bestMove;
bool foundWin = 0;
vector<vector<vector<int> > > allMyPossibleMoves = getAllPossibleMoves(board,1);
unsigned int myMoves = allMyPossibleMoves.size();
//for each of my possible moves, check if it results in win, if so return win
for(unsigned int myMove=0; myMove<myMoves; myMove++){
int winLoseDraw = nextBestMoveSub(allMyPossibleMoves[myMove], 1);
if(winLoseDraw==2) return allMyPossibleMoves[myMove];//next move win, return it
if(winLoseDraw==1){
bestMove = allMyPossibleMoves[myMove];//sure win in unknown number of moves
foundWin = 1;
}
if(bestMove.size()==0) bestMove = allMyPossibleMoves[myMove];//not initialized, just take the move as default
if(!foundWin && winLoseDraw==0) bestMove = allMyPossibleMoves[myMove];//if winning move haven't been found, take draw
}
return bestMove;
}
void playGame(){
while(true){
//initialize the board
const unsigned int size = 3;
vector<vector<int> > board = vector<vector<int> >(size);
for(unsigned int i=0; i < size; i++){
board[i] = vector<int>(size);
}
//randomly choose a spot to move to
srand(time(NULL));
unsigned int firstMoveRow = rand()%size;
unsigned int firstMoveCol = rand()%size;
board[firstMoveRow][firstMoveCol]=1;
//print board
printBoard(board);
int outcome = 0;
//while board still has movable space
while(!boardFull(board)){
unsigned int row = 0;
unsigned int col = 0;
//ask user for input
while(true){
cout<<"please make a move by entering row and col numbers (eg: for the first square, 0 0)"<<endl;
cin>>row>>col;
if(cin.fail()||(row<0)||(row>=size)||(col<0)||(col>=size)){
cout<<"input error, please try again"<<endl;
cin.clear();
cin.ignore(1000, '\n');
continue;
}
//check if spot is taken
if(board[row][col]!=0){
cout<<"spot already taken, please try again"<<endl;
printBoard(board);
}else{
board[row][col]=2;
//print board
printBoard(board);
break;
}
}
if(isWin(board, 2)){
outcome = 2;
break;
}
//nextMove(board)
cout<<"my move"<<endl;
board = nextBestMove(board);
//print board
printBoard(board);
if(isWin(board,1)){
outcome = 1;
break;
}
}
vector<string> endGameMessage(3);
endGameMessage[0] = "We draw, you want to play again(y,n)?";
endGameMessage[1] = "I win!, you want to play again(y,n)?";
endGameMessage[2] = "You Win!!, this should never have happened, you want to play again(y,n)?";
cout<<endGameMessage[outcome]<<endl;
string playAgain = "n";
cin>>playAgain;
if(playAgain!="y") return;
}
}
int main (){
playGame();
//assignment1Question2();
//assignment1Question2();
//testIsTrivial();
//problem1();
return 0;
}
No comments:
Post a Comment