commit 9ecfb4f311241b025bebdf122001605a9d2cb07a Author: Saba_frm Date: Tue Apr 14 09:40:49 2026 +0000 Upload files to "/" diff --git a/min.cpp b/min.cpp new file mode 100644 index 0000000..8e4af02 --- /dev/null +++ b/min.cpp @@ -0,0 +1,493 @@ +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +struct Player +{ + string name; + char color; // 'B' یا 'W' + bool isBot; +}; +const int MAXN = 10; +int N = 8; +char board[MAXN][MAXN]; +//صفحه بازی +int dr[8] = +{-1,-1,-1,0,0,1,1,1}; +int dc[8] = +{-1,0,1,-1,1,-1,0,1}; +bool inBounds(int r, int c) +{ + return r >= 0 && c >= 0 && r < N && c < N; +} +void initBoard() +{ + for (int r = 0; r < N; ++r) + for (int c = 0; c < N; ++c) + board[r][c] = ' '; + int mid = N / 2; + board[mid - 1][mid - 1] = 'W'; + board[mid][mid] = 'W'; + board[mid - 1][mid] = 'B'; + board[mid][mid - 1] = 'B'; +} + +bool hasFlipsInDir(int r, int c, char me, int dirIndex, int& endR, int& endC) + +{ + char opp; + if (me == 'B') + { + opp = 'W'; + } else + { + opp = 'B'; + } + + int nr = r + dr[dirIndex]; + int nc = c + dc[dirIndex]; + + if (!inBounds(nr, nc)) + { + return false; + } + if (board[nr][nc] != opp) + { + return false; + } + + while (inBounds(nr, nc)) + { + if (board[nr][nc] == opp) + { + nr = nr + dr[dirIndex]; + nc = nc + dc[dirIndex]; + } + else if (board[nr][nc] == me) + { + endR = nr; + endC = nc; + return true; + } + else + { + return false; + } + } + + return false; +} + +bool isValidMove(int r, int c, char me) +{ + if (!inBounds(r, c) || board[r][c] != ' ') + return false; + + for (int d = 0; d < 8; ++d) + { + int endR, endC; + if (hasFlipsInDir(r, c, me, d, endR, endC)) return true; + } + return false; +} + + +void applyMove(int r, int c, char me) +{ + board[r][c] = me; + for (int d = 0; d < 8; ++d) + { + int endR, endC; + if (hasFlipsInDir(r, c, me, d, endR, endC)) + { + int nr = r + dr[d]; + int nc = c + dc[d]; + while (!(nr == endR && nc == endC)) + { + board[nr][nc] = me; + nr += dr[d]; + nc += dc[d]; + } + } + } +} + +void saveGame(const string& playerBlack, const string& playerWhite, char nextTurn) +{ + ofstream file("save.txt"); + if (!file) + { + cout << "Error saving game!\n"; + return; + } + file << N << "\n" << playerBlack << "\n" << playerWhite << "\n" << nextTurn << "\n"; + for (int i = 0; i < N; ++i) + { + for (int j = 0; j < N; ++j) file << board[i][j]; + file << "\n"; + } + file.close(); +} + +void saveToHistory(const string& pBlack, const string& pWhite, int blackScore, int whiteScore, const string& winner) +{ + ofstream file("history.txt", ios::app); + if (!file) + { + cout << "Error saving to history!\n"; + return; + } + + time_t now = time(0); + char* dt = ctime(&now); + dt[strlen(dt)-1] = '\0'; + + file << "Date: " << dt << "\n"; + file << "Players: " << pBlack << " (Black) vs " << pWhite << " (White)\n"; + file << "Score: " << blackScore << " - " << whiteScore << "\n"; + file << "Winner: " << winner << "\n"; + file << "-----------------------------------\n"; + + file.close(); +} + +void showGameHistory() +{ + ifstream file("history.txt"); + if (!file) { + cout << "No game history yet.\n"; + return; + } + + cout << "\n=== GAME HISTORY ===\n\n"; + string line; + while (getline(file, line)) { + cout << line << "\n"; + } + cout << "\n"; + file.close(); +} + +bool hasAnyMove(char me) +{ + for (int r = 0; r < N; ++r) + for (int c = 0; c < N; ++c) + if (isValidMove(r, c, me)) return true; + return false; +} + +int countPieces(char piece) +{ + int cnt = 0; + for (int r = 0; r < N; ++r) + for (int c = 0; c < N; ++c) + if (board[r][c] == piece) cnt++; + return cnt; +} + +void setColor(int color) +{ + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color); +} + + +void printBoardWithHints(char turn, int cursorR = -1, int cursorC = -1) +{ + int blackCount = countPieces('B'); + int whiteCount = countPieces('W'); + + setColor(14); // رنگ زرد روشن برای امتیاز + cout << "\nScore -> Black: " << blackCount << " | White: " << whiteCount << "\n"; + setColor(10); + cout << "\n "; + for (int c = 0; c < N; ++c) + cout << c + 1 << " "; + cout << "\n"; + + cout << " ┌"; + for (int c = 0; c < N; ++c) + cout << "───" << (c < N - 1 ? "┬" : ""); + cout << "┐\n"; + + for (int r = 0; r < N; ++r) + { + cout << r + 1 << " │"; + for (int c = 0; c < N; ++c) + { + if (r == cursorR && c == cursorC) setColor(12); // کرسر قرمز + else if (board[r][c] == ' ' && isValidMove(r, c, turn)) setColor(6); + else if (board[r][c] == 'B') setColor(8); + else if (board[r][c] == 'W') setColor(15); + else setColor(10); + + if (r == cursorR && c == cursorC && board[r][c] == ' ') cout << "[ ]"; + else if (board[r][c] == 'B') cout << " ● "; + else if (board[r][c] == 'W') cout << " ○ "; + else if (board[r][c] == ' ' && isValidMove(r, c, turn)) cout << " * "; + else cout << " "; + + setColor(10); + cout << "│"; + } + cout << "\n"; + if (r < N - 1) + { + cout << " ├"; + for (int c = 0; c < N; ++c) + cout << "───" << (c < N - 1 ? "┼" : ""); + cout << "┤\n"; + } + + } + cout << " └"; + for (int c = 0; c < N; ++c) + cout << "───" << (c < N - 1 ? "┴" : ""); + cout << "┘\n"; + setColor(7); +} + + +void helpScreen() +{ + setColor(6); + cout << "\n--- Help ---\n"; + setColor(13); + cout << "Othello (Reversi) rules summary:\n"; + cout << "- Board size can be 6x6, 8x8, or 10x10. Initial center has 2 Black and 2 White discs in a cross.\n"; + cout << "- A valid move places a disc on an empty cell that brackets opponent discs\n"; + cout << " in at least one direction (horizontal, vertical, or diagonal) between\n"; + cout << " the new disc and an existing disc of the mover.\n"; + cout << "- All bracketed opponent discs in those directions flip to the mover's color.\n"; + cout << "- If a player has no valid moves, they pass. If both cannot move, game ends.\n"; + cout << "- Winner is the player with more discs. Symbols: B=Black, W=White, .=empty, *=hint , ●=Black , ○=White\n"; + cout << "- During the game, enter 0 0 to save and exit.\n"; + setColor(6); + cout << "------------\n\n"; + setColor(7); +} + +void botMove(char me) +{ + for (int r = 0; r < N; ++r) + { + for (int c = 0; c < N; ++c) + { + if (isValidMove(r, c, me)) + { + applyMove(r, c, me); + cout << "Bot placed at: row " << (r + 1) << ", col " << (c + 1) << "\n"; + return; + } + } + } +} + +bool loadGame(string& playerBlack, string& playerWhite, char& turn) +{ + ifstream file("save.txt"); + if (!file) { + cout << "No saved game found.\n"; + return false; + } + + int size; + file >> size; + N = size; + file >> ws; + getline(file, playerBlack); + getline(file, playerWhite); + file >> turn; + file.ignore(); + for (int r = 0; r < N; ++r) + for (int c = 0; c < N; ++c) + board[r][c] = ' '; + + + for (int r = 0; r < N; ++r) + { + string line; + getline(file, line); + for (int c = 0; c < N && c < (int)line.size(); ++c) + { + board[r][c] = line[c]; + } + } + + file.close(); + cout << "Game loaded successfully!\n"; + return true; +} + +void playGame(bool singlePlayer, bool loadExisting = false) +{ + string playerBlack, playerWhite; + char turn = 'B'; + int cursorR = 0, cursorC = 0; // موقعیت کرسر + if (loadExisting) + { + if (!loadGame(playerBlack, playerWhite, turn)) + { + cout << "Starting new game instead.\n"; + loadExisting = false; + } + } + + if (!loadExisting) + { + cout << "Choose board size (6 / 8 / 10): "; + cin >> N; + while (N != 6 && N != 8 && N != 10) + { + cout << "Invalid size! Choose 6, 8 or 10: "; + cin >> N; + } + + cout << "Enter Black player name: "; + getline(cin >> ws, playerBlack); + + if (singlePlayer) + playerWhite = "Bot"; + else + { + cout << "Enter White player name: "; + getline(cin >> ws, playerWhite); + } + + initBoard(); + } + + while (true) + { + system("cls"); + printBoardWithHints(turn, cursorR, cursorC); + cout << "Turn: " << (turn == 'B' ? playerBlack : playerWhite) + << " (" << turn << ")" + << " | Score: " << countPieces('B') << " - " << countPieces('W') << "\n"; + + if (!hasAnyMove(turn)) + { + cout << "No valid moves for " << (turn == 'B' ? "Black" : "White") << ". PASS.\n"; + char nextTurn = (turn == 'B') ? 'W' : 'B'; + if (!hasAnyMove(nextTurn)) + { + cout << "No valid moves for both players. Game over.\n"; + break; + } + turn = nextTurn; + _getch(); + continue; + } + + if (singlePlayer && turn == 'W') + { + botMove(turn); + turn = 'B'; + _getch(); + continue; + } + + cout << "Use W/A/S/D to move, Enter to place, 0 to save.\n"; + + char key = _getch(); + if (key == 'w' || key == 'W') cursorR = max(0, cursorR - 1); + else if (key == 's' || key == 'S') cursorR = min(N - 1, cursorR + 1); + else if (key == 'a' || key == 'A') cursorC = max(0, cursorC - 1); + else if (key == 'd' || key == 'D') cursorC = min(N - 1, cursorC + 1); + else if (key == '\r') // Enter + { + if (isValidMove(cursorR, cursorC, turn)) + { + applyMove(cursorR, cursorC, turn); + turn = (turn == 'B') ? 'W' : 'B'; + } + else + { + cout << "Invalid move!\n"; + _getch(); + } + } + else if (key == '0') + { + saveGame(playerBlack, playerWhite, turn); + cout << "Game saved! Returning to main menu.\n"; + _getch(); + return; + } + } + + system("cls"); + printBoardWithHints('B'); + int black = countPieces('B'); + int white = countPieces('W'); + cout << "Final count -> Black: " << black << " | White: " << white << "\n"; + + string winner; + if (black > white) winner = playerBlack + " (Black)"; + else if (white > black) winner = playerWhite + " (White)"; + else winner = "Draw"; + + cout << "Winner: " << winner << "\n"; + saveToHistory(playerBlack, playerWhite, black, white, winner); + _getch(); +} + + +int main() +{ + SetConsoleOutputCP(CP_UTF8); + SetConsoleCP(CP_UTF8); + int choice; + do + { + setColor(2); + cout << "\n-------------------"; + setColor(14); + cout << "\n--- Main Menu ---\n"; + setColor(11); + cout << " 1. Two-player game\n"; + cout << " 2. Single-player (vs bot)\n"; + cout << " 3. Help\n"; + cout << " 4. Game History\n"; + cout << " 5. Load Game\n"; + cout << " 0. Exit\n"; + setColor(15); + cout << "Select: "; + setColor(2); + + cout << "\n-------------------\n"; + setColor(7); + cin >> choice; + + if (choice == 1) + { + playGame(false); + } else if (choice == 2) + { + playGame(true); + } else if (choice == 3) + { + helpScreen(); + + }else if (choice == 4) + { + showGameHistory(); + + }else if (choice == 5) + { + playGame(false,true); + } + else if (choice == 0) + { + cout << "Goodbye!\n"; + } else { + cout << "Invalid option.\n"; + } + } while (choice != 0); + + return 0; +} \ No newline at end of file