Tic Tac Toe
unknown
c_cpp
2 years ago
6.6 kB
30
Indexable
/*
* TIC-TAC-TOE GAME USING VECTORS *(AND NCURSES LIBRARY FOR GUI)
* Author: Edewor Righteous
* Date: 11/10/023 12:44 PM
* Last Modified: 11/10/023 12:48 PM
* Website: https://edewor.dev (under development)
*/
#include <iostream>
#include <string>
#include <cstdlib>
#include <vector>
#include <algorithm>
#define PLAYER_1_INT 1
#define PLAYER_2_INT 2
#define CELL_TOTAL_INT 9
#define MIN_CELL_WIN_INT 3
using namespace std;
vector<char> cell {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
vector<int> plrc1;
vector<int> plrc2;
vector<int> occl;
vector<vector<int>> winmv {
{1, 2, 3}, {4, 5, 6},
{7, 8, 9}, {1, 4, 7},
{2, 5, 8}, {3, 6, 9},
{1, 5, 9}, {3, 5, 7}
};
int idx, counter = 0, player = PLAYER_1_INT;
bool isgmovr = false, isinputv = false;
char marker;
string ipt;
void dwboard(char cell);
void start();
void vinput();
void chkwin();
void restart();
vector<vector<int>> get_winmv(vector<int> plrc);
int main() {
system("cls");
start();
return 0;
}
// ***** Draw board with loop... You have thought about the logic and how to use a variable to store each character used in the game board to represent objects and draw the board with those variable in a loop... *****//
void dwboard(vector<char> cell) {
for(int n : cell) {
cout << n;
}
cout << endl;
cout << "___________________________" << endl << endl;
cout << " TIC TAC TOE GAME" << endl;
cout << "___________________________" << endl << endl << endl;
cout << " | | " << endl;
cout << " " << cell.at(0) << " | " << cell.at(1) << " | " << cell.at(2) << " " << endl;
cout << " | | " << endl;
cout << "--------+---------+--------" << endl;
cout << " | | " << endl;
cout << " " << cell.at(3) << " | " << cell.at(4) << " | " << cell.at(5) << " " << endl;
cout << " | | " << endl;
cout << "--------+---------+--------" << endl;
cout << " | | " << endl;
cout << " " << cell.at(6) << " | " << cell.at(7) << " | " << cell.at(8) << " " << endl;
cout << " | | " << endl << endl;
}
void start() {
do {
system("cls");
dwboard(cell);
// accept input if the total number of cells entered by both players is not greater than 9
if(counter < CELL_TOTAL_INT) {
vinput();
occl.push_back(idx);
// store the valid cell numbers entered by each players
if(player == PLAYER_1_INT) {
plrc1.push_back(idx);
} else {
plrc2.push_back(idx);
}
marker = (player == PLAYER_1_INT) ? 'X' : 'O';
cell[--idx] = marker;
// check if a player has won after entering 3 valid cells
chkwin();
player = (player == PLAYER_1_INT) ? PLAYER_2_INT : PLAYER_1_INT;
} else {
cout << "\nGame is a Draw..." << endl;
isgmovr = true;
}
} while(!isgmovr);
if(isgmovr == true) {
char restart_ipt;
counter = 0;
idx = 0;
player = PLAYER_1_INT;
isgmovr = false;
isinputv = false;
plrc1.clear();
plrc2.clear();
occl.clear();
cell.clear();
for(int i = 0; i < CELL_TOTAL_INT; i++) {
cell.push_back(++counter);
}
counter = 0;
cout << "\n\n> Restart? (y/n) ";
cin >> restart_ipt;
if(restart_ipt == 'y') {
start();
} else {
exit(0);
}
}
}
void vinput() {
isinputv = false;
while(!isinputv) {
try {
cout << "> Player " << player << " turn. Choose a cell: ";
cin >> ipt;
// <string>::stoi(s) converts the string input to an integer value
idx = stoi(ipt);
// validate input: valid input is an integer starting from 1 to 9
if(idx < 1 || idx > 9) {
cout << "!! Invalid cell... Cell MUST be from 1 to 9.\n\n";
} else if(find(occl.begin(), occl.end(), idx) != occl.end()) {
cout << "!! Cell " << idx << " taken... Choose another cell.\n\n";
} else {
counter++;
isinputv = true;
}
} catch(...) {
cout << "!! Invalid cell... Cell MUST be from 1 to 9.\n\n";
}
}
}
void chkwin() {
vector<int> plrc;
vector<vector<int>> plrwm;
// only check if any player has won when the player has entered at least 3 cells
if(plrc1.size() >= MIN_CELL_WIN_INT || plrc2.size() >= MIN_CELL_WIN_INT) {
plrc = (player == PLAYER_1_INT) ? plrc1 : plrc2;
sort(plrc.begin(), plrc.end());
/*
checks if a player has won if the player has entered at least 4 cells or when the player has entered exactly 3 cells
*/
if(plrc.size() > MIN_CELL_WIN_INT) {
plrwm = get_winmv(plrc);
/*
loops through all the correct win moves in the game and matches them with all the possible win moves a player can have when the player has entered at least 4 cells
*/
for(vector<int> mv : winmv) {
for(vector<int> pmv : plrwm) {
if(pmv == mv) {
cout << "** Player " << player << " wins... **" << endl;
isgmovr = true;
}
}
}
} else {
/*
loops through all the actual win moves in the game and matches them with the player move to win on entering a 3rd cell
*/
for(vector<int> m : winmv) {
if(plrc == m) {
cout << "** Player " << player << " wins... **" << endl;
isgmovr = true;
}
}
}
}
}
vector<vector<int>> get_winmv(vector<int> plrc) {
vector<int> temp;
vector<vector<int>> winmv;
int pos1, pos2, pos3;
const int CELL_SIZE = plrc.size();
pos1 = pos2 = pos3 = 0;
// finds the permutation of win moves of the total cells entered by the player
//** if the player has entered exactly 4 cells
if(CELL_SIZE == MIN_CELL_WIN_INT + 1) {
for(int i = 0; i < CELL_SIZE; i++) {
if(i == 0 || i == 2) {
pos2++;
if(i == 0) {
pos3 += 2;
}
} else if(i == 1) {
pos3++;
} else {
pos1++;
}
temp.insert(temp.begin(), {plrc.at(pos1), plrc.at(pos2), plrc.at(pos3)});
winmv.insert(winmv.begin(), temp);
temp.clear();
}
}
//** if the player has entered exactly 5 cells
else if(CELL_SIZE == MIN_CELL_WIN_INT + 2) {
for(int i = 0; i < CELL_SIZE; i++) {
if(i == 0 || i == 3 || i == 5) {
pos2++;
if(i == 0) {
pos3 += 2;
} else if(i == 3) {
pos1++;
pos3--;
} else {
pos1++;
}
} else if(i == 1 || i == 2 || i == 4) {
pos3++;
}
temp.insert(temp.begin(), {plrc.at(pos1), plrc.at(pos2), plrc.at(pos3)});
winmv.insert(winmv.begin(), temp);
temp.clear();
}
}
return winmv;
}Editor is loading...