Initial commit on develop branch

This commit is contained in:
2026-04-16 00:07:38 +03:30
commit f1421805e2
+829
View File
@@ -0,0 +1,829 @@
#include <iostream>
#include <string>
#include <conio.h>
#include <windows.h>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <fstream>
using namespace std;
const int KEY_UP = 72;
const int KEY_DOWN = 80;
const int KEY_ENTER = 13;
const int N = 8;
const int dx[8] = { -1,-1,-1,0,0,1,1,1 };
const int dy[8] = { -1,0,1,-1,1,-1,0,1 };
const string EMPTY = " ";
const string BLACK = u8"\u25CB";
const string WHITE = u8"\u25CF";
int selX = 3, selY = 3;
string board[N][N];
bool blackTurn = true;
string name[2];
string box1 = u8"\u250C"; // گوشه بالا چپ
string box2 = u8"\u2510"; // گوشه بالا راست
string box3 = u8"\u2514"; // گوشه پایین چپ
string box4 = u8"\u2518"; // گوشه پایین راست
string box5 = u8"\u2500"; // خط افقی
string box6 = u8"\u2502"; // خط عمودی
string box7 = u8"\u252C"; // ┬
string box8 = u8"\u2534"; // ┴
string box9 = u8"\u251C"; // ├
string box10 = u8"\u2524"; // ┤
string box11 = u8"\u253C"; // ┼
const string RESET = "\033[0m";
const string GREENDARK = "\033[42m";
const string BROWN = "\033[38;5;94m";
const string YELLOW = "\033[93m";
const string BLUE = "\033[1;36m";
const string RED = "\033[1;31m";
const string GREEN = "\033[92m";
struct
{
string name1;
string name2;
string winner;
string time;
int count1;
int count2;
} gamehistory;
// menu
int ShowMenu();
int ShowMenuTadadPlayer();
int Endmenu();
void Help();
void ShowGameHistory();
// game
void DrawBoard();
bool Inside(int y, int x);
bool CanFlip(int y, int x, int dirY, int dirX, const string me, const string opp);
bool ValidMove(int y, int x, const string me, const string opp);
void ApplyMove(int y, int x, const string me, const string opp);
void FirstBoard();
bool HaveValidMove(string me, string opp);
// game history
int CountPlayer(string Color);
string GetCurrentDateTime();
void SaveGameHistory();
// bot
int GoodPoints(int x, int y);
int CountFlips(int x, int y, const string me, const string opp);
int FindBestScore(int x, int y, const string me, const string opp);
void DEMONKING();
bool BadPoints(int x, int y);
int main ()
{
startProgram:
int CountMenu, CountMenuTadadPlayer, countplayer1, countplayer2,end;
bool running = true, End = false;
string Winner, Time;
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(65001);
CountMenu = ShowMenu();
if (CountMenu == 5)
{
exit(0);
}
else if (CountMenu == 4)
{
cout << BLUE << "Do good and throw it into the Tigris; God will return it to you in the desert." << RESET;
cout << endl << endl << RED << "6219_8618_7708_8780" << RESET;
cout << endl << endl << BLUE << "Don't be a fucking Jew!!" << endl << "(This is a joke.)"<< RESET;
char key = _getch();
if (key == 27)
goto startProgram;
}
else if (CountMenu == 2)
{
Help();
char key = _getch();
if (key == 27)
goto startProgram;
}
else if (CountMenu == 3)
{
ShowGameHistory();
char key = _getch();
if (key == 27)
goto startProgram;
}
else if ( CountMenu == 0)
{
CountMenuTadadPlayer = ShowMenuTadadPlayer();
if( CountMenuTadadPlayer == 1)
{
cout << RED << "Player1 Name:" << RESET;
cin >> name[0];
cout << RED << "Player2 Name:" << RESET;
cin >> name[1];
startProgram1:
selX = 3;
selY = 3;
blackTurn = true;
End = false;
FirstBoard();
while (true)
{
DrawBoard();
char key = _getch();
if (key == 27) break;
if ((key == 'w' || key == 'W') && selY > 0) selY--;
if ((key == 's' || key == 'S') && selY < 7) selY++;
if ((key == 'a' || key == 'A') && selX > 0) selX--;
if ((key == 'd' || key == 'D') && selX < 7) selX++;
if (key == KEY_ENTER)
{
const string me = blackTurn ? BLACK : WHITE;
const string opp = blackTurn ? WHITE : BLACK;
if (ValidMove(selY, selX, me, opp))
{
ApplyMove(selY, selX, me, opp);
bool curHas = HaveValidMove(me, opp);
blackTurn = !blackTurn;
const string nextme = blackTurn ? BLACK : WHITE;
const string nextopp = blackTurn ? WHITE : BLACK;
bool nextHas = HaveValidMove(nextme, nextopp);
if (!nextHas)
{
cout << RED << "PASS" << RESET;
Sleep(3000);
blackTurn = !blackTurn;
}
if (!curHas && !nextHas)
{
DrawBoard();
Sleep(3000);
End = true;
}
if( End == true)
{
countplayer1 = CountPlayer(BLACK);
countplayer2 = CountPlayer(WHITE);
if( countplayer1 == countplayer2)
{
Winner = "Draw";
}
else if (countplayer1 > countplayer2)
{
Winner = name[0];
}
else
{
Winner = name[1];
}
Time = GetCurrentDateTime();
gamehistory.name1 = name[0];
gamehistory.name2 = name[1];
gamehistory.count1 = countplayer1;
gamehistory.count2 = countplayer2;
gamehistory.winner = Winner;
gamehistory.time = Time;
SaveGameHistory();
end = Endmenu();
if( end == 0)
goto startProgram1;
if( end == 1)
goto startProgram;
if( end == 2)
return 0;
}
}
}
}
}
else
{
cout << RED << "Player Name:" << RESET;
cin >> name[0];
name[1] = "Demon King ";
startProgram2:
selX = 3;
selY = 3;
blackTurn = true;
End = false;
FirstBoard();
while (true)
{
DrawBoard();
char key = _getch();
if (key == 27) break;
if ((key == 'w' || key == 'W') && selY > 0) selY--;
if ((key == 's' || key == 'S') && selY < 7) selY++;
if ((key == 'a' || key == 'A') && selX > 0) selX--;
if ((key == 'd' || key == 'D') && selX < 7) selX++;
if (key == KEY_ENTER)
{
const string me = blackTurn ? BLACK : WHITE;
const string opp = blackTurn ? WHITE : BLACK;
if (ValidMove(selY, selX, me, opp))
{
ApplyMove(selY, selX, me, opp);
DrawBoard();
blackTurn = !blackTurn;
if (!blackTurn)
{
if (HaveValidMove(WHITE, BLACK))
{
Sleep(1000);
DEMONKING();
}
else
{
cout << RED << "PASS" << RESET;
Sleep(2000);
}
blackTurn = true;
}
const string nextme = blackTurn ? BLACK : WHITE;
const string nextopp = blackTurn ? WHITE : BLACK;
bool curHas = HaveValidMove(me, opp);
bool nextHas = HaveValidMove(nextme, nextopp);
if (!nextHas)
{
cout << RED << "PASS" << RESET;
Sleep(3000);
blackTurn = !blackTurn;
}
if (!curHas && !nextHas)
{
DrawBoard();
Sleep(3000);
End = true;
}
if( End == true)
{
countplayer1 = CountPlayer(BLACK);
countplayer2 = CountPlayer(WHITE);
if( countplayer1 == countplayer2)
{
Winner = "Draw";
}
else if (countplayer1 > countplayer2)
{
Winner = name[0];
}
else
{
Winner = name[1];
}
Time = GetCurrentDateTime();
gamehistory.name1 = name[0];
gamehistory.name2 = name[1];
gamehistory.count1 = countplayer1;
gamehistory.count2 = countplayer2;
gamehistory.winner = Winner;
gamehistory.time = Time;
SaveGameHistory();
end = Endmenu();
if( end == 0)
goto startProgram2;
if( end == 1)
goto startProgram;
if( end == 2)
exit(0);
}
}
}
}
}
}
}
int ShowMenu() // این تابع منوی اولیه بازی رو نشون می ده
{
string menuItems[6] = {"New Game","Load Game","Help","Game History","Donate","Exit"};
int itemCount = 6;
int selectedItem = 0;
bool running = true;
while (running)
{
system("cls");
cout << BLUE << box1;
for (int i = 0; i < 25; i++) cout << box5;
cout << box2 << endl;
for (int i = 0; i < itemCount; i++)
{
cout << box6;
if ( i == selectedItem)
{
cout << RESET << RED << " > " << menuItems[i];
for(int s = 0; s < 22 - menuItems[i].length();s++) cout << RESET << " ";
cout << BLUE << box6 << endl;
}
else
{
cout << RESET << " " << RED << menuItems[i] << RESET;
for (int s = 0; s < 22 - menuItems[i].length(); s++) cout << " ";
cout << BLUE << box6 << endl;
}
}
cout << box3;
for (int i = 0; i < 25; i++) cout << box5;
cout << box4 << RESET << endl;
int key = _getch();
if (key == 224)
{
key = _getch();
if ( key == KEY_UP)
{
selectedItem = (selectedItem - 1 + itemCount) % itemCount;
}
else if ( key == KEY_DOWN)
{
selectedItem = (selectedItem + 1) % itemCount;
}
}
else if (key == KEY_ENTER)
{
system("cls");
return selectedItem;
}
}
return 0;
}
int ShowMenuTadadPlayer() // این تابع منوی تعداد پلیر نشون می ده
{
string menuItems[5] = {"Singleplayer","Multiplayer"};
int itemCount = 2;
int selectedItem = 0;
bool running = true;
while (running)
{
system("cls");
for (int i = 0; i < itemCount; i++)
{
if ( i == selectedItem)
{
cout << RED <<" > " << menuItems[i] << RESET << endl;
}
else
{
cout << " " << RED << menuItems[i] << RESET << endl;
}
}
int key = _getch();
if (key == 224)
{
key = _getch();
if ( key == KEY_UP)
{
selectedItem = (selectedItem - 1 + itemCount) % itemCount;
}
else if ( key == KEY_DOWN)
{
selectedItem = (selectedItem + 1) % itemCount;
}
}
else if (key == KEY_ENTER)
{
system("cls");
return selectedItem;
}
}
return 0;
}
void FirstBoard() // تابع 4 مهره اول بازی رسم می کنه
{
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
board[i][j] = EMPTY;
board[3][3] = WHITE;
board[3][4] = BLACK;
board[4][3] = BLACK;
board[4][4] = WHITE;
}
void DrawBoard() // این تابع برد بازی نشون می ده و هعی اپدیت میشه
{
system("cls");
cout << YELLOW << "Turn: " << (blackTurn ? name[0] : name[1]) << RESET << "\n\n";
cout << BROWN << box1;
for (int i = 0; i < 7; i++) cout << box5 << box5 << box5 << box7;
cout << box5 << box5 << box5 << box2 << RESET << endl;
for (int i = 0; i < 8; i++)
{
cout << BROWN << box6 << RESET;
for (int j = 0; j < 8; j++)
{
string cell = board[i][j];
if (i == selY && j == selX)
{
if (cell != " ")
cout << GREENDARK << "[" << cell << "]" << RESET;
else
cout << GREENDARK << "[ ]" << RESET;
} else
{
if (cell != " ")
cout << GREENDARK << " " << cell << " " << RESET;
else
cout << GREENDARK << " " << RESET;
}
cout << BROWN << box6 << RESET;
}
cout << endl;
if (i != 7) {
cout << BROWN << box9;
for (int k = 0; k < 7; k++) cout << box5 << box5 << box5 << box11;
cout << box5 << box5 << box5 << box10 << RESET << endl;
}
}
cout << BROWN << box3;
for (int i = 0; i < 7; i++) cout << box5 << box5 << box5 << box8;
cout << box5 << box5 << box5 << box4 << RESET << endl;
}
bool Inside(int y, int x) // این تابع بررسی می کنه که حرکت کاربر از برد خارج نشه
{
return x >= 0 && x < N && y >= 0 && y < N;
}
bool CanFlip(int y, int x, int dirY, int dirX, const string me, const string opp) // این تابع نشون می ده ایا مهره گذاشته شده مهره ای رو بر می گردونه یا خیر
{
y += dirY;
x += dirX;
if (!Inside(y, x) || board[y][x] != opp) return false;
while (Inside(y, x)) {
if (board[y][x] == EMPTY) return false;
if (board[y][x] == me) return true;
y += dirY;
x += dirX;
}
return false;
}
bool ValidMove(int y, int x, const string me, const string opp) // این تابع نشون می ده که ایا مهره گذاشته شده حرکتش درست هست یاه خیر
{
if (board[y][x] != EMPTY) return false;
for (int i = 0; i < 8; i++)
if (CanFlip(y, x, dy[i], dx[i], me, opp))
return true;
return false;
}
void ApplyMove(int y, int x, const string me, const string opp) // این تابع تغییرات صفحه رو ایجاد می کنه
{
board[y][x] = me;
for (int i = 0; i < 8; i++)
{
if (CanFlip(y, x, dy[i], dx[i], me, opp))
{
int ny = y + dy[i], nx = x + dx[i];
while (board[ny][nx] == opp)
{
board[ny][nx] = me;
ny += dy[i];
nx += dx[i];
}
}
}
}
bool HaveValidMove(string me, string opp) // این تابع چک می کنه که ایا بازیکن هنوز حرکتی داره یا خیر
{
for (int k = 0; k < N; k++)
{
for (int h = 0; h < N; h++)
{
if (board[k][h] == EMPTY)
{
for (int i = 0; i < 8; i++) {
if (CanFlip(k, h, dy[i], dx[i], me, opp))
{
return true;
}
}
}
}
}
return false;
}
string GetCurrentDateTime()// این تابع تاریخ و زمان از سیستم می گیره و خروجی می ده
{
time_t now = time(nullptr);
tm localTime;
localtime_s(&localTime, &now);
stringstream ss;
ss << put_time(&localTime, "%Y/%m/%d %H:%M:%S");
return ss.str();
}
void SaveGameHistory() // این تابع اطلاعات بازی رو خروجی می ده
{
const string filename = "Game History.txt";
ifstream inFile(filename);
string oldContent;
string line;
if (inFile)
{
while (getline(inFile, line))
{
oldContent += line + "\n";
}
inFile.close();
}
ofstream outFile(filename);
outFile << "\033[38;5;94m" << "| " << RESET << "Player1: " << BLUE << gamehistory.name1 << RESET << "\033[38;5;94m" << " | " << RESET << "Player2: " << BLUE << gamehistory.name2 << RESET << "\033[38;5;94m" << " | " << RESET << "Winner: " << (gamehistory.winner == "Draw" ? "\033[96mDraw" : GREEN + gamehistory.winner) << RESET << u8"\U0001F3C6" << "\033[38;5;94m" << " | " << RESET << "\033[90m" << "Black: " << gamehistory.count1 << u8"\U0001F468\U0001F3FF" << " | White: " << gamehistory.count2 << u8"\U0001F468\U0001F3FB" << " | Time: " << gamehistory.time << u8"\U0001F552" << RESET << endl;
outFile << oldContent;
outFile.close();
}
int Endmenu() // این تابع منوی پایانی بازی نشون می ده
{
string menuItems[3] = {"Try Again","Main Menu","Exit"};
int itemCount = 3;
int selectedItem = 0;
bool running = true;
while (running)
{
system("cls");
cout << BLUE << box1;
for (int i = 0; i < 25; i++) cout << box5;
cout << box2 << endl;
cout << box6 << RESET << RED << " Winner:" << RESET << GREEN << gamehistory.winner << RESET;
for(int s = 0; s < 15 - gamehistory.winner.length();s++) cout << " ";
cout << BLUE << box6 << endl;
for (int i = 0; i < itemCount ; i++)
{
cout << box6;
if ( i == selectedItem )
{
cout << RED << " > " << menuItems[i] << RESET;
for(int s = 0; s < 22 - menuItems[i].length();s++) cout << " ";
cout << BLUE << box6 << endl;
}
else
{
cout << RESET << " " << RED << menuItems[i] << RESET;
for (int s = 0; s < 22 - menuItems[i].length(); s++) cout << " ";
cout << BLUE << box6 << endl;
}
}
cout << box3;
for (int i = 0; i < 25; i++) cout << box5;
cout << box4 << RESET << endl;
int key = _getch();
if (key == 224)
{
key = _getch();
if ( key == KEY_UP)
{
selectedItem = (selectedItem - 1 + itemCount) % itemCount;
}
else if ( key == KEY_DOWN)
{
selectedItem = (selectedItem + 1) % itemCount;
}
}
else if (key == KEY_ENTER)
{
system("cls");
return selectedItem;
}
}
return 0;
}
int CountPlayer(string Color) //این تابع تعداد مهره های هر بازیکن می شمارد
{
int count =0;
for ( int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
if(board[i][j] == Color)
count++;
}
}
return count;
}
int CountFlips(int x, int y, const string me, const string opp) // این تابع بررسی می کنه که هر حرکت چند تا رو می تونه بر گردونه
{
if (board[y][x] != EMPTY) return 0;
int total = 0;
for (int d = 0; d < 8; d++)
{
int nx = x + dx[d];
int ny = y + dy[d];
int cnt = 0;
while (Inside(ny, nx) && board[ny][nx] == opp)
{
cnt++;
nx += dx[d];
ny += dy[d];
}
if (cnt > 0 && Inside(ny, nx) && board[ny][nx] == me)
total += cnt;
}
return total;
}
int GoodPoints(int x, int y) // یکی سری نقاط توی بازی اهمیت بیشتری داره برای حرکت ربات اگر ربات اون حرکت انجام بده بهش امتیاز می ده
{
if ((x == 0 || x == 7) && (y == 0 || y == 7))
return 100;
if (x == 0 || x == 7 || y == 0 || y == 7)
return 20;
return 5;
}
bool BadPoints(int x, int y) // این تابع مثل تابع قبل فقط نقاط منفی مشخص می کنه
{
return (x == 1 && y == 1) || (x == 6 && y == 1) || (x == 1 && y == 6) || (x == 6 && y == 6);
}
int FindBestScore(int x, int y,const string me, const string opp) // این تابع میاد با استفاده از 3 تابع قبل نقاطی که بهش داده میشه رو امتیازشون بررسی می کنه
{
if (!ValidMove(y, x, me, opp))
return -100;
int flips = CountFlips(x, y, me, opp);
if (flips == 0)
return -100;
int score = 0;
score += flips * 10;
score += GoodPoints(x, y);
if (BadPoints(x, y))
score -= 50;
return score;
}
void DEMONKING() // این تابع مال ربات که با تابع قبل میاد بهترین حرکت ممکن انتخاب می کنه
{
const string me = WHITE;
const string opp = BLACK;
int bestscore = -100;
int bestx = -1, besty = -1;
for (int y = 0; y < N; y++)
{
for (int x = 0; x < N; x++)
{
int score = FindBestScore(x, y, me, opp);
if (score > bestscore)
{
bestscore = score;
bestx = x;
besty = y;
}
}
}
if (bestx != -1 && ValidMove(besty, bestx, me, opp))
{
ApplyMove(besty, bestx, me, opp);
}
}
void Help() // این تابع بخش کمک بازی رو نشون می ده
{
cout << "Hello! How are you? 👋" << endl
<< "Im here to help you enjoy the game more easily and have a better experience." << endl
<< "First of all, the game has two modes:" << endl << "🎮 Single Player (Play against the AI)" << endl
<< "👥 Multiplayer (Two players)" << endl << "Heres a friendly tip for you:" << endl
<< "⚠️ Dont underestimate the AI — sometimes it can be really scary!" << endl << endl
<< "In both modes, you can move around the board using the W, A, S, D keys." << endl
<< "To place your piece and confirm your move, press ENTER." << endl
<< "If your move is not placed, it means that move is not valid according to the game rules." << endl << endl
<< "You can press ESC at any time to exit the game." << endl
<< "To save your game, press CTRL + SAVE." << endl << endl
<< "✨ I wish you an amazing and unforgettable Othello experience." << endl
<< "Good luck, and have fun! 🎯🖤⚪" << endl;
}
void ShowGameHistory() // این تابع گیم هیستوری نشون می ده
{
ifstream file("Game History.txt");
if (!file)
{
cout << "First start a Game" << endl;
}
string line;
while (getline(file, line))
{
cout << line << endl;
}
file.close();
}