Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Use C++ Tic-Tac-Toe, also called X\'s and O\'s, Noughts and Crosses, and X and 0

ID: 3589725 • Letter: U

Question

Use C++

Tic-Tac-Toe, also called X's and O's, Noughts and Crosses, and X and 0 is a simple game played on a 3x3 grid, referred to as the board. The grid starts epty, and the two players take turns placing their respective symbols, X and O, on an empty grid cell, referred to as making a move The first player to get a straight line of three symbols wins. If all the cells on the board are filled and neither player has a line of3 symbols, the game is a tie. Lines may be horizontal, vertical, or dia gonal You will implement a Board class to represent the 3x3 grid. This class will ha ve functions to determine which symbol if any, is in a cell, to place a symbol in a cell, to determine the winner, if any so far, and to print the board to standard output. The board should appear as below You will implement an abstract Player class to determine the player's moves. The Player class should store which symbol it will place and contain a pure virtual function to determine the Player's next move. This function will be overridden by the subclasses of Player You will implement PlayerHuman as a subclass of Player. When this subclass is to choose a move, it should print out the curent board and ask the user for the row and co lumn to place a symbol This class should detect if the user enters an invalid location either because it is not in the grid or it already has a symbol and if the location is invalid, ask the user again. You will implement PlayerRandom as a subclass of Player. When this subclass is to choose a move, it sho uld re turn a random position in the grid that does not yet have a symbol. You will implement a program to play the Tic Tac Toe game. The program should begin by asking the user if each team should be controlled by a human or by the conputer. The program should then use dynamic memory allocation to create instances ofthe appropriate subclasses of Player. These must be stored with pointers oftype Player*·The first team should place X symbols, while the second team should place O symbols. The program should then alternate asking the players for moves until one player wins, or the board is full and the game is a tie After the game is over, the program should print the winner and the board and exit.

Explanation / Answer

Solution:

/* game.h header file for a class that represents a TicTacToe board */

#include <iostream>

using namespace std;

const char human = 'X';
const char ai = 'O';

enum Player { HUMAN, AI };

struct Move {
int x;
int y;
};

class Game {
char board[3][3];

public:
Game();

void printBoard();
// Prints the board pretty-ly

bool gameOver();
// Returns true if a winner has been found or there are no empty spaces

bool checkWin(Player player);
// Checks for a win

void play();
// Primary game driver, loops through turn-by-turn until there's
// a winner or full game board (draw)

void getHumanMove();
// Takes in values from the input stream and places them on the board
// if valid. Expects input in coordinate notation, ex (1,3)

int score();
// Function to score game board states based on their outcome
// Returns 10 for human win, -10 for AI win, 0 for draw

Move minimax(char AIboard[3][3]);
// Returns the best AI move's x, y coords via the minimax algorithm

int minSearch(char AIboard[3][3]);
// minimax helper fn for finding the next move for AI player, chooses the
// move with the least possible score

int maxSearch(char AIboard[3][3]);
// minimax helper fn for finding the next move for human player, chooses
// the move with the least possible score
};

/* game.cpp implementation file for the TicTacToe class */

#include <iostream>
#include <sstream>
#include <iomanip>
#include "game.h"

using namespace std;

Game::Game() {
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
board[i][j] = '-';
}
}
}

void Game::printBoard() {
cout << "-------------------";
for(int i = 0; i < 3; i++) {
cout << ' ' << "|";
for(int j = 0; j < 3; j++) {
cout << setw(3) << board[i][j] << setw(3) << " |";
}
}
cout << ' ' << "-------------------" << ' ';
}

bool Game::gameOver() {
if(checkWin(HUMAN)) return true;
else if(checkWin(AI)) return true;

bool emptySpace = false;
for(int i = 0; i < 3; i++) {
if(board[i][0] == '-' || board[i][1] == '-' || board[i][2] == '-')
emptySpace = true;
}
return !emptySpace;
}

bool Game::checkWin(Player player) {
char playerChar;
if(player == HUMAN) playerChar = human;
else playerChar = ai;

for(int i = 0; i < 3; i++) {
// Check horizontals
if(board[i][0] == playerChar && board[i][1] == playerChar
&& board[i][2] == playerChar)
return true;

// Check verticals
if(board[0][i] == playerChar && board[1][i] == playerChar
&& board[2][i] == playerChar)
return true;
}

// Check diagonals
if (board[0][0] == playerChar && board[1][1] == playerChar
&& board[2][2] == playerChar) {
return true;
} else if (board[0][2] == playerChar && board[1][1] == playerChar
&& board[2][0] == playerChar) {
return true;
}

return false;
}

int Game::score() {
if(checkWin(HUMAN)) { return 10; }
else if(checkWin(AI)) { return -10; }
return 0; // draw
}

Move Game::minimax(char AIboard[3][3]) {
int bestMoveScore = 100; // -100 is arbitrary
Move bestMove;

for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(AIboard[i][j] == '-') {
AIboard[i][j] = ai;
int tempMoveScore = maxSearch(AIboard);
if(tempMoveScore <= bestMoveScore) {
bestMoveScore = tempMoveScore;
bestMove.x = i;
bestMove.y = j;
}
AIboard[i][j] = '-';
}
}
}

return bestMove;
}

int Game::maxSearch(char AIboard[3][3]) {
if(gameOver()) return score();
Move bestMove;

int bestMoveScore = -1000;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(AIboard[i][j] == '-') {
AIboard[i][j] = human;
int tempMoveScore = minSearch(AIboard);
if(tempMoveScore >= bestMoveScore) {
bestMoveScore = tempMoveScore;
bestMove.x = i;
bestMove.y = j;
}
AIboard[i][j] = '-';
}
}
}

return bestMoveScore;
}

int Game::minSearch(char AIboard[3][3]) {
if(gameOver()) return score();
Move bestMove;

int bestMoveScore = 1000;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(AIboard[i][j] == '-') {
AIboard[i][j] = ai;
int tempMove = maxSearch(AIboard);
if(tempMove <= bestMoveScore) {
bestMoveScore = tempMove;
bestMove.x = i;
bestMove.y = j;
}
AIboard[i][j] = '-';
}
}
}

return bestMoveScore;
}

void Game::getHumanMove() {
int x, y = -1; // arbitrary assignment to init loop
while(x < 0 || x > 2 || y < 0 || y > 2) {
// Loop until a valid move is entered
cout << "Enter your move in coordinate form, ex: (1,3)." << endl;
cout << "Your Move: ";
char c;
string restofline;
cin >> c >> c;
x = c - '0' - 1;
cin >> c >> c;
y = c - '0' - 1;
getline(cin, restofline); // get garbage chars after move
}
board[x][y] = human;
}

void Game::play() {
int turn = 0;
printBoard();
while(!checkWin(HUMAN) && !checkWin(AI) && !gameOver()) {
// human move
if(turn % 2 == 0) {
getHumanMove();
if(checkWin(HUMAN)) cout << "Human Player Wins" << endl;
turn++;
printBoard();
} else {
cout << endl << "Computer Player Move:" << endl;
Move AImove = minimax(board);
board[AImove.x][AImove.y] = ai;
if(checkWin(AI)) cout << "Computer Player Wins" << endl;
turn++;
printBoard();
}
}
}

/* play.cpp code that uses the TicTacToe class to play the game */

#include <iostream>
#include "game.h"

using namespace std;

int main() {
Game tictactoe;

tictactoe.play();

return 0;
}

I hope this helps if you find any problem. Please comment below. Don't forget to give a thumbs up if you liked it. :)

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote