TurboSchach/Chessboard.cpp

299 lines
8.6 KiB
C++
Raw Normal View History

//
// Created by hamac on 18.12.2024.
//
#include "Utils.cpp"
#include <iostream>
#include <queue>
#include <string>
#include <unordered_map>
#include <vector>
class Chessboard {
private:
/* Constants */
// Chars to display board
// Corners
const std::string topLeft = "";
const std::string topRight = "";
const std::string bottomLeft = "";
const std::string bottomRight = "";
// Line chars
const std::string horizontal = "";
const std::string vertical = "";
const std::string topIntersection = "";
const std::string bottomIntersection = "";
const std::string middleIntersection = "";
// White pieces
const std::string whiteSquare = "";
const std::string whiteKing = "";
const std::string whiteQueen = "";
const std::string whiteRook = "";
const std::string whiteBischop = "";
const std::string whiteKnight = "";
const std::string whitePawn = "";
// Black pieces
const std::string blackSquare = "";
const std::string blackKing = "";
const std::string blackQueen = "";
const std::string blackRook = "";
const std::string blackBischop = "";
const std::string blackKnight = "";
const std::string blackPawn = "";
/* class fields */
std::vector<std::vector<char>> currentBoard;
// Starting formatting
std::vector<std::vector<char>> startBoard = {
{'r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'},
{'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'},
{'w', 'x', 'w', 'x' ,'w', 'x', 'w', 'x'},
{'x', 'w', 'x', 'w', 'x', 'w', 'x', 'w'},
{'w', 'x', 'w', 'x' ,'w', 'x', 'w', 'x'},
{'x', 'w', 'x', 'w', 'x', 'w', 'x', 'w'},
{'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'},
{'R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R'},
};
// ToDo: Mathematisch sicherlich weg rationalisierbar
std::vector<std::vector<char>> emptyBoard = {
{'w', 'x', 'w', 'x' ,'w', 'x', 'w', 'x'},
{'x', 'w', 'x', 'w', 'x', 'w', 'x', 'w'},
{'w', 'x', 'w', 'x' ,'w', 'x', 'w', 'x'},
{'x', 'w', 'x', 'w', 'x', 'w', 'x', 'w'},
{'w', 'x', 'w', 'x' ,'w', 'x', 'w', 'x'},
{'x', 'w', 'x', 'w', 'x', 'w', 'x', 'w'},
{'w', 'x', 'w', 'x' ,'w', 'x', 'w', 'x'},
{'x', 'w', 'x', 'w', 'x', 'w', 'x', 'w'}
};
// Saves turn order; true = white and false = black
bool turnOrder = true;
// ToDo: Max Size definieren?
std::queue<std::string> queue;
/* methods */
// Method returns unicode for chess icon depending on the identifier
std::string getChessIcon(char identifier) {
switch (identifier) {
case 'x': return blackSquare;
case 'r': return blackRook;
case 'n': return blackKnight;
case 'b': return blackBischop;
case 'q': return blackQueen;
case 'k': return blackKing;
case 'p': return blackPawn;
case 'w': return whiteSquare;
case 'R': return whiteRook;
case 'N': return whiteKnight;
case 'B': return whiteBischop;
case 'Q': return whiteQueen;
case 'K': return whiteKing;
case 'P': return whitePawn;
default: return "";
}
}
void generateTopLine() {
display += " " + horizontal + " " + topLeft;
for (int col = 0; col < boardSize; ++col) {
display += horizontal + horizontal + horizontal;
if (col < boardSize - 1) display += topIntersection;
}
display += topRight + "\n";
}
void generatePlayingField(const std::vector<std::vector<char>>& chessboard) {
char desc = 56;
for (int row = 0; row < boardSize; ++row) {
display += " ";
display += desc--;
display += " " + vertical;
for (int col = 0; col < boardSize; ++col) {
display += " " + getChessIcon(chessboard[row][col]) + " " + vertical;
}
display += "\n";
// Horizontale Trennlinie (außer nach der letzten Zeile)
if (row < boardSize - 1) {
display += " " + horizontal + " " + vertical;
for (int col = 0; col < boardSize; ++col) {
display += horizontal + horizontal + horizontal;
if (col < boardSize - 1) display += middleIntersection;
}
display += vertical + "\n";
}
}
}
void generateBottomLine() {
char desc = 65;
display += " " + horizontal + " " + bottomLeft;
for (int col = 0; col < boardSize; ++col) {
display += horizontal + horizontal + horizontal;
if (col < boardSize - 1) display += bottomIntersection;
}
display += bottomRight + "\n";
display += " " + vertical;
for (int col = 0; col < boardSize; ++col) {
display += " ";
display += (desc++);
display += " " + vertical;
}
}
public:
/* fields */
std::string display;
int boardSize = 8;
bool getTurnOrder() {
return this->turnOrder;
}
void setTurnOrder(bool turnOrder) {
this->turnOrder = turnOrder;
}
/* methods */
void setBoard(std::vector<std::vector<char>> board) {
this->currentBoard = board;
}
std::vector<std::vector<char>> getBoard() {
return this->currentBoard;
}
std::vector<std::vector<char>> getStartBoard() {
return this->startBoard;
}
std::vector<std::vector<char>> getEmptyBoard() {
return this->emptyBoard;
}
void draw () {
draw(getStartBoard());
}
void draw (const std::vector<std::vector<char>>& chessboard) {
// Obere Rahmenlinie
generateTopLine();
// Schachbrett mit vertikalen Linien
generatePlayingField(chessboard);
// Untere Rahmenlinie
generateBottomLine();
setBoard(chessboard);
std::cout << display << std::endl;
}
// ToDo:
// Methode um mögliche Züge anzuzeigen
// Rochade
// Mate
// Schachmate
// En Passond
// Restlichen moves
// Angabe mit Menü Optionen als Zahlen
// Figuren wählen mit Schachnotation
char getCorrectPiece(char pieceIdentifier) {
bool isWhite = getTurnOrder();
if (!isWhite) return pieceIdentifier + 32;
return pieceIdentifier;
}
std::pair<int, int> convertPosition(const std::string &pos) {
static const std::unordered_map<int, int> fileConvertion = {
{0, 7},
{1, 6},
{2, 5},
{3, 4},
{4, 3},
{5, 2},
{6, 1},
{7, 0}
};
int y = pos[pos.size()-2] - 'a';
int x = fileConvertion.find((pos[pos.size()-1] - '0')-1)->second;
return std::make_pair(x, y);
}
//
void move(std::string move) {
// ToDo:
// add move to history queue
std::vector<std::string> splitMove;
if (move.find('#') != std::string::npos) {
// Schachmate
// Finish game
} else if (move.rfind("0-0", 0) == 0) { // Kleine Rochade
// Check for Rochade
} else if (move.rfind("0-0-0", 0) == 0) {
// Große Rochade
}
// Standard move
if (move.find('-')) {
splitMove = Utils::split(move, '-');
} else if (move.find('x')) {
splitMove = Utils::split(move, 'x');
}
std::pair oldCoords = convertPosition(splitMove[0]);
std::pair newCoords = convertPosition(splitMove[1]);
std::vector<std::vector<char>> board = getBoard();
board[oldCoords.first][oldCoords.second] = getEmptyBoard()[oldCoords.first][oldCoords.second];
board[newCoords.first][newCoords.second] = getCorrectPiece(splitMove[0][0]);
draw(board);
// Notation
// Start with current position - dash - new position
// eg.: b1-c3
// Letter first than number
// eg.: a5
// Pawn: e4 or p e4 (pawn)
// R for rook
// N for Knight
// K for King
// B for Bischop
// Q for Queen
// Special:
// 0-0 short castle
// 0-0-0 long castle
// en passond: write square where pawn lands
// capture: x
// check: +
// checkmate: #
// draw/stalemate: 1/2-1/2
}
// This method saves the current board state
void saveBoard(Chessboard& chessboard) {
}
// This method loads a save state
void loadBoard(int saveState) {
// readJSONFile
//
}
};