Created
November 15, 2023 11:39
-
-
Save etherealxx/c4d2210ee73e37d6eca3af5a261b262e to your computer and use it in GitHub Desktop.
Object oriented tic tac toe.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 2023 Jibril Wathon | |
// github.com/etherealxx | |
// Public Domain | |
#include <iostream> | |
#include <vector> | |
using namespace std; | |
class TicTacToeBoard { | |
public: | |
int getSquareValueFromNumber(int squareNumber){ | |
// from left to right, top to bottom, 1 to 9 | |
return squareValues[(squareNumber - 1)]; // because of zero index | |
} | |
// check the owner of a square, and display the mark if any | |
char chr(int squareNumber){ | |
int squareValue = getSquareValueFromNumber(squareNumber); | |
string temp; | |
switch(squareValue){ | |
case 0: | |
// display the square number if there's no mark | |
temp = to_string(squareNumber); | |
break; | |
case 1: | |
temp = "@"; // First player own this square | |
break; | |
case 2: | |
temp = "#"; // Second player own this square | |
break; | |
}; | |
auto printedchar = temp.c_str()[0]; | |
return printedchar; | |
} | |
bool isGameOver(){ | |
if (winningState || drawState) return true; | |
else false; | |
} | |
void placeMark(int squareNumber){ | |
int squareValue = getSquareValueFromNumber(squareNumber); | |
if (squareValue == 0){ | |
// the selected square is now marked by the current player | |
squareValues[(squareNumber - 1)] = playerID; | |
playerID = (playerID == 1) ? 2 : 1; // toggle between player 1 and 2 | |
failedMove = false; | |
} else { // placing mark on occupied square | |
failedMove = true; | |
} | |
} | |
void checkLine(int firstSquare, int secondSquare, int thirdSquare){ | |
if (!winningState) { | |
int square1st_val = getSquareValueFromNumber(firstSquare); | |
int square2nd_val = getSquareValueFromNumber(secondSquare); | |
int square3rd_val = getSquareValueFromNumber(thirdSquare); | |
if (square1st_val == square2nd_val | |
&& square2nd_val == square3rd_val | |
&& (square1st_val +square2nd_val + square3rd_val) != 0){ // it's not an empty row | |
winningState = true; | |
winningSquares = {firstSquare, secondSquare, thirdSquare}; | |
} | |
} | |
} | |
void checkWinner(){ | |
checkLine(1,2,3); // top row | |
checkLine(4,5,6); // middle row | |
checkLine(7,8,9); // bottom row | |
checkLine(1,4,7); // left column | |
checkLine(2,5,8); // middle column | |
checkLine(3,6,9); // right column | |
checkLine(1,5,9); // diagonal top-left to bottom-right | |
checkLine(3,5,7); // diagonal top-right to bottom-left | |
} | |
void checkDraw(){ | |
if (!winningState){ | |
int checkDraw = 1; | |
for (int v: squareValues) { // iterate on every square | |
// draw in tictactoe will happen if the board is full but no line | |
// if one of the square isn't marked, then the board is not full | |
if (v == 0){ | |
checkDraw = 0; | |
break; | |
} | |
} | |
if (checkDraw == 1) drawState = true; | |
} | |
} | |
void printWinner(){ | |
if (winningState){ | |
cout << endl << "Player " << ((playerID == 1) ? 2 : 1) | |
<< " is the winner!" << endl; | |
printf("A straight line at square %d, %d, and %d!\n", | |
winningSquares[0], winningSquares[1], winningSquares[2]); | |
} else if (drawState){ | |
cout << endl << "No more space left, it's a draw!" << endl << endl; | |
} | |
} | |
void printCheckPlayer(){ | |
cout << "Currently it's Player " << playerID << " turn!" << endl; | |
} | |
void printAdditionalInfo(){ | |
if (failedMove){ | |
cout << "That space is already occupied, choose another!" << endl; | |
failedMove = false; | |
} | |
} | |
void printBoard(){ | |
cout << "|||| || || || ||||" << endl; | |
printf("|||| %c %c %c ||||\n", chr(1), chr(2), chr(3)); | |
printf("|||| %c %c %c ||||\n", chr(4), chr(5), chr(6)); | |
printf("|||| %c %c %c ||||\n", chr(7), chr(8), chr(9)); | |
cout << "|||| || || || ||||" << endl; | |
} | |
private: | |
int playerID = 1; | |
bool failedMove = false; | |
bool winningState = false; | |
bool drawState = false; | |
// the number is player who marked the square currently | |
// 1 for player 1 (@), 2 for player 2 (#) | |
// 0 means no one marked the square yet | |
vector<int> squareValues = {0,0,0,0,0,0,0,0,0}; | |
// list of squares that make a line for the winner | |
vector<int> winningSquares = {0,0,0}; | |
}; | |
int main(){ | |
int markNumber; | |
TicTacToeBoard board; | |
while (1 > 0) { // infinite loop | |
system("cls"); // clearing the console | |
cout << "Ether's TicTacToe" << endl << endl; | |
cout << "Player 1: @ / Player 2: #" << endl << endl; | |
board.printBoard(); | |
if (!board.isGameOver()) { | |
board.printCheckPlayer(); | |
board.printAdditionalInfo(); // tell if the player fails to mark before | |
cout << "Type a number to put your mark there: "; | |
cin >> markNumber; | |
board.placeMark(markNumber); | |
board.checkWinner(); | |
board.checkDraw(); | |
} else { | |
board.printWinner(); | |
break; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment