Upload files to "/"
This commit is contained in:
@@ -0,0 +1,493 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <windows.h>
|
||||
#include <conio.h>
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user