Upload files to "code"

This commit is contained in:
2026-04-13 12:28:36 +00:00
parent 1b73a1c25a
commit 41baf263f2
3 changed files with 704 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
matin,45,ali,18,matin,Thu Jan 1 22:32:39 2026
matin,15,Bot,20,Bot,Tue Jan 6 11:10:18 2026
+702
View File
@@ -0,0 +1,702 @@
// ==============================================Importing Libraries==============================
#include <iostream>
#include <string>
#include <iomanip> // cout
#include <conio.h> // inputs
#include <cstdlib> // random
#include <ctime> // time
#include <fstream> // file
#include <windows.h> // delay
using namespace std;
//==============================================Structures & Global variables=======================================
int board_size = 8;
// --- ANSI Color Codes ---
const string RESET = "\033[0m";
const string BLACK_TXT = "\033[30m"; // black text
const string RED_TXT = "\033[31m"; // red text
const string GREEN_TXT = "\033[32m"; // green text
const string YELLOW_TXT = "\033[33m"; // yellow text
const string WHITE_TXT = "\033[97m"; // white text
const string BG_GREEN = "\033[42m"; // green background
const string BG_YELLOW = "\033[43m"; // yellow background
const string BG_DEFAULT = "\033[49m"; // default background
const string CYAN_TXT = "\033[36m";
const string MAGENTA_TXT = "\033[35m";
const string BOLD = "\033[1m";
const string MARGIN = " ";
struct ColorChanger{
int startI, startJ;
int endI, endJ;
int directionX, directionY;
};
struct Game{
int **board;
int turn;
string player1name;
string player2name;
bool isSinglePlayerMode;
int black_count;
int white_count;
ColorChanger color_changer;
};
struct CellState{
const int empty = 0, black = 1, white = 2;
};
Game game;
CellState cell_state;
int curserI, curserJ;
/*
history file format:
player1name,player1discs,player2name,player2discs,winner,gamedate
*/
// crowling through a cell's nieghbors
int IndX[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
int IndY[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
//=============================================Function prototypes===============================
void ShowBoard(int i, int j);
void ShowMenu();
void GameMode(); // single player mode or two player mode
void PlayGame();
void PlaceCell(int i, int j);
void SwitchTurn();
bool CheckValidTurn(int turn);
bool CheckValidMove(int i, int j, bool change_color);
void ChangeColor();
void ShowHistory();
void BotMove();
void SelectBoardSize();
void AllocateBoard();
void DeallocateBoard();
//=============================================Main Function=====================================
int main(){
system("chcp 65001"); // for showing the unicode characters in terminal
srand(static_cast<unsigned int>(time(nullptr)));
// preparing board for the start of the game
game.board = nullptr;
ShowMenu();
return 0;
}
//============================================Functions=========================================
// THE GAME
void PlayGame(){
// recieving names and declaring turns
system("cls");
cout << "\n\n";
cout << MARGIN << BOLD << CYAN_TXT << u8"╔══════════════════════════════════╗" << RESET << endl;
cout << MARGIN << BOLD << CYAN_TXT << u8"║ GAME SETUP ║" << RESET << endl;
cout << MARGIN << BOLD << CYAN_TXT << u8"╚══════════════════════════════════╝" << RESET << endl;
cout << endl;
if(!game.isSinglePlayerMode){ // two player mode
cout << MARGIN << YELLOW_TXT << "Player 1 Name (Black): " << CYAN_TXT;
cin >> game.player1name;
cout << RESET << "\n";
cout << MARGIN << YELLOW_TXT << "Player 2 Name (White): " << CYAN_TXT;
cin >> game.player2name;
cout << RESET;
}
else{
cout << MARGIN << YELLOW_TXT << "Enter Your Name: " << CYAN_TXT;
cin >> game.player1name;
cout << RESET;
game.player2name = "Bot";
}
game.turn = 1;
// moving through the board
bool running = true;
int opposite_turn;
while(running){
ShowBoard(curserI, curserJ);
if(game.isSinglePlayerMode && game.turn == 2){
Sleep(500); // a delay for palyer to see bot's move
BotMove();
SwitchTurn();
}
else {
char pressed_key = getch();
switch(pressed_key)
{
case 'w': case 'W':
if(curserI > 0) curserI--;
break;
case 's': case 'S':
if(curserI < board_size - 1) curserI++;
break;
case 'd': case 'D':
if(curserJ < board_size - 1) curserJ++;
break;
case 'a': case 'A':
if(curserJ > 0) curserJ--;
break;
case '\r': // Enter
if(CheckValidMove(curserI, curserJ, true)){
PlaceCell(curserI, curserJ);
SwitchTurn();
}
else{
cout << "\a";
}
break;
case ' ': // emergency exit
running = false;
// DeallocateBoard();
break;
}
}
if(!running) break;
// end of game or switch turn because of no valid move
opposite_turn = (game.turn == 1 ? 2 : 1);
bool currentHasMove = CheckValidTurn(game.turn);
bool opponentHasMove = CheckValidTurn(opposite_turn);
if(!currentHasMove && opponentHasMove){
cout << "\nNo Valid Moves for " << (game.turn == 1 ? game.player1name : game.player2name) << "! Passing turn...";
getch();
SwitchTurn();
}
else if(!currentHasMove && !opponentHasMove){ // end of game
ShowBoard(-1, -1);
time_t now = time(0);
string winnerName = "Tie";
if(game.black_count > game.white_count) winnerName = game.player1name;
else if(game.black_count < game.white_count) winnerName = game.player2name;
cout << "\n========================\n";
if (winnerName == "Tie") cout << " TIE GAME!";
else cout << " WINNER: " << winnerName;
cout << "\n========================\n";
ofstream history("history.txt", ios::app);
if(history.is_open()){
// AI generated
char* dt = ctime(&now); // converting datetime to string
// deleting \n from the end of the time string
string dateStr = string(dt);
if (!dateStr.empty() && dateStr[dateStr.length()-1] == '\n') {
dateStr.erase(dateStr.length()-1);
}
//...
history << game.player1name << "," << game.black_count << ","
<< game.player2name << "," << game.white_count << ","
<< winnerName << ","
<< dateStr << endl;
history.close();
cout << "Game saved to history." << endl;
} else {
cout << "Error saving history!" << endl;
}
cout << "Press any key to exit...";
getch();
running = false;
// DeallocateBoard();
// preparing board for the start of the game
for(int i = 0; i < board_size; i++){
for(int j = 0; j < board_size; j++){
game.board[i][j] = cell_state.empty;
}
}
game.board[3][3] = cell_state.white;
game.board[4][4] = cell_state.white;
game.board[3][4] = cell_state.black;
game.board[4][3] = cell_state.black;
}
}
DeallocateBoard();
ShowMenu();
}
// selecting size of the board (6 or 8 or 10)
void SelectBoardSize(){
while(true){
system("cls");
cout << "\n\n";
cout << MARGIN << BOLD << CYAN_TXT << u8"╔══════════════════════════════════╗" << RESET <<endl;
cout << MARGIN << BOLD << CYAN_TXT << u8"║ SELECT BOARD SIZE ║" << RESET <<endl;
cout << MARGIN << BOLD << CYAN_TXT << u8"╚══════════════════════════════════╝" << RESET <<endl;
cout << endl;
cout << MARGIN << YELLOW_TXT << "[1]" << WHITE_TXT << " Small (6 x 6)" << endl;
cout << MARGIN << YELLOW_TXT << "[2]" << WHITE_TXT << " Normal (8 x 8)" << endl;
cout << MARGIN << YELLOW_TXT << "[3]" << WHITE_TXT << " Large (10 x 10)" << endl;
cout << endl << MARGIN << "Select size: ";
char choice = getch();
if(choice == '1'){
board_size = 6;
break;
}
else if(choice == '2'){
board_size = 8;
break;
}
else if(choice == '3'){
board_size = 10;
break;
}
else cout << '\a';
}
}
void AllocateBoard(){
game.board = new int*[board_size];
for(int i = 0; i < board_size; i++){
game.board[i] = new int[board_size];
}
for(int i = 0; i < board_size; i++){
for(int j = 0; j < board_size; j++){
game.board[i][j] = cell_state.empty;
}
}
int mid = board_size / 2;
game.board[mid-1][mid-1] = cell_state.white;
game.board[mid][mid] = cell_state.white;
game.board[mid-1][mid] = cell_state.black;
game.board[mid][mid-1] = cell_state.black;
}
void DeallocateBoard(){
if(game.board != nullptr) {
for(int i = 0; i < board_size; i++){
delete[] game.board[i];
}
delete[] game.board;
game.board = nullptr;
}
}
// drawing the game board
void ShowBoard(int i = -1, int j = -1){ // curser is the selected cell by keyboard
system("cls");
game.black_count = 0;
game.white_count = 0;
bool show_hint = (!game.isSinglePlayerMode) || (game.turn == 1);
cout << "\n A B C D E F G H\n";
for(int i = 0; i < board_size; i++){
if(i+1 != 10) cout << " " << (i + 1) << " ";
else cout << " " << (i + 1) << " ";
for(int j = 0; j < board_size; j++){
if(curserI == i && curserJ == j){
cout << BG_YELLOW << BLACK_TXT << u8" \u25A0 " << RESET; // full square
continue;
}
if(game.board[i][j] == cell_state.empty && !CheckValidMove(i, j, false)){
cout << BG_GREEN << BLACK_TXT << u8" \u25A1 " << RESET; // empty square
}
else if(game.board[i][j] == cell_state.black){
cout << BG_GREEN << BLACK_TXT << u8" \u25CF " << RESET; // black circle
game.black_count++;
}
else if(game.board[i][j] == cell_state.white){
cout << BG_GREEN << WHITE_TXT << u8" \u25CF " << RESET; // white circle
game.white_count++;
}
else if(show_hint && game.board[i][j] == cell_state.empty && CheckValidMove(i, j, false)){
cout << BG_GREEN << RED_TXT << " * " << RESET;
}
}
cout << RESET << endl;
}
cout << RESET << "\n";
cout << MARGIN << CYAN_TXT << u8"══════════════════════════════════" << RESET << endl;
string p2name = (game.isSinglePlayerMode ? "Bot" : game.player2name);
cout << MARGIN << BLACK_TXT << RESET << game.player1name << ": "
<< BOLD << game.black_count << RESET;
cout << " ";
cout << WHITE_TXT << RESET << p2name << ": "
<< BOLD << game.white_count << RESET << endl;
cout << endl;
cout << MARGIN << " Turn: ";
if(game.turn == 1) {
cout << BG_YELLOW << BLACK_TXT << " " << u8"\u25CF " << game.player1name << " " << RESET;
}
else {
cout << BG_YELLOW << BLACK_TXT << " " << u8"\u25CB " << p2name << " " << RESET;
}
cout << endl;
}
// menu
void ShowMenu(){
system("cls");
cout << "\n\n";
cout << MARGIN << BOLD << CYAN_TXT << u8"╔══════════════════════════════════╗" << RESET << endl;
cout << MARGIN << BOLD << CYAN_TXT << u8"║ OTHELLO GAME ║" << RESET << endl;
cout << MARGIN << BOLD << CYAN_TXT << u8"╚══════════════════════════════════╝" << RESET << endl;
cout << endl;
cout << MARGIN << YELLOW_TXT << "[1]" << WHITE_TXT << " Start New Game" << endl;
cout << MARGIN << " " << GREEN_TXT << "Play vs Bot or Friend" << RESET << "\n\n";
cout << MARGIN << YELLOW_TXT << "[2]" << WHITE_TXT << " How to Play (Help)" << endl;
cout << MARGIN << " " << GREEN_TXT << "Learn the rules" << RESET << "\n\n";
cout << MARGIN << YELLOW_TXT << "[3]" << WHITE_TXT << " Game History" << endl;
cout << MARGIN << " " << GREEN_TXT << "View past match results" << RESET << "\n\n";
cout << MARGIN << YELLOW_TXT << "[4]" << WHITE_TXT << " Exit" << endl;
cout << endl << MARGIN << "Select an option: ";
char choice = getch();
char temp;
switch(choice)
{
case '1': // new game
SelectBoardSize();
AllocateBoard();
GameMode();
break;
case '2': // help
system("cls");
cout << "\n\n";
cout << MARGIN << BOLD << MAGENTA_TXT << "=== HOW TO PLAY OTHELLO ===" << RESET << "\n\n";
cout << MARGIN << "Othello is a strategy board game for two players." << endl;
cout << MARGIN << "Played on an 8x8 uncheckered board." << endl << endl;
cout << MARGIN << YELLOW_TXT << "1. Objective:" << RESET << endl;
cout << MARGIN << " Have the majority of discs in your color at the end." << endl << endl;
cout << MARGIN << YELLOW_TXT << "2. The Rules:" << RESET << endl;
cout << MARGIN << " - Black always moves first." << endl;
cout << MARGIN << " - Place a disc to 'bracket' opponent's discs." << endl;
cout << MARGIN << " - Bracketing can be horizontal, vertical, or diagonal." << endl;
cout << MARGIN << " - Bracketed discs are flipped to your color." << endl << endl;
cout << MARGIN << YELLOW_TXT << "3. Winning:" << RESET << endl;
cout << MARGIN << " The game ends when the board is full or no valid moves remain." << endl;
cout << MARGIN << " The player with the most discs wins." << endl;
cout << "\n\n" << MARGIN << BG_GREEN << BLACK_TXT << " Press any key to return... " << RESET;
getch();
ShowMenu();
break;
case '3': // History
ShowHistory();
break;
case '4': // exit
return; // closing terminal
break;
default:
cout << "\a";
ShowMenu();
break;
}
}
// choosing which game mode we are gonna have
void GameMode(){
system("cls");
cout << "\n\n";
cout << MARGIN << BOLD << CYAN_TXT << u8"╔══════════════════════════════════╗" << RESET << endl;
cout << MARGIN << BOLD << CYAN_TXT << u8"║ SELECT GAME MODE ║" << RESET << endl;
cout << MARGIN << BOLD << CYAN_TXT << u8"╚══════════════════════════════════╝" << RESET << endl;
cout << endl;
cout << MARGIN << YELLOW_TXT << "[1]" << WHITE_TXT << " Single Player" << endl;
cout << MARGIN << " " << GREEN_TXT << "Challenge the AI Bot" << RESET << "\n\n";
cout << MARGIN << YELLOW_TXT << "[2]" << WHITE_TXT << " Two Players" << endl;
cout << MARGIN << " " << GREEN_TXT << "Play with a friend on this device" << RESET << "\n\n";
cout << MARGIN << YELLOW_TXT << "[3]" << WHITE_TXT << " Back to Main Menu" << endl;
cout << endl << MARGIN << "Select an option: ";
char choice = getch();
switch(choice)
{
case '1': // Single player mode
game.isSinglePlayerMode = true;
PlayGame();
break;
case '2': // Two player mode
game.isSinglePlayerMode = false;
PlayGame();
break;
case '3':
ShowMenu();
break;
default:
cout << '\a';
GameMode();
break;
}
}
// changing the selected cell
void PlaceCell(int i, int j){
if(game.turn == 1){
game.board[i][j] = cell_state.black;
}
else{
game.board[i][j] = cell_state.white;
}
}
// switchin turn in game
void SwitchTurn(){
if(game.turn == 1) game.turn = 2;
else game.turn = 1;
}
// checking if the cell is available for the player
bool CheckValidMove(int curserI, int curserJ, bool change_color){
bool validMove = false;
if(game.board[curserI][curserJ] != cell_state.empty) {
return false;
}
int opponent;
int myColor;
if(game.turn == 1){
myColor = cell_state.black;
opponent = cell_state.white;
}
else{
myColor = cell_state.white;
opponent = cell_state.black;
}
for(int k = 0; k < 8; k++){
int dx = IndX[k];
int dy = IndY[k];
int x = curserI + dx;
int y = curserJ + dy;
if(x >= 0 && x < board_size && y >= 0 && y < board_size && game.board[x][y] == opponent){
// going on in the same direction
while(true){
x += dx;
y += dy;
if(x < 0 || x >= board_size || y < 0 || y >= board_size) {
break;
}
if(game.board[x][y] == cell_state.empty){
break;
}
if(game.board[x][y] == myColor){
game.color_changer.startI = curserI;
game.color_changer.startJ = curserJ;
game.color_changer.endI = x;
game.color_changer.endJ = y;
game.color_changer.directionX = dx;
game.color_changer.directionY = dy;
if(change_color) ChangeColor(); // if we are checking the cell for a player move then we change the colors int the same process
validMove = true;
}
}
}
}
return validMove;
}
// checking if the player can play a move
bool CheckValidTurn(int turn){
for(int i = 0; i < board_size; i++){
for(int j = 0; j < board_size; j++){
if(game.board[i][j] == cell_state.empty && CheckValidMove(i, j, false))
return true;
}
}
return false;
}
// changin cells after a valid move
void ChangeColor(){
int opposite_color = (game.turn == 1 ? cell_state.black : cell_state.white);
int x = game.color_changer.startI;
int y = game.color_changer.startJ;
while(true){
x += game.color_changer.directionX;
y += game.color_changer.directionY;
if(game.board[x][y] != opposite_color){
game.board[x][y] = opposite_color;
}
else{
break;
}
}
}
// showing history (crawling through history.txt file which is considered a database for this game)
void ShowHistory(){
system("cls");
cout << "\n\n";
cout << MARGIN << BOLD << CYAN_TXT << u8"╔══════════════════════════════════════════════════════════════╗" << RESET << endl;
cout << MARGIN << BOLD << CYAN_TXT << u8"║ GAME HISTORY ARCHIVE ║" << RESET << endl;
cout << MARGIN << BOLD << CYAN_TXT << u8"╚══════════════════════════════════════════════════════════════╝" << RESET << endl;
cout << endl;
ifstream history("history.txt");
if(!history.is_open()){
cout << MARGIN << RED_TXT << "No history found or could not open file." << RESET << endl;
cout << "\n" << MARGIN << "Press any key to return...";
getch();
ShowMenu();
return;
}
cout << MARGIN << YELLOW_TXT << left
<< setw(12) << "Player 1"
<< setw(8) << "Score"
<< setw(12) << "Player 2"
<< setw(8) << "Score"
<< setw(12) << "Winner"
<< setw(20) << "Date"
<< RESET << endl;
cout << MARGIN << CYAN_TXT << u8"──────────────────────────────────────────────────────────────────────" << RESET << endl;
string line;
string player1, player2, winner, date;
string player1discs, player2discs;
int splitter[5];
while(getline(history, line)){
for(int i = 0; i < 5; i++){
if(i == 0)
splitter[i] = line.find(",");
else
splitter[i] = line.find(",", splitter[i - 1] + 1);
}
player1 = line.substr(0, splitter[0]);
player1discs = line.substr(splitter[0] + 1, splitter[1] - splitter[0] - 1);
player2 = line.substr(splitter[1] + 1, splitter[2] - splitter[1] - 1);
player2discs = line.substr(splitter[2] + 1, splitter[3] - splitter[2] - 1);
winner = line.substr(splitter[3] + 1, splitter[4] - splitter[3] - 1);
date = line.substr(splitter[4] + 1);
cout << MARGIN << left
<< CYAN_TXT << setw(12) << player1
<< BOLD << WHITE_TXT << setw(8) << player1discs
<< RESET << CYAN_TXT << setw(12) << player2
<< BOLD << WHITE_TXT << setw(8) << player2discs
<< RESET << GREEN_TXT << setw(12) << winner
<< RESET << setw(20) << date
<< endl;
}
history.close();
cout << "\n\n" << MARGIN << BG_GREEN << BLACK_TXT << " Press any key to return... " << RESET;
getch();
ShowMenu();
}
void BotMove(){
if(CheckValidTurn(game.turn)){
// allocating an array for bot's available moves
int **availabe_moves = new int*[board_size*board_size];
for(int i = 0; i < (board_size*board_size); i++){
availabe_moves[i] = new int[2];
}
// adding available moves to the array
int counter = 0;
for(int i = 0; i < board_size; i++){
for(int j = 0; j < board_size; j++){
if(CheckValidMove(i, j, false)){
availabe_moves[counter][0] = i;
availabe_moves[counter][1] = j;
counter++;
}
}
}
if (counter > 0) {
int randomIndex = rand() % counter;
curserI = availabe_moves[randomIndex][0];
curserJ = availabe_moves[randomIndex][1];
CheckValidMove(curserI, curserJ, true);
PlaceCell(curserI, curserJ);
}
// deallocating availabe moves array
for(int i = 0; i < board_size*board_size; i++){
delete[] availabe_moves[i];
}
delete[] availabe_moves;
}
else{
SwitchTurn();
}
}
BIN
View File
Binary file not shown.