0% found this document useful (0 votes)
112 views6 pages

Hex Game with AI Opponent

This program allows a user to play the game of hex against a computer opponent. The computer uses artificial intelligence to make strategic moves. The program displays a hex board graph and prompts users to enter their moves as row,column coordinates. The computer analyzes the board to determine the best defensive move using a trial-based algorithm that simulates random games, tracks winning moves, and chooses the most frequent winning move.

Uploaded by

vvaswin2004
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
112 views6 pages

Hex Game with AI Opponent

This program allows a user to play the game of hex against a computer opponent. The computer uses artificial intelligence to make strategic moves. The program displays a hex board graph and prompts users to enter their moves as row,column coordinates. The computer analyzes the board to determine the best defensive move using a trial-based algorithm that simulates random games, tracks winning moves, and chooses the most frequent winning move.

Uploaded by

vvaswin2004
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

//This program lets the user play the game of hex with

//the computer as opponent. The computer uses AI to play


//the game the right way. Each player's move should have
//the following form: i,j. Write the two number in the
//same line with a comma in between. The computer seems
//to play very smart and is unbeatable in a size 5 board.
//Enjoy.
//Christos Drilakis, 23/01/2021.

#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <utility>
#include <ctime>
#include <iterator>
#include <algorithm>

using namespace std;

enum class player { BLUE, RED };

class BoardGraph
{
public:
BoardGraph() {}
BoardGraph(int size):
size(size), board(size, vector<char>(size, '.'))
{
edges = "\\";
for (int i=1; i<size; i++)
{
edges += " / \\";
}
}

//make a move and if it's legal, return true


bool makeMove(int x, int y, player p);

//undo a false move


bool undo(int x, int y);

//see if a player won or not


bool win(int x, int y);

//print the board


void printBoardGraph();

//compute the best move with AI


pair<int,int> AIalgorithm();

//copy constructor
BoardGraph(const BoardGraph &board2)
{
board = [Link];
edges = [Link];
size = [Link];
}
private:
bool ValidMove(int x, int y);
void checkBorders(int x, int y,
vector<bool> &flags, char side);

const static int directions[6][2]; //six directions


const static char Blue = 'X'; //blue is the first player
const static char Red = 'O';
const static char Blank = '.';
int size;
string edges;
vector<vector<char> > board;
};

void BoardGraph::printBoardGraph()
{
//first line
cout << board[0][0];
for (int j=1; j<size; j++)
cout << " - " << board[0][j];
cout << endl;

string space = "";


for (int i=1; i<size; i++)
{
space += ' ';
cout << space << edges << endl;
space += ' ';
cout << space << board[i][0];
for (int j=1; j<size; j++)
cout << " - " << board[i][j];
cout << endl;
}
}

bool BoardGraph::ValidMove(int x, int y)


{
return x>=0 && x<size && y>=0 && y<size && board[x][y] == Blank;
}

void BoardGraph::checkBorders(int x, int y,


vector<bool> &flags, char side)
{
if (side == Blue)
{
if (y == 0)
flags[0] = true;
if (y == size - 1)
flags[1] = true;
}
else if (side == Red)
{
if (x == 0)
flags[0] = true;
if (x == size - 1)
flags[1] = true;
}
}
const int BoardGraph::directions[6][2] =
{
{-1, 0}, {-1, 1}, //top left, top right
{0, -1}, {0, 1}, //left, right
{1, -1}, {1, 0} //buttom left, buttom right
};

bool BoardGraph::makeMove(int x, int y , player p)


{
if (ValidMove(x, y) == false)
return false;

if (p == player::BLUE)
board[x][y] = Blue;
else if (p == player::RED)
board[x][y] = Red;

return true;
}

bool BoardGraph::undo(int x, int y)


{
if (ValidMove(x, y) == false)
return false;

board[x][y] = Blank;

return true;
}

bool BoardGraph::win(int x, int y)


{

char side = board[x][y];


vector<bool> flags(2, false);

vector<vector<bool> > visited(size, vector<bool>(size));


queue<pair<int, int> > traces;
[Link](make_pair(x, y));
visited[x][y] = true;

while (![Link]())
{
auto top = [Link]();
checkBorders([Link], [Link], flags, side);
[Link]();

for (int n=0; n<6; n++)


{
int curX = [Link] + directions[n][0];
int curY = [Link] + directions[n][1];
if (curX>=0 && curX<size && curY>=0 && curY<size &&
board[curX][curY] == side && visited[curX][curY] == false)
{
visited[curX][curY] = true;
[Link](make_pair(curX, curY));
}
}
}
return flags[0] && flags[1];
}

pair<int,int> BoardGraph::AIalgorithm()
{
//vectors for shuffling and counting the empty spots
vector<int> emptySpots, emptySpotsCounter(size*size);

for (int x=0; x<size; ++x)


for (int y=0; y<size; ++y)
if(board[x][y]==Blank)
{
emptySpots.push_back(x*size+y); //vector with all remaining empty
spots
++emptySpotsCounter[x*size+y]; //all the empty spots take value 1
}

vector<int> emptySpotsCopy = emptySpots; //copy vector for initialization

int wins=0, turn = 0, lastElement;


vector<int> bestMoves(size*size); //stores all the best moves

vector<vector<char>> testboard = board; //copy of hex board for initialization

for(int trials=0; trials<10000; ++trials)


{
board = testboard;
emptySpots = emptySpotsCopy;
random_shuffle([Link](), [Link]());
while ([Link]()) //fill up the remaining empty spots on the board
{
lastElement = emptySpots[[Link]()-1];
turn = !turn;
if (turn == 1)
{
makeMove(lastElement/size, lastElement%size, player::BLUE);
emptySpots.pop_back();
}
else
{
makeMove(lastElement/size, lastElement%size, player::RED);
emptySpots.pop_back();
}
}

for (int x=0; x<size; ++x)


{
for (int y=0; y<size; ++y)
{
if(board[x][y]==Blue && win(x,y) && emptySpotsCounter[x*size+y]==1)
{
++bestMoves[x*size+y]; //store all the moves that led to a win
++wins;
}
}
}
}
vector<int>::iterator maxElement; //iterator to find the move with the best
chances to win
maxElement = max_element([Link](), [Link]()); //max value means
best move

int dist = distance([Link](), maxElement); //position of max value


//transpose into 2d coordinates
int row = dist/size;
int col = dist%size;

if (*maxElement==0) //in case there is no winning choice


{
row = emptySpotsCopy[0]/size;
col = emptySpotsCopy[0]%size;
}

return make_pair(row, col);


}

int main()
{
const int SIZE = 5;
BoardGraph board1(SIZE); //create the board to play

int turn = 0;
int steps = 0;
int x, y;
char comma;
srand(time(0));

pair<int,int> AImove; //the move that AI decides to play

while (true)
{
steps++;
turn = !turn;
if (turn == 1)
{
BoardGraph board2 = board1; //copy of the board for testing the
best play
AImove = [Link](); //the AI method outputs a pair of
ints
x = [Link];
y = [Link];
[Link](x, y, player::BLUE); //
cout << "Computer: (" << x << "," << y << ")" << endl;
[Link]();
}
else
{
while (true)
{
cout << "Input coordinates (write \"x,y\" and then press enter): ";
cin >> x >> comma >> y;
if ([Link](x, y, player::RED)==true)
break;
else
cout << "Invalid values! Try again!\n";
}
cout << "Human: (" << x << "," << y << ")" << endl;
}

if ([Link](x, y))
{
if (turn==0)
[Link]();
cout << (turn ? "Computer" : "Human") << " wins!" << endl;
cout << "Total steps = " << steps << endl;
break;
}
}

return 0;
}

You might also like