Initial commit on develop branch

This commit is contained in:
2026-04-17 20:07:57 +03:30
commit 9b68b97ae6
52 changed files with 3499 additions and 0 deletions
+83
View File
@@ -0,0 +1,83 @@
#include "codes/Database/GameHistoryManager.h"
#include "codes/Structures/Config.h"
#include "codes/ConfigModifier.h"
#include "codes/GameMaster.h"
#include "codes/GameReporter.h"
#include "codes/GameReviewer.h"
#include "codes/Helper.h"
#include <iostream>
#include <conio.h>
#include <windows.h>
int main()
{
system("cls");
Config::initialize();
syncGameHistoryWithLimit();
int chosenOption = 0;
while (true)
{
system("cls");
std::cout << "Welcome to Othello game!" << std::endl
<< (chosenOption == 0 ? " > ":" ") << " new game" << std::endl
<< (chosenOption == 1 ? " > ":" ") << " load game" << std::endl
<< (chosenOption == 2 ? " > ":" ") << " help" << std::endl
<< (chosenOption == 3 ? " > ":" ") << " games history" << std::endl
<< (chosenOption == 4 ? " > ":" ") << " settings" << std::endl
<< (chosenOption == 5 ? " > ":" ") << " exit" << std::endl;
int userInput = getch();
if (userInput == static_cast<int>('w') || userInput == 72)
{
if (chosenOption > 0)
{
chosenOption--;
continue;
}
}
if (userInput == static_cast<int>('s') || userInput == 80)
{
if (chosenOption < 5)
{
chosenOption++;
continue;
}
}
if (userInput == 13)
{
if (chosenOption == 0)
{
executeGameMaster(false);
}
else if (chosenOption == 1)
{
executeGameMaster(true);
}
else if (chosenOption == 2)
{
executeHelper();
}
else if (chosenOption == 3)
{
executeGameReporter();
}
else if (chosenOption == 4)
{
executeConfigModifier();
}
else if (chosenOption == 5)
{
break;
}
}
}
return 0;
}
+214
View File
@@ -0,0 +1,214 @@
#include "ConfigModifier.h"
#include "Database/ConfigManager.h"
#include "Database/GameHistoryManager.h"
#include <conio.h>
#include <windows.h>
#include <limits>
#include <iostream>
bool madeChanges = false;
void handleGameHistoryLimit();
void handleBoardSize();
void handlShowAvailablePlacesToPieces();
void executeConfigModifier()
{
int chosenOption = 0;
while (true)
{
system("cls");
std::cout << "current setting are:" << std::endl
<< "The number of games inside game history: " << getGameHistoryLimit() << std::endl
<< "The size of the board: " << getBoardSize() << std::endl
<< "Show available places for pieces: " << (getShowAvailablePlacesForPieces() ? "Yes":"No") << std::endl << std::endl;
std::cout << "Which of these properties do you wish to change?" << std::endl;
std::cout << (chosenOption == 0 ? " >":" ") << " The number of games inside game history" << std::endl
<< (chosenOption == 1 ? " >":" ") << " The size of the board" << std::endl
<< (chosenOption == 2 ? " >":" ") << " Showing avaibale places for pieces" << std::endl
<< (chosenOption == 3 ? " >":" ") << " Apply the changes and exit" << std::endl;
int userInput = getch();
if (userInput == static_cast<int>('w') || userInput == 72)
{
if (chosenOption > 0)
{
chosenOption--;
continue;
}
}
if (userInput == static_cast<int>('s') || userInput == 80)
{
if (chosenOption < 3)
{
chosenOption++;
continue;
}
}
if (userInput == 13)
{
if (chosenOption == 0)
{
handleGameHistoryLimit();
}
else if (chosenOption == 1)
{
handleBoardSize();
}
else if (chosenOption == 2)
{
handlShowAvailablePlacesToPieces();
}
else if (chosenOption == 3)
{
break;
}
}
}
system("cls");
if (madeChanges == false) std::cout << "No changes has been made\nPress any key to continue";
else if (madeChanges == true) std::cout << "Please restart the game for changes to be applied to the game\nPress any key to continue";
getch();
system("cls");
return;
}
void handleGameHistoryLimit()
{
system("cls");
std::cout << "the current value of the number of games inside game history is "
<< getGameHistoryLimit() << std::endl
<< "Please set the new value: " << std::endl;
int newValue;
std::cin >> newValue;
if (getGameHistoryLimit() == newValue)
{
return handleGameHistoryLimit();
}
if (newValue > 100)
{
std::cout << "Inputed number is too big, you might face slow loading when recieving reports or loading games"
<< std::endl << "Do you procced? [Y/N]" << std::endl;
char procceded;
std::cin >> procceded;
if (!(procceded == 'Y' || procceded == 'y'))
{
return handleGameHistoryLimit();
}
}
modifyGameHistoryLimit(newValue);
syncGameHistoryWithLimit();
std::cout << "Change has been made\nPress any key to continue";
getch();
return;
}
void handleBoardSize()
{
system("cls");
std::cout << "the current value of the size of the board is "
<< getBoardSize() << std::endl
<< "Please set the new value: " << std::endl;
int newValue;
std::cin >> newValue;
if (getBoardSize() == newValue)
{
return handleBoardSize();
}
if (newValue > 50)
{
std::cout << "Inputed number is too big, please set a number lower than or equal to 50\nPress any key to continue" << std::endl;
getch();
return handleBoardSize();
}
if (newValue % 2 == 1)
{
std::cout << "Board size cannot be an odd number, please set an even number\nPress any key to continue";
getch();
return handleBoardSize();
}
modifyBoardSize(newValue);
std::cout << "Change has been made\nPress any key to continue";
getch();
return;
}
void handlShowAvailablePlacesToPieces()
{
system("cls");
bool curValue = getShowAvailablePlacesForPieces();
std::cout << (curValue ?
"Currently, you will see available places for putting your piece durning the game":
"Currently, you won't see available places for putting your piece durning the game"
) << std::endl;
std::cout << "Do you proceed to change the behavour? [Y/N]" << std::endl;
char procceded;
std::cin >> procceded;
if (!(procceded == 'Y' || procceded == 'y'))
{
return;
}
madeChanges = true;
if (curValue)
{
modifyShowAvailablePlacesForPieces(false);
}
else
{
modifyShowAvailablePlacesForPieces(true);
}
std::cout << "Change has been made\nPress any key to continue";
getch();
return;
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
void executeConfigModifier();
+10
View File
@@ -0,0 +1,10 @@
{
GAME_HISTORY_LIMIT = 100
BOARD_SIZE = 8
BOARD_COLOR = black
BOARD_BORDER_COLOR = white
SOUND = 0
SHOW_AVAILABLE_PLACES_FOR_PIECES = 1
HINT = 0
HINT_LIMIT = 3
}
+201
View File
@@ -0,0 +1,201 @@
#include <iostream>
#include <fstream>
#include "../Utilities/StrToInt.h"
#include "../utilities/IntToStr.h"
#include "ConfigManager.h"
using namespace std;
string getElementOfConfig(int index);
int getGameHistoryLimit();
int getBoardSize();
std::string getBoardColor();
std::string getBoardBorderColor();
bool getSound();
bool getShowAvailablePlacesForPieces();
bool getHint();
int getHintLimit();
void modifyElementOfConfig(int index, string newValue);
void modifyGameHistoryLimit(int);
void modifyBoardSize(int);
void modifyBoardColor(std::string);
void modifyBoardBorderColor(std::string);
void modifySound(bool);
void modifyShowAvailablePlacesForPieces(bool);
void modifyHint(bool);
void modifyHintLimit(int);
string getElementOfConfig(int index)
{
if (index > 7)
{
throw 2; // out of bond
}
ifstream file ("codes/Database/Config.txt");
if (!file.is_open())
{
throw 1; // failed to read the file
}
string line;
for (int i{0}; i <= index + 1; i++)
{
getline(file, line);
}
int startingIndex = line.find("=") + 2;
string result = line.substr(startingIndex, line.size());
file.close();
return result;
}
void modifyElementOfConfig(int index, string newValue)
{
if (index > 7)
{
throw 2; // out of bounds
}
std::ifstream fileToRead("codes/Database/Config.txt");
if (!fileToRead.is_open())
{
throw 1; // failed to read the file
}
std::string lines[10];
for (int i{0}; i < 10; i++)
{
getline(fileToRead, lines[i]);
}
fileToRead.close();
string targetLine = lines[index + 1];
int startingIndex = targetLine.find("=") + 2;
targetLine = targetLine.substr(0, startingIndex) + newValue;
lines[index + 1] = targetLine;
std::ofstream fileToWrite ("codes/Database/Config.txt");
if (!fileToWrite.is_open())
{
throw 1; // failed to read the file
}
for (std::string l : lines)
{
fileToWrite << l << "\n";
}
fileToWrite.close();
}
int getGameHistoryLimit()
{
return strToInt(getElementOfConfig(0));
}
int getBoardSize()
{
return strToInt(getElementOfConfig(1));
}
string getBoardColor()
{
return getElementOfConfig(2);
}
string getBoardBorderColor()
{
return getElementOfConfig(3);
}
bool getSound()
{
int intBool = strToInt(getElementOfConfig(4));
return static_cast<bool>(intBool);
}
bool getShowAvailablePlacesForPieces()
{
int intBool = strToInt(getElementOfConfig(5));
return static_cast<bool>(intBool);
}
bool getHint()
{
int intBool = strToInt(getElementOfConfig(6));
return static_cast<bool>(intBool);
}
int getHintLimit()
{
return strToInt(getElementOfConfig(7));
}
void modifyGameHistoryLimit(int gameHistoryLimit)
{
modifyElementOfConfig(0, intToStr(gameHistoryLimit));
}
void modifyBoardSize(int boardSize)
{
modifyElementOfConfig(1, intToStr(boardSize));
}
void modifyBoardColor(string color)
{
modifyElementOfConfig(2, color);
}
void modifyBoardBorderColor(string color)
{
modifyElementOfConfig(3, color);
}
void modifySound(bool sound)
{
int soundToSave = static_cast<int>(sound);
modifyElementOfConfig(4, intToStr(soundToSave));
}
void modifyShowAvailablePlacesForPieces(bool newValue)
{
int newValueToSave = static_cast<int>(newValue);
modifyElementOfConfig(5, intToStr(newValueToSave));
}
void modifyHint(bool hint)
{
int hintToSave = static_cast<int>(hint);
modifyElementOfConfig(6, intToStr(hintToSave));
}
void modifyHintLimit(int hintLimit)
{
modifyElementOfConfig(7, intToStr(hintLimit));
}
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include <string>
int getGameHistoryLimit();
int getBoardSize();
std::string getBoardColor();
std::string getBoardBorderColor();
bool getSound();
bool getShowAvailablePlacesForPieces();
bool getHint();
int getHintLimit();
void modifyGameHistoryLimit(int);
void modifyBoardSize(int);
void modifyBoardColor(std::string);
void modifyBoardBorderColor(std::string);
void modifySound(bool);
void modifyShowAvailablePlacesForPieces(bool);
void modifyHint(bool);
void modifyHintLimit(int);
+3
View File
@@ -0,0 +1,3 @@
[0][.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|W|B|.|.|.|.|.|.|W|B|B|.|.|.|.|.|W|B|W|.|.|.|.|.|B|.|.|.|.|.|.|B|W|.|.|.|.|.|.|.|.|.|.|.|.|.][2Player][ramtin|W][farzad|W][W][0]
[1][.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|W|B|.|.|.|.|.|B|B|B|B|.|.|.|.|W|W|W|W|.|.|.|.|.|.|B|B|W|.|.|.|.|W|B|B|.|.|.|.|.|.|.|.|.|.|.][2Player][ramtin|W][farzad|B][B][0]
[2][W|W|W|W|W|W|W|W|W|B|B|B|B|W|B|W|W|W|W|W|B|B|W|W|W|B|W|W|W|W|B|W|W|B|W|W|W|W|B|W|W|W|W|W|B|W|W|W|W|B|B|B|W|W|W|W|W|W|W|W|W|W|B|W][1Player][ramtin|B][Hard Bot|3][W][2]
@@ -0,0 +1,391 @@
// a saved game will follow this patter:
// [gameId][.|.|.|.][1Player][PlayerName|PlayerColor][BotName or PlayerName|BotColor or PlayerColor]['B'][0] and winner at the end
// GameBoard mode Player1 Player2 or Bot current turn
#include "../Structures/Config.h"
#include "../Structures/SinglePlayerGame.h"
#include "../Structures/MultiPlayerGame.h"
#include "../Utilities/StrToInt.h"
#include "../Utilities/IntSqrt.h"
#include "../Utilities/StrToSymbol.h"
#include "GameHistoryManager.h"
#include <fstream>
// file managing
void writeTempoToGameHistory();
void updateLine(int lineIndex, std::string str);
void addLine(std::string str);
void freeLastLine();
// internal uses
int getLinesCount();
std::string getProperty(int propertyId, std::string game);
int getGameId(std::string game);
int getSavedBoardElementCount(std::string board);
// adding data
void saveGame(SinglePlayerGame* game);
void saveGame(MultiPlayerGame* game);
// extracting data
std::string getGameById(int gameId);
int getLineIndexById(int gameId);
std::string getLineByLineIndex(int lineIndex);
// external uses
SinglePlayerGame getSinglePlayerGame(int id);
MultiPlayerGame getMultiPlayerGame(int id);
void syncGameHistoryWithLimit();
int getFirstGameId();
int getLastGameId();
//----------------------------------- file managing --------------------------------------------------------------
void writeTempoToGameHistory()
{
std::ifstream tempoFileToRead("codes/Database/tempo.txt");
std::ofstream GameHistoryToWrite("codes/Database/GameHistory.txt");
if (!GameHistoryToWrite.is_open() && !tempoFileToRead.is_open())
{
throw 1; // faild to read file
}
std::string line;
while (getline(tempoFileToRead, line))
{
GameHistoryToWrite << line << "\n";
}
tempoFileToRead.close();
GameHistoryToWrite.close();
}
void freeLastLine()
{
std::ifstream GameHistoryToRead("codes/Database/GameHistory.txt");
std::ofstream tempoFileToWrite("codes/Database/tempo.txt");
if (!GameHistoryToRead.is_open() && !tempoFileToWrite.is_open())
{
throw 1; // faild to read file
}
std::string line;
getline(GameHistoryToRead, line); // skipping the first line
while (getline(GameHistoryToRead, line))
{
tempoFileToWrite << line << "\n";
}
tempoFileToWrite.close();
GameHistoryToRead.close();
writeTempoToGameHistory();
}
void updateLine(int lineIndex, std::string str)
{
std::ifstream GameHistoryToRead("codes/Database/GameHistory.txt");
std::ofstream tempoFileToWrite("codes/Database/tempo.txt");
if (!GameHistoryToRead.is_open() && !tempoFileToWrite.is_open())
{
throw 1; // faild to read file
}
int curLineIndex = 0;
std::string line;
while (getline(GameHistoryToRead, line))
{
if (curLineIndex == lineIndex)
{
tempoFileToWrite << str << "\n";
}
else
{
tempoFileToWrite << line << "\n";
}
curLineIndex++;
}
tempoFileToWrite.close();
GameHistoryToRead.close();
writeTempoToGameHistory();
}
void addLine(std::string str)
{
std::ofstream GameHistory("codes/Database/GameHistory.txt", std::ios::app);
GameHistory << str << "\n";
GameHistory.close();
}
//----------------------------------- internal use -----------------------------------------------
int getLinesCount()
{
int count = 0;
std::string line;
std::ifstream fileToRead("codes/Database/GameHistory.txt");
if (!fileToRead.is_open())
{
throw 1; // faild to read file
}
while (getline(fileToRead, line))
{
if (!line.empty()) count++;
}
return count;
}
std::string getProperty(int propertyId, std::string game)
{
for (int i = 0; i < propertyId; i++)
{
int endingIndex = game.find("]");
game = game.substr(endingIndex + 1, game.size());
}
int EndingIndex = game.find("]");
std::string property = game.substr(
1, EndingIndex - 1
);
return property;
}
int getGameId(std::string game)
{
return strToInt(getProperty(0, game));
}
void syncGameHistoryWithLimit()
// has to be called when limit changes, so GameHistory.txt stays within its new limit
{
int curCount = getLinesCount();
int limit = Config::getInstance() -> GAME_HISTORY_LIMIT;
if (curCount > limit)
{
int toRemove = curCount - limit;
for (int i = 0; i < toRemove; i++)
{
freeLastLine();
}
}
}
int getSavedBoardElementCount(std::string board)
{
int count = 0;
for (char element : board)
{
if (element == '|') count++;
}
return count + 1;
}
//--------------------------------------------- adding data --------------------------------------------------
void saveGame(SinglePlayerGame* game)
{
int thisGameId = game -> id;
std::string gameToSave = game -> retrieveGame();
int lineIndex = getLineIndexById(thisGameId);
if (lineIndex == -1)
{
addLine(gameToSave);
syncGameHistoryWithLimit();
}
else
{
updateLine(lineIndex, gameToSave);
}
}
void saveGame(MultiPlayerGame* game)
{
int thisGameId = game -> id;
std::string gameToSave = game -> retrieveGame();
int lineIndex = getLineIndexById(thisGameId);
if (lineIndex == -1)
{
addLine(gameToSave);
syncGameHistoryWithLimit();
}
else
{
updateLine(lineIndex, gameToSave);
}
}
//--------------------------------------------- extraxting data --------------------------------------------------
std::string getGameById(int gameId)
{
std::string line;
std::ifstream fileToRead("codes/Database/GameHistory.txt");
if (!fileToRead.is_open())
{
throw 1; // faild to read file
}
while (getline(fileToRead, line))
{
if (getGameId(line) == gameId)
{
return line;
}
}
return "";
}
int getLineIndexById(int gameId)
{
std::string line;
std::ifstream fileToRead("codes/Database/GameHistory.txt");
if (!fileToRead.is_open())
{
throw 1; // faild to read file
}
int id = 0;
while (getline(fileToRead, line))
{
if (getGameId(line) == gameId)
{
return id;
}
id++;
}
return -1;
}
std::string getLineByLineIndex(int lineIndex)
{
std::string line;
std::ifstream fileToRead("codes/Database/GameHistory.txt");
if (!fileToRead.is_open())
{
throw 1; // faild to read file
}
int linesCount = getLinesCount();
for (int i = 0; i < linesCount; i++)
{
getline(fileToRead, line);
if (i == lineIndex) return line;
}
return "";
}
//-------------------------------------------- external uses -----------------------------------------
int getFirstGameId()
{
int liensCount = getLinesCount();
if (liensCount == 0) return -1; // file is empty
std::string game = getLineByLineIndex(0);
return getGameId(game);
}
int getLastGameId()
{
int liensCount = getLinesCount();
if (liensCount == 0) return -1; // file is empty
std::string game = getLineByLineIndex(liensCount - 1);
return getGameId(game);
}
SinglePlayerGame getSinglePlayerGame(int id)
{
std::string savedGame = getGameById(id);
std::string savedBoard = getProperty(1, savedGame);
int boardSize = intSqrt(
getSavedBoardElementCount(savedBoard)
);
Board board {boardSize};
board.loadBoard(savedBoard);
Player player {"", 0};
player.loadPlayer(getProperty(3, savedGame));
Bot bot {"", 0};
bot.loadBot(getProperty(4, savedGame));
char turn = strToSymbol(getProperty(5, savedGame));
SinglePlayerGame game {&board, &player, &bot, turn};
game.id = id;
return game;
}
MultiPlayerGame getMultiPlayerGame(int id)
{
std::string savedGame = getGameById(id);
std::string savedBoard = getProperty(1, savedGame);
int boardSize = intSqrt(
getSavedBoardElementCount(savedBoard)
);
Board board {boardSize};
board.loadBoard(savedBoard);
Player player1 {"", 0};
player1.loadPlayer(getProperty(3, savedGame));
Player player2 {"", 0};
player2.loadPlayer(getProperty(4, savedGame));
char turn = strToSymbol(getProperty(5, savedGame));
MultiPlayerGame game {&board, &player1, &player2, turn};
game.id = id;
return game;
}
@@ -0,0 +1,17 @@
#pragma once
#include <string>
#include "../Structures/MultiPlayerGame.h"
#include "../Structures/SinglePlayerGame.h"
void saveGame(SinglePlayerGame* game);
void saveGame(MultiPlayerGame* game);
SinglePlayerGame getSinglePlayerGame(int id);
MultiPlayerGame getMultiPlayerGame(int id);
std::string getGameById(int gameId);
void syncGameHistoryWithLimit();
std::string getProperty(int propertyId, std::string game);
int getSavedBoardElementCount(std::string board);
int getGameId(std::string game);
int getFirstGameId();
int getLastGameId();
+2
View File
@@ -0,0 +1,2 @@
1 3 B
1 4 W
+77
View File
@@ -0,0 +1,77 @@
#include "../Structures/Move.h"
#include <fstream>
#include <string>
void clearGameLog();
void addLog(Move move);
int countLogs();
Move getLog(int logIndex);
void clearGameLog()
{
std::ofstream file ("codes/Database/GameLog.txt", std::ios::trunc);
if (!file.is_open())
{
throw 1; // failed to read file
}
file.close();
}
void addLog(Move move)
{
std::ofstream file("codes/Database/GameLog.txt", std::ios::app);
if (!file.is_open())
{
throw 1; // failed to read file
}
file << move.retrieveMove() << "\n";
file.close();
}
int countLogs()
{
int logCount = 0;
std::ifstream file("codes/Database/GameLog.txt");
std::string line;
while(std::getline(file, line))
{
if (line.empty()) continue;
logCount++;
}
return logCount;
}
Move getLog(int logIndex)
{
std::ifstream file ("codes/Database/GameLog.txt");
if (!file.is_open())
{
throw 1; // failed to read the file
}
std::string line;
for (int i{0}; i <= logIndex; i++)
{
std::getline(file, line);
}
Move move{0, 0, '0'};
move.loadMove(line);
return move;
}
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include "../Structures/Move.h"
void clearGameLog();
void addLog(Move move);
int countLogs();
Move getLog(int logIndex);
+3
View File
@@ -0,0 +1,3 @@
[0][.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|W|B|.|.|.|.|.|.|W|B|B|.|.|.|.|.|W|B|W|.|.|.|.|.|B|.|.|.|.|.|.|B|W|.|.|.|.|.|.|.|.|.|.|.|.|.][2Player][ramtin|W][farzad|W][W][0]
[1][.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|W|B|.|.|.|.|.|B|B|B|B|.|.|.|.|W|W|W|W|.|.|.|.|.|.|B|B|W|.|.|.|.|W|B|B|.|.|.|.|.|.|.|.|.|.|.][2Player][ramtin|W][farzad|B][B][0]
[2][W|W|W|W|W|W|W|W|W|B|B|B|B|W|B|W|W|W|W|W|B|B|W|W|W|B|W|W|W|W|B|W|W|B|W|W|W|W|B|W|W|W|W|W|B|W|W|W|W|B|B|B|W|W|W|W|W|W|W|W|W|W|B|W][1Player][ramtin|B][Hard Bot|3][W][2]
+483
View File
@@ -0,0 +1,483 @@
#include <windows.h>
#include <conio.h>
#include <iostream>
#include <limits>
#include "GameMaster.h"
#include "Database/GameLogManager.h"
#include "GameReviewer.h"
#include "Database/GameHistoryManager.h"
#include "Structures/Board.h"
#include "Structures/Player.h"
#include "Structures/Bot.h"
#include "Structures/SinglePlayerGame.h"
#include "Structures/MultiPlayerGame.h"
#include "Structures/Config.h"
#include "Utilities/outputDecoratedSavedGame.h"
#include "Utilities/GetSavedBoardSize.h"
#include <fstream>
void handleLoadGame();
void handleNewGame();
void loadSinglePlayerGame(int gameId);
void loadMultiPlayerGame(int gameId);
void handleSinglePlayerNewGame();
void handleMultiPlayerNewGame();
void executeGameMaster(bool loadGameMode)
{
clearGameLog(); // emptying GameLog for the new game
if (loadGameMode) handleLoadGame();
else handleNewGame();
}
void handleLoadGame()
{
system("cls");
std::cout << "You've chosen to load a previous unfinished game\n"
<< "Previous unfunished games are: \n";
int startingGameId = getFirstGameId();
int lastGameId = getLastGameId();
if (startingGameId == -1)
{
std::cout << "\n There are no games inside game history\n Press any key to continue";
getch();
return;
}
for (int i = startingGameId; i <= lastGameId; i++)
{
if (getProperty(6, getGameById(i)) == "0")
{
outputDecoratedSavedGame(getGameById(i));
}
}
int gameId;
std::string wantedGame;
while (true)
{
std::cout << "\n Please type the id of the game you wish to continue playing: ";
std::cin >> gameId;
std::string savedGame = getGameById(gameId);
if (getProperty(6, savedGame) != "0")
{
std::cout << "The id entered belong to a finished game, please choose an id from the given list\n";
continue;
}
wantedGame = savedGame;
break;
}
if (getProperty(2, wantedGame) == "1Player")
{
loadSinglePlayerGame(gameId);
}
else
{
loadMultiPlayerGame(gameId);
}
}
void loadSinglePlayerGame(int gameId)
{
int id = getSinglePlayerGame(gameId).id;
Board board = *(getSinglePlayerGame(gameId).GameBoard);
Player player = *(getSinglePlayerGame(gameId).Player1);
Bot bot = *(getSinglePlayerGame(gameId).GameBot);
char CurrentTurnColor = getSinglePlayerGame(gameId).CurrentTurnColor;
SinglePlayerGame game {&board, &player, &bot, CurrentTurnColor};
game.id = id;
game.Winner = 0;
game.mode = "1Player";
game.start();
std::cout << "\n The game has finished, Press any key to continue" << std::endl;
getch();
game.GameBoard -> deleteBoardMemory();
}
void loadMultiPlayerGame(int gameId)
{
int id = getMultiPlayerGame(gameId).id;
Board board = *(getMultiPlayerGame(gameId).GameBoard);
Player player1 = *(getMultiPlayerGame(gameId).Player1);
Player player2 = *(getMultiPlayerGame(gameId).Player2);
char CurrentTurnColor = getMultiPlayerGame(gameId).CurrentTurnColor;
MultiPlayerGame game {&board, &player1, &player2, CurrentTurnColor};
game.id = id;
game.Winner = 0;
game.mode = "2Player";
game.start();
std::cout << "\n The game has finished, Press any key to continue" << std::endl;
getch();
game.GameBoard -> deleteBoardMemory();
}
void handleNewGame()
{
int chosenOption = 0;
while (true)
{
system("cls");
std::cout << (chosenOption == 0 ? " > ":" ") << " Single Player" << std::endl
<< (chosenOption == 1 ? " > ":" ") << " MultiPlayer" << std::endl;
int userInput = getch();
if (userInput == static_cast<int>('w') || userInput == 72)
{
if (chosenOption == 1)
{
chosenOption--;
continue;
}
}
if (userInput == static_cast<int>('s') || userInput == 80)
{
if (chosenOption == 0)
{
chosenOption++;
continue;
}
}
if (userInput == 13)
{
if (chosenOption == 0)
{
handleSinglePlayerNewGame();
}
else if (chosenOption == 1)
{
handleMultiPlayerNewGame();
}
break;
}
}
}
void handleSinglePlayerNewGame()
{
Bot bot{"0", 0};
int chosenOption = 0;
while (true)
{
system("cls");
std::cout << "Please choose the difficulty: \n"
<< (chosenOption == 0 ? " > ":" ") << " Easy" << std::endl
<< (chosenOption == 1 ? " > ":" ") << " Medium" << std::endl
<< (chosenOption == 2 ? " > ":" ") << " Hard" << std::endl;
int userInput = getch();
if (userInput == static_cast<int>('w') || userInput == 72)
{
if (chosenOption != 0)
{
chosenOption--;
continue;
}
}
if (userInput == static_cast<int>('s') || userInput == 80)
{
if (chosenOption != 2)
{
chosenOption++;
continue;
}
}
if (userInput == 13)
{
if (chosenOption == 0)
{
bot.difficulty = 1;
bot.name = "Easy Bot";
}
else if (chosenOption == 1)
{
bot.difficulty = 2;
bot.name = "Medium Bot";
}
else if (chosenOption == 2)
{
bot.difficulty = 3;
bot.name = "Hard Bot";
}
break;
}
}
Player player{"0", 'W'};
while (true)
{
system("cls");
std::string name;
std::cout << "Please set your name: ";
std::cin >> name;
std::cout << std::endl;
if (name.find("|") != -1 || name.find("[") != -1 || name.find("]") != -1)
{
std::cout << "One day you will die"
<< "\nSome poeple will attend your funeral only for the food"
<< "\nYour friends will hang out again after 1 month"
<< "\nYour kids will go to work casually after 2 months"
<< "\nYour wife/husband will laugh with a comedy movie after 6 month"
<< "\nEventually, your name will be forgotten and memories of you fade away"
<< "\nYet some poeple like you think they can escape this fact by putting | or [ or ] inside their names"
<< "\nYou guys think noone is going to forget your name because they be like:"
<< "\n Damn bro this guy has a | or [ or ] inside their name! I'm going to remember this name till my last breath"
<< "\nLet's be real, nobody will say that unless they're high and high poeple can't remember anything more than 5 seconds"
<< "\nSo stop annoying me and choose a name without | or [ or ]"
<< "\nNow click any freaking key to continue...";
getch();
continue;
}
player.name = name;
system("cls");
break;
}
chosenOption = 0;
while (true)
{
system("cls");
std::cout << "Please choose your color\n"
<< (chosenOption == 0 ? " > ":" ") << " Black" << std::endl
<< (chosenOption == 1 ? " > ":" ") << " White" << std::endl;
int userInput = getch();
if (userInput == static_cast<int>('w') || userInput == 72)
{
if (chosenOption == 1)
{
chosenOption--;
continue;
}
}
if (userInput == static_cast<int>('s') || userInput == 80)
{
if (chosenOption == 0)
{
chosenOption++;
continue;
}
}
if (userInput == 13)
{
if (chosenOption == 0)
{
player.color = 'B';
}
else if (chosenOption == 1)
{
player.color = 'W';
}
break;
}
}
system("cls");
Board board{Config::instance -> BOARD_SIZE};
board.newGameSetup();
SinglePlayerGame game{&board, &player, &bot, 'B'};
game.start();
std::cout << "\n The game has finished, would you like to see the replay? [Y/N]" << std::endl;
char procceded;
std::cin >> procceded;
if (procceded == 'Y' || procceded == 'y')
{
executeGameReviewer(*game.GameBoard);
}
game.GameBoard -> deleteBoardMemory();
}
void handleMultiPlayerNewGame()
{
Player player1{"0", 'W'};
while (true)
{
system("cls");
std::string name;
std::cout << "Player1, Please set your name: ";
std::cin >> name;
std::cout << std::endl;
if (name.find("|") != -1 || name.find("[") != -1 || name.find("]") != -1)
{
std::cout << "One day you will die"
<< "\nSome poeple will attend your funeral only for the food"
<< "\nYour friends will hang out again after 1 month"
<< "\nYour kids will go to work casually after 2 months"
<< "\nYour wife/husband will laugh with a comedy movie after 6 month"
<< "\nEventually, your name will be forgotten and memories of you fade away"
<< "\nYet some poeple like you think they can escape this fact by putting | or [ or ] inside their names"
<< "\nYou guys think noone is going to forget your name because they be like:"
<< "\n Damn bro this guy has a | or [ or ] inside their name! I'm going to remember this name till my last breath"
<< "\nLet's be real, nobody will say that unless they're high and high poeple can't remember anything more than 5 seconds"
<< "\nSo stop annoying me and choose a name without | or [ or ]"
<< "\nNow click any freaking key to continue...";
getch();
continue;
}
player1.name = name;
system("cls");
break;
}
int chosenOption = 0;
while (true)
{
system("cls");
std::cout << "Player1, please choose your color\n"
<< (chosenOption == 0 ? " > ":" ") << " Black" << std::endl
<< (chosenOption == 1 ? " > ":" ") << " White" << std::endl;
int userInput = getch();
if (userInput == static_cast<int>('w') || userInput == 72)
{
if (chosenOption == 1)
{
chosenOption--;
continue;
}
}
if (userInput == static_cast<int>('s') || userInput == 80)
{
if (chosenOption == 0)
{
chosenOption++;
continue;
}
}
if (userInput == 13)
{
if (chosenOption == 0)
{
player1.color = 'B';
}
else if (chosenOption == 1)
{
player1.color = 'W';
}
break;
}
}
Player player2{"0", 'W'};
while (true)
{
system("cls");
std::string name;
std::cout << "Player2, Please set your name: ";
std::cin >> name;
std::cout << std::endl;
if (name.find("|") != -1 || name.find("[") != -1 || name.find("]") != -1)
{
std::cout << "One day you will die"
<< "\nSome poeple will attend your funeral only for the food"
<< "\nYour friends will hang out again after 1 month"
<< "\nYour kids will go to work casually after 2 months"
<< "\nYour wife/husband will laugh with a comedy movie after 6 month"
<< "\nEventually, your name will be forgotten and memories of you fade away"
<< "\nYet some poeple like you think they can escape this fact by putting | or [ or ] inside their names"
<< "\nYou guys think noone is going to forget your name because they be like:"
<< "\n Damn bro this guy has a | or [ or ] inside their name! I'm going to remember this name till my last breath"
<< "\nLet's be real, nobody will say that unless they're high and high poeple can't remember anything more than 5 seconds"
<< "\nSo stop annoying me and choose a name without | or [ or ]"
<< "\nNow click any freaking key to continue...";
getch();
continue;
}
player2.name = name;
player2.color = (player1.color == 'W' ? 'B':'W');
system("cls");
break;
}
system("cls");
Board board{Config::getInstance() -> BOARD_SIZE};
board.newGameSetup();
MultiPlayerGame game{&board, &player1, &player2, 'B'};
game.start();
std::cout << "\n The game has finished, would you like to see the replay? [Y/N]" << std::endl;
char procceded;
std::cin >> procceded;
if (procceded == 'Y' || procceded == 'y')
{
executeGameReviewer(*game.GameBoard);
}
game.GameBoard -> deleteBoardMemory();
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
void executeGameMaster(bool loadGameMode);
+36
View File
@@ -0,0 +1,36 @@
#include <iostream>
#include <conio.h>
#include <windows.h>
#include "GameReporter.h"
#include "Structures/Config.h"
#include "DataBase/GameHistoryManager.h"
#include "Utilities/outputDecoratedSavedGame.h"
void executeGameReporter()
{
system("cls");
std::cout << "Here is the history of the last "
<< Config::getInstance() -> GAME_HISTORY_LIMIT
<< " Played Games" << std::endl
<< "If you wish to change the number of saved games inside the history, you can change this number inside settings section of the game";
int firstId = getFirstGameId();
int lastId = getLastGameId();
if (firstId == -1)
{
std::cout << "\n There are no games inside game history\n Press any key to continue";
getch();
return;
}
for (int id = lastId; id >= firstId; id--)
{
outputDecoratedSavedGame(getGameById(id));
}
std::cout << "\nPress any key to continue";
getch();
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
void executeGameReporter();
+63
View File
@@ -0,0 +1,63 @@
#include "GameReviewer.h"
#include "Database/GameLogManager.h"
#include "Structures/Move.h"
#include "Structures/Board.h"
#include "conio.h"
#include <iostream>
#include <windows.h>
void executeGameReviewer(Board board)
{
board.CursorX = -1;
board.CursorY = -1;
int logsCount = countLogs();
int logId = -1;
while (true)
{
system("cls");
std::cout << "Press any key for next move, ESC to exit...\n";
if (logId == -1)
{
board.newGameSetup();
board.prepareBoardForMove('W');
}
else
{
Move move = getLog(logId);
board.putPiece(move.x, move.y, move.color);
if (move.color == 'B')
{
board.prepareBoardForMove('W');
}
else
{
board.prepareBoardForMove('B');
}
}
board.display();
int userInput = _getch();
if(userInput == 27)
{
break;
}
else
{
if (logId == logsCount - 1)
{
break;
}
logId++;
}
}
system("cls");
}
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include "Structures/Board.h"
void executeGameReviewer(Board board);
+8
View File
@@ -0,0 +1,8 @@
#include "Helper.h"
#include "Structures/Board.h"
#include <iostream>
void executeHelper()
{
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
void executeHelper();
+422
View File
@@ -0,0 +1,422 @@
#include "Config.h"
#include "Board.h"
#include "Move.h"
#include "../Database/GameLogManager.h"
#include "../Utilities/SymbolToStr.h"
#include <iostream>
//------------------------------- Constructor & deconstructor ----------------------------------------
Board::Board(int boardSize)
// grid holds the matrix used for game logic
// validMovesGrid is only used to show valid moves
// display grid is used to potentially combine grid and validMovesGrid for displaying the board
{
BoardSize = boardSize;
grid = new char*[boardSize];
for (int i = 0; i < boardSize; ++i) {
grid[i] = new char[boardSize];
}
validMovesGrid = new char*[boardSize];
for (int i = 0; i < boardSize; ++i) {
validMovesGrid[i] = new char[boardSize];
}
displayGrid = new char*[boardSize];
for (int i = 0; i < boardSize; ++i) {
displayGrid[i] = new char[boardSize];
}
for (int y = 0; y < boardSize; y++)
{
for (int x = 0; x < boardSize; x++)
{
grid[y][x] = '.';
validMovesGrid[y][x] = '.';
displayGrid[y][x] = '.';
}
}
}
void Board::deleteBoardMemory()
// when the game is over and maybe GameReviewer was executed
// this method has to be called to free up the allocated memory
// a destructor could do the job too
{
for (int i = 0; i < BoardSize; ++i)
{
delete[] grid[i];
}
delete[] grid;
for (int i = 0; i < BoardSize; ++i)
{
delete[] validMovesGrid[i];
}
delete[] validMovesGrid;
for (int i = 0; i < BoardSize; ++i)
{
delete[] displayGrid[i];
}
delete[] displayGrid;
}
//-------------------------------- Database & pre-game operations ------------------------------------
std::string Board::retrieveBoard()
// turns grid into string format to be saved inside database
// this string can be used to create a grid using loadBoard method
{
int size = BoardSize * BoardSize + BoardSize;
std::string result = "";
for (int y = 0; y < BoardSize; y++)
{
for (int x = 0; x < BoardSize; x++)
{
result += symbolToStr(grid[y][x]);
if (!(y == BoardSize-1 && x == BoardSize-1))
{
result += "|";
}
}
}
return result;
}
void Board::newGameSetup()
// grid represents the starting state of the board when playing a new game
// called for board before passing its pointer for creating a SinglePlayerGame/MultiPlayerGame instance
{
for (int y = 0; y < BoardSize; y++)
{
for (int x = 0; x < BoardSize; x++)
{
grid[y][x] = '.';
}
}
grid[BoardSize/2 - 1][BoardSize/2 - 1] = 'W';
grid[BoardSize/2][BoardSize/2] = 'W';
grid[BoardSize/2][BoardSize/2 - 1] = 'B';
grid[BoardSize/2 - 1][BoardSize/2] = 'B';
updateDisplayGrid();
}
void Board::loadBoard(std::string Board)
// recreates grid based on a string inside database
// this string is created by retrieveBoard method
{
int index = 0;
for (int y = 0; y < BoardSize; y++)
{
for (int x = 0; x < BoardSize; x++)
{
grid[y][x] = static_cast<char>(Board[index]);
index += 2;
}
}
updateDisplayGrid();
}
// ------------------------------------- grid and game operations -----------------------------------------
void Board::prepareBoardForMove(char thisTurnColor)
// this method has to be called when a valid move is made
// updated displayGrid with the latest changes in grid
// validMovesGrid will find valid moves based on the new grid
// if user has chosen to see valid moves inside the board (SHOW_AVAILABLE_PLACES_FOR_PIECES is set to true)
// then they are putted inside the displayGrid (combining grid and validMovesGrid)
{
updateDisplayGrid();
prepareValidMovesGrid(thisTurnColor);
if (Config::getInstance() -> SHOW_AVAILABLE_PLACES_FOR_PIECES)
putValidMoves();
}
void Board::flip(int x, int y)
// changes the color of the piece inside the given coordinates
{
if (grid[y][x] == 'B')
grid[y][x] = 'W';
else if (grid[y][x] == 'W')
grid[y][x] = 'B';
}
void Board::putPiece(int x, int y, char color)
{
grid[y][x] = color;
Move move(x, y, color);
addLog(move);
// each comnination of coresponding elements represent a diraction
// left-up & left & left-down & up & down & right-uo & right & right-down
const int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1};
const int dy[] = {-1, 0, 1, -1, 1, -1, 0, 1};
for (int d = 0; d < 8; ++d)
{
int flips = countFlipsInDirection(x, y, dx[d], dy[d], color);
if (flips > 0)
{
int xc = x + dx[d];
int yc = y + dy[d];
for (int step = 0; step < flips; ++step)
{
flip(xc, yc);
xc += dx[d];
yc += dy[d];
}
}
}
}
int Board::countBlack()
// counts the black pieces of the Board
{
int count = 0;
for (int y = 0; y < BoardSize; y++)
{
for (int x = 0; x < BoardSize; x++)
{
if (grid[y][x] == 'B') count++;
}
}
return count;
}
int Board::countWhite()
// counts the white pieces of the Board
{
int count = 0;
for (int y = 0; y < BoardSize; y++)
{
for (int x = 0; x < BoardSize; x++)
{
if (grid[y][x] == 'W') count++;
}
}
return count;
}
//------------------------------------------ validGrid operations --------------------------------------------
int Board::countValidMoves()
// returns the number of valid moves that can be made for the current turn
// should be called when validMovesGrid is created for the turn
// in a nutshell, after prepareBoardForMove method is called
// used to decide of a game has to end
{
int count = 0;
for (int y = 0; y < BoardSize; y++)
{
for (int x = 0; x < BoardSize; x++)
{
if (validMovesGrid[y][x] == 'O') count++;
}
}
return count;
}
int Board::isValid(int x, int y, char color)
// returns the number of gains (opponent pieces fliped) if a piece with the given color is put in the given coords
// if it returns 0, then the move is inValid
// used as the primary parameter for the medium bot
{
if (grid[y][x] != '.') return 0;
int totalFlips = 0;
// each comnination of coresponding elements represent a diraction
// left-up & left & left-down & up & down & right-uo & right & right-down
const int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1};
const int dy[] = {-1, 0, 1, -1, 1, -1, 0, 1};
for (int d = 0; d < 8; d++)
{
totalFlips += countFlipsInDirection(x, y, dx[d], dy[d], color);
}
return totalFlips;
}
int Board::countFlipsInDirection(int x, int y, int dx, int dy, char color)
// counts the number of flips happened by putting a piece with the given color inside the given coordinates
// dx and dy represent the direction and more specificly, the steps of x and y
{
char oppColor = (color == 'B' ? 'W' : 'B');
int flips = 0;
int xc = x + dx;
int yc = y + dy;
while ((xc >= 0 && xc < BoardSize) && (yc >= 0 && yc < BoardSize) && grid[yc][xc] == oppColor)
{
flips++;
xc += dx;
yc += dy;
}
// if loop doesn't meet a same colored piece, one of x coords or y coords will get out of bond
// or the element loop breaked for is whether a '.' (empty place)
if ((xc < 0 || xc == BoardSize) || (yc < 0 || yc == BoardSize) || grid[yc][xc] != color)
{
return 0;
}
return flips;
}
void Board::resetValidMovesGrid()
// clears validGrid elements to empty places
{
for (int y = 0; y < BoardSize; y++)
{
for (int x = 0; x < BoardSize; x++)
{
validMovesGrid[y][x] = '.';
}
}
}
void Board::prepareValidMovesGrid(char color)
// first ValidMovesGrid resets itself so previous data won't interupt the process
// then check each place in grid, if it's valid, it'll put O inside the coresponding coordinates inside itself
{
resetValidMovesGrid();
for (int y = 0; y < BoardSize; y++)
{
for (int x = 0; x < BoardSize; x++)
{
if (isValid(x, y, color) != 0)
validMovesGrid[y][x] = 'O';
}
}
}
//----------------------------------- display and displayGrid operations -----------------------------------------
void Board::updateDisplayGrid()
// displayGrid be copied based on the elements (pieces) inside grid
{
for (int y = 0; y < BoardSize; y++)
{
for (int x = 0; x < BoardSize; x++)
{
displayGrid[y][x] = grid[y][x];
}
}
}
void Board::putValidMoves()
// validMovesGrid has the valid moves coordinates inside itself
// by calling this method, displayGrid will mark valid moves which
// validMovesGrid marks
{
for (int y = 0; y < BoardSize; y++)
{
for (int x = 0; x < BoardSize; x++)
{
if (validMovesGrid[y][x] == 'O')
{
displayGrid[y][x] = 'O';
}
}
}
}
void Board::display()
// outputs displayGrid with viasual decorations
{
std::cout << " ";
for (int i = 1; i <= BoardSize; i++)
{
std::cout << i << " ";
}
std::cout << std::endl;
std::cout << " ";
std::cout << (char)201;
for (int i = 0; i < BoardSize; i++)
{
std::cout << (char)205 << (char)205 << (char)205;
}
std::cout << (char)187 << std::endl;
for (int y = 0; y < BoardSize; y++)
{
std::cout << y + 1 << " " << (char)186;
for (int x = 0; x < BoardSize; x++)
{
if (y == CursorY && x == CursorX) std::cout << "[";
else std::cout << " ";
char element = displayGrid[y][x];
if (element == 'W') // white piece
{
std::cout << 'X';
}
else if (element == 'B') // black piece
{
std::cout << 'O';
}
else if (element == '.') // empty space
{
std::cout << ' ';
}
else if (element == 'O') // valid move
{
std::cout << (char)249; // ∙
}
if (y == CursorY && x == CursorX) std::cout << "]";
else std::cout << " ";
}
std::cout << (char)186 << std::endl;
}
std::cout << " ";
std::cout << (char)200;
for (int i = 0; i < BoardSize; i++)
{
std::cout << (char)205 << (char)205 << (char)205;
}
std::cout << (char)188 << std::endl;
}
// (char)186 = ║ (char)200 = ╚ (char)188 = ╝ (char)205 = ═ (char)206 = ╦ (char)202 = ╩ (char)187 = ╗ (char)201 = ╔
// (char)79 = O
// (char)254 = ■
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include <string>
struct Board
{
int BoardSize;
char** grid;
char** validMovesGrid;
char** displayGrid;
int CursorX = 0;
int CursorY = 0;
public:
Board(int boardSize);
void deleteBoardMemory();
std::string retrieveBoard();
void newGameSetup();
void loadBoard(std::string Board);
void prepareBoardForMove(char thisTurnColor);
void putPiece(int x, int y, char color);
int countBlack();
int countWhite();
int isValid(int x, int y, char color);
int countValidMoves();
void display();
public:
void flip(int x, int y);
int countFlipsInDirection(int x, int y, int dx, int dy, char color);
void resetValidMovesGrid();
void prepareValidMovesGrid(char color);
void updateDisplayGrid();
void putValidMoves();
};
+372
View File
@@ -0,0 +1,372 @@
#include "Bot.h"
#include "Board.h"
#include "Move.h"
#include "../Utilities/IntToStr.h"
#include "../Utilities/StrToInt.h"
#include <string>
#include <random>
#include <climits>
Bot::Bot(std::string name, int difficulty)
{
this -> name = name;
this -> difficulty = difficulty;
}
Move Bot::suggestMove(Board& board, char color)
// the fucntion called by GameMaster when it's bot's turn to move
// this function should be called when prepareBoardForMove is called
// so bot will work as expected
{
if (difficulty == 1) // easy
{
return suggestEasyMove(board, color);
}
else if (difficulty == 2) // medium
{
return suggestMediumMove(board, color);
}
else if (difficulty == 3) // hard
{
return suggestHardMove(board, color);
}
else
{
return suggestMediumMove(board, color); // fallback
}
}
Move Bot::suggestEasyMove(Board& board, char color)
// the decision a bot would make in easy mode
// the act is based on a random choice
{
int validMovesCount = board.countValidMoves();
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> distrib(0, validMovesCount-1);
int randomNumber = distrib(gen);
int moveNumber = 0;
for (int y = 0; y < board.BoardSize; y++)
{
for (int x = 0; x < board.BoardSize; x++)
{
if (board.validMovesGrid[y][x] == 'O')
{
if (moveNumber == randomNumber)
{
Move move{x, y, color};
return move;
}
else
{
moveNumber++;
}
}
}
}
}
Move Bot::suggestMediumMove(Board& board, char color)
// the decision a bot would make in medium mode
// the act is based on how much gain each move will have
// the move with the most gain is made
{
int moveX, moveY;
int maxGain = 0;
for (int y = 0; y < board.BoardSize; y++)
{
for (int x = 0; x < board.BoardSize; x++)
{
if (board.validMovesGrid[y][x] == 'O')
{
int gain = board.isValid(x, y, color);
if (gain > maxGain)
{
moveY = y;
moveX = x;
maxGain = gain;
}
}
}
}
Move move{moveX, moveY, color};
return move;
}
Move Bot::suggestHardMove(Board& board, char color)
// the decision a bot would make in hard mode
{
char oppColor = (color == 'W' ? 'B':'W');
int index = 0;
int validMovesCount = board.countValidMoves();
Move moves[validMovesCount];
for (int y = 0; y < board.BoardSize; y++)
{
for (int x = 0; x < board.BoardSize; x++)
{
if (board.validMovesGrid[y][x] == 'O')
{
Move move {x, y, color};
moves[index] = move;
index++;
}
}
}
Move bestMove = moves[0];
int bestScore = INT_MIN;
for (int i = 0; i < validMovesCount; i++)
{
Move move = moves[i];
Board dummyBoard {board.BoardSize};
deepCopy(board, dummyBoard);
dummyBoard.putPiece(move.x, move.y, move.color);
dummyBoard.prepareBoardForMove(oppColor);
int score = minimax(oppColor, dummyBoard, false, color); // start minimizing since its user's turn
if (score > bestScore)
{
bestScore = score;
bestMove = move;
}
}
return bestMove;
}
std::string Bot::retrieveBot()
// turns Bot structure into a string to be saved inside database
// this string will be loaded using loadBot method
{
return name + "|" + intToStr(difficulty);
}
void Bot::loadBot(std::string bot)
// fills Bot's properties according to the given string
// this string is bot's informating saved inside database
// this string was made using retrieveBot method
{
int seperatorIndex = bot.find("|");
name = bot.substr(0, seperatorIndex);
difficulty = strToInt(bot.substr(seperatorIndex + 1, bot.size()));
}
//----------------------------------------- minimax algorithm ----------------------------------------------------
int Bot::ratePlacement(int x, int y, int boardSize)
// Board is passed by refrence for time optimization
// if we put a piece with these information, what score would the piece get
// for the coordinates itselves
{
// corners
if ((x == boardSize - 1 || x == 0) && (y == boardSize - 1 || y == 0))
return 100;
// leading to corner moves:
else if (
(x == boardSize - 2 && y == 1) ||
(x == boardSize - 2 && y == boardSize - 2) ||
(x == 1 && y == 1) ||
(x == 1 && y == boardSize - 2)
)
return -50;
else if (
(x == boardSize - 2 && y == boardSize - 1) ||
(x == boardSize - 2 && y == 0) ||
(x == 1 && y == 0) ||
(x == 1 && y == boardSize - 1) ||
(x == boardSize - 1 && y == 1) ||
(x == boardSize - 1 && y == boardSize - 2) ||
(x == 0 && y == 1) ||
(x == 0 && y == boardSize - 2)
)
return -30;
// edges (corners and corner neighbour already handled)
else if (x == 0 || x == boardSize - 1 || y == 0 || y == boardSize - 1)
return 3;
// center
else if (
(x == boardSize/2 && y == boardSize/2) ||
(x == boardSize/2 && y == boardSize/2 - 1) ||
(x == boardSize/2 - 1 && y == boardSize/2) ||
(x == boardSize/2 - 1 && y == boardSize/2 - 1)
)
return 3;
// other places have no value on their own
return 0;
}
int Bot::rateBoard(Board& board, char botColor)
{
char oppColor = (botColor == 'W' ? 'B':'W');
Board dummyBoard {board.BoardSize};
deepCopy(board, dummyBoard);
int botScore = 0, playerScore = 0;
// possible moves rating
dummyBoard.prepareBoardForMove(botColor);
botScore += dummyBoard.countValidMoves();
dummyBoard.prepareBoardForMove(oppColor);
botScore -= dummyBoard.countValidMoves();
// greedy strategy
int blackCount = dummyBoard.countBlack();
int whiteCount = dummyBoard.countWhite();
if (botColor == 'B')
{
botScore += blackCount;
botScore -= whiteCount;
}
else
{
botScore -= blackCount;
botScore += whiteCount;
}
// placement score
for (int y = 0; y < board.BoardSize; y++)
{
for (int x =0; x < board.BoardSize; x++)
{
char element = board.grid[y][x];
if (element == 'W' || element == 'B')
{
int score = ratePlacement(x, y, board.BoardSize);
if (element == botColor)
{
botScore += score;
}
else
{
botScore -= score;
}
}
}
}
return botScore;
}
int Bot::minimax(char color, Board dummyBoard, bool isMaxAgent, char botColor, int depth, int upFloor, int downFloor)
{
int index = 0;
int validMovesCount = dummyBoard.countValidMoves();
if (depth == 3 || validMovesCount == 0)
{
return rateBoard(dummyBoard, botColor);
}
Move moves[validMovesCount];
for (int y = 0; y < dummyBoard.BoardSize; y++)
{
for (int x = 0; x < dummyBoard.BoardSize; x++)
{
if (dummyBoard.validMovesGrid[y][x] == 'O')
{
Move move {x, y, color};
moves[index] = move;
index++;
}
}
}
if (isMaxAgent) // maximizing
{
int curMax = INT_MIN;
// for each valid move in this turn
for (int i = 0; i < validMovesCount; i++)
{
Move move = moves[i];
Board newBoard{dummyBoard.BoardSize};
deepCopy(dummyBoard, newBoard);
newBoard.putPiece(move.x, move.y, move.color);
newBoard.prepareBoardForMove(move.color == 'B' ? 'W':'B');
int minAgentAnswer = minimax((move.color == 'B' ? 'W':'B'), newBoard, false, botColor, depth + 1, upFloor, downFloor);
curMax = std::max(curMax, minAgentAnswer);
upFloor = std::max(upFloor, curMax);
if (upFloor >= downFloor) break;
}
return curMax;
}
else // minimizing
{
int curMin = INT_MAX;
// for each valid move in this turn
for (int i = 0; i < validMovesCount; i++)
{
Move move = moves[i];
Board newBoard{dummyBoard.BoardSize};
deepCopy(dummyBoard, newBoard);
newBoard.putPiece(move.x, move.y, move.color);
newBoard.prepareBoardForMove(move.color == 'B' ? 'W':'B');
int maxAgentAnswer = minimax((move.color == 'B' ? 'W':'B'), newBoard, true, botColor, depth + 1, upFloor, downFloor);
curMin = std::min(curMin, maxAgentAnswer);
downFloor = std::min(downFloor, curMin);
if (upFloor >= downFloor) break;
}
return curMin;
}
}
void Bot::deepCopy(Board& board, Board& newBoard)
{
for (int y = 0; y < board.BoardSize; y++)
{
for (int x = 0; x < board.BoardSize; x++)
{
newBoard.grid[y][x] = board.grid[y][x];
}
}
}
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#include <string>
#include "Board.h"
#include "Move.h"
struct Bot
{
std::string name;
int difficulty;
public:
Bot(std::string name, int difficulty);
Move suggestMove(Board& board, char color);
std::string retrieveBot();
void loadBot(std::string bot);
private:
Move suggestEasyMove(Board& borad, char color);
Move suggestMediumMove(Board& board, char color);
Move suggestHardMove(Board& board, char color);
int ratePlacement(int x, int y, int boardSize);
int rateBoard(Board& board, char botColor);
int minimax(char color, Board dummyBoard, bool isMaxAgent, char botColor, int depth = 0, int upFloor = INT_MIN, int downFloor = INT_MAX);
void deepCopy(Board& board, Board& newBoard);
};
+58
View File
@@ -0,0 +1,58 @@
#include "../Database/ConfigManager.h"
#include "Config.h"
#include <iostream>
#include <windows.h>
Config* Config::instance = nullptr;
Config::Config()
{
try
{
GAME_HISTORY_LIMIT = getGameHistoryLimit();
BOARD_SIZE = getBoardSize();
BOARD_COLOR = getBoardColor();
BOARD_BORDER_COLOR = getBoardBorderColor();
SOUND = getSound();
SHOW_AVAILABLE_PLACES_FOR_PIECES = getShowAvailablePlacesForPieces();
HINT = getHint();
HINT_LIMIT = getHintLimit();
}
catch (int errorCode)
{
if (errorCode == 1)
{
system("cls");
std::cout << "An error acoured while opening Config.txt \nPerhaps another program is using it\nPress any key to continue";
getchar();
}
else if (errorCode == 2)
{
system("cls");
std::cout << "the inputed index is out of the bond of Config, the last index is 7\nPress any key to continue";
getchar();
}
else
{
system("cls");
std::cout << "Unexpected error acoured\nPress any key to continue";
getchar();
}
}
}
Config* Config::getInstance()
{
if (!instance)
throw 3; // config not initialized
return instance;
}
void Config::initialize()
{
if (!instance)
instance = new Config();
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include <string>
struct Config
{
static Config* instance;
int GAME_HISTORY_LIMIT;
int BOARD_SIZE;
std::string BOARD_COLOR;
std::string BOARD_BORDER_COLOR;
bool SOUND;
bool SHOW_AVAILABLE_PLACES_FOR_PIECES;
bool HINT;
int HINT_LIMIT;
private:
Config();
public:
static Config* getInstance();
static void initialize();
};
+44
View File
@@ -0,0 +1,44 @@
#include "Move.h"
#include "../Utilities/StrToInt.h"
#include "../Utilities/IntToStr.h"
#include "../Utilities/StrToSymbol.h"
#include "../Utilities/SymbolToStr.h"
#include <string>
Move::Move()
{
this -> x = 0;
this -> y = 0;
this -> color = 'B';
}
Move::Move(int x, int y, char color)
{
this -> x = x;
this -> y = y;
this -> color = color;
}
std::string Move::retrieveMove()
{
return intToStr(x) + " " + intToStr(y) + " " + symbolToStr(color);
}
void Move::loadMove(std::string move)
{
int xLastIndex = move.find(" ");
std::string x = move.substr(0, xLastIndex);
move = move.substr(xLastIndex + 1, move.size());
int yLastIndex = move.find(" ");
std::string y = move.substr(0, yLastIndex);
move = move.substr(yLastIndex + 1, move.size());
std::string color = move.substr(0, move.size());
this -> x = strToInt(x);
this -> y = strToInt(y);
this -> color = strToSymbol(color);
};
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include <string>
struct Move
{
int x;
int y;
char color;
public:
Move(int x, int y, char color);
Move();
std::string retrieveMove();
void loadMove(std::string move);
};
@@ -0,0 +1,190 @@
#include "../Database/GameHistoryManager.h"
#include "../Database/GameLogManager.h"
#include "../Utilities/IntToStr.h"
#include "../Utilities/SymbolToStr.h"
#include "Board.h"
#include "Player.h"
#include "MultiPlayerGame.h"
#include <conio.h>
#include <iostream>
#include <windows.h>
MultiPlayerGame::MultiPlayerGame(Board* GameBoard, Player* Player1, Player* Player2, char CurrentTurnColor)
{
int lastId = getLastGameId();
this -> id = lastId + 1;
this -> GameBoard = GameBoard;
this -> mode = "2Player";
this -> Player1 = Player1;
this -> Player2 = Player2;
this -> CurrentTurnColor = CurrentTurnColor;
this -> Winner = 0;
}
void MultiPlayerGame::changeTurn()
{
if (CurrentTurnColor == 'B')
{
CurrentTurnColor = 'W';
}
else
{
CurrentTurnColor = 'B';
}
}
void MultiPlayerGame::start()
{
clearGameLog();
(*GameBoard).prepareBoardForMove(CurrentTurnColor);
this -> save();
while (true)
{
system("cls");
std::cout << (CurrentTurnColor == Player1 -> color ? Player2 -> name + "it's your turn" : Player2 -> name + "it's your turn") << std::endl;
(*GameBoard).display();
int userInput = getch();
if (userInput == static_cast<int>('w') || userInput == 72)
{
if (GameBoard -> CursorY != 0)
{
GameBoard -> CursorY--;
}
}
else if (userInput == static_cast<int>('s') || userInput == 80)
{
if (GameBoard -> CursorY != GameBoard -> BoardSize - 1)
{
GameBoard -> CursorY++;
}
}
else if (userInput == static_cast<int>('a') || userInput == 75)
{
if (GameBoard -> CursorX != 0)
{
GameBoard -> CursorX--;
}
}
else if (userInput == static_cast<int>('d') || userInput == 77)
{
if (GameBoard -> CursorX != GameBoard -> BoardSize - 1)
{
GameBoard -> CursorX++;
}
}
else if (userInput == 13)
{
if ( (*GameBoard).validMovesGrid[GameBoard -> CursorY][GameBoard -> CursorX] == 'O')
{
(*GameBoard).putPiece(GameBoard -> CursorX, GameBoard -> CursorY, CurrentTurnColor);
changeTurn();
(*GameBoard).prepareBoardForMove(CurrentTurnColor);
this -> save();
if ((*GameBoard).countValidMoves() == 0)
{
changeTurn();
(*GameBoard).prepareBoardForMove(CurrentTurnColor);
this -> save();
if ( (*GameBoard).countValidMoves() == 0)
{
end();
return;
}
}
}
}
}
}
void MultiPlayerGame::end()
{
int blackCount = (*GameBoard).countBlack();
int whiteCount = (*GameBoard).countWhite();
system("cls");
(*GameBoard).display();
std::cout << "\nFinal Score: Black: " << blackCount
<< " | White: " << whiteCount << "\n\n";
if (blackCount > whiteCount)
{
if (Player1->color == 'B')
{
Winner = 1;
std::cout << "Congratulations " << Player1->name << "! You won!\n";
}
else
{
Winner = 2;
std::cout << "Congratulations " << Player2->name << "! You won!\n";
}
}
else if (whiteCount > blackCount)
{
if (Player1->color == 'W')
{
Winner = 1;
std::cout << "Congratulations " << Player1->name << "! You won!\n";
}
else
{
Winner = 2;
std::cout << "You lost. The bot won.\n";
}
}
else
{
Winner = 3; // Draw
std::cout << "It's a draw!\n";
}
this->save();
}
void MultiPlayerGame::save()
// saves the game inside GameHistory.txt
{
saveGame(this);
}
std::string MultiPlayerGame::retrieveGame()
// turns current Game instance into a string
// this string can be turned into a Game instance via loadGame method
{
std::string idToSave = intToStr(id);
std::string boardToSave = (*GameBoard).retrieveBoard();
std::string player1ToSave = Player1 -> retrievePlayer();
std::string player2ToSave = Player2 -> retrievePlayer();
std::string currentTurnToSave = symbolToStr(CurrentTurnColor);
std::string winnerToSave = intToStr(Winner);
return "[" + idToSave + "]["
+ boardToSave + "]["
+ mode + "]["
+ player1ToSave + "]["
+ player2ToSave + "]["
+ currentTurnToSave + "]["
+ winnerToSave + "]";
}
@@ -0,0 +1,26 @@
#pragma once
#include "Board.h"
#include "Player.h"
#include <string>
struct MultiPlayerGame
{
int id;
Board* GameBoard;
std::string mode;
Player* Player1;
Player* Player2;
char CurrentTurnColor;
int Winner;
public:
MultiPlayerGame(Board* GameBoard, Player* Player1, Player* Player2, char CurrentTurnColor);
void start();
std::string retrieveGame();
private:
void end();
void save();
void changeTurn();
};
+27
View File
@@ -0,0 +1,27 @@
#include <string>
#include "Player.h"
#include "../Utilities/SymbolToStr.h"
#include "../Utilities/StrToSymbol.h"
Player::Player(std::string name, char color)
{
this -> name = name;
this -> color = color;
}
std::string Player::retrievePlayer()
{
return name + "|" + symbolToStr(color);
}
void Player::loadPlayer(std::string player)
{
int speratorIndex = player.find("|");
std::string name = player.substr(0, speratorIndex);
std::string color = player.substr(speratorIndex + 1, player.size());
this -> name = name;
this -> color = strToSymbol(color);
}
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include <string>
struct Player
{
std::string name;
char color;
public:
Player(std::string name, char color);
std::string retrievePlayer();
void loadPlayer(std::string player);
};
@@ -0,0 +1,213 @@
#include "../Database/GameHistoryManager.h"
#include "../Database/GameLogManager.h"
#include "../Utilities/IntToStr.h"
#include "../Utilities/SymbolToStr.h"
#include "Board.h"
#include "Bot.h"
#include "Player.h"
#include "SinglePlayerGame.h"
#include <conio.h>
#include <iostream>
#include <windows.h>
SinglePlayerGame::SinglePlayerGame(Board *GameBoard, Player* Player1, Bot* GameBot, char CurrentTurnColor)
{
int lastId = getLastGameId();
this -> id = lastId + 1;
this -> GameBoard = GameBoard;
this -> mode = "1Player";
this -> Player1 = Player1;
this -> GameBot = GameBot;
this -> CurrentTurnColor = CurrentTurnColor;
this -> Winner = 0;
}
void SinglePlayerGame::changeTurn()
{
if (CurrentTurnColor == 'B')
{
CurrentTurnColor = 'W';
}
else
{
CurrentTurnColor = 'B';
}
}
void SinglePlayerGame::start()
{
clearGameLog();
(*GameBoard).prepareBoardForMove(CurrentTurnColor);
this -> save();
while (true)
{
if (CurrentTurnColor != Player1 -> color) // Bot turn
{
Move botMove = GameBot -> suggestMove( (*GameBoard), CurrentTurnColor);
GameBoard -> putPiece(botMove.x, botMove.y, CurrentTurnColor);
changeTurn();
(*GameBoard).prepareBoardForMove(CurrentTurnColor);
this -> save();
if ( (*GameBoard).countValidMoves() == 0)
{
changeTurn();
(*GameBoard).prepareBoardForMove(CurrentTurnColor);
this -> save();
if ( (*GameBoard).countValidMoves() == 0)
{
end();
return;
}
}
}
system("cls");
(*GameBoard).display();
int userInput = getch();
if (userInput == static_cast<int>('w') || userInput == 72)
{
if (GameBoard -> CursorY != 0)
{
GameBoard -> CursorY--;
}
}
else if (userInput == static_cast<int>('s') || userInput == 80)
{
if (GameBoard -> CursorY != GameBoard -> BoardSize - 1)
{
GameBoard -> CursorY++;
}
}
else if (userInput == static_cast<int>('a') || userInput == 75)
{
if (GameBoard -> CursorX != 0)
{
GameBoard -> CursorX--;
}
}
else if (userInput == static_cast<int>('d') || userInput == 77)
{
if (GameBoard -> CursorX != GameBoard -> BoardSize - 1)
{
GameBoard -> CursorX++;
}
}
else if (userInput == 13)
{
if ( (*GameBoard).validMovesGrid[GameBoard -> CursorY][GameBoard -> CursorX] == 'O')
{
(*GameBoard).putPiece(GameBoard -> CursorX, GameBoard -> CursorY, CurrentTurnColor);
changeTurn();
(*GameBoard).prepareBoardForMove(CurrentTurnColor);
this -> save();
if ((*GameBoard).countValidMoves() == 0)
{
changeTurn();
(*GameBoard).prepareBoardForMove(CurrentTurnColor);
this -> save();
if ( (*GameBoard).countValidMoves() == 0)
{
end();
return;
}
}
}
}
}
}
void SinglePlayerGame::end()
{
int blackCount = (*GameBoard).countBlack();
int whiteCount = (*GameBoard).countWhite();
system("cls");
(*GameBoard).display();
std::cout << "\nFinal Score: Black: " << blackCount
<< " | White: " << whiteCount << "\n\n";
if (blackCount > whiteCount)
{
if (Player1->color == 'B')
{
Winner = 1;
std::cout << "Congratulations " << Player1->name << "! You won!\n";
}
else
{
Winner = 2;
std::cout << "You lost. The bot won.\n";
}
}
else if (whiteCount > blackCount)
{
if (Player1->color == 'W')
{
Winner = 1;
std::cout << "Congratulations " << Player1->name << "! You won!\n";
}
else
{
Winner = 2;
std::cout << "You lost. The bot won.\n";
}
}
else
{
Winner = 3; // Draw
std::cout << "It's a draw!\n";
}
this->save();
}
void SinglePlayerGame::save()
// saves the game inside GameHistory.txt
{
saveGame(this);
}
std::string SinglePlayerGame::retrieveGame()
// turns current Game instance into a string
// this string can be turned into a Game instance via loadGame method
{
std::string idToSave = intToStr(id);
std::string boardToSave = (*GameBoard).retrieveBoard();
std::string playerToSave = Player1 -> retrievePlayer();
std::string botToSave = GameBot -> retrieveBot();
std::string currentTurnToSave = symbolToStr(CurrentTurnColor);
std::string winnerToSave = intToStr(Winner);
return "[" + idToSave + "]["
+ boardToSave + "]["
+ mode + "]["
+ playerToSave + "]["
+ botToSave + "]["
+ currentTurnToSave + "]["
+ winnerToSave + "]";
}
@@ -0,0 +1,27 @@
#pragma once
#include "Board.h"
#include "Bot.h"
#include "Player.h"
#include <string>
struct SinglePlayerGame
{
int id;
Board* GameBoard;
std::string mode;
Player* Player1;
Bot* GameBot;
char CurrentTurnColor;
int Winner;
public:
SinglePlayerGame(Board* GameBoard, Player* Player1, Bot* GameBot, char CurrentTurnColor);
void start();
std::string retrieveGame();
private:
void end();
void save();
void changeTurn();
};
@@ -0,0 +1,10 @@
#include "../Database/GameHistoryManager.h"
#include "IntSqrt.h"
#include "GetSavedBoardSize.h"
#include <string>
int getSavedBoardSize(std::string board)
{
int elementCount = getSavedBoardElementCount(board);
return intSqrt(elementCount);
}
@@ -0,0 +1,5 @@
#pragma once
#include <string>
int getSavedBoardSize(std::string board);
+10
View File
@@ -0,0 +1,10 @@
#include "IntSqrt.h"
int intSqrt(int number)
{
for (int i = 1; i < 100000000; i++)
{
if (i * i == number) return i;
}
return -1;
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
int intSqrt(int);
+73
View File
@@ -0,0 +1,73 @@
#include <string>
#include "IntToStr.h"
char getChar(int digit);
int getDigitsCount(int number);
std::string intToStr(int number)
{
int numberLen = getDigitsCount(number);
char result[numberLen];
for (int i = numberLen - 1; i >= 0; i--)
{
result[i] = getChar(number % 10);
number /= 10;
}
std::string resultStr = "";
for (int i = 0; i < numberLen; i++)
{
resultStr += result[i];
}
return resultStr;
}
char getChar(int digit)
{
switch (digit)
{
case 0:
return '0';
case 1:
return '1';
case 2:
return '2';
case 3:
return '3';
case 4:
return '4';
case 5:
return '5';
case 6:
return '6';
case 7:
return '7';
case 8:
return '8';
case 9:
return '9';
}
}
int getDigitsCount(int number)
{
if (number == 0) return 1;
int count = 0;
while(number != 0)
{
number /= 10;
count++;
}
return count;
}
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include <string>
std::string intToStr(int);
+7
View File
@@ -0,0 +1,7 @@
#include <iostream>
#include "Print.h"
void print(std::string subject, int count)
{
for (int i = 0; i < count; i++) std::cout << subject;
}
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include <string>
void print(std::string subject, int count);
+51
View File
@@ -0,0 +1,51 @@
#include <string>
#include "StrToInt.h"
int getNumber(char digit);
// turns a string containing digits into a integer
int strToInt(std::string number)
{
int result = 0;
while (number != "")
{
result = result*10 + getNumber((char) number[0]);
number = number.substr(1, number.size());
}
return result;
}
int getNumber(char digit)
{
switch (digit)
{
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
default:
return 0;
}
}
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include <string>
int strToInt(std::string number);
+25
View File
@@ -0,0 +1,25 @@
#include <string>
char strToSymbol(std::string character)
{
if (character == "W")
{
return 'W';
}
else if (character == "B")
{
return 'B';
}
else if (character == ".")
{
return '.';
}
else if (character == "X")
{
return 'X';
}
else if (character == "O")
{
return 'O';
}
}
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include <string>
char strToSymbol(std::string character);
+25
View File
@@ -0,0 +1,25 @@
#include <string>
std::string symbolToStr(char character)
{
if (character == 'W')
{
return "W";
}
else if (character == 'B')
{
return "B";
}
else if (character == '.')
{
return ".";
}
else if (character == 'X')
{
return "X";
}
else if (character == 'O')
{
return "O";
}
}
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include <string>
std::string symbolToStr(char);
@@ -0,0 +1,129 @@
#include "../Database/GameHistoryManager.h"
#include "../Utilities/IntToStr.h"
#include "../Structures/Board.h"
#include "../Structures/Player.h"
#include "../Structures/Bot.h"
#include "../Structures/SinglePlayerGame.h"
#include "../Structures/MultiPlayerGame.h"
#include "GetSavedBoardSize.h"
#include "Print.h"
#include "outputDecoratedSavedGame.h"
#include <iostream>
void outputDecoratedSavedSinglePlayerGame(std::string savedGame);
void outputDecoratedSavedMultiPlayerGame(std::string savedGame);
void outputDecoratedSavedGame(std::string savedGame)
{
std::string gameMode = getProperty(2, savedGame);
if (gameMode == "1Player")
{
return outputDecoratedSavedSinglePlayerGame(savedGame);
}
else
{
return outputDecoratedSavedMultiPlayerGame(savedGame);
}
}
void outputDecoratedSavedSinglePlayerGame(std::string savedGame)
{
int id = getGameId(savedGame);
Board board = *(getSinglePlayerGame(id).GameBoard);
Player player = *(getSinglePlayerGame(id).Player1);
Bot bot = *(getSinglePlayerGame(id).GameBot);
char CurrentTurnColor = getSinglePlayerGame(id).CurrentTurnColor;
int Winner = getSinglePlayerGame(id).Winner;
SinglePlayerGame game {&board, &player, &bot, CurrentTurnColor};
game.id = id;
game.Winner = Winner;
game.mode = "1Player";
game.GameBoard -> CursorX = -1;
game.GameBoard -> CursorY = -1;
std::cout << "{\n id = " << intToStr(game.id) << "\n";
std::cout << " game board = { \n";
game.GameBoard -> display();
std::cout << " mode = single player\n";
std::cout << " Player = {\n"
<< " name = " << game.Player1 -> name << std::endl
<< " color = " << (game.Player1 -> color == 'W' ? "White":"Black") << std::endl
<< " }\n";
int botDifficulty = game.GameBot -> difficulty;
std::string difficultyToOutput = (
botDifficulty == 1 ?
"easy" : botDifficulty == 2 ?
"medium" : "hard"
);
std::cout << " Bot = {\n"
<< " difficulty = " << difficultyToOutput << std::endl
<< " }\n";
int winner = game.Winner;
std::string winnerToOutput = (
winner == 0 ?
"The game is unfinished" : winner == 1 ?
"Player has won this game" : winner == 2 ?
"Bot has won this game" : "The game resulted in a draw"
);
std::cout << " " << winnerToOutput << "\n}\n";
}
void outputDecoratedSavedMultiPlayerGame(std::string savedGame)
{
int id = getGameId(savedGame);
Board board = *(getMultiPlayerGame(id).GameBoard);
Player player1 = *(getMultiPlayerGame(id).Player1);
Player player2 = *(getMultiPlayerGame(id).Player2);
char CurrentTurnColor = getMultiPlayerGame(id).CurrentTurnColor;
int Winner = getMultiPlayerGame(id).Winner;
MultiPlayerGame game {&board, &player1, &player2, CurrentTurnColor};
game.id = id;
game.Winner = Winner;
game.mode = "2Player";
game.GameBoard -> CursorX = -1;
game.GameBoard -> CursorY = -1;
std::cout << "{\n id = " << intToStr(game.id) << "\n";
std::cout << " game board = { \n";
game.GameBoard -> display();
std::cout << " mode = Multiplayer\n";
std::cout << " Player1 = {\n"
<< " name = " << game.Player1 -> name << std::endl
<< " color = " << (game.Player1 -> color == 'W' ? "White":"Black") << std::endl
<< " }\n";
std::cout << " Player2 = {\n"
<< " name = " << game.Player2 -> name << std::endl
<< " color = " << (game.Player2 -> color == 'W' ? "White":"Black") << std::endl
<< " }\n";
int winner = game.Winner;
std::string winnerToOutput = (
winner == 0 ?
"The game is unfinished" : winner == 1 ?
"Player1 has won this game" : winner == 2 ?
"Player2 has won this game" : "The game resulted in a draw"
);
std::cout << " " << winnerToOutput << "\n}\n";
}
@@ -0,0 +1,5 @@
#pragma once
#include <string>
void outputDecoratedSavedGame(std::string savedGame);
Binary file not shown.