#include #include #include #include #include #include using namespace std; // کامنت ها برای اینه که تو صورت سوال گفته شده کد باید کامنت گذاری شده باشه struct game { string name1; string name2; int countB; int countW; string result; string date; string time; }; string board[8][8]; int moves[64][2]; int countPass = 0; int countW; int countB; //تابعی که بررسی میکنه یک جهت دارای حداقل یک مهره حریف و بعد از اون حداقل یک خودیه یا نه bool checkDirection(string board[8][8], int row, int col, string color,int drow,int dcol) { string opponent; if (color == "●") { opponent = "○"; } else { opponent = "●"; } int currentRow = row + drow; int currentCol = col + dcol; if (currentRow < 0 || currentRow >= 8 || currentCol < 0 || currentCol >= 8) { return false; } //چک اینکه مهره کناری حتما حریف باشه if (board[currentRow][currentCol] != opponent) { return false; } while (currentRow >= 0 && currentRow < 8 && currentCol >= 0 && currentCol < 8) { if (board[currentRow][currentCol] == opponent) { currentRow += drow; currentCol += dcol; } else if (board[currentRow][currentCol] == color) { return true; } else { break; } } return false; } //بررسی میکنه حداقل یه جهت با شرایطی که تو کامنت بالایی گفتم وجود داره یا نه bool existsValidDirection(string board[8][8], int row, int col, string color) { int d[] = {-1, 0, 1}; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (i == 1 && j == 1) { continue; } if (checkDirection(board, row, col, color, d[i], d[j]) == true) { return true; } } } return false; } //بررسی میکنه شرایط برای گذاشتن مهره توی اون خونه انتخاب شده هست یا نه bool isValidMove(string board[8][8], int row, int col, string color) { if (board[row][col] == " " && existsValidDirection(board, row, col, color) == true) { return true; } return false; } //تمام خونه هایی که میشه توش با توجه به شرایط مهره گذاشت رو پیدا و شمارش میکنه void findValidMoves(string board[8][8], string color, int moves[][2], int& count) { //int& برای اینه که وقتی تابع رو صدا زدیم و کارش رو انجام داد مقدار count بیرون از تابع تغییر نکنه //راحتتر این بود که int عادی بذاریم و بعد count رو برگردونیم ولی خب. count = 0; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if (isValidMove(board, i, j, color) == true ) { moves[count][0] = i; moves[count][1] = j; count++; } } } } //به طور رندوم یکی از خونه های معتبر رو انتخاب میکنه int chooseMove(int count) { int randomNum = rand() % count; return randomNum; } //توی خونه انتخاب شده مهره میذاره و مهره های محاصره شده حریف رو تبدیل میکنه به مهره های خودی void applyMove(string board[8][8], int row, int col, string color) { int d[] = {-1, 0, 1}; string opponent = (color == "●") ? "○" : "●"; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (i == 1 && j == 1) { continue; } if (checkDirection(board, row, col, color, d[i], d[j])) { int currentRow = row + d[i]; int currentCol = col + d[j]; while (board[currentRow][currentCol] == opponent) { board[currentRow][currentCol] = color; currentRow += d[i]; currentCol += d[j]; } } } } board[row][col] = color; } //صفحه بازی رو توی یه جدول چاپ میکنه void printBoard(string board[8][8], int cursorRow, int cursorCol) { cout << "┌"; for (int col = 0; col < 8; col++) { cout << "─"; if (col != 7) { cout << "┬"; } else { cout << "┐"; } } cout << endl; for (int row = 0; row < 8; row++) { cout << "│"; for (int col = 0; col < 8; col++) { //به خاطر شرط پایین وقتی به کرسرها -1 بدیم صفحه بدون کرسر چاپ میشه if (row == cursorRow && col == cursorCol) { if (board[row][col] == " ") { cout << "*"; } else { cout << board[row][col]; } } else { cout << board[row][col]; } cout << "│"; } cout << endl; if (row != 7) { cout << "├"; for (int col = 0; col < 8; col++) { cout << "─"; if (col != 7) { cout << "┼"; } else { cout << "┤"; } } cout << endl; } } cout << "└"; for (int col = 0; col < 8; col++) { cout << "─"; if (col != 7) { cout << "┴"; } else { cout << "┘"; } } cout << endl; } //با استفاده از تابع های تعریف و پیاده سازی شده، تمام کارایی که ربات باید توی نوبتش انجام بده رو انجام میده bool robotTurn(string board[8][8], string color) { int count = 0; findValidMoves(board, color, moves, count); system("cls"); if (count == 0) { //برای اینکه صفحه بدون کرسر چاپ بشه printBoard(board, -1, -1); return false; } else { int chosenMove = chooseMove(count); int row = moves[chosenMove][0]; int col = moves[chosenMove][1]; applyMove(board, row, col, color); printBoard(board, -1, -1); return true; } } //کلیدهایی که کاربر برای حرکت روی صفحه بازی میزنه رو شناسایی میکنه و کرسر رو نشون میده. //با استفاده از تابع های تعریف و پیاده سازی شده، وقتی بازیکن خونه موردنظرش رو انتخاب کرد //اگر خونه دارای شرایط لازم وجود نداشت پیام پاس میده یا اگر خونه نامعتبر بود اخطار میده //اگر معتبر بود مهره های محاصره شده حریف رو تبدیل میکنه به مهره های خودی و مهره رو توی خونه انتخاب شده میذاره bool humanTurn(string board[8][8],string name, string turn) { int count = 0; bool isSelected = false; int row; int col; int cursorRow = 0; int cursorCol = 0; findValidMoves(board, turn, moves, count); if (count == 0) { system("cls"); cout << "Pass" << endl << "Press any key to continue." << endl; getch(); return false; } while (!isSelected) { system("cls"); printBoard(board, cursorRow, cursorCol); cout << "Turn: " << turn << endl; char key = getch(); if (key == 'w') { cursorRow--; if (cursorRow < 0) cursorRow = 0; } else if (key == 'a') { cursorCol--; if (cursorCol < 0) cursorCol = 0; } else if (key == 's') { cursorRow++; if (cursorRow > 7) cursorRow = 7; } else if (key == 'd') { cursorCol++; if (cursorCol > 7) cursorCol = 7; } if (key == '\r') { if (isValidMove(board, cursorRow, cursorCol, turn)) { row = cursorRow; col = cursorCol; isSelected = true; } else { cout << "Invalid move!" << endl << "Press any key to choose again." << endl; getch(); } } } applyMove(board, row, col, turn); return true; } int main() { srand(static_cast(time(nullptr))); bool running = true; string color = "●"; int choice = 0; int capacity = 10; int size; game* history; history = new game[capacity]; ifstream file("history.txt"); size = 0; game temp; //تا وقتی به ته فایل نرسیده while (!file.eof()) { file >> temp.name1 >> temp.name2 >> temp.countB >> temp.countW >> temp.result >> temp.date >> temp.time; if (file.eof()) break; if (size == capacity) { int newCapacity = capacity * 2; game* newHistory = new game[newCapacity]; for (int i = 0; i < size; i++) { newHistory[i] = history[i]; } delete[] history; history = newHistory; capacity = newCapacity; } history[size] = temp; // بازی رو که خوند میریزه تو آرایه size++; } file.close(); while (running) { cout << "1) New Game" << endl; cout << "2) Help" << endl; cout << "3) Game History" << endl; cout << "4) Exit" << endl; cin >> choice; //بازی جدید if (choice == 1) { for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { board[i][j]= " "; } } board[3][3] = "○"; board[4][4] = "○"; board[3][4] = "●"; board[4][3] = "●"; int players; cout << "1) Single Player" << endl; cout << "2) Two Player" << endl; cin >> players; cin.ignore(); if (players == 1) { //بازی یک نفره. حریف بازیکن ربات است string name; cout << "Enter your name:"; cin >> name; cout << "The game starts with " << name << " (●)." << endl; cout << "Use keys w/a/s/d to move and Enter to apply." << endl; cout << "Press any key to start." << endl; getch(); string playerColor = "●"; string robotColor = "○"; string turn = playerColor; countPass = 0; int cursorRow = 0; int cursorCol = 0; while (countPass < 2) { //نوبت بازیکن if (turn == "●") { if (humanTurn(board, name, playerColor) == true) { countPass = 0; } else { countPass++; } turn = robotColor; } //نوبت ربات else if (turn == "○") { if (robotTurn(board, robotColor) == true) { countPass = 0; } else { countPass++; } turn = playerColor; } } //شمارش مهره ها countW = 0; countB = 0; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if (board[i][j] == "○") { countW++; } else if (board[i][j] == "●") { countB++; } } } system("cls"); cout << "Game over." << endl; cout << "Black: " << countB << endl; cout << "White: " << countW << endl; if (countW > countB) { cout << "White won!" << endl; } else if (countB > countW) { cout << "Black won!" << endl; } if (countW == countB) { cout << "The game is drawn" << endl; } //فرایند ذخیره تاریخچه game currentGame; currentGame.name1 = name; currentGame.name2 = "computer"; currentGame.countB = countB; currentGame.countW = countW; if (countB > countW) currentGame.result = "Black"; else if (countW > countB) currentGame.result = "White"; else currentGame.result = "Draw"; //کمک از ai: time_t now = time(nullptr); tm* localtm = localtime(&now); string currentDate = to_string(localtm->tm_mday) + "/" + to_string(localtm->tm_mon + 1) + "/" + to_string(localtm->tm_year + 1900); string currentTime = to_string(localtm->tm_hour) + ":" + to_string(localtm->tm_min) + ":" + to_string(localtm->tm_sec); currentGame.date = currentDate; currentGame.time = currentTime; if (size == capacity) { int newCapacity = capacity * 2; game* newHistory = new game[newCapacity]; for (int i = 0; i < size; i++) { newHistory[i] = history[i]; } delete[] history; history = newHistory; capacity = newCapacity; } history[size] = currentGame; size++; } else if (players == 2) { //بازی دونفره string name1, name2; cout << "Enter players' names:"; cin.ignore(); getline(cin, name1); getline(cin, name2); cout << "The game starts with Black (●)." << endl; cout << "Use keys w/a/s/d to move and Enter to apply." << endl; cout << "Press any key to start."; getch(); string playerColorb = "●"; string playerColorw = "○"; string turn = playerColorb; int countb = 0; int countw = 0; int cursorRow = 0; int cursorCol = 0; countPass = 0; bool gameOver = false; while (countPass < 2) { if (turn == "●") { if (humanTurn(board, name1, playerColorb) == true) { countPass = 0; } else { countPass++; } turn = playerColorw; } else if (turn == "○") { if (humanTurn(board, name2, playerColorw) == true) { countPass = 0; } else { countPass++; } turn = playerColorb; } } countW = 0; countB = 0; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if (board[i][j] == "○") { countW++; } else if (board[i][j] == "●") { countB++; } } } gameOver = true; system("cls"); cout << "Game over." << endl; cout << "Black: " << countB << endl; cout << "White: " << countW << endl; if (countW > countB) { cout << "White won!" << endl; } else if (countB > countW) { cout << "Black won!" << endl; } if (countW == countB) { cout << "The game is drawn" << endl; } game currentGame; currentGame.name1 = name1; currentGame.name2 = name2; currentGame.countB = countB; currentGame.countW = countW; if (countB > countW) currentGame.result = "Black"; else if (countW > countB) currentGame.result = "White"; else currentGame.result = "Draw"; //کمک از ai: time_t now = time(nullptr); tm* localtm = localtime(&now); string currentDate = to_string(localtm->tm_mday) + "/" + to_string(localtm->tm_mon + 1) + "/" + to_string(localtm->tm_year + 1900); string currentTime = to_string(localtm->tm_hour) + ":" + to_string(localtm->tm_min) + ":" + to_string(localtm->tm_sec); currentGame.date = currentDate; currentGame.time = currentTime; if (size == capacity) { int newCapacity = capacity * 2; game* newHistory = new game[newCapacity]; for (int i = 0; i < size; i++) { newHistory[i] = history[i]; } delete[] history; history = newHistory; capacity = newCapacity; } history[size] = currentGame; size++; } } //راهنما else if (choice == 2) { cout << "keys: " << endl; cout << "w: up" << endl << "a: left" << endl << "s: down" << endl << "d: right" << endl << "Enter: to place" << endl; cout << "In single-player mode, after you move, the robot plays immediately, then it's your turn again. Don't get confused!" << endl; cout << "Othello is a two-player board game played on an 8*8 grid. " << "Players take turns placing discs on the board, with one side black and the other white." << " A move is valid if it traps one or more of the opponent's discs between the new disc and another disc of the same color, " << " causing the trapped discs to flip." << " The game ends when no valid moves remain, " << "and the player with the most discs on the board wins." << endl; } //نمایش تاریخچه else if (choice == 3) { if (size == 0) { cout << "No game history found." << endl; } else { for (int i = 0; i < size; i++) { cout << i + 1 << "." << history[i].name1 << " vs " << history[i].name2 << " / score: " << history[i].countB << "-" << history[i].countW << " / winner: " << history[i].result << " / date: " << history[i].date << " / time: " << history[i].time<< endl; } } } //خروج از بازی else if (choice == 4) { running = false; break; } else { cout << "invalid choice." << endl; } } //نوشتن تاریخچه در فایل ofstream outfile("history.txt"); if (!outfile.is_open()) { cout << "Cannot open history.txt for writing!" << endl; } for (int i = 0; i < size; i++) { outfile << history[i].name1 << " " << history[i].name2 << " " << history[i].countB << " " << history[i].countW << " " << history[i].result << " " << history[i].date << " " << history[i].time << endl; } outfile.close(); delete[] history; return 0; }