Compare commits

...

3 Commits

18 changed files with 419 additions and 394 deletions

View File

@@ -5,13 +5,10 @@
* @param move The move that uses the short algebraic notation. * @param move The move that uses the short algebraic notation.
*/ */
ChessPieceMove::ChessPieceMove(std::string move) { ChessPieceMove::ChessPieceMove(std::string move) {
move = this->Normalize(move); this->_move = this->Normalize(move);
if (this->IsValidShortNotation(move)) { if (this->IsValidShortNotation()) {
this->_move = move;
this->ParseShortNotation(); this->ParseShortNotation();
} else {
throw std::invalid_argument("invalid move notation");
} }
} }

View File

@@ -19,39 +19,43 @@
#include "../ChessPieces/Queen.hpp" #include "../ChessPieces/Queen.hpp"
#include "../ChessPieces/Rook.hpp" #include "../ChessPieces/Rook.hpp"
void Chessboard::InitializeStartBoard() { void Chessboard::SetStartingPosition() {
Chessboard::InitializeBoard(defaultBoard);
}
void Chessboard::InitializeBoard(std::set<Board_ChessPiece> board) { // black chess pieces
for (const auto& piece : board) { this->SetChessPiece(new Rook(ChessPieceColor::Black, ChessPiecePosition("A8")));
ChessPiecePosition pos = ChessPiecePosition(piece.position.first, piece.position.second); this->SetChessPiece(new Knight(ChessPieceColor::Black, ChessPiecePosition("B8")));
ChessPieceColor color = (piece.color == 0) ? ChessPieceColor::Black : ChessPieceColor::White; this->SetChessPiece(new Bishop(ChessPieceColor::Black, ChessPiecePosition("C8")));
this->SetChessPiece(new Queen(ChessPieceColor::Black, ChessPiecePosition("D8")));
this->SetChessPiece(new King(ChessPieceColor::Black, ChessPiecePosition("E8")));
this->SetChessPiece(new Bishop(ChessPieceColor::Black, ChessPiecePosition("F8")));
this->SetChessPiece(new Knight(ChessPieceColor::Black, ChessPiecePosition("G8")));
this->SetChessPiece(new Rook(ChessPieceColor::Black, ChessPiecePosition("H8")));
this->SetChessPiece(new Pawn(ChessPieceColor::Black, ChessPiecePosition("A7")));
this->SetChessPiece(new Pawn(ChessPieceColor::Black, ChessPiecePosition("B7")));
this->SetChessPiece(new Pawn(ChessPieceColor::Black, ChessPiecePosition("C7")));
this->SetChessPiece(new Pawn(ChessPieceColor::Black, ChessPiecePosition("D7")));
this->SetChessPiece(new Pawn(ChessPieceColor::Black, ChessPiecePosition("E7")));
this->SetChessPiece(new Pawn(ChessPieceColor::Black, ChessPiecePosition("F7")));
this->SetChessPiece(new Pawn(ChessPieceColor::Black, ChessPiecePosition("G7")));
this->SetChessPiece(new Pawn(ChessPieceColor::Black, ChessPiecePosition("H7")));
switch (piece.type) { // white chess pieces
case 'R': this->SetChessPiece(new Rook(ChessPieceColor::White, ChessPiecePosition("A1")));
SetChessPiece(new Rook(color, pos)); this->SetChessPiece(new Knight(ChessPieceColor::White, ChessPiecePosition("B1")));
break; this->SetChessPiece(new Bishop(ChessPieceColor::White, ChessPiecePosition("C1")));
case 'N': this->SetChessPiece(new Queen(ChessPieceColor::White, ChessPiecePosition("D1")));
SetChessPiece(new Knight(color, pos)); this->SetChessPiece(new King(ChessPieceColor::White, ChessPiecePosition("E1")));
break; this->SetChessPiece(new Bishop(ChessPieceColor::White, ChessPiecePosition("F1")));
case 'B': this->SetChessPiece(new Knight(ChessPieceColor::White, ChessPiecePosition("G1")));
SetChessPiece(new Bishop(color, pos)); this->SetChessPiece(new Rook(ChessPieceColor::White, ChessPiecePosition("H1")));
break; this->SetChessPiece(new Pawn(ChessPieceColor::White, ChessPiecePosition("A2")));
case 'Q': this->SetChessPiece(new Pawn(ChessPieceColor::White, ChessPiecePosition("B2")));
SetChessPiece(new Queen(color, pos)); this->SetChessPiece(new Pawn(ChessPieceColor::White, ChessPiecePosition("C2")));
break; this->SetChessPiece(new Pawn(ChessPieceColor::White, ChessPiecePosition("D2")));
case 'K': this->SetChessPiece(new Pawn(ChessPieceColor::White, ChessPiecePosition("E2")));
SetChessPiece(new King(color, pos)); this->SetChessPiece(new Pawn(ChessPieceColor::White, ChessPiecePosition("F2")));
break; this->SetChessPiece(new Pawn(ChessPieceColor::White, ChessPiecePosition("G2")));
case 'P': this->SetChessPiece(new Pawn(ChessPieceColor::White, ChessPiecePosition("H2")));
SetChessPiece(new Pawn(color, pos));
break;
default:
std::cout << "Invalid ChessPieceType!" << std::endl;
return;
}
}
} }
/** /**

View File

@@ -41,66 +41,11 @@ class Chessboard {
void RemoveChessPiece(ChessPiecePosition position); void RemoveChessPiece(ChessPiecePosition position);
public: public:
struct Board_ChessPiece {
int color;
char type;
std::pair<char, int> position;
Board_ChessPiece(const int& c, const char& t, std::pair<char,int> p) : color(c), type(t), position(p) {}
bool operator<(const Board_ChessPiece& other) const {
if (position != other.position) {
return position < other.position;
}
if (color != other.color) {
return color < other.color;
}
return type < other.type;
}
};
inline static const std::set<Board_ChessPiece> defaultBoard = {
{0, 'P', {'A', 7}},
{0, 'P', {'B', 7}},
{0, 'P', {'C', 7}},
{0, 'P', {'D', 7}},
{0, 'P', {'E', 7}},
{0, 'P', {'F', 7}},
{0, 'P', {'G', 7}},
{0, 'P', {'H', 7}},
{0, 'R', {'A', 8}},
{0, 'N', {'B', 8}},
{0, 'B', {'C', 8}},
{0, 'Q', {'D', 8}},
{0, 'K', {'E', 8}},
{0, 'B', {'F', 8}},
{0, 'N', {'G', 8}},
{0, 'R', {'H', 8}},
{1, 'P', {'A', 2}},
{1, 'P', {'B', 2}},
{1, 'P', {'C', 2}},
{1, 'P', {'D', 2}},
{1, 'P', {'E', 2}},
{1, 'P', {'F', 2}},
{1, 'P', {'G', 2}},
{1, 'P', {'H', 2}},
{1, 'R', {'A', 1}},
{1, 'N', {'B', 1}},
{1, 'B', {'C', 1}},
{1, 'Q', {'D', 1}},
{1, 'K', {'E', 1}},
{1, 'B', {'F', 1}},
{1, 'N', {'G', 1}},
{1, 'R', {'H', 1}}
};
~Chessboard(); ~Chessboard();
std::string GetAmountOfGames();
std::vector<ChessPieceMove> GetHistoryMoves(); std::vector<ChessPieceMove> GetHistoryMoves();
std::vector<std::pair<ChessPiecePosition, ChessPiecePosition>> GetHistoryPositions(); std::vector<std::pair<ChessPiecePosition, ChessPiecePosition>> GetHistoryPositions();
std::string GetTodaysDate(std::string format); std::string GetTodaysDate(std::string format);
void InitializeStartBoard(); void SetStartingPosition();
void InitializeBoard(std::set<Board_ChessPiece> board);
//void SetChessPiece(std::unique_ptr<ChessPiece> piece);
void SetChessPiece(ChessPiece* chesspiece); void SetChessPiece(ChessPiece* chesspiece);
bool IsDraw(); bool IsDraw();
bool IsEmptyField(ChessPiecePosition* position); bool IsEmptyField(ChessPiecePosition* position);

View File

@@ -5,7 +5,7 @@
#include "Visualizer/ImportVisualizer.hpp" #include "Visualizer/ImportVisualizer.hpp"
#include "Visualizer/PlayingViewVisualizer.hpp" #include "Visualizer/PlayingViewVisualizer.hpp"
#include "Visualizer/PlaySelectVisualizer.hpp" #include "Visualizer/PlaySelectVisualizer.hpp"
#include <filesystem>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
@@ -17,227 +17,238 @@ MenuController::~MenuController() {
// Destruktor, falls nötig // Destruktor, falls nötig
} }
void MenuController::HandlePlayingNavigation(std::string choice, Chessboard& chessboard, PlayingViewVisualizer& playView, bool isGameOver) {
if (choice.empty() == false) {
if (choice.at(0) == '$') {
if (choice == "$0") {
return;
} else if (choice == "$1") {
HandleThirdOption();
} else if (choice == "$2") {
chessboard.ExportFilePGN("chessgames/save_games/");
} else if (choice == "$3") {
if (isGameOver) {
playView.SetMessage("Game is over! No moves allowed.");
} else {
chessboard.SetWinner(chessboard.GetOpponentPlayer());
}
}
} else {
if (isGameOver) {
playView.SetMessage("Game is over! No moves allowed.");
} else {
playView.SetMessage(chessboard.MoveChessPiece(choice));
}
}
}
}
void MenuController::HandleFirstOption() { void MenuController::HandleFirstOption() {
BaseVisualizer::ClearTerminal(); PlaySelectVisualizer playerSelect(3);
PlaySelectVisualizer playerSelect(3); std::string choiceA;
playerSelect.DisplayElement(); std::string choiceB;
std::string input; do {
std::cout << "\x1B[u"; // Cursor-Positionierung playerSelect.SetLabelPlayerName("first player");
choiceA = playerSelect.ShowMenu();
// ToDo: Fehlerbehandlung if (choiceA.length() > 40) {
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); choiceA.clear();
std::getline(std::cin, input); }
} while (choiceA.empty());
std::vector<std::string> vec = split(input, '&', true); do {
playerSelect.SetLabelPlayerName("second player");
choiceB = playerSelect.ShowMenu();
if (choiceB.length() > 40) {
choiceB.clear();
};
} while (choiceB.empty());
// Spieler initialisieren // Spieler initialisieren
Player* playerA = new Player(vec[0]); Player* playerA = new Player(choiceA);
Player* playerB = new Player(vec[1]); Player* playerB = new Player(choiceB);
// Schachbrett initialisieren // Schachbrett initialisieren
Chessboard chessboard; Chessboard chessboard;
chessboard.SetPlayers(playerA, playerB); chessboard.SetPlayersRdm(playerA, playerB);
chessboard.InitializeStartBoard(); chessboard.SetStartingPosition();
chessboard.UpdateChessPieces(); chessboard.UpdateChessPieces();
SetChessboard(&chessboard); SetChessboard(&chessboard);
// Spielansicht vorbereiten
PlayingViewVisualizer playView(&chessboard, 4, 12); PlayingViewVisualizer playView(&chessboard, 4, 12);
while (!chessboard.IsCheckmate() && !chessboard.IsStalemate() && !chessboard.IsDraw() && chessboard.IsFinished() == false) { std::string choiceChessboard;
playView.DisplayElement();
std::string input; do {
std::cout << "\x1B[u"; // Cursor-Positionierung
std::cin >> input;
std::string command = ExtractAfterDollar(input);
if (!command.empty()) {
HandleCommandOptions(command);
if (command == "0") {
return;
}
} else {
std::string status = chessboard.MoveChessPiece(input);
if (status.empty() == false) {
playView.SetMessage(status);
}
}
}
std::string winner = chessboard.GetWinner();
if (winner.empty()) {
playView.SetMessage("Game is over! - Draw");
} else {
playView.SetMessage("Game is over! - " + winner + " has won the game!");
}
while (true) {
playView.DisplayElement();
std::string input;
std::cout << "\x1B[u"; // Cursor-Positionierung
std::cin >> input;
std::string command = ExtractAfterDollar(input);
if (command == "0") {
return;
}
}
}
void MenuController::HandleSecondOption() {
BaseVisualizer::ClearTerminal();
ImportVisualizer import;
import.DisplayElement();
std::string input;
std::string filePath;
std::cout << "\x1B[u";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::getline(std::cin, filePath);
if (filePath.empty()) {
return;
}
Chessboard chessboard;
chessboard.InitializeStartBoard();
chessboard.UpdateChessPieces();
SetChessboard(&chessboard);
std::string status = chessboard.ImportFilePGN(filePath);
if (status.empty() == false) {
return;
}
BaseVisualizer::ClearTerminal();
PlayingViewVisualizer playView(&chessboard, 4, 12);
playView.SetMessage(status);
playView.DisplayElement();
bool isFirstDisplayed = true;
if (status.empty() == false) {
playView.SetMessage(status);
} else {
while (!chessboard.IsCheckmate() && !chessboard.IsStalemate() && !chessboard.IsDraw() && chessboard.IsFinished() == false) { while (!chessboard.IsCheckmate() && !chessboard.IsStalemate() && !chessboard.IsDraw() && chessboard.IsFinished() == false) {
if (isFirstDisplayed) { choiceChessboard = playView.ShowMenu();
isFirstDisplayed = false; this->HandlePlayingNavigation(choiceChessboard, chessboard, playView, false);
} else {
playView.DisplayElement();
}
std::cout << "\x1B[u"; // Cursor-Positionierung
std::cin.clear();
std::getline(std::cin, input);
std::string command = ExtractAfterDollar(input);
if (!command.empty()) {
HandleCommandOptions(command);
if (command == "0") {
}
} else {
std::string status = chessboard.MoveChessPiece(input);
if (status.empty() == false) {
playView.SetMessage(status);
}
}
} }
std::string winner = chessboard.GetWinner(); std::string winner = chessboard.GetWinner();
choiceChessboard = "$0";
if (winner.empty()) { if (winner.empty()) {
playView.SetMessage("Game is over! - Draw"); playView.SetMessage("Game is over! - Draw");
} else { } else {
playView.SetMessage("Game is over! - " + winner + " has won the game!"); playView.SetMessage("Game is over! - " + winner + " has won the game!");
} }
} while (choiceChessboard != "$0");
do {
choiceChessboard = playView.ShowMenu();
this->HandlePlayingNavigation(choiceChessboard, chessboard, playView, true);
} while (choiceChessboard != "$0");
// while (!chessboard.IsCheckmate() && !chessboard.IsStalemate() && !chessboard.IsDraw() && chessboard.IsFinished() == false) {
// playView.DisplayElement();
// std::string input;
// std::cout << "\x1B[u"; // Cursor-Positionierung
// std::cin >> input;
// std::string command = ExtractAfterDollar(input);
// if (!command.empty()) {
// HandleCommandOptions(command);
// if (command == "0") {
// return;
// }
// } else {
// std::string status = chessboard.MoveChessPiece(input);
// if (status.empty() == false) {
// playView.SetMessage(status);
// }
// }
// }
// std::string winner = chessboard.GetWinner();
// if (winner.empty()) {
// playView.SetMessage("Game is over! - Draw");
// } else {
// playView.SetMessage("Game is over! - " + winner + " has won the game!");
// }
// while (true) {
// playView.DisplayElement();
// std::string input;
// std::cout << "\x1B[u"; // Cursor-Positionierung
// std::cin >> input;
// std::string command = ExtractAfterDollar(input);
// if (command == "0") {
// return;
// }
// }
}
void MenuController::HandleSecondOption() {
ImportVisualizer importSelect;
std::string filePath;
do {
filePath = importSelect.ShowMenu();
if (std::filesystem::exists(filePath) == false) {
filePath.clear();
}
} while (filePath.empty());
Chessboard chessboard;
chessboard.SetStartingPosition();
chessboard.UpdateChessPieces();
SetChessboard(&chessboard);
std::string status = chessboard.ImportFilePGN(filePath);
PlayingViewVisualizer playView(&chessboard, 4, 12);
playView.SetMessage(status);
std::string choiceChessboard;
do {
while (!chessboard.IsCheckmate() && !chessboard.IsStalemate() && !chessboard.IsDraw() && chessboard.IsFinished() == false) {
choiceChessboard = playView.ShowMenu();
this->HandlePlayingNavigation(choiceChessboard, chessboard, playView, false);
} }
while (true) { std::string winner = chessboard.GetWinner();
playView.DisplayElement(); choiceChessboard = "$0";
std::string input;
std::cout << "\x1B[u"; // Cursor-Positionierung
std::cin >> input;
std::string command = ExtractAfterDollar(input); if (winner.empty()) {
if (command == "0") { playView.SetMessage("Game is over! - Draw");
return; } else {
} playView.SetMessage("Game is over! - " + winner + " has won the game!");
} }
} while (choiceChessboard != "$0");
do {
choiceChessboard = playView.ShowMenu();
this->HandlePlayingNavigation(choiceChessboard, chessboard, playView, true);
} while (choiceChessboard != "$0");
} }
// ToDo:: Hier muss aus irgendeinem Grund immer zweimal die Eingabe abgeschickt werden. Why!? // ToDo:: Hier muss aus irgendeinem Grund immer zweimal die Eingabe abgeschickt werden. Why!?
void MenuController::HandleThirdOption() { void MenuController::HandleThirdOption() {
BaseVisualizer::ClearTerminal();
InstructionsVisualizer instructions; InstructionsVisualizer instructions;
instructions.DisplayElement(); instructions.DrawView();
std::string dummyInput;
// Eingabepuffer leeren
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "\x1B[u"; // Cursor-Positionierung
std::cin.clear();
std::getline(std::cin, dummyInput);
} }
void MenuController::HandleCommandOptions(const std::string& command) { // void MenuController::HandleCommandOptions(const std::string& command) {
if (command == "1") { // if (command == "1") {
HandleThirdOption(); // HandleThirdOption();
return; // return;
} else if (command == "2") { // } else if (command == "2") {
CHESSBOARD->ExportFilePGN("chessgames/save_games/"); // CHESSBOARD->ExportFilePGN("chessgames/save_games/");
std::cout << "Save game functionality is not implemented yet.\n"; // std::cout << "Save game functionality is not implemented yet.\n";
} else if (command == "3") { // } else if (command == "3") {
// resign // CHESSBOARD->SetWinner(CHESSBOARD->GetOpponentPlayer());
CHESSBOARD->SetWinner(CHESSBOARD->GetOpponentPlayer()); // return;
return; // } else if (command == "0") { // exit
} else if (command == "0") { // exit // return;
return; // } else {
} else { // std::cout << "Invalid command. Please try again.\n";
std::cout << "Invalid command. Please try again.\n"; // }
} // }
}
std::string MenuController::ExtractAfterDollar(const std::string& userInput) { // std::string MenuController::ExtractAfterDollar(const std::string& userInput) {
if (!userInput.empty() && userInput[0] == '$') { // if (!userInput.empty() && userInput[0] == '$') {
return userInput.substr(1); // Rückgabe des Teils nach '$' // return userInput.substr(1); // Rückgabe des Teils nach '$'
} // }
return ""; // Leerer String, wenn kein '$' am Anfang // return ""; // Leerer String, wenn kein '$' am Anfang
} // }
Chessboard* MenuController::GetChessboard() { // Chessboard* MenuController::GetChessboard() {
return CHESSBOARD; // return CHESSBOARD;
} // }
void MenuController::SetChessboard(Chessboard* chessboard) { void MenuController::SetChessboard(Chessboard* chessboard) {
CHESSBOARD = chessboard; CHESSBOARD = chessboard;
} }
std::string MenuController::trim(const std::string& str) { // std::string MenuController::trim(const std::string& str) {
size_t start = str.find_first_not_of(" \t\n\r\f\v"); // size_t start = str.find_first_not_of(" \t\n\r\f\v");
if (start == std::string::npos) return ""; // Nur Leerzeichen // if (start == std::string::npos) return ""; // Nur Leerzeichen
size_t end = str.find_last_not_of(" \t\n\r\f\v"); // size_t end = str.find_last_not_of(" \t\n\r\f\v");
return str.substr(start, end - start + 1); // return str.substr(start, end - start + 1);
} // }
std::vector<std::string> MenuController::split(const std::string& str, char delimiter, bool trimWhitespace) { // std::vector<std::string> MenuController::split(const std::string& str, char delimiter, bool trimWhitespace) {
std::vector<std::string> tokens; // std::vector<std::string> tokens;
std::istringstream stream(str); // std::istringstream stream(str);
std::string token; // std::string token;
while (std::getline(stream, token, delimiter)) { // while (std::getline(stream, token, delimiter)) {
if (trimWhitespace) { // if (trimWhitespace) {
token = trim(token); // Trimme die Tokens, falls gewünscht // token = trim(token); // Trimme die Tokens, falls gewünscht
} // }
tokens.push_back(token); // tokens.push_back(token);
} // }
return tokens; // return tokens;
} // }

View File

@@ -2,13 +2,14 @@
#define MENU_CONTROLLER_HPP #define MENU_CONTROLLER_HPP
#include "Chessboard/Chessboard.hpp" #include "Chessboard/Chessboard.hpp"
#include "Visualizer/PlayingViewVisualizer.hpp"
#include <string> #include <string>
class MenuController { class MenuController {
private: private:
std::string ExtractAfterDollar(const std::string& userInput); std::string ExtractAfterDollar(const std::string& userInput);
void InitializeGame(); void HandlePlayingNavigation(std::string choice, Chessboard& chessboard, PlayingViewVisualizer& playView, bool isGameOver);
Chessboard* CHESSBOARD; Chessboard* CHESSBOARD;
@@ -19,11 +20,11 @@ public:
void HandleFirstOption(); void HandleFirstOption();
void HandleSecondOption(); void HandleSecondOption();
void HandleThirdOption(); void HandleThirdOption();
void HandleCommandOptions(const std::string& command); // void HandleCommandOptions(const std::string& command);
Chessboard* GetChessboard(); // Chessboard* GetChessboard();
void SetChessboard(Chessboard* chessboard); void SetChessboard(Chessboard* chessboard);
std::string trim(const std::string& str); // std::string trim(const std::string& str);
std::vector<std::string> split(const std::string& str, char delimiter, bool trimWhitespace = false); // std::vector<std::string> split(const std::string& str, char delimiter, bool trimWhitespace = false);
}; };
#endif // MENU_CONTROLLER_HPP #endif // MENU_CONTROLLER_HPP

View File

@@ -11,6 +11,7 @@ void CommandMenuVisualizer::GenerateElement() {
std::string str_temp = ((CHESSBOARD->GetCurrentPlayer()->GetColor() == ChessPieceColor::White) ? "White" : "Black"); std::string str_temp = ((CHESSBOARD->GetCurrentPlayer()->GetColor() == ChessPieceColor::White) ? "White" : "Black");
BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, "Move [" + str_temp + "] : \x1B[s", true, PADDING); BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, "Move [" + str_temp + "] : \x1B[s", true, PADDING);
BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, false, true); BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, false, true);
display_vector.push_back({" "});
BaseVisualizer::display_vector.push_back({std::string(" ").append(GetMessage())}); BaseVisualizer::display_vector.push_back({std::string(" ").append(GetMessage())});
} }

View File

@@ -1,4 +1,5 @@
#include "HistorieVisualizer.hpp" #include "HistorieVisualizer.hpp"
#include <algorithm>
#include "../ChessPieces/ChessPieceMove.hpp" #include "../ChessPieces/ChessPieceMove.hpp"
void HistorieVisualizer::GenerateElement() { void HistorieVisualizer::GenerateElement() {
@@ -18,49 +19,34 @@ void HistorieVisualizer::GenerateElement() {
BaseVisualizer::GenerateTableLine(MAX_MENU_WIDTH, {playerName1, playerName2}, true); BaseVisualizer::GenerateTableLine(MAX_MENU_WIDTH, {playerName1, playerName2}, true);
BaseVisualizer::GenerateTableSeperator(MAX_MENU_WIDTH, true); BaseVisualizer::GenerateTableSeperator(MAX_MENU_WIDTH, true);
std::vector<ChessPieceMove> moves = this->CHESSBOARD->GetHistoryMoves(); std::vector<ChessPieceMove> moves = this->CHESSBOARD->GetHistoryMoves();
// ToDo: History einlesen und anzeigen lassenF
if (moves.size() == 0) { if (moves.size() % 2 == 0) {
for (size_t i = 0; i < 5; i++) { moves = std::vector<ChessPieceMove>(moves.end() - std::min<int>(moves.size(), 10), moves.end());
BaseVisualizer::GenerateTableLine(MAX_MENU_WIDTH, {"", ""}, true); } else {
moves = std::vector<ChessPieceMove>(moves.end() - std::min<int>(moves.size(), 9), moves.end());
}
std::vector<std::string> rowMoves;
int rows = 0;
for (int moveIndex = 0; moveIndex < moves.size(); moveIndex++) {
if (moveIndex % 2 == 0) rowMoves.clear();
rowMoves.push_back(moves[moveIndex].ToString());
if (moveIndex % 2 == 1) {
BaseVisualizer::GenerateTableLine(MAX_MENU_WIDTH, rowMoves, true);
rows++;
} else if (moveIndex == moves.size() - 1) {
rowMoves.push_back("");
BaseVisualizer::GenerateTableLine(MAX_MENU_WIDTH, rowMoves, true);
rows++;
} }
} }
if (moves.size() > 0 && moves.size() < 11) { for (int rowIndex = rows; rowIndex < 5; rowIndex++) {
int rows = 0; BaseVisualizer::GenerateTableLine(MAX_MENU_WIDTH, {"", ""}, true);
for (int moveIndex = moves.size(); moveIndex > 0; moveIndex =- 2) {
if (moveIndex == 1) { // Sonderfall: Letztes Element bei ungerader Anzahl
BaseVisualizer::GenerateTableLine(MAX_MENU_WIDTH, {moves[moveIndex-1].ToString(), ""}, true);
} else {
BaseVisualizer::GenerateTableLine(MAX_MENU_WIDTH, {moves[moveIndex-2].ToString(), moves[moveIndex-1].ToString()}, true);
}
if (moveIndex % 2 == 0) {
rows++;
}
}
for (size_t i = 0; i < 5-rows; i++) {
BaseVisualizer::GenerateTableLine(MAX_MENU_WIDTH, {"", ""}, true);
}
} }
if (moves.size() >= 11) {
size_t rows = 0;
for (size_t moveIndex = moves.size(); moveIndex > moves.size()-10; moveIndex -= 2) {
if (moveIndex == 1) { // Sonderfall: Letztes Element bei ungerader Anzahl
BaseVisualizer::GenerateTableLine(MAX_MENU_WIDTH, {moves[moveIndex-1].ToString(), ""}, true);
} else {
BaseVisualizer::GenerateTableLine(MAX_MENU_WIDTH, {moves[moveIndex-2].ToString(), moves[moveIndex-1].ToString()}, true);
}
rows++;
}
for (size_t i = 1; i < 5-(rows/2); i++) {
BaseVisualizer::GenerateTableLine(MAX_MENU_WIDTH, {"", ""}, true);
}
}
BaseVisualizer::GenerateTableTopBottom(MAX_MENU_WIDTH, false, true); BaseVisualizer::GenerateTableTopBottom(MAX_MENU_WIDTH, false, true);
} }

View File

@@ -1,13 +1,36 @@
#include "ImportVisualizer.hpp" #include "ImportVisualizer.hpp"
void ImportVisualizer::GenerateElement() { void ImportVisualizer::GenerateElement() {
BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, true, false); // BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, true, false);
BaseVisualizer::AddEmptyLines(2, MAX_MENU_WIDTH, false); // BaseVisualizer::AddEmptyLines(2, MAX_MENU_WIDTH, false);
for (const auto& content : menuContent) { // for (const auto& content : menuContent) {
BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, content, false, PADDING); // BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, content, false, PADDING);
} // }
BaseVisualizer::AddEmptyLines(2, MAX_MENU_WIDTH, false); // BaseVisualizer::AddEmptyLines(2, MAX_MENU_WIDTH, false);
BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, "You can get a lot of PGN files from chessgames.com.", false, PADDING); // BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, "You can get a lot of PGN files from chessgames.com.", false, PADDING);
BaseVisualizer::AddEmptyLines(5, MAX_MENU_WIDTH, false); // BaseVisualizer::AddEmptyLines(5, MAX_MENU_WIDTH, false);
BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, false, false); // BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, false, false);
}
void ImportVisualizer::DrawView() {
BaseVisualizer::ClearTerminal();
this->display_vector.clear();
BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, true, false);
BaseVisualizer::GenerateEmptyLine(MAX_MENU_WIDTH, false);
BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, "Please enter a path to a PGN (Portable Game Notation) file:", false, PADDING);
BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, "\x1B[s", false, PADDING);
BaseVisualizer::GenerateEmptyLine(MAX_MENU_WIDTH, false);
BaseVisualizer::GenerateEmptyLine(MAX_MENU_WIDTH, false);
BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, "On https://chessgames.com/ you will find many more chess", false, PADDING);
BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, "games in PGN format, to import into TurboSchach.", false, PADDING);
BaseVisualizer::GenerateEmptyLine(MAX_MENU_WIDTH, false);
BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, false, false);
BaseVisualizer::DisplayElement();
std::cout << "\x1B[u";
}
std::string ImportVisualizer::ShowMenu() {
this->DrawView();
std::string choice;
std::getline(std::cin, choice);
return choice;
} }

View File

@@ -15,6 +15,8 @@ class ImportVisualizer : public BaseVisualizer {
ImportVisualizer() : BaseVisualizer(60, 4) { ImportVisualizer() : BaseVisualizer(60, 4) {
ImportVisualizer::GenerateElement(); ImportVisualizer::GenerateElement();
}; };
std::string ShowMenu();
void DrawView();
}; };
#endif //INSTRUCTIONSVISUALIZER_HPP #endif //INSTRUCTIONSVISUALIZER_HPP

View File

@@ -7,7 +7,14 @@ void InstructionsVisualizer::GenerateElement() {
BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, content, false, PADDING); BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, content, false, PADDING);
} }
BaseVisualizer::AddEmptyLines(2, MAX_MENU_WIDTH, false); BaseVisualizer::AddEmptyLines(2, MAX_MENU_WIDTH, false);
BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, "Enter any key to return to menu: \x1B[s", false, PADDING); BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, "Press enter to continue: \x1B[s", false, PADDING);
BaseVisualizer::AddEmptyLines(2, MAX_MENU_WIDTH, false); BaseVisualizer::AddEmptyLines(2, MAX_MENU_WIDTH, false);
BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, false, false); BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, false, false);
} }
void InstructionsVisualizer::DrawView() {
BaseVisualizer::ClearTerminal();
BaseVisualizer::DisplayElement();
std::cout << "\x1B[u";
std::string choice;
std::getline(std::cin, choice);
}

View File

@@ -8,38 +8,45 @@ class InstructionsVisualizer : public BaseVisualizer {
inline static const std::vector<std::string> menuContent = { inline static const std::vector<std::string> menuContent = {
"1. Algebraische Notation", "1. Algebraische Notation",
"", "",
"Um die Figuren auf dem Schachbrett zu bewegen, wird die kurze algebraische Notation nach [FIDE](https://handbook.fide.com/chapter/E012023)", "Um die Figuren auf dem Schachbrett zu bewegen, wird die kurze algebraische Notation",
"(siehe Appendix C) unterstützt. Es werden die Schachfiguren sowohl in deutscher als auch in englischer Sprache unterstützt.", "FIDE-Handbuch (siehe Appendix C) unterstützt. Es werden die Schachfiguren sowohl in",
"deutscher als auch in englischer Sprache unterstützt.",
"", "",
"| -------------------------------------- |", "┌───────────────────┬─────────┬──────────┐",
"| Schachfigur | Deutsch | Englisch |", " Schachfigur Deutsch Englisch ",
"| ----------------- | ------- | -------- |", "├───────────────────┼─────────┼──────────┤",
"| Bauer (Pawn) | B | P |", " Bauer (Pawn) B P ",
"| Springer (Knight) | S | N |", " Springer (Knight) S N ",
"| Läufer (Bishop) | L | B |", " Läufer (Bishop) L B ",
"| Turm (Rook) | T | R |", " Turm (Rook) T R ",
"| Dame (Queen) | D | Q |", " Dame (Queen) D Q ",
"| König (King) | K | K |", " König (King) K K ",
"| -------------------------------------- |", "└───────────────────┴─────────┴──────────┘",
"", "",
"Bei der kurzen Notation wird immer nur das Zielfeld eines Spielzuges genannt. Sollte der Ursprung nicht eindeutig sein kann auch die Spalte", "Bei der kurzen Notation wird immer nur das Zielfeld eines Spielzuges genannt. Sollte",
"oder Zeile der zu bewegenden Figur genannt werden. So gibt der Spielzug `dxe5` an dass der Bauer in der Spalte D auf das Feld E5 zieht. Das", "der Ursprung nicht eindeutig sein kann auch die Spalte oder Zeile der zu bewegenden Figur",
"`x` gibt an dass dabei eine Spielfigur des Gegeners geschlagen wird. Dies muss aber nicht zwingend angegeben werden. Der Bauer wird in den", "genannt werden. So gibt der Spielzug 'dxe5' an dass der Bauer in der Spalte D auf das Feld",
"Spielzügen nicht benannt. Der Spielzug `b4` ist daher der Zug eines Bauern auf das Feld B4. Alle anderen Schachfiguren werden im Zug mit", "E5 zieht. Das 'x' gibt an dass dabei eine Spielfigur des Gegeners geschlagen wird. Dies muss",
"ihrem entsprechenden Buchstaben genannt. So gibt der Spielzug `Bc4` an dass der Läufer auf das Feld C4 gezogen wird.", "aber nicht zwingend angegeben werden. Der Bauer wird in den Spielzügen nicht benannt. Der",
"Spielzug 'b4' ist daher der Zug eines Bauern auf das Feld B4. Alle anderen Schachfiguren werden",
"im Zug mit ihrem entsprechenden Buchstaben genannt. So gibt der Spielzug 'Bc4' an dass der Läufer",
"auf das Feld C4 gezogen wird.",
"", "",
"Beispiele:", "Beispiele:",
" - `(=)` Angebot für ein Draw. Um das Spiel mit einem Draw zu beenden muss das Angebot direkt im nächsten Zug bestätigt werden.", "",
" - `b4` Der Bauer zieht auf das Feld B4.", " - (=) Angebot für ein Draw. Um das Spiel mit einem Draw zu beenden muss das Angebot direkt im",
" - `Bc4` Der Läufer zieht auf das Feld C4.", " nächsten Zug bestätigt werden.",
" - `0-0` Kleine Rochade (Rochade am Königsflügel)", " - b4 Der Bauer zieht auf das Feld B4.",
" - `0-0-0` Große Rochade (Rochade am Damenflügel)", " - Bc4 Der Läufer zieht auf das Feld C4.",
" - `d8Q` Umwandlung: Der Bauer zieht auf D8 und wandelt sich zur Dame.", " - 0-0 Kleine Rochade (Rochade am Königsflügel)",
" - 0-0-0 Große Rochade (Rochade am Damenflügel)",
" - d8Q Umwandlung: Der Bauer zieht auf D8 und wandelt sich zur Dame.",
"", "",
"2. PGN (Portable Game Notation)", "2. PGN (Portable Game Notation)",
"TurboSchach unterstützt das Datenformat PGN, welches zur Speicherung von Schachpartien verwendet wird. Auf der Website https://www.chessgames.com/", "",
"werden viele Schachpartien von offiziellen Turnieren im PGN-Format zur Verfügung gestellt. Diese Dateien können in TurboSchach importiert werden.", "TurboSchach unterstützt das Datenformat PGN, welches zur Speicherung von Schachpartien verwendet",
"Über den Menüpunkt 2 direkt nach dem Start der Anwendung ist dieser Import möglich." "wird. Auf der Website https://www.chessgames.com/ werden viele Schachpartien von offiziellen Turnieren",
"im PGN-Format zur Verfügung gestellt. Diese Dateien können in TurboSchach importiert werden."
}; };
void GenerateElement() override; void GenerateElement() override;
@@ -47,6 +54,7 @@ class InstructionsVisualizer : public BaseVisualizer {
InstructionsVisualizer() : BaseVisualizer(BaseVisualizer::FindMaxLength(menuContent), 4) { InstructionsVisualizer() : BaseVisualizer(BaseVisualizer::FindMaxLength(menuContent), 4) {
InstructionsVisualizer::GenerateElement(); InstructionsVisualizer::GenerateElement();
}; };
void DrawView();
}; };
#endif //INSTRUCTIONSVISUALIZER_HPP #endif //INSTRUCTIONSVISUALIZER_HPP

View File

@@ -1,13 +1,13 @@
#include "PlaySelectVisualizer.hpp" #include "PlaySelectVisualizer.hpp"
void PlaySelectVisualizer::GenerateElement() { void PlaySelectVisualizer::GenerateElement() {
BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, true, false); // BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, true, false);
BaseVisualizer::GenerateEmptyLine(MAX_MENU_WIDTH, false); // BaseVisualizer::GenerateEmptyLine(MAX_MENU_WIDTH, false);
for (const auto& content : menuContent) { // for (const auto& content : menuContent) {
BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, content, false, PADDING); // BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, content, false, PADDING);
} // }
BaseVisualizer::GenerateEmptyLine(MAX_MENU_WIDTH, false); // BaseVisualizer::GenerateEmptyLine(MAX_MENU_WIDTH, false);
BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, false, false); // BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, false, false);
} }
std::vector<std::pair<int, int>> PlaySelectVisualizer::GetCursorPositions() { std::vector<std::pair<int, int>> PlaySelectVisualizer::GetCursorPositions() {
@@ -17,3 +17,27 @@ std::vector<std::pair<int, int>> PlaySelectVisualizer::GetCursorPositions() {
void PlaySelectVisualizer::AddToCursorPositions(const std::pair<int, int>& position) { void PlaySelectVisualizer::AddToCursorPositions(const std::pair<int, int>& position) {
this->cursorPositions.push_back(position); this->cursorPositions.push_back(position);
} }
void PlaySelectVisualizer::DrawView() {
BaseVisualizer::ClearTerminal();
this->display_vector.clear();
BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, true, false);
BaseVisualizer::GenerateEmptyLine(MAX_MENU_WIDTH, false);
if (this->labelPlayerName.empty()) {
this->labelPlayerName = "player";
}
BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, "Please enter a name for the " + this->labelPlayerName + ":", false, PADDING);
BaseVisualizer::GenerateBoxMenuLine(MAX_MENU_WIDTH, "\x1B[s", false, PADDING);
BaseVisualizer::GenerateEmptyLine(MAX_MENU_WIDTH, false);
BaseVisualizer::GenerateTopBottomBorder(MAX_MENU_WIDTH, false, false);
BaseVisualizer::DisplayElement();
std::cout << "\x1B[u";
}
std::string PlaySelectVisualizer::ShowMenu() {
this->DrawView();
std::string choice;
std::getline(std::cin, choice);
return choice;
}
void PlaySelectVisualizer::SetLabelPlayerName(std::string label) {
this->labelPlayerName = label;
}

View File

@@ -5,6 +5,7 @@
class PlaySelectVisualizer : public BaseVisualizer { class PlaySelectVisualizer : public BaseVisualizer {
private: private:
std::string labelPlayerName;
// ToDo: Exit // ToDo: Exit
inline static const std::vector<std::string> menuContent = { inline static const std::vector<std::string> menuContent = {
"Please enter your names! Enter your names with '&' seperated.", "Please enter your names! Enter your names with '&' seperated.",
@@ -21,6 +22,9 @@ class PlaySelectVisualizer : public BaseVisualizer {
void GenerateElement(); void GenerateElement();
void AddToCursorPositions(const std::pair<int, int>& position); void AddToCursorPositions(const std::pair<int, int>& position);
std::vector<std::pair<int, int>> GetCursorPositions(); std::vector<std::pair<int, int>> GetCursorPositions();
void DrawView();
std::string ShowMenu();
void SetLabelPlayerName(std::string label);
}; };
#endif //PLAYSELECTVISUALIZER_HPP #endif //PLAYSELECTVISUALIZER_HPP

View File

@@ -113,3 +113,17 @@ std::string PlayingViewVisualizer::GetMessage() {
void PlayingViewVisualizer::SetMessage(std::string message) { void PlayingViewVisualizer::SetMessage(std::string message) {
this->message = message; this->message = message;
} }
void PlayingViewVisualizer::DrawView() {
BaseVisualizer::ClearTerminal();
this->DisplayElement();
std::cout << "\x1B[u";
}
std::string PlayingViewVisualizer::ShowMenu() {
this->DrawView();
this->SetMessage("");
std::string choice;
std::getline(std::cin, choice);
return choice;
}

View File

@@ -27,6 +27,8 @@ class PlayingViewVisualizer : public BaseVisualizer {
std::string GetMove(); std::string GetMove();
std::string GetMessage(); std::string GetMessage();
void SetMessage(std::string message); void SetMessage(std::string message);
void DrawView();
std::string ShowMenu();
}; };
#endif //PLAYINGVIEWVISUALIZER_HPP #endif //PLAYINGVIEWVISUALIZER_HPP

View File

@@ -52,15 +52,20 @@ void StartMenuVisualizer::SetSelectedOption(int optionSelect) {
selectedOption = selectedOption; selectedOption = selectedOption;
}; };
void StartMenuVisualizer::DisplayElement1() { void StartMenuVisualizer::DrawView() {
BaseVisualizer::ClearTerminal(); BaseVisualizer::ClearTerminal();
int temp; BaseVisualizer::DisplayElement();
for (const auto& row : display_vector) {
for (const auto& cell : row) {
std::cout << cell;
}
std::cout << std::endl;
}
std::cout << "\x1B[u"; std::cout << "\x1B[u";
std::cin >> selectedOption; }
StartMenuVisualizer::StartMenuOption StartMenuVisualizer::ShowMenu() {
this->DrawView();
std::string choice;
std::getline(std::cin, choice);
if (choice == "1") return StartMenuOption::NewGame;
if (choice == "2") return StartMenuOption::LoadGame;
if (choice == "3") return StartMenuOption::Instructions;
if (choice == "0") return StartMenuOption::Exit;
return StartMenuOption::None;
} }

View File

@@ -30,10 +30,17 @@ class StartMenuVisualizer : public BaseVisualizer {
StartMenuVisualizer(size_t padding) : BaseVisualizer(BaseVisualizer::CountVisibleCharacters(StartMenuVisualizer::ACSII_ART_TURBO_SCHACH[0]), padding) { StartMenuVisualizer(size_t padding) : BaseVisualizer(BaseVisualizer::CountVisibleCharacters(StartMenuVisualizer::ACSII_ART_TURBO_SCHACH[0]), padding) {
StartMenuVisualizer::GenerateElement(); StartMenuVisualizer::GenerateElement();
} }
enum StartMenuOption {
NewGame,
LoadGame,
Instructions,
Exit,
None
};
int GetSelectedOption(); int GetSelectedOption();
void SetSelectedOption(int selectedOption); void SetSelectedOption(int selectedOption);
void DisplayElement1(); void DrawView();
StartMenuOption ShowMenu();
}; };
#endif //STARTMENUVISUALIZER_H #endif //STARTMENUVISUALIZER_H

View File

@@ -13,42 +13,26 @@ int main(int argc, char* argv[]) {
SetConsoleOutputCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);
#endif #endif
BaseVisualizer::ClearTerminal();
StartMenuVisualizer startMenu(3); StartMenuVisualizer startMenu(3);
MenuController menuController; // Instanz der Klasse MenuController menuController;
StartMenuVisualizer::StartMenuOption optionStartMenu = StartMenuVisualizer::StartMenuOption::None;
while (startMenu.GetSelectedOption() != 0) { do {
BaseVisualizer::ClearTerminal(); switch (optionStartMenu = startMenu.ShowMenu()) {
startMenu.DisplayElement1(); case StartMenuVisualizer::StartMenuOption::NewGame:
switch (startMenu.GetSelectedOption()) {
case 1:
menuController.HandleFirstOption(); menuController.HandleFirstOption();
break; break;
case 2: case StartMenuVisualizer::StartMenuOption::LoadGame:
menuController.HandleSecondOption(); menuController.HandleSecondOption();
break; break;
case 3: case StartMenuVisualizer::StartMenuOption::Instructions:
menuController.HandleThirdOption(); menuController.HandleThirdOption();
break; break;
default: default:
std::cout << "Invalid option. Please try again.\n"; continue;
break; break;
} }
} } while (optionStartMenu != StartMenuVisualizer::StartMenuOption::Exit);
return 0; return 0;
} }
/*
Export (Almost)
Historie
Message -> Farbe?
Sebro
Fehlermeldung durch Bewegung PlayViewVisualizer::message
*/