Initial commit on develop branch
This commit is contained in:
+970
@@ -0,0 +1,970 @@
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <conio.h>
|
||||
#include <windows.h>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
using namespace std;
|
||||
|
||||
struct Player {
|
||||
string name;
|
||||
char color; // 'B' or 'W'
|
||||
int discs;
|
||||
};
|
||||
|
||||
|
||||
void initialBoard();
|
||||
void drawBoard(int cursorRow, int cursorCol, bool blackTurn, bool invalidMove, const string& message);
|
||||
bool cursor(int& cursorRow, int& cursorCol, bool blackTurn, bool invalidMove, const string& message, bool viewOnly);
|
||||
bool possibleMoveB(int row, int col);
|
||||
bool possibleMoveW(int row, int col);
|
||||
bool hasAnyMoveB();
|
||||
bool hasAnyMoveW();
|
||||
void placeB(int row, int col);
|
||||
void placeW(int row, int col);
|
||||
void flipB(int row, int col);
|
||||
void flipW(int row, int col);
|
||||
int blackCount();
|
||||
int whiteCount();
|
||||
void singlePlayerB(string& s);
|
||||
bool aiMoveWhite();
|
||||
void gameOverB(string& s);
|
||||
void singlePlayerW(string& s);
|
||||
bool aiMoveBlack();
|
||||
void gameOverW(string& s);
|
||||
void multiPlayer(string& s, string& t);
|
||||
void gameOverM(string& s, string& t);
|
||||
void saveHistory(const string& mode, const Player& black, const Player& white, const string& result);
|
||||
void showHistory();
|
||||
void help();
|
||||
void newGame();
|
||||
void menu();
|
||||
|
||||
|
||||
char B='B'; //○
|
||||
char W='W'; //●
|
||||
bool blackTurn=true;
|
||||
|
||||
|
||||
const int BOARD_SIZE = 8;
|
||||
string board[BOARD_SIZE][BOARD_SIZE];
|
||||
|
||||
// Arrow key codes
|
||||
const int KEY_UP = 72;
|
||||
const int KEY_DOWN = 80;
|
||||
const int KEY_LEFT = 75;
|
||||
const int KEY_RIGHT = 77;
|
||||
const int ENTER = 13;
|
||||
const int ESC = 27;
|
||||
|
||||
|
||||
void initialBoard() {
|
||||
for (int i = 0; i < BOARD_SIZE; i++) {
|
||||
for (int j = 0; j < BOARD_SIZE; j++) {
|
||||
board[i][j] = " ";
|
||||
}
|
||||
}
|
||||
|
||||
board[3][3] = "●";
|
||||
board[3][4] = "○";
|
||||
board[4][3] = "○";
|
||||
board[4][4] = "●";
|
||||
}
|
||||
|
||||
void drawBoard(int cursorRow, int cursorCol, bool blackTurn, bool invalidMove, const string& message="") {
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
system("cls");
|
||||
|
||||
cout << "┏";
|
||||
for (int i = 0; i < BOARD_SIZE; i++) {
|
||||
cout << "━━━";
|
||||
if (i < BOARD_SIZE - 1) {cout << "┳";}
|
||||
}
|
||||
cout << "┓\n";
|
||||
|
||||
for (int i = 0; i < BOARD_SIZE; i++) {
|
||||
cout << "┃";
|
||||
for (int j = 0; j < BOARD_SIZE; j++) {
|
||||
|
||||
bool valid;
|
||||
if (blackTurn)
|
||||
{valid = possibleMoveB(i, j);}
|
||||
else
|
||||
{valid = possibleMoveW(i, j);}
|
||||
|
||||
if (i == cursorRow && j == cursorCol) {
|
||||
if (valid)
|
||||
{cout << "[*]";}
|
||||
else
|
||||
{cout << "[" << board[i][j] << "]";}
|
||||
}
|
||||
else {
|
||||
if (valid)
|
||||
{cout << " * ";}
|
||||
else
|
||||
{cout << " " << board[i][j] << " ";}
|
||||
}
|
||||
|
||||
cout << "┃";
|
||||
}
|
||||
cout << "\n";
|
||||
|
||||
if (i < BOARD_SIZE - 1) {
|
||||
cout << "┣";
|
||||
for (int j = 0; j < BOARD_SIZE; j++) {
|
||||
cout << "━━━";
|
||||
if (j < BOARD_SIZE - 1) {cout << "╋";}
|
||||
}
|
||||
cout << "┫\n";
|
||||
}
|
||||
}
|
||||
|
||||
cout << "┗";
|
||||
for (int i = 0; i < BOARD_SIZE; i++) {
|
||||
cout << "━━━";
|
||||
if (i < BOARD_SIZE - 1) {cout << "┻";}
|
||||
}
|
||||
cout << "┛\n";
|
||||
|
||||
|
||||
//cout << "\n";
|
||||
|
||||
cout <<" Black(○): " << blackCount()<< " White(●): " << whiteCount() << "\n";
|
||||
|
||||
cout << " Turn: ";
|
||||
if (blackTurn) {cout << "Black(○)\n";}
|
||||
else {cout << "White(●)\n";}
|
||||
|
||||
cout<<"\n";
|
||||
|
||||
if (!message.empty())
|
||||
{cout << " " << message << "\n\n";}
|
||||
|
||||
|
||||
|
||||
|
||||
else if (invalidMove)
|
||||
{cout << " Invalid Move!\n\n";}
|
||||
|
||||
else
|
||||
{cout << "\n\n";}
|
||||
|
||||
|
||||
cout << " Press ESC To Return To The Menu "<<"\n";
|
||||
|
||||
}
|
||||
|
||||
bool cursor(int& cursorRow, int& cursorCol, bool blackTurn, bool invalidMove = false, const string& message = "", bool viewOnly = false) {
|
||||
while (true) {
|
||||
drawBoard(cursorRow, cursorCol, blackTurn, invalidMove, message);
|
||||
|
||||
int ch = _getch();
|
||||
if (ch == 0 || ch == 224) {
|
||||
ch = _getch();
|
||||
switch (ch) {
|
||||
case KEY_UP: if (cursorRow > 0) cursorRow--; break;
|
||||
case KEY_DOWN: if (cursorRow < BOARD_SIZE - 1) cursorRow++; break;
|
||||
case KEY_LEFT: if (cursorCol > 0) cursorCol--; break;
|
||||
case KEY_RIGHT: if (cursorCol < BOARD_SIZE - 1) cursorCol++; break;
|
||||
}
|
||||
}
|
||||
else if (ch == ENTER) {
|
||||
if (!viewOnly) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
else if (ch == ESC) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool possibleMoveB(int row, int col) {
|
||||
int r, c;
|
||||
|
||||
if (board[row][col]==" ") {
|
||||
r=row+1;
|
||||
if (r<BOARD_SIZE && board[r][col]=="●") {
|
||||
while (r<BOARD_SIZE && board[r][col]=="●") {r++;}
|
||||
if (r<BOARD_SIZE && board[r][col]=="○") {return true;}}
|
||||
r=row-1;
|
||||
if (r>=0 && board[r][col]=="●") {
|
||||
while (r>=0 && board[r][col]=="●") {r--;}
|
||||
if (r>=0 && board[r][col]=="○") {return true;}}
|
||||
c=col+1;
|
||||
if (c<BOARD_SIZE && board[row][c]=="●") {
|
||||
while (c<BOARD_SIZE && board[row][c]=="●") {c++;}
|
||||
if (c<BOARD_SIZE && board[row][c]=="○") {return true;}}
|
||||
c=col-1;
|
||||
if (c>=0 && board[row][c]=="●") {
|
||||
while (c>=0 && board[row][c]=="●") {c--;}
|
||||
if (c>=0 && board[row][c]=="○") {return true;}}
|
||||
r=row+1;
|
||||
c=col+1;
|
||||
if (r<BOARD_SIZE && c<BOARD_SIZE && board[r][c]=="●") {
|
||||
while (r<BOARD_SIZE && c<BOARD_SIZE && board[r][c]=="●") {r++; c++;}
|
||||
if (r<BOARD_SIZE && c<BOARD_SIZE && board[r][c]=="○") {return true;}}
|
||||
r=row+1;
|
||||
c=col-1;
|
||||
if (r<BOARD_SIZE && c>=0 && board[r][c]=="●") {
|
||||
while (r<BOARD_SIZE && c>=0 && board[r][c]=="●") {r++; c--;}
|
||||
if (r<BOARD_SIZE && c>=0 && board[r][c]=="○") {return true;}}
|
||||
r=row-1;
|
||||
c=col+1;
|
||||
if (r>=0 && c<BOARD_SIZE && board[r][c]=="●") {
|
||||
while (r>=0 && c<BOARD_SIZE && board[r][c]=="●") {r--; c++;}
|
||||
if (r>=0 && c<BOARD_SIZE && board[r][c]=="○") {return true;}}
|
||||
r=row-1;
|
||||
c=col-1;
|
||||
if (r>=0 && c>=0 && board[r][c]=="●") {
|
||||
while (r>=0 && c>=0 && board[r][c]=="●") {r--; c--;}
|
||||
if (r>=0 && c>=0 && board[r][c]=="○") {return true;}}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool possibleMoveW(int row, int col) {
|
||||
int r, c;
|
||||
|
||||
if (board[row][col]==" ") {
|
||||
r=row+1;
|
||||
if (r<BOARD_SIZE && board[r][col]=="○") {
|
||||
while (r<BOARD_SIZE && board[r][col]=="○") {r++;}
|
||||
if (r<BOARD_SIZE && board[r][col]=="●") {return true;}}
|
||||
r=row-1;
|
||||
if (r>=0 && board[r][col]=="○") {
|
||||
while (r>=0 && board[r][col]=="○") {r--;}
|
||||
if (r>=0 && board[r][col]=="●") {return true;}}
|
||||
c=col+1;
|
||||
if (c<BOARD_SIZE && board[row][c]=="○") {
|
||||
while (c<BOARD_SIZE && board[row][c]=="○") {c++;}
|
||||
if (c<BOARD_SIZE && board[row][c]=="●") {return true;}}
|
||||
c=col-1;
|
||||
if (c>=0 && board[row][c]=="○") {
|
||||
while (c>=0 && board[row][c]=="○") {c--;}
|
||||
if (c>=0 && board[row][c]=="●") {return true;}}
|
||||
r=row+1;
|
||||
c=col+1;
|
||||
if (r<BOARD_SIZE && c<BOARD_SIZE && board[r][c]=="○") {
|
||||
while (r<BOARD_SIZE && c<BOARD_SIZE && board[r][c]=="○") {r++; c++;}
|
||||
if (r<BOARD_SIZE && c<BOARD_SIZE && board[r][c]=="●") {return true;}}
|
||||
r=row+1;
|
||||
c=col-1;
|
||||
if (r<BOARD_SIZE && c>=0 && board[r][c]=="○") {
|
||||
while (r<BOARD_SIZE && c>=0 && board[r][c]=="○") {r++; c--;}
|
||||
if (r<BOARD_SIZE && c>=0 && board[r][c]=="●") {return true;}}
|
||||
r=row-1;
|
||||
c=col+1;
|
||||
if (r>=0 && c<BOARD_SIZE && board[r][c]=="○") {
|
||||
while (r>=0 && c<BOARD_SIZE && board[r][c]=="○") {r--; c++;}
|
||||
if (r>=0 && c<BOARD_SIZE && board[r][c]=="●") {return true;}}
|
||||
r=row-1;
|
||||
c=col-1;
|
||||
if (r>=0 && c>=0 && board[r][c]=="○") {
|
||||
while (r>=0 && c>=0 && board[r][c]=="○") {r--; c--;}
|
||||
if (r>=0 && c>=0 && board[r][c]=="●") {return true;}}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool hasAnyMoveB() {
|
||||
for (int i = 0; i < BOARD_SIZE; i++) {
|
||||
for (int j = 0; j < BOARD_SIZE; j++) {
|
||||
if (possibleMoveB(i, j)) {return true;}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasAnyMoveW() {
|
||||
for (int i = 0; i < BOARD_SIZE; i++) {
|
||||
for (int j = 0; j < BOARD_SIZE; j++) {
|
||||
if (possibleMoveW(i, j)) {return true;}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void placeB(int row, int col) {
|
||||
board[row][col]="○";
|
||||
}
|
||||
|
||||
void placeW(int row, int col) {
|
||||
board[row][col]="●";
|
||||
}
|
||||
|
||||
|
||||
void flipB(int row, int col) {
|
||||
int r, c, count, k;
|
||||
|
||||
r=row+1;
|
||||
count=0;
|
||||
while (r<BOARD_SIZE && board[r][col]=="●") {count++; r++;}
|
||||
if (count>0 && r<BOARD_SIZE && board[r][col]=="○") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row+k][col]="○";
|
||||
}
|
||||
}
|
||||
r=row-1;
|
||||
count=0;
|
||||
while (r>=0 && board[r][col]=="●") {count++; r--;}
|
||||
if (count>0 && r>=0 && board[r][col]=="○") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row-k][col]="○";
|
||||
}
|
||||
}
|
||||
c=col+1;
|
||||
count=0;
|
||||
while (c<BOARD_SIZE && board[row][c]=="●") {count++; c++;}
|
||||
if (count>0 && c<BOARD_SIZE && board[row][c]=="○") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row][col+k]="○";
|
||||
}
|
||||
}
|
||||
c=col-1;
|
||||
count=0;
|
||||
while (c>=0 && board[row][c]=="●") {count++; c--;}
|
||||
if (count>0 && c>=0 && board[row][c]=="○") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row][col-k]="○";
|
||||
}
|
||||
}
|
||||
r=row+1;
|
||||
c=col+1;
|
||||
count=0;
|
||||
while (r<BOARD_SIZE && c<BOARD_SIZE && board[r][c]=="●") {count++; r++; c++;}
|
||||
if (count>0 && r<BOARD_SIZE && c<BOARD_SIZE && board[r][c]=="○") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row+k][col+k]="○";
|
||||
}
|
||||
}
|
||||
r=row+1;
|
||||
c=col-1;
|
||||
count=0;
|
||||
while (r<BOARD_SIZE && c>=0 && board[r][c]=="●") {count++; r++; c--;}
|
||||
if (count>0 && r<BOARD_SIZE && c>=0 && board[r][c]=="○") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row+k][col-k]="○";
|
||||
}
|
||||
}
|
||||
r=row-1;
|
||||
c=col+1;
|
||||
count=0;
|
||||
while (r>=0 && c<BOARD_SIZE && board[r][c]=="●") {count++; r--; c++;}
|
||||
if (count>0 && r>=0 && c<BOARD_SIZE && board[r][c]=="○") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row-k][col+k]="○";
|
||||
}
|
||||
}
|
||||
r=row-1;
|
||||
c=col-1;
|
||||
count=0;
|
||||
while (r>=0 && c>=0 && board[r][c]=="●") {count++; r--; c--;}
|
||||
if (count>0 && r>=0 && c>=0 && board[r][c]=="○") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row-k][col-k]="○";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flipW(int row, int col) {
|
||||
int r, c, count, k;
|
||||
|
||||
r=row+1;
|
||||
count=0;
|
||||
while (r<BOARD_SIZE && board[r][col]=="○") {count++; r++;}
|
||||
if (count>0 && r<BOARD_SIZE && board[r][col]=="●") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row+k][col]="●";
|
||||
}
|
||||
}
|
||||
r=row-1;
|
||||
count=0;
|
||||
while (r>=0 && board[r][col]=="○") {count++; r--;}
|
||||
if (count>0 && r>=0 && board[r][col]=="●") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row-k][col]="●";
|
||||
}
|
||||
}
|
||||
c=col+1;
|
||||
count=0;
|
||||
while (c<BOARD_SIZE && board[row][c]=="○") {count++; c++;}
|
||||
if (count>0 && c<BOARD_SIZE && board[row][c]=="●") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row][col+k]="●";
|
||||
}
|
||||
}
|
||||
c=col-1;
|
||||
count=0;
|
||||
while (c>=0 && board[row][c]=="○") {count++; c--;}
|
||||
if (count>0 && c>=0 && board[row][c]=="●") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row][col-k]="●";
|
||||
}
|
||||
}
|
||||
r=row+1;
|
||||
c=col+1;
|
||||
count=0;
|
||||
while (r<BOARD_SIZE && c<BOARD_SIZE && board[r][c]=="○") {count++; r++; c++;}
|
||||
if (count>0 && r<BOARD_SIZE && c<BOARD_SIZE && board[r][c]=="●") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row+k][col+k]="●";
|
||||
}
|
||||
}
|
||||
r=row+1;
|
||||
c=col-1;
|
||||
count=0;
|
||||
while (r<BOARD_SIZE && c>=0 && board[r][c]=="○") {count++; r++; c--;}
|
||||
if (count>0 && r<BOARD_SIZE && c>=0 && board[r][c]=="●") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row+k][col-k]="●";
|
||||
}
|
||||
}
|
||||
r=row-1;
|
||||
c=col+1;
|
||||
count=0;
|
||||
while (r>=0 && c<BOARD_SIZE && board[r][c]=="○") {count++; r--; c++;}
|
||||
if (count>0 && r>=0 && c<BOARD_SIZE && board[r][c]=="●") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row-k][col+k]="●";
|
||||
}
|
||||
}
|
||||
r=row-1;
|
||||
c=col-1;
|
||||
count=0;
|
||||
while (r>=0 && c>=0 && board[r][c]=="○") {count++; r--; c--;}
|
||||
if (count>0 && r>=0 && c>=0 && board[r][c]=="●") {
|
||||
for (k=1; k<=count; k++) {
|
||||
board[row-k][col-k]="●";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int blackCount() {
|
||||
int count=0;
|
||||
for (int i = 0; i < BOARD_SIZE; i++) {
|
||||
for (int j = 0; j < BOARD_SIZE; j++) {
|
||||
if (board[i][j]=="○") {count++;}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int whiteCount() {
|
||||
int count=0;
|
||||
for (int i = 0; i < BOARD_SIZE; i++) {
|
||||
for (int j = 0; j < BOARD_SIZE; j++) {
|
||||
if (board[i][j]=="●") {count++;}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void singlePlayerB(string& s) {
|
||||
initialBoard();
|
||||
int cursorRow = 0, cursorCol = 0;
|
||||
bool blackTurn = true;
|
||||
bool invalidMove = false;
|
||||
string currentMessage = "";
|
||||
|
||||
while (true) {
|
||||
|
||||
|
||||
if (!hasAnyMoveB() && !hasAnyMoveW()) {
|
||||
gameOverB(s);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (blackTurn && !hasAnyMoveB()) {
|
||||
currentMessage = "Black(○) has no valid moves. Skipping Turn...";
|
||||
drawBoard(cursorRow, cursorCol, blackTurn, false, currentMessage);
|
||||
Sleep(2000);
|
||||
currentMessage = "";
|
||||
blackTurn=false;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!blackTurn && !hasAnyMoveW()) {
|
||||
currentMessage = "White(●) has no valid moves. Skipping Turn...";
|
||||
drawBoard(cursorRow, cursorCol, blackTurn, false, currentMessage);
|
||||
Sleep(2000);
|
||||
currentMessage = "";
|
||||
blackTurn=true;
|
||||
continue;
|
||||
}
|
||||
|
||||
drawBoard(cursorRow, cursorCol, blackTurn, invalidMove, currentMessage);
|
||||
|
||||
|
||||
if (blackTurn) {
|
||||
|
||||
bool pressedEnter = cursor(cursorRow, cursorCol, blackTurn, invalidMove, currentMessage);
|
||||
if (!pressedEnter) {return;}
|
||||
|
||||
if (possibleMoveB(cursorRow, cursorCol)) {
|
||||
placeB(cursorRow, cursorCol);
|
||||
flipB(cursorRow, cursorCol);
|
||||
blackTurn = false;
|
||||
invalidMove = false;
|
||||
} else {
|
||||
invalidMove = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else {
|
||||
Sleep(800);
|
||||
aiMoveWhite();
|
||||
blackTurn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool aiMoveWhite() {
|
||||
int rows[64];
|
||||
int cols[64];
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < BOARD_SIZE; i++) {
|
||||
for (int j = 0; j < BOARD_SIZE; j++) {
|
||||
if (possibleMoveW(i, j)) {
|
||||
rows[count] = i;
|
||||
cols[count] = j;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) return false;
|
||||
|
||||
int r = rand() % count;
|
||||
|
||||
int row = rows[r];
|
||||
int col = cols[r];
|
||||
|
||||
placeW(row, col);
|
||||
flipW(row, col);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void gameOverB(string& s) {
|
||||
int cursorRow = 0;
|
||||
int cursorCol = 0;
|
||||
|
||||
Player blackPlayer;
|
||||
Player whitePlayer;
|
||||
|
||||
blackPlayer.name = s;
|
||||
blackPlayer.color = 'B';
|
||||
blackPlayer.discs = blackCount();
|
||||
|
||||
whitePlayer.name = "Bot";
|
||||
whitePlayer.color = 'W';
|
||||
whitePlayer.discs = whiteCount();
|
||||
|
||||
string winnerMessage;
|
||||
string result;
|
||||
|
||||
if (blackPlayer.discs > whitePlayer.discs) {
|
||||
winnerMessage = "Congrats " + blackPlayer.name + "! You Won!";
|
||||
result = blackPlayer.name + " Won";}
|
||||
else if (whitePlayer.discs > blackPlayer.discs) {
|
||||
winnerMessage = "You Lost " + blackPlayer.name + ". Better Luck Next Time!";
|
||||
result = whitePlayer.name + " Won";}
|
||||
else {
|
||||
winnerMessage = "It's a DRAW!";
|
||||
result = "Draw";}
|
||||
|
||||
|
||||
|
||||
saveHistory("Single Player", blackPlayer, whitePlayer, result);
|
||||
|
||||
|
||||
|
||||
cursor(cursorRow, cursorCol, true, false, winnerMessage, true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void singlePlayerW(string& s) {
|
||||
initialBoard();
|
||||
int cursorRow = 0, cursorCol = 0;
|
||||
bool blackTurn = true;
|
||||
bool invalidMove = false;
|
||||
string currentMessage = "";
|
||||
|
||||
while (true) {
|
||||
|
||||
|
||||
if (!hasAnyMoveB() && !hasAnyMoveW()) {
|
||||
gameOverW(s);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (blackTurn && !hasAnyMoveB()) {
|
||||
currentMessage = "Black(○) has no valid moves. Skipping Turn...";
|
||||
drawBoard(cursorRow, cursorCol, blackTurn, false, currentMessage);
|
||||
Sleep(2000);
|
||||
currentMessage = "";
|
||||
blackTurn=false;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!blackTurn && !hasAnyMoveW()) {
|
||||
currentMessage = "White(●) has no valid moves. Skipping Turn...";
|
||||
drawBoard(cursorRow, cursorCol, blackTurn, false, currentMessage);
|
||||
Sleep(2000);
|
||||
currentMessage = "";
|
||||
blackTurn=true;
|
||||
continue;
|
||||
}
|
||||
|
||||
drawBoard(cursorRow, cursorCol, blackTurn, invalidMove, currentMessage);
|
||||
|
||||
|
||||
if (!blackTurn) {
|
||||
|
||||
bool pressedEnter = cursor(cursorRow, cursorCol, blackTurn, invalidMove, currentMessage);
|
||||
if (!pressedEnter) {return;}
|
||||
|
||||
if (possibleMoveW(cursorRow, cursorCol)) {
|
||||
placeW(cursorRow, cursorCol);
|
||||
flipW(cursorRow, cursorCol);
|
||||
blackTurn = true;
|
||||
invalidMove = false;
|
||||
} else {
|
||||
invalidMove = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else {
|
||||
Sleep(800);
|
||||
aiMoveBlack();
|
||||
blackTurn = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool aiMoveBlack() {
|
||||
int rows[64];
|
||||
int cols[64];
|
||||
int count=0;
|
||||
|
||||
for (int i = 0; i<BOARD_SIZE; i++) {
|
||||
for (int j = 0; j<BOARD_SIZE; j++) {
|
||||
if (possibleMoveB(i, j)) {
|
||||
rows[count] = i;
|
||||
cols[count] = j;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count==0) return false;
|
||||
|
||||
int r = rand() % count;
|
||||
|
||||
int row=rows[r];
|
||||
int col=cols[r];
|
||||
|
||||
placeB(row, col);
|
||||
flipB(row, col);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void gameOverW(string& s) {
|
||||
int cursorRow = 0;
|
||||
int cursorCol = 0;
|
||||
|
||||
Player blackPlayer;
|
||||
Player whitePlayer;
|
||||
|
||||
blackPlayer.name = "Bot";
|
||||
blackPlayer.color = 'B';
|
||||
blackPlayer.discs = blackCount();
|
||||
|
||||
whitePlayer.name = s;
|
||||
whitePlayer.color = 'W';
|
||||
whitePlayer.discs = whiteCount();
|
||||
|
||||
string winnerMessage;
|
||||
string result;
|
||||
|
||||
if (whitePlayer.discs > blackPlayer.discs) {
|
||||
winnerMessage = "Congrats " + whitePlayer.name + "! You Won!";
|
||||
result = whitePlayer.name + " Won";}
|
||||
else if (blackPlayer.discs > whitePlayer.discs) {
|
||||
winnerMessage = "You Lost " + whitePlayer.name + ". Better Luck Next Time!";
|
||||
result = blackPlayer.name + " Won";}
|
||||
else {
|
||||
winnerMessage = "It's a DRAW!";
|
||||
result = "Draw";}
|
||||
|
||||
|
||||
saveHistory("Single Player", blackPlayer, whitePlayer, result);
|
||||
|
||||
|
||||
|
||||
cursor(cursorRow, cursorCol, true, false, winnerMessage, true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void multiPlayer(string& s, string& t) {
|
||||
initialBoard();
|
||||
int cursorRow = 0, cursorCol = 0;
|
||||
bool blackTurn = true;
|
||||
bool invalidMove = false;
|
||||
string currentMessage = "";
|
||||
|
||||
while (true) {
|
||||
|
||||
if (!hasAnyMoveB() && !hasAnyMoveW()) {
|
||||
gameOverM(s, t);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (blackTurn && !hasAnyMoveB()) {
|
||||
currentMessage = "Black(○) has no valid moves. Skipping Turn...";
|
||||
drawBoard(cursorRow, cursorCol, blackTurn, false, currentMessage);
|
||||
Sleep(2000);
|
||||
currentMessage = "";
|
||||
blackTurn=false;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!blackTurn && !hasAnyMoveW()) {
|
||||
currentMessage = "White(●) has no valid moves. Skipping Turn...";
|
||||
drawBoard(cursorRow, cursorCol, blackTurn, false, currentMessage);
|
||||
Sleep(2000);
|
||||
currentMessage = "";
|
||||
blackTurn=true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
drawBoard(cursorRow, cursorCol, blackTurn, invalidMove, currentMessage);
|
||||
|
||||
bool pressedEnter = cursor(cursorRow, cursorCol, blackTurn, invalidMove, currentMessage);
|
||||
|
||||
if (!pressedEnter) {return;}
|
||||
|
||||
|
||||
invalidMove = false;
|
||||
currentMessage = "";
|
||||
|
||||
|
||||
bool valid;
|
||||
if (blackTurn)
|
||||
{valid = possibleMoveB(cursorRow, cursorCol);}
|
||||
else
|
||||
{valid = possibleMoveW(cursorRow, cursorCol);}
|
||||
|
||||
if (valid) {
|
||||
if (blackTurn) {
|
||||
placeB(cursorRow, cursorCol);
|
||||
flipB(cursorRow, cursorCol);
|
||||
} else {
|
||||
placeW(cursorRow, cursorCol);
|
||||
flipW(cursorRow, cursorCol);
|
||||
}
|
||||
blackTurn = !blackTurn;
|
||||
} else {
|
||||
invalidMove = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gameOverM(string& s, string& t) {
|
||||
int cursorRow = 0;
|
||||
int cursorCol = 0;
|
||||
|
||||
Player blackPlayer;
|
||||
Player whitePlayer;
|
||||
|
||||
|
||||
blackPlayer.name = s;
|
||||
blackPlayer.color = 'B';
|
||||
blackPlayer.discs = blackCount();
|
||||
|
||||
whitePlayer.name = t;
|
||||
whitePlayer.color = 'W';
|
||||
whitePlayer.discs = whiteCount();
|
||||
|
||||
string winnerMessage;
|
||||
string result;
|
||||
|
||||
if (blackPlayer.discs > whitePlayer.discs) {
|
||||
winnerMessage = "Congrats " + blackPlayer.name + "! You Won!";
|
||||
result = blackPlayer.name + " Won";}
|
||||
else if (blackPlayer.discs < whitePlayer.discs) {
|
||||
winnerMessage = "Congrats " + whitePlayer.name + "! You Won!";
|
||||
result = whitePlayer.name + " Won";}
|
||||
else {
|
||||
winnerMessage = "It's a DRAW!";
|
||||
result = "Draw";}
|
||||
|
||||
|
||||
|
||||
saveHistory("Multiplayer", blackPlayer, whitePlayer, result);
|
||||
|
||||
|
||||
cursor(cursorRow, cursorCol, true, false, winnerMessage, true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void saveHistory(const string& mode, const Player& black, const Player& white, const string& result) {
|
||||
|
||||
ifstream inFile("History.txt");
|
||||
string oldContent;
|
||||
string line;
|
||||
while (getline(inFile, line)) {
|
||||
oldContent += line+"\n";
|
||||
}
|
||||
inFile.close();
|
||||
|
||||
|
||||
ofstream outFile("History.txt");
|
||||
if (!outFile) {
|
||||
cout<<"Error: Could not open History.txt for writing.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
outFile<<oldContent;
|
||||
//outFile<<" Game Number "<<r<<endl;
|
||||
outFile<<"Mode: "<<mode<<endl;
|
||||
outFile<<"Black: "<<black.name<<" ("<<black.discs<<" discs)"<<endl;
|
||||
outFile<<"White: "<<white.name<<" (" <<white.discs<<" discs)"<<endl;
|
||||
outFile<<"Result: "<<result<<endl;
|
||||
outFile<<"------------------------"<< endl;
|
||||
|
||||
outFile.close();
|
||||
}
|
||||
|
||||
|
||||
void showHistory() {
|
||||
system("cls");
|
||||
|
||||
ifstream file("History.txt");
|
||||
if (!file || file.peek()==EOF) {
|
||||
cout<<"No game history found yet.\n\n";
|
||||
} else {
|
||||
string line;
|
||||
while (getline(file, line)) {
|
||||
cout<<line<<endl;
|
||||
}
|
||||
file.close();
|
||||
cout<<"\n";
|
||||
}
|
||||
|
||||
cout<<"Press ESC to return to the menu.";
|
||||
while (true) {
|
||||
int ch=_getch();
|
||||
if (ch==ESC) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void help() {
|
||||
system("cls");
|
||||
|
||||
cout<<"========== HOW TO PLAY OTHELLO ==========\n\n";
|
||||
cout<<"- Othello is a turn-based game which is played on an 8x8 board.\n";
|
||||
cout<<"- Black(○) always goes first.\n";
|
||||
cout<<"- A move is valid if it flips at least one opponent disc.\n";
|
||||
cout<<"- Discs are flipped when they are trapped between two discs of opposite color.\n";
|
||||
cout<<"- If a player has no valid moves, their turn is skipped.\n";
|
||||
cout<<"- The game ends when neither player can move.\n\n";
|
||||
cout<<"Use ARROW KEYS to move through the board.\n";
|
||||
cout<<"Press ENTER to place a disc.\n";
|
||||
cout<<"=========================================\n\n";
|
||||
cout<<"Press ESC to return to the menu.";
|
||||
|
||||
while (true) {
|
||||
int ch=_getch();
|
||||
if (ch==ESC) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void newGame() {
|
||||
cout<<"1. Single Player"<<endl;
|
||||
cout<<"2. Multiplayer"<<endl;;
|
||||
int n;
|
||||
string s, t;
|
||||
char a;
|
||||
cin>>n;
|
||||
if (n==1) {
|
||||
cout<<"Enter Your Name: ";
|
||||
cin>>s;
|
||||
cout<<"Choose Your Color (B/W): ";
|
||||
cin>>a;
|
||||
if (a=='B') {
|
||||
singlePlayerB(s);}
|
||||
if (a=='W') {
|
||||
singlePlayerW(s);}
|
||||
}
|
||||
if (n==2) {
|
||||
cout<<"Enter Your Name (P1 as Black): ";
|
||||
cin>>s;
|
||||
cout<<"Enter Your Name (P2 as White): ";
|
||||
cin>>t;
|
||||
multiPlayer(s, t);
|
||||
}
|
||||
}
|
||||
|
||||
void menu() {
|
||||
system("cls");
|
||||
cout<<" Welcome To Othello!"<<endl;
|
||||
cout<<"1. New Game"<<endl;
|
||||
cout<<"2. Help"<<endl;
|
||||
cout<<"3. Game History"<<endl;
|
||||
cout<<"4. Exit"<<endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
while (true) {
|
||||
menu();
|
||||
int choice, r;
|
||||
cin>>choice;
|
||||
if (choice==1)
|
||||
{newGame();}
|
||||
else if (choice==2)
|
||||
{help();}
|
||||
else if (choice == 3)
|
||||
{showHistory();}
|
||||
else if (choice==4)
|
||||
{return 0;}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user