Tic Tac Toe
unknown
c_cpp
2 months ago
6.6 kB
2
Indexable
Never
/* * 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; }