I recently began learning C++ and would appreciate your review of this simple tic-tac-toe game I made. I know the "3-in-a-row algorithm" is inefficient, but in what other ways could I improve the code? Thanks for the help!
#include <iostream> #include <cstdlib> #include <time.h> #include <string> std::string endText; bool gameOver = false; int w = 18; int h = 18; char numbers[3][3] = { {'1', '2', '3'}, {'4', '5', '6'}, {'7', '8', '9'} }; void drawBoard() { system("cls"); for (int i = 1; i < w; i++) { for (int j = 1; j < h; j++) { if (i % (h / 3) == 0) { std::cout << "# "; } else if (j % (w / 3) == 0) { std::cout << "# "; } else if (i % 3 == 0 && j % 3 == 0) { int column = ((j / 3) - 1) / 2; int row = ((i / 3) - 1) / 2; std::cout << numbers[row][column] << " "; } else { std::cout << " "; } } std::cout << std::endl; } std::cout << std::endl; } void playerInput() { int numInput; bool numFound = false; std::cout << "Select a box to mark: "; std::cin >> numInput; while (std::cin.fail()) { drawBoard(); std::cin.clear(); std::cin.ignore(); std::cout << "Invalid input." << std::endl << std::endl; std::cout << "Select a box to mark: "; std::cin >> numInput; } for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { int charInt = numbers[i][j] - '0'; if (numInput == charInt) { numbers[i][j] = 'X'; drawBoard(); numFound = true; break; } else if (j == 2 && i == 2) { std::cout << "Invalid input." << std::endl << std::endl; playerInput(); } } if (numFound) { break; } } } void compRandInput() { int row = rand() % 3; int column = rand() % 3; if (numbers[row][column] != 'X' && numbers[row][column] != 'O') { numbers[row][column] = 'O'; } else { compRandInput(); } } void checkRow(bool & madeTurn, char check) { for (int i = 0; i < 3; i++) { int symbolCount = 0; int columnNumber = -1; for (int j = 0; j < 3; j++) { if (numbers[i][j] == check) { symbolCount++; } else if (numbers[i][j] != 'X' && numbers[i][j] != 'O') { columnNumber = j; } } if (symbolCount == 2 && columnNumber >= 0) { numbers[i][columnNumber] = 'O'; madeTurn = true; break; } } } void checkColumn(bool & madeTurn, char check) { for (int j = 0; j < 3; j++) { int symbolCount = 0; int rowNumber = -1; for (int i = 0; i < 3; i++) { if (numbers[i][j] == check) { symbolCount++; } else if (numbers[i][j] != 'X' && numbers[i][j] != 'O') { rowNumber = i; } } if (symbolCount == 2 && rowNumber >= 0) { numbers[rowNumber][j] = 'O'; madeTurn = true; break; } } } //Diagonal from top left to bottom right void checkTwoInDiagonalsB(bool & madeTurn, char check, char place) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (numbers[i][j] == check) { if (j == 0 && i == 0) { if (numbers[i + 1][j + 1] == check && numbers[i + 2][j + 2] != 'O' && numbers[i + 2][j + 2] != 'X') { numbers[i + 2][j + 2] = place; madeTurn = true; break; } else if (numbers[i + 2][j + 2] == check && numbers[i + 1][j + 1] != 'O' && numbers[i + 1][j + 1] != 'X') { numbers[i + 1][j + 1] = place; madeTurn = true; break; } } else if (j == 1 && i == 1) { if (numbers[i - 1][j - 1] == check && numbers[i + 1][j + 1] != 'O' && numbers[i + 1][j + 1] != 'X') { numbers[i + 1][j + 1] = place; madeTurn = true; break; } else if (numbers[i + 1][j + 1] == check && numbers[i - 1][j - 1] != 'O' && numbers[i - 1][j - 1] != 'X') { numbers[i - 1][j - 1] = place; madeTurn = true; break; } } else if (j == 2 && i == 2) { if (numbers[i - 2][j - 2] == check && numbers[i - 1][j - 1] != 'O' && numbers[i - 1][j - 1] != 'X') { numbers[i - 1][j - 1] = place; madeTurn = true; break; } else if (numbers[i - 1][j - 1] == check && numbers[i - 2][j - 2] != 'O' && numbers[i - 2][j - 2] != 'X') { numbers[i - 2][j - 2] = place; madeTurn = true; break; } } } } if (madeTurn) { break; } } } //Diagonal from top right to bottom left void checkTwoInDiagonalsF(bool & madeTurn, char check, char place) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (numbers[i][j] == check) { if (j == 2 && i == 0) { if (numbers[i + 1][j - 1] == check && numbers[i + 2][j - 2] != 'O' && numbers[i + 2][j - 2] != 'X') { numbers[i + 2][j - 2] = place; madeTurn = true; break; } else if (numbers[i + 2][j - 2] == check && numbers[i + 1][j - 1] != 'O' && numbers[i + 1][j - 1] != 'X') { numbers[i + 1][j - 1] = place; madeTurn = true; break; } } else if (j == 1 && i == 1) { if (numbers[i - 1][j + 1] == check && numbers[i + 1][j - 1] != 'O' && numbers[i + 1][j - 1] != 'X') { numbers[i + 1][j - 1] = place; madeTurn = true; break; } else if (numbers[i + 1][j - 1] == check && numbers[i - 1][j + 1] != 'O' && numbers[i - 1][j + 1] != 'X') { numbers[i - 1][j + 1] = place; madeTurn = true; break; } } else if (j == 0 && i == 2) { if (numbers[i - 2][j + 2] == check && numbers[i - 1][j + 1] != 'O' && numbers[i - 1][j + 1] != 'X') { numbers[i - 1][j + 1] = place; madeTurn = true; break; } else if (numbers[i - 1][j + 1] == check && numbers[i - 2][j + 2] != 'O' && numbers[i - 2][j + 2] != 'X') { numbers[i - 2][j + 2] = place; madeTurn = true; break; } } } } if (madeTurn) { break; } } } void compInput() { bool turnMade = false; //Computer checks if it can make 3 in a row checkColumn(turnMade, 'O'); if (!turnMade) { checkRow(turnMade, 'O'); } if (!turnMade) { checkTwoInDiagonalsB(turnMade, 'O', 'O'); } if (!turnMade) { checkTwoInDiagonalsF(turnMade, 'O', 'O'); } //Computer checks if the player can be blocked if (!turnMade) { checkColumn(turnMade, 'X'); } if (!turnMade) { checkRow(turnMade, 'X'); } if (!turnMade) { checkTwoInDiagonalsB(turnMade, 'X', 'O'); } if (!turnMade) { checkTwoInDiagonalsF(turnMade, 'X', 'O'); } //Computer makes random move if (!turnMade) { compRandInput(); } //Reset board with new marking drawBoard(); } void checkWin(char symbol) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { //Column if (i == 0 && numbers[i][j] == symbol) { if (numbers[i + 1][j] == symbol && numbers[i + 2][j] == symbol) { gameOver = true; } } //Row if (j == 0 && numbers[i][j] == symbol) { if (numbers[i][j + 1] == symbol && numbers[i][j + 2] == symbol) { gameOver = true; } } //Diagonal if (i == 0 && j == 0 && numbers[i][j] == symbol) { if (numbers[i + 1][j + 1] == symbol && numbers[i + 2][j + 2] == symbol) { gameOver = true; } } if (i == 0 && j == 2 && numbers[i][j] == symbol) { if (numbers[i + 1][j - 1] == symbol && numbers[i + 2][j - 2] == symbol) { gameOver = true; } } } } } void checkCatsGame() { bool catsGame = true; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (numbers[i][j] != 'X' && numbers[i][j] != 'O') { catsGame = false; } } } if (catsGame) { gameOver = true; } } int main() { srand(time(0)); drawBoard(); while (!gameOver) { checkCatsGame(); if (gameOver) { endText = "Cat's game! "; break; } playerInput(); checkWin('X'); if (gameOver) { endText = "You win! "; break; } checkCatsGame(); if (gameOver) { endText = "Cat's game! "; break; } compInput(); checkWin('O'); if (gameOver) { endText = "You lose. "; break; } } std::cout << endText << "Press enter to exit the console." << std::endl; std::cin.get(); std::cin.get(); return 0; }
std::cout. Loads of things to improve. \$\endgroup\$