Skip to content

Instantly share code, notes, and snippets.

@etherealxx
Created November 15, 2023 11:39
Show Gist options
  • Save etherealxx/c4d2210ee73e37d6eca3af5a261b262e to your computer and use it in GitHub Desktop.
Save etherealxx/c4d2210ee73e37d6eca3af5a261b262e to your computer and use it in GitHub Desktop.
Object oriented tic tac toe.
// 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