I just finished the TripleX tutorial. I’ve had a bit of C++ experience in the past, and plenty of experience with python, so I wanted to push myself to create something more challenging. I made a simple noughts and crosses game that even has another AI player! I’m pretty happy with how it turned out.
Let me know what you think!
#include <iostream>
#include <list>
#include <string>
#include <tuple>
#include <ctime>
using namespace std;
void PrintGame(string game[], string caps[]) {
// Print the game based on the values in the game array
cout << " 1 2 3\n";
for (int i = 0; i < 3; i++) { // starts a new row
cout << " " << caps[i] << " |";
for (int j = 0; j < 3; j++) { // starts a new column
cout << " " << game[j+i*3] << " |";
}
cout << "\n";
}
}
string * UpdateValue(string game[], int index, string value) {
// changes a value in the game array to the desired symbol (either X or O)
static string new_game[9];
for (int i = 0; i < 9; i++) {
new_game[i] = game[i];
}
new_game[index] = value;
return new_game;
}
int GetIndex(string letter, string caps[]) {
// gets the numerical representation of a letter that is entered
for (int i = 0; i < 3; i++) {
if (letter == caps[i]) {
return i;
}
}
return -1;
}
int ParsePosition(tuple<string, int> position, string caps[]) {
// turns a (x, y) coordinate that is entered into an index on the game array
int row = GetIndex(get<0>(position), caps);
int column = get<1>(position) - 1;
return column + row * 3;
}
bool CheckWin(string game[], string team) {
// checks if there is a 3 in a row for the specified team. I know this is very inefficient XD
if (game[0] == team && game[3] == team && game[6] == team) {
return true;
} else if (game[1] == team && game[4] == team && game[7] == team) {
return true;
} else if (game[2] == team && game[5] == team && game[8] == team) {
return true;
} else if (game[0] == team && game[1] == team && game[2] == team) {
return true;
} else if (game[3] == team && game[4] == team && game[5] == team) {
return true;
} else if (game[6] == team && game[7] == team && game[8] == team) {
return true;
} else if (game[0] == team && game[4] == team && game[8] == team) {
return true;
} else if (game[2] == team && game[4] == team && game[6] == team) {
return true;
} else {
return false;
}
}
int GenerateAiMove(string game[]) {
// chooses a random position to place the AIs O. If that space has already been chosen, it rolls again
int move = rand() % 9;
if (game[move] == "X" || game[move] == "O") {
return GenerateAiMove(game);
}
return move;
}
int main() {
srand(time(NULL));
string Capitals[] {"A", "B", "C"};
string Game[] {"-", "-", "-", "-", "-", "-", "-", "-", "-"};
cout << "Welcome to noughts and crosses!\n";
PrintGame(Game, Capitals);
while (true) {
cout << endl;
cout << "Where would you like to place an X: ";
tuple<string, int> Position;
string letter;
int number;
cin >> letter;
cin >> number;
Position = make_tuple(letter, number);
int index = ParsePosition(Position, Capitals);
if (Game[index] == "X" || Game[index] == "O") { // if there is already something there
cout << "\nInvalid input\n";
} else {
string *g;
g = UpdateValue(Game, index, "X");
for (int i = 0; i < 9; i++)
{
Game[i] = *(g + i); // reassigns the game array
}
if (CheckWin(Game, "X") == true) {
cout << "You win!!!";
break;
}
index = GenerateAiMove(Game);
g = UpdateValue(Game, index, "O");
for (int i = 0; i < 9; i++)
{
Game[i] = *(g + i);
}
}
PrintGame(Game, Capitals);
if (CheckWin(Game, "O") == true) {
cout << "You lose :(";
break;
}
}
return 0;
}