nord vpnnord vpn
Ad

Tic Tac Toe

mail@pastecode.io avatar
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;
}

nord vpnnord vpn
Ad