In: Computer Science
explain a pseudocode for tic tac toe in c++ between a computer and a player in words
Tic-tac-toe is a game where two players X and O fill the hash (#) shaped box (consist of two vertical lines crossing two horizontal lines) with their alternate turns. The player who first fills the box with 3Xs or 3Os in a horizontal, vertical, or diagonal manner will win the game.
In some cases, when none of the players succeeds in filling the boxes horizontally, vertically, or diagonally with 3Xs or 3Os, then the game will be considered a draw.
Implementation of Tic-Tac-Toe game
Rules of the Game
What more can be done in the program?
The program is in not played optimally by both sides because the
moves are chosen randomly. The program can be easily modified so
that both players play optimally (which will fall under the
category of Artificial Intelligence). Also the program can be
modified such that the user himself gives the input (using scanf()
or cin).
Winning Strategy – An Interesting Fact
If both the players play optimally then it is destined that you
will never lose (“although the match can still be drawn”). It
doesn’t matter whether you play first or second.In another ways – “
Two expert players will always draw ”.
Describing a Perfect Game of Tic Tac Toe
To begin, let's start by defining what it means to play a perfect game of tic tac toe:
If I play perfectly, every time I play I will either win the game, or I will draw the game. Furthermore if I play against another perfect player, I will always draw the game.
How might we describe these situations quantitatively? Let's assign a score to the "end game conditions:"
So now we have a situation where we can determine a possible score for any game end state.
Looking at a Brief Example
To apply this, let's take an example from near the end of a game, where it is my turn. I am X. My goal here, obviously, is to maximize my end game score.
If the top of this image represents the state of the game I see when it is my turn, then I have some choices to make, there are three places I can play, one of which clearly results in me wining and earning the 10 points. If I don't make that move, O could very easily win. And I don't want O to win, so my goal here, as the first player, should be to pick the maximum scoring move.
But What About O?
What do we know about O? Well we should assume that O is also playing to win this game, but relative to us, the first player, O wants obviously wants to chose the move that results in the worst score for us, it wants to pick a move that would minimize our ultimate score. Let's look at things from O's perspective, starting with the two other game states from above in which we don't immediately win:
The choice is clear, O would pick any of the moves that result in a score of -10.
// A C++ Program to play tic-tac-toe
#include<bits/stdc++.h>
using namespace std;
#define COMPUTER 1
#define HUMAN 2
#define SIDE 3 // Length of the board
// Computer will move with 'O'
// and human with 'X'
#define COMPUTERMOVE 'O'
#define HUMANMOVE 'X'
// A function to show the current board status
void showBoard(char board[][SIDE])
{
printf("\n\n");
printf("\t\t\t %c | %c | %c \n", board[0][0],
board[0][1], board[0][2]);
printf("\t\t\t--------------\n");
printf("\t\t\t %c | %c | %c \n", board[1][0],
board[1][1], board[1][2]);
printf("\t\t\t--------------\n");
printf("\t\t\t %c | %c | %c \n\n", board[2][0],
board[2][1], board[2][2]);
return;
}
// A function to show the instructions
void showInstructions()
{
printf("\t\t\t Tic-Tac-Toe\n\n");
printf("Choose a cell numbered from 1 to 9 as
below"
" and
play\n\n");
printf("\t\t\t 1 | 2 | 3 \n");
printf("\t\t\t--------------\n");
printf("\t\t\t 4 | 5 | 6 \n");
printf("\t\t\t--------------\n");
printf("\t\t\t 7 | 8 | 9 \n\n");
printf("-\t-\t-\t-\t-\t-\t-\t-\t-\t-\n\n");
return;
}
// A function to initialise the game
void initialise(char board[][SIDE], int moves[])
{
// Initiate the random number generator so that
// the same configuration doesn't arises
srand(time(NULL));
// Initially the board is empty
for (int i=0; i<SIDE; i++)
{
for (int j=0; j<SIDE; j++)
board[i][j] = '
';
}
// Fill the moves with numbers
for (int i=0; i<SIDE*SIDE; i++)
moves[i] = i;
// randomise the moves
random_shuffle(moves, moves + SIDE*SIDE);
return;
}
// A function to declare the winner of the game
void declareWinner(int whoseTurn)
{
if (whoseTurn == COMPUTER)
printf("COMPUTER has won\n");
else
printf("HUMAN has won\n");
return;
}
// A function that returns true if any of the row
// is crossed with the same player's move
bool rowCrossed(char board[][SIDE])
{
for (int i=0; i<SIDE; i++)
{
if (board[i][0] == board[i][1]
&&
board[i][1] ==
board[i][2] &&
board[i][0] != '
')
return
(true);
}
return(false);
}
// A function that returns true if any of the column
// is crossed with the same player's move
bool columnCrossed(char board[][SIDE])
{
for (int i=0; i<SIDE; i++)
{
if (board[0][i] == board[1][i]
&&
board[1][i] ==
board[2][i] &&
board[0][i] != '
')
return
(true);
}
return(false);
}
// A function that returns true if any of the diagonal
// is crossed with the same player's move
bool diagonalCrossed(char board[][SIDE])
{
if (board[0][0] == board[1][1] &&
board[1][1] == board[2][2]
&&
board[0][0] != ' ')
return(true);
if (board[0][2] == board[1][1] &&
board[1][1] == board[2][0]
&&
board[0][2] != ' ')
return(true);
return(false);
}
// A function that returns true if the game is over
// else it returns a false
bool gameOver(char board[][SIDE])
{
return(rowCrossed(board) || columnCrossed(board)
||
diagonalCrossed(board) );
}
// A function to play Tic-Tac-Toe
void playTicTacToe(int whoseTurn)
{
// A 3*3 Tic-Tac-Toe board for playing
char board[SIDE][SIDE];
int moves[SIDE*SIDE];
// Initialise the game
initialise(board, moves);
// Show the instructions before playing
showInstructions();
int moveIndex = 0, x, y;
// Keep playing till the game is over or it is a
draw
while (gameOver(board) == false &&
moveIndex !=
SIDE*SIDE)
{
if (whoseTurn == COMPUTER)
{
x =
moves[moveIndex] / SIDE;
y =
moves[moveIndex] % SIDE;
board[x][y] =
COMPUTERMOVE;
printf("COMPUTER
has put a %c in cell %d\n",
COMPUTERMOVE,
moves[moveIndex]+1);
showBoard(board);
moveIndex
++;
whoseTurn =
HUMAN;
}
else if (whoseTurn == HUMAN)
{
x =
moves[moveIndex] / SIDE;
y =
moves[moveIndex] % SIDE;
board[x][y] =
HUMANMOVE;
printf ("HUMAN
has put a %c in cell %d\n",
HUMANMOVE,
moves[moveIndex]+1);
showBoard(board);
moveIndex
++;
whoseTurn =
COMPUTER;
}
}
// If the game has drawn
if (gameOver(board) == false &&
moveIndex ==
SIDE * SIDE)
printf("It's a draw\n");
else
{
// Toggling the user to declare the
actual
// winner
if (whoseTurn == COMPUTER)
whoseTurn =
HUMAN;
else if (whoseTurn == HUMAN)
whoseTurn =
COMPUTER;
// Declare the winner
declareWinner(whoseTurn);
}
return;
}
// Driver program
int main()
{
// Let us play the game with COMPUTER starting
first
playTicTacToe(COMPUTER);
return (0);
}