#include <iostream>
#include <string>
#include <map>
#include <random>
#include <ctime>
#include <cstdlib>
//This function shows the current grid and where the noughts and crosses are on the board.
void displayGrid(int GRID[3][3], std::map<int, char>& playerPositions)
{
for (int i = 0; i < 3; i++)
{
for (int x = 0; x < 3; x++)
{
std::string outputValue = std::to_string(GRID[i][x]);
if (playerPositions.count(GRID[i][x])) outputValue = playerPositions[GRID[i][x]];
std::cout << outputValue << " ";
}
std::cout << "\n";
}
std::cout << "\n";
}
//Automagically make the next move.
int autoMove(std::map<int, char>& playerPositions)
{
std::srand(std::time(0));
unsigned int randNum = 0;
do { randNum = rand() % 9 + 1;;
} while (playerPositions.count(randNum) && randNum != 0);
return randNum;
}
//This enables the user to make their move and ensures that the position has not been already taken.
void playMove(std::map<int, char>& playerPositions, const char player)
{
int userInput = 0;
do {
std::cout << "[ " << player << " ] player, please make your move: ";
std::cin >> userInput;
//If the user enters 0, make the move for them.
if (userInput == 0)
userInput = autoMove(playerPositions);
} while (playerPositions.count(userInput) && userInput != 0);
playerPositions.insert({ userInput, player });
}
//This function checks if a player has one the game.
std::string checkForWin(int GRID[3][3], std::map<int, char>& playerPositions)
{
//This changes the grid array into a string array so it can compare against the player variable later in the function.
std::string cGRID[3][3];
for (int i = 0; i < 3; i++)
{
for (int x = 0; x < 3; x++)
{
if (playerPositions.count(GRID[i][x])) cGRID[i][x] = playerPositions[GRID[i][x]];
else cGRID[i][x] = std::to_string(GRID[i][x]);
}
}
for (int i = 0; i < 2; i++)
{
std::string player = "O";
if (i == 1)
player = "X";
if (cGRID[0][0] == player && cGRID[0][1] == player && cGRID[0][2] == player) return player;
else if (cGRID[1][0] == player && cGRID[1][1] == player && cGRID[1][2] == player) return player;
else if (cGRID[2][0] == player && cGRID[2][1] == player && cGRID[2][2] == player) return player;
else if (cGRID[0][0] == player && cGRID[1][0] == player && cGRID[2][0] == player) return player;
else if (cGRID[0][1] == player && cGRID[1][1] == player && cGRID[2][1] == player) return player;
else if (cGRID[0][2] == player && cGRID[1][2] == player && cGRID[2][2] == player) return player;
else if (cGRID[0][0] == player && cGRID[1][1] == player && cGRID[2][2] == player) return player;
else if (cGRID[0][2] == player && cGRID[1][1] == player && cGRID[2][0] == player) return player;
}
return "";
}
//This function announces the winner of the game.
void announceWinner(int GRID[3][3], std::map<int, char>& playerPositions, const char winner)
{
system("cls");
displayGrid(GRID, playerPositions);
std::cout << "\n\n" << winner << " Wins the Game!\n\n";
}
int main()
{
//Initializes the grid array and the map to store the player positions.
int GRID[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
std::map<int, char> playerPositions;
//Gives the player 9 moves in total.
for (int i = 0; i < 9; i++)
{
system("cls");
displayGrid(GRID, playerPositions);
//Oscillates between the nought player and the cross player.
char player = 'X';
if (i % 2) player = 'O';
playMove(playerPositions, player);
//Check if anyone has won the game.
char winStatus = checkForWin(GRID, playerPositions)[0];
if (winStatus == 'X' || winStatus == 'O')
{
announceWinner(GRID, playerPositions, winStatus);
return 0;
}
}
std::cout << "\n\nEveryone is a winner!";
}