Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <Windows.h>
- #include "PromotionChoiceForm.h"
- namespace ChessApplication {
- using namespace System;
- using namespace System::ComponentModel;
- using namespace System::Collections;
- using namespace System::Collections::Generic;
- using namespace System::Windows::Forms;
- using namespace System::Data;
- using namespace System::Drawing;
- // Оголошення класу фігури
- class ChessPiece {
- private:
- bool hasMoved;
- public:
- bool isBlack; // true for white pieces, false for black pieces
- int capturedPositionX;
- int capturedPositionY;
- // Constructor to set the color of the piece
- ChessPiece(bool isBlack) : isBlack(isBlack), hasMoved(false) {}
- // Отримати, чи фігура вже була рухнута
- bool HasMoved() { return hasMoved; }
- // Встановити прапорець, що фігура була рухнута
- void SetMoved(bool moved) { hasMoved = moved; }
- virtual bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) = 0;
- void Capture(int x, int y)
- {
- capturedPositionX = x;
- capturedPositionY = y;
- }
- };
- // Оголошення класу фігури Канцлер
- class Chancellor : public ChessPiece {
- public:
- Chancellor(bool isBlack) : ChessPiece(isBlack) {}
- bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) {
- // Chancellor moves like a combination of a Rook and a Knight
- int dx = abs(fromX - toX);
- int dy = abs(fromY - toY);
- // Check if the move is like a Knight (L-shaped)
- if ((dx == 2 && dy == 1) || (dx == 1 && dy == 2)) {
- // A Knight-like move is valid, check if the destination cell is empty or has an opponent's piece
- ChessPiece* targetPiece = board[toX][toY];
- return targetPiece == nullptr || (targetPiece->isBlack != isBlack);
- }
- // Check if the move is like a Rook (horizontally or vertically)
- if ((dx == 0 && dy > 0) || (dx > 0 && dy == 0)) {
- // A Rook-like move is valid, check for obstacles along the path
- int stepX = (toX > fromX) ? 1 : (toX < fromX) ? -1 : 0;
- int stepY = (toY > fromY) ? 1 : (toY < fromY) ? -1 : 0;
- int x = fromX + stepX;
- int y = fromY + stepY;
- while (x != toX || y != toY) {
- if (board[x][y] != nullptr) {
- // There is an obstacle in the way, move is invalid
- return false;
- }
- x += stepX;
- y += stepY;
- }
- ChessPiece* targetPiece = board[toX][toY];
- return targetPiece == nullptr || (targetPiece->isBlack != isBlack);
- }
- return false; // Invalid move for the Chancellor
- }
- };
- // Оголошення класу фігури Архієпископ
- class Archbishop : public ChessPiece {
- public:
- Archbishop(bool isBlack) : ChessPiece(isBlack) {}
- bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) {
- // Archbishop moves like a combination of a Bishop and a Knight
- int dx = abs(fromX - toX);
- int dy = abs(fromY - toY);
- // Check if the move is like a Knight (L-shaped)
- if ((dx == 2 && dy == 1) || (dx == 1 && dy == 2)) {
- // A Knight-like move is valid, check if the destination cell is empty or has an opponent's piece
- ChessPiece* targetPiece = board[toX][toY];
- return targetPiece == nullptr || (targetPiece->isBlack != isBlack);
- }
- // Check if the move is like a Bishop (diagonally)
- if (dx == dy) {
- // A Bishop-like move is valid, check for obstacles along the path
- int stepX = (toX > fromX) ? 1 : (toX < fromX) ? -1 : 0;
- int stepY = (toY > fromY) ? 1 : (toY < fromY) ? -1 : 0;
- int x = fromX + stepX;
- int y = fromY + stepY;
- while (x != toX || y != toY) {
- if (board[x][y] != nullptr) {
- // There is an obstacle in the way, move is invalid
- return false;
- }
- x += stepX;
- y += stepY;
- }
- // Check if the destination cell is empty or has an opponent's piece
- ChessPiece* targetPiece = board[toX][toY];
- return targetPiece == nullptr || (targetPiece->isBlack != isBlack);
- }
- return false; // Invalid move for the Archbishop
- }
- };
- // Оголошення класу фігури Слон
- class Bishop : public ChessPiece {
- public:
- Bishop(bool isBlack) : ChessPiece(isBlack) {}
- bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) {
- // Bishop moves diagonally
- int dx = abs(fromX - toX);
- int dy = abs(fromY - toY);
- if (dx != dy) {
- return false; // Bishop can only move diagonally
- }
- // Check if there are any pieces in the path
- int xDir = (toX > fromX) ? 1 : -1;
- int yDir = (toY > fromY) ? 1 : -1;
- int x = fromX + xDir;
- int y = fromY + yDir;
- while (x != toX && y != toY) {
- if (x < 0 || x >= 10 || y < 0 || y >= 8) {
- return false; // Out of bounds
- }
- if (board[x][y] != nullptr) {
- return false; // There is a piece in the path
- }
- x += xDir;
- y += yDir;
- }
- // Check if the destination position is empty or has an opponent's piece
- if (x < 0 || x >= 10 || y < 0 || y >= 8) {
- return false; // Out of bounds
- }
- ChessPiece* destinationPiece = board[x][y];
- if (destinationPiece != nullptr && destinationPiece->isBlack == isBlack) {
- return false; // Cannot capture own piece
- }
- return true;
- }
- };
- // Оголошення класу фігури Король
- class King : public ChessPiece {
- public:
- King(bool isBlack) : ChessPiece(isBlack) {}
- bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) {
- // King moves one square in any direction
- int dx = abs(fromX - toX);
- int dy = abs(fromY - toY);
- return (dx <= 1 && dy <= 1);
- }
- };
- // Оголошення класу фігури Королева
- class Queen : public ChessPiece {
- public:
- Queen(bool isBlack) : ChessPiece(isBlack) {}
- bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) {
- // Queen moves like a combination of a Rook and a Bishop
- int dx = abs(fromX - toX);
- int dy = abs(fromY - toY);
- // Check if the move is along a straight line or diagonal
- if (!((fromX == toX && fromY != toY) || (fromX != toX && fromY == toY) || (dx == dy))) {
- return false;
- }
- // Check for obstacles along the path (straight or diagonal)
- int stepX = (toX == fromX) ? 0 : (toX > fromX) ? 1 : -1;
- int stepY = (toY == fromY) ? 0 : (toY > fromY) ? 1 : -1;
- int x = fromX + stepX;
- int y = fromY + stepY;
- while (x != toX || y != toY) {
- if (board[x][y] != nullptr) {
- // There is an obstacle in the way, move is invalid
- return false;
- }
- x += stepX;
- y += stepY;
- }
- return true;
- }
- };
- // Оголошення класу фігури Ладья (Rook)
- class Rook : public ChessPiece {
- public:
- Rook(bool isBlack) : ChessPiece(isBlack) {}
- bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) override {
- // Rook moves along a straight line (horizontal or vertical)
- int dx = abs(fromX - toX);
- int dy = abs(fromY - toY);
- // Check if the move is along a straight line
- if (!((fromX == toX && fromY != toY) || (fromX != toX && fromY == toY))) {
- return false;
- }
- // Check for obstacles along the path
- int stepX = (toX == fromX) ? 0 : (toX > fromX) ? 1 : -1;
- int stepY = (toY == fromY) ? 0 : (toY > fromY) ? 1 : -1;
- int x = fromX + stepX;
- int y = fromY + stepY;
- while (x != toX || y != toY) {
- if (board[x][y] != nullptr) {
- // There is an obstacle in the way, move is invalid
- return false;
- }
- x += stepX;
- y += stepY;
- }
- return true;
- }
- };
- // Оголошення класу фігури Конь (Knight)
- class Knight : public ChessPiece {
- public:
- Knight(bool isBlack) : ChessPiece(isBlack) {}
- bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) override {
- // Рух Коня може бути здійснений у вигляді букви "L" (дві клітинки по одній осі і одна по іншій)
- int dx = abs(fromX - toX);
- int dy = abs(fromY - toY);
- return (dx == 2 && dy == 1) || (dx == 1 && dy == 2);
- }
- };
- // Оголошення класу фігури Пішак
- class Pawn : public ChessPiece {
- public:
- Pawn(bool isBlack) : ChessPiece(isBlack) {}
- bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) {
- int dx = abs(fromX - toX);
- int dy = abs(fromY - toY);
- if (board[fromX][fromY] == nullptr) {
- return false; // No piece to move
- }
- if (isBlack) {
- if (fromX == toX && fromY == toY - 1 && board[toX][toY] == nullptr) {
- return true; // Move one square forward
- }
- if (fromX == toX - 1 && fromY == toY - 1 && board[toX][toY] != nullptr && !board[toX][toY]->isBlack) {
- return true; // Capture diagonally to the left
- }
- if (fromX == toX + 1 && fromY == toY - 1 && board[toX][toY] != nullptr && !board[toX][toY]->isBlack) {
- return true; // Capture diagonally to the right
- }
- if (fromY == 1 && toY == 3 && fromX == toX && board[toX][toY] == nullptr && board[toX][toY - 1] == nullptr) {
- return true; // Move two squares forward on the first move
- }
- }
- else {
- if (fromX == toX && fromY == toY + 1 && board[toX][toY] == nullptr) {
- return true; // Move one square forward
- }
- if (fromX == toX - 1 && fromY == toY + 1 && board[toX][toY] != nullptr && board[toX][toY]->isBlack) {
- return true; // Capture diagonally to the left
- }
- if (fromX == toX + 1 && fromY == toY + 1 && board[toX][toY] != nullptr && board[toX][toY]->isBlack) {
- return true; // Capture diagonally to the right
- }
- if (fromY == 6 && toY == 4 && fromX == toX && board[toX][toY] == nullptr && board[toX][toY + 1] == nullptr) {
- return true; // Move two squares forward on the first move
- }
- }
- return false;
- }
- };
- // Оголошення класу дошки
- class ChessBoard {
- private:
- std::vector<std::vector<ChessPiece*>> board;
- public:
- void setPiece(int x, int y, ChessPiece* piece) {
- board[x][y] = piece;
- }
- ChessBoard() : board(10, std::vector<ChessPiece*>(8, nullptr)) {
- // Початкове розташування фігур на дошці
- board[0][0] = new Rook(true); // Ладья
- board[1][0] = new Knight(true); // Конь
- board[2][0] = new Archbishop(true); // Архієпископ
- board[3][0] = new Bishop(true); // Слон
- board[4][0] = new Queen(true); // Королева
- board[5][0] = new King(true); // Король
- board[6][0] = new Bishop(true); // Слон
- board[7][0] = new Chancellor(true); // Канцлер
- board[8][0] = new Knight(true); // Конь
- board[9][0] = new Rook(true); // Ладья
- // Вторая линия фигур (белые пешки)
- for (int y = 0; y < 10; y++) {
- board[y][1] = new Pawn(true); // Пішаки (другая лінія)
- }
- // Седьмая линия фигур (черные пешки)
- for (int y = 0; y < 10; y++) {
- board[y][6] = new Pawn(false); // Пішаки (сьома лінія)
- }
- // Восьмая линия фигур (черные фигуры)
- board[0][7] = new Rook(false); // Ладья
- board[1][7] = new Knight(false); // Конь
- board[2][7] = new Archbishop(false); // Архієпископ
- board[3][7] = new Bishop(false); // Слон
- board[4][7] = new Queen(false); // Королева
- board[5][7] = new King(false); // Король
- board[6][7] = new Bishop(false); // Слон
- board[7][7] = new Chancellor(false); // Канцлер
- board[8][7] = new Knight(false); // Конь
- board[9][7] = new Rook(false); // Ладья
- }
- bool performCastling(int kingFromX, int kingFromY, int kingToX, int kingToY, int rookFromX, int rookFromY, int rookToX, int rookToY) {
- ChessPiece* king = board[kingFromX][kingFromY];
- ChessPiece* rook = board[rookFromX][rookFromY];
- // Перевірка чи фігури король та ладья знаходяться на відповідних позиціях
- if (!king || !rook || !dynamic_cast<King*>(king) || !dynamic_cast<Rook*>(rook)) {
- return false;
- }
- // Перевірка наявності фігур між королем і ладьєю
- int minRookX = System::Math::Min(rookFromX, rookToX);
- int maxRookX = System::Math::Max(rookFromX, rookToX);
- for (int x = minRookX + 1; x < maxRookX; x++) {
- if (board[x][kingFromY] != nullptr) {
- return false;
- }
- }
- // Виконуємо рокировку
- board[kingFromX][kingFromY] = nullptr;
- board[rookFromX][rookFromY] = nullptr;
- board[kingToX][kingToY] = king;
- board[rookToX][rookToY] = rook;
- return true;
- }
- ~ChessBoard() {
- // Звільняємо пам'ять від фігур
- for (int i = 0; i < 8; i++) {
- for (int j = 0; j < 8; j++) {
- delete board[i][j];
- }
- }
- }
- bool promotePawn(int x, int y, char pieceType) {
- ChessPiece* piece = board[x][y];
- if (piece != nullptr && dynamic_cast<Pawn*>(piece)) {
- bool isBlack = piece->isBlack;
- delete board[x][y];
- ChessPiece* newPiece = nullptr;
- switch (pieceType) {
- case 'Q': newPiece = new Queen(isBlack); break;
- case 'R': newPiece = new Rook(isBlack); break;
- case 'B': newPiece = new Bishop(isBlack); break;
- case 'N': newPiece = new Knight(isBlack); break;
- case 'C': newPiece = new Chancellor(isBlack); break;
- case 'A': newPiece = new Archbishop(isBlack); break;
- }
- if (newPiece != nullptr) {
- board[x][y] = newPiece;
- return true;
- }
- }
- return false;
- }
- ChessPiece* getPiece(int x, int y) {
- // Метод для отримання фігури на позиції (x, y) на дошці
- // Повертає nullptr, якщо клітинка порожня
- if (x >= 0 && x < 10 && y >= 0 && y < 8) {
- return board[x][y];
- }
- return nullptr;
- }
- bool makeMove(int fromX, int fromY, int toX, int toY) {
- // Метод для здійснення ходу
- if (!isValidMove(fromX, fromY, toX, toY)) {
- return false;
- }
- ChessPiece* piece = board[fromX][fromY];
- board[fromX][fromY] = nullptr;
- board[toX][toY] = piece;
- return true;
- }
- bool isValidMove(int fromX, int fromY, int toX, int toY) {
- // Метод для перевірки чи дозволений хід фігури з позиції (fromX, fromY) на позицію (toX, toY)
- // Включає логіку перевірки правил руху для конкретної фігури
- // Перевірка чи позиції відповідають допустимому діапазону
- if (fromX < 0 || fromX >= 10 || fromY < 0 || fromY >= 8 ||
- toX < 0 || toX >= 10 || toY < 0 || toY >= 8) {
- return false;
- }
- // Перевірка чи на позиції (fromX, fromY) є фігура
- ChessPiece* piece = board[fromX][fromY];
- if (piece == nullptr) {
- return false;
- }
- // Перевірка чи хід є допустимим для даної фігури
- if (!piece->isValidMove(fromX, fromY, toX, toY, board)) {
- return false;
- }
- // Перевірка, чи на позиції (toX, toY) є фігура т ого ж кольору
- ChessPiece* targetPiece = board[toX][toY];
- if (targetPiece != nullptr && targetPiece->isBlack == piece->isBlack) {
- return false;
- }
- return true;
- }
- bool movePiece(int fromX, int fromY, int toX, int toY) {
- // Здійснюємо хід фігурою
- if (fromX < 0 || fromX >= 8 || fromY < 0 || fromY >= 8 || toX < 0 || toX >= 8 || toY < 0 || toY >= 8) {
- return false; // За межами дошки
- }
- ChessPiece* piece = board[fromX][fromY];
- if (piece == nullptr) {
- return false; // Немає фігури для переміщення
- }
- if (piece->isValidMove(fromX, fromY, toX, toY, board)) {
- delete board[toX][toY];
- board[toX][toY] = piece;
- board[fromX][fromY] = nullptr;
- return true;
- }
- return false;
- }
- bool makeMoveRook(int fromX, int fromY, int toX, int toY) {
- ChessPiece* piece = board[fromX][fromY];
- board[fromX][fromY] = nullptr;
- board[toX][toY] = piece;
- return true;
- }
- };
- public ref class MyForm : public System::Windows::Forms::Form
- {
- public:
- MyForm(void)
- {
- InitializeComponent();
- board = new ChessBoard();
- InitializeChessboard();
- // Підписка на події кліків по клітинках
- for (int x = 0; x < 10; x++) {
- for (int y = 0; y < 8; y++) {
- boardPictureBoxes[x, y]->Click += gcnew EventHandler(this, &MyForm::Cell_Click);
- }
- }
- }
- protected:
- ~MyForm()
- {
- if (components)
- {
- delete components;
- }
- }
- private:
- System::ComponentModel::Container^ components;
- // Графічний інтерфейс
- array<PictureBox^, 2>^ boardPictureBoxes;
- ChessBoard* board;
- Graphics^ g;
- int selectedX = -1; // Stores the X coordinate of the selected piece
- int selectedY = -1; // Stores the Y coordinate of the selected piece
- bool validMovesHighlighted = false;
- List<Tuple<int, int>^>^ validMoves = gcnew List<Tuple<int, int>^>();
- const int imageWidth = 40; // Зменшені розміри фігур по ширині
- const int imageHeight = 40; // Зменшені розміри фігур по висоті
- void InitializeComponent(void)
- {
- this->components = gcnew System::ComponentModel::Container();
- this->Size = System::Drawing::Size(820, 660);
- this->Text = L"Chess";
- this->AutoScaleDimensions = System::Drawing::SizeF(8, 16);
- this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
- // Створення PictureBox для клітинок шахівниці
- boardPictureBoxes = gcnew array<PictureBox^, 2>(10, 8);
- for (int x = 0; x < 10; x++) {
- for (int y = 0; y < 8; y++) {
- boardPictureBoxes[x, y] = gcnew PictureBox();
- boardPictureBoxes[x, y]->Size = System::Drawing::Size(60, 60);
- boardPictureBoxes[x, y]->Location = System::Drawing::Point(x * 60, y * 60);
- boardPictureBoxes[x, y]->BackColor = ((x + y) % 2 == 0) ? Color::Bisque : Color::DarkOrange;
- this->Controls->Add(boardPictureBoxes[x, y]);
- }
- }
- }
- Image^ LoadImageForPiece(ChessPiece* piece, int x, int y) {
- Image^ image = nullptr;
- if (dynamic_cast<Chancellor*>(piece)) {
- if (piece->isBlack) {
- image = Image::FromFile("C:\\chess\\black-chess\\сhancellor.png");
- }
- else {
- image = Image::FromFile("C:\\chess\\white-chess\\сhancellor.png");
- }
- }
- else if (dynamic_cast<Archbishop*>(piece)) {
- if (piece->isBlack) {
- image = Image::FromFile("C:\\chess\\black-chess\\archbishop.png");
- }
- else {
- image = Image::FromFile("C:\\chess\\white-chess\\archbishop.png");
- }
- }
- else if (dynamic_cast<Pawn*>(piece)) {
- if (piece->isBlack) {
- image = Image::FromFile("C:\\chess\\black-chess\\pawn.png");
- }
- else {
- image = Image::FromFile("C:\\chess\\white-chess\\pawn.png");
- }
- }
- else if (dynamic_cast<Queen*>(piece)) {
- if (piece->isBlack) {
- image = Image::FromFile("C:\\chess\\black-chess\\queen.png");
- }
- else {
- image = Image::FromFile("C:\\chess\\white-chess\\queen.png");
- }
- }
- else if (dynamic_cast<King*>(piece)) {
- if (piece->isBlack) {
- image = Image::FromFile("C:\\chess\\black-chess\\king.png");
- }
- else {
- image = Image::FromFile("C:\\chess\\white-chess\\king.png");
- }
- }
- else if (dynamic_cast<Bishop*>(piece)) {
- if (piece->isBlack) {
- image = Image::FromFile("C:\\chess\\black-chess\\bishop.png");
- }
- else {
- image = Image::FromFile("C:\\chess\\white-chess\\bishop.png");
- }
- }
- else if (dynamic_cast<Knight*>(piece)) {
- if (piece->isBlack) {
- image = Image::FromFile("C:\\chess\\black-chess\\knight.png");
- }
- else {
- image = Image::FromFile("C:\\chess\\white-chess\\knight.png");
- }
- }
- else if (dynamic_cast<Rook*>(piece)) {
- if (piece->isBlack) {
- image = Image::FromFile("C:\\chess\\black-chess\\rook.png");
- }
- else {
- image = Image::FromFile("C:\\chess\\white-chess\\rook.png");
- }
- }
- if (image != nullptr) {
- // Змініть розмір зображення фігури на imageWidth та imageHeight
- image = gcnew Bitmap(image, imageWidth, imageHeight);
- }
- return image;
- }
- bool IsInCheck(bool isBlack, ChessBoard* board) {
- // Знаходимо позицію короля поточного гравця
- int kingX = -1;
- int kingY = -1;
- for (int x = 0; x < 10; x++) {
- for (int y = 0; y < 8; y++) {
- ChessPiece* piece = board->getPiece(x, y);
- if (piece != nullptr && piece->isBlack == isBlack && dynamic_cast<King*>(piece)) {
- kingX = x;
- kingY = y;
- break;
- }
- }
- if (kingX != -1 && kingY != -1) {
- break;
- }
- }
- // Перевіряємо, чи є можливі ходи опонента, які можуть атакувати короля
- for (int x = 0; x < 10; x++) {
- for (int y = 0; y < 8; y++) {
- ChessPiece* piece = board->getPiece(x, y);
- if (piece != nullptr && piece->isBlack != isBlack) {
- if (board->isValidMove(x, y, kingX, kingY)) {
- return true;
- }
- }
- }
- }
- // Exclude exceptX, exceptY from checking
- for (int x = 0; x < 10; x++) {
- for (int y = 0; y < 8; y++) {
- ChessPiece* piece = board->getPiece(x, y);
- if (piece != nullptr && piece->isBlack != isBlack) {
- if (board->isValidMove(x, y, kingX, kingY)) {
- return true;
- }
- }
- }
- }
- return false;
- }
- bool IsCheckmate(bool isBlack, ChessBoard* board) {
- // Перевіряємо, чи король в шаху
- if (!IsInCheck(isBlack, board)) {
- return false; // Немає шаху, немає мату
- }
- // Перевіряємо, чи є можливі ходи для короля
- int kingX = -1;
- int kingY = -1;
- // Check if squares between kings are under threat
- int kingDestX = 2; // Assuming king's target position after castling
- int kingOrigX = 4; // Assuming king's original position
- if (kingDestX < kingOrigX && IsInCheck(isBlack, board)) {
- return false; // Castling not possible because squares are under threat
- }
- for (int x = 0; x < 10; x++) {
- for (int y = 0; y < 8; y++) {
- ChessPiece* piece = board->getPiece(x, y);
- if (piece != nullptr && piece->isBlack == isBlack && dynamic_cast<King*>(piece)) {
- kingX = x;
- kingY = y;
- break;
- }
- }
- if (kingX != -1 && kingY != -1) {
- break;
- }
- }
- for (int dx = -1; dx <= 1; dx++) {
- for (int dy = -1; dy <= 1; dy++) {
- int destX = kingX + dx;
- int destY = kingY + dy;
- if (board->isValidMove(kingX, kingY, destX, destY) && !IsInCheckAfterMove(kingX, kingY, destX, destY, isBlack, board)) {
- return false; // Є можливий хід для короля
- }
- }
- }
- // Шах і немає можливих ходів для короля
- // Перевіряємо, чи можуть інші фігури захистити короля або блокувати атакуючі фігури
- for (int x = 0; x < 10; x++) {
- for (int y = 0; y < 8; y++) {
- ChessPiece* piece = board->getPiece(x, y);
- if (piece != nullptr && piece->isBlack == isBlack) {
- List<Tuple<int, int>^>^ moves = GetValidMoves(x, y, board);
- for each (Tuple<int, int> ^ move in moves) {
- int destX = move->Item1;
- int destY = move->Item2;
- if (!IsInCheckAfterMove(x, y, destX, destY, isBlack, board)) {
- return false; // Існує можливий хід для іншої фігури
- }
- }
- }
- }
- }
- return true; // Шах і мат
- }
- bool IsInCheckAfterMove(int startX, int startY, int destX, int destY, bool isBlack, ChessBoard* board) {
- // Збережіть фігуру, яку збираєтеся зрушити
- ChessPiece* tempDestPiece = board->getPiece(destX, destY);
- // Зробіть хід на тимчасовій дошці
- board->movePiece(startX, startY, destX, destY);
- // Перевірте, чи король буде в шаху після цього ходу
- bool result = IsInCheck(isBlack, board);
- // Відновіть попередній стан дошки, скасовуючи хід
- board->movePiece(destX, destY, startX, startY);
- //board->setPiece(destX, destY, tempDestPiece);
- // Check if any square between original and target king positions is under threat
- int dx = (destX > startX) ? 1 : -1;
- for (int x = startX + dx; x != destX; x += dx) {
- if (IsInCheck(isBlack, board)) {
- return true;
- }
- }
- return result;
- }
- //void MyForm::PerformCastling(int kingX, int kingY, int rookX, int rookY) {
- // // Виконання рокіровки:
- // int direction = (rookX > kingX) ? 1 : -1;
- // int newKingX = kingX + 2 * direction;
- // int newRookX = kingX + direction;
- // // Переміщення короля
- // board->movePiece(kingX, kingY, newKingX, kingY);
- // // Переміщення тури
- // board->movePiece(rookX, rookY, newRookX, rookY);
- // // Оновлення графічного відображення
- // DrawPiece(kingX, kingY);
- // DrawPiece(rookX, rookY);
- // DrawPiece(newKingX, kingY);
- // DrawPiece(newRookX, rookY);
- //}
- List<Tuple<int, int>^>^ GetValidMoves(int x, int y, ChessBoard* board) {
- List<Tuple<int, int>^>^ validMoves = gcnew List<Tuple<int, int>^>();
- ChessPiece* piece = board->getPiece(x, y);
- if (piece == nullptr) {
- return validMoves; // Пуста клітинка
- }
- // Реалізуйте генерацію можливих ходів для конкретної фігури (пішака, кінь, тощо)
- return validMoves;
- }
- bool MyForm::IsCastlingValid(int startX, int startY, int destX, int destY) {
- ChessPiece* piece = board->getPiece(startX, startY);
- ChessPiece* destPiece = board->getPiece(destX, destY);
- if (piece == nullptr || destPiece != nullptr || piece->HasMoved() == true) {
- return false; // Немає фігури для рокіровки або клітинка зайнята
- }
- // Перевірка на те, чи король і тура ще не ходили
- //if (!piece->HasMoved() && dynamic_cast<Rook*>(destPiece) != nullptr && !destPiece->HasMoved()) {
- //MessageBox::Show("qw");
- int dx = destX - startX;
- int dy = destY - startY;
- // Перевірка на коротку рокіровку (вправо)
- if (dx == 2 && dy == 0) {
- // Перевірка, що між королем і турою немає інших фігур
- for (int i = startX + 1; i < destX; i++) {
- if (board->getPiece(i, startY) != nullptr) {
- return false;
- }
- }
- return true;
- }
- // Перевірка на довгу рокіровку (вліво)
- if (dx == -2 && dy == 0) {
- // Перевірка, що між королем і турою немає інших фігур
- for (int i = startX - 1; i > destX; i--) {
- if (board->getPiece(i, startY) != nullptr) {
- return false;
- }
- }
- return true;
- }
- //}
- return false;
- }
- bool isBlacksTurn;
- void MyForm::Cell_Click(Object^ sender, EventArgs^ e) {
- PictureBox^ pictureBox = (PictureBox^)sender;
- int x = pictureBox->Location.X / 60;
- int y = pictureBox->Location.Y / 60;
- // If no piece is currently selected, try to select one
- ChessPiece* piece = board->getPiece(x, y);
- if (selectedX == -1 && selectedY == -1) {
- if (piece != nullptr && ((isBlacksTurn && piece->isBlack) || (!isBlacksTurn && !piece->isBlack))) {
- validMoves = GetValidMoves(x, y);
- HighlightValidMoves();
- pictureBox->BorderStyle = BorderStyle::FixedSingle;
- // Update selected IsInCheck
- selectedX = x;
- selectedY = y;
- // Check for promotion for a pawn reaching the last rank
- if (dynamic_cast<Pawn*>(piece) && ((piece->isBlack && y == 7) || (!piece->isBlack && y == 0))) {
- // Prompt the user for promotion
- char pieceType = 'Q'; // Default to Queen
- PromotionChoiceForm^ promotionForm = gcnew PromotionChoiceForm();
- if (promotionForm->ShowDialog() == System::Windows::Forms::DialogResult::OK) {
- pieceType = promotionForm->GetSelectedPieceSymbol();
- }
- bool success = board->promotePawn(x, y, pieceType);
- if (success) {
- DrawPiece(x, y);
- }
- }
- }
- }
- else {
- // A piece is already selected, try to make a move to the clicked cell
- if (board->isValidMove(selectedX, selectedY, x, y)) {
- //MessageBox::Show("x = " + x.ToString() + "\ny = " + y.ToString() + "\n sx = " + selectedX.ToString() + "\n sy = " + selectedY.ToString());
- // Check for castling
- if (IsCastlingValid(selectedX, selectedY, x, y)) {
- int kingFromX, kingToX, rookFromX, rookToX;
- // Права рокіровка
- if (selectedX == 9) {
- //MessageBox::Show("x = " + x.ToString() + "\ny = " + y.ToString() + "\n sx = " + selectedX.ToString() + "\n sy = " + selectedY.ToString());
- kingFromX = 5;
- kingToX = 8;
- rookFromX = 9;
- rookToX = 7;
- }
- // Ліва рокіровка
- else if (selectedX == 0) {
- MessageBox::Show("x = " + x.ToString() + "\ny = " + y.ToString() + "\n sx = " + selectedX.ToString() + "\n sy = " + selectedY.ToString());
- kingFromX = 5;
- kingToX = 2;
- rookFromX = 0;
- rookToX = 3;
- }
- //bool castlingResult = board->performCastling(5, 7, 8, 7, 9, 7, 7, 7);
- bool castlingResult = board->performCastling(kingFromX, selectedY, kingToX, selectedY, rookFromX, selectedY, rookToX, selectedY);
- if (castlingResult) {
- // Оновлення графічного відображення після рокіровки
- DrawPiece(kingFromX, selectedY);
- DrawPiece(kingToX, selectedY);
- DrawPiece(rookFromX, selectedY);
- DrawPiece(rookToX, selectedY);
- }
- }
- // Attempt to make the move
- bool moveResult = board->makeMove(selectedX, selectedY, x, y);
- if (moveResult) {
- // Move was successful, update the graphical representation
- DrawPiece(selectedX, selectedY); // Clear the source cell
- DrawPiece(x, y); // Draw the piece on the destination cell
- // Toggle the turn between players
- isBlacksTurn = !isBlacksTurn;
- }
- }
- // Перевіряємо на шах та мат
- //bool isBlack = currentPlayer == Player::Black;
- if (IsCheckmate(isBlacksTurn, board)) {
- // Оголошуємо мат
- if (isBlacksTurn) {
- MessageBox::Show("Білий гравець переміг (чорний гравець у маті)!");
- }
- else {
- MessageBox::Show("Чорний гравець переміг (білий гравець у маті)!");
- }
- }
- else if (IsInCheck(isBlacksTurn, board)) {
- // Попередження про шах
- MessageBox::Show("Шах!");
- }
- validMoves->Clear();
- UnhighlightValidMoves();
- boardPictureBoxes[selectedX, selectedY]->BorderStyle = BorderStyle::None;
- // Reset selected coordinates
- selectedX = -1;
- selectedY = -1;
- }
- }
- List<Tuple<int, int>^>^ GetValidMoves(int x, int y) {
- List<Tuple<int, int>^>^ moves = gcnew List<Tuple<int, int>^>();
- ChessPiece* piece = board->getPiece(x, y);
- if (piece != nullptr) {
- for (int destX = 0; destX < 10; destX++) {
- for (int destY = 0; destY < 8; destY++) {
- if (board->isValidMove(x, y, destX, destY)) {
- moves->Add(gcnew Tuple<int, int>(destX, destY));
- }
- }
- }
- }
- return moves;
- }
- void HighlightValidMoves() {
- Color highlightColor = Color::Green;
- for each (Tuple<int, int> ^ move in validMoves) {
- int x = move->Item1;
- int y = move->Item2;
- // Create a new Pen with the highlight color and thickness
- Pen^ highlightPen = gcnew Pen(highlightColor, 3);
- // Draw a rectangle (outline) around the PictureBox to highlight it
- Graphics^ g = boardPictureBoxes[x, y]->CreateGraphics();
- g->DrawRectangle(highlightPen, 0, 0, boardPictureBoxes[x, y]->Width - 1, boardPictureBoxes[x, y]->Height - 1);
- // Dispose of the Pen to release resources
- delete highlightPen;
- }
- }
- void UnhighlightValidMoves() {
- for (int x = 0; x < 10; x++) {
- for (int y = 0; y < 8; y++) {
- if ((x + y) % 2 == 0) {
- Pen^ highlightPen = gcnew Pen(Color::Bisque, 3);
- // Draw a rectangle (outline) around the PictureBox to highlight it
- Graphics^ g = boardPictureBoxes[x, y]->CreateGraphics();
- g->DrawRectangle(highlightPen, 0, 0, boardPictureBoxes[x, y]->Width - 1, boardPictureBoxes[x, y]->Height - 1);
- // Dispose of the Pen to release resources
- delete highlightPen;
- }
- else {
- //boardPictureBoxes[x, y]->BackColor = Color::DarkOrange;
- Pen^ highlightPen = gcnew Pen(Color::DarkOrange, 3);
- // Draw a rectangle (outline) around the PictureBox to highlight it
- Graphics^ g = boardPictureBoxes[x, y]->CreateGraphics();
- g->DrawRectangle(highlightPen, 0, 0, boardPictureBoxes[x, y]->Width - 1, boardPictureBoxes[x, y]->Height - 1);
- // Dispose of the Pen to release resources
- delete highlightPen;
- }
- }
- }
- }
- void InitializeChessboard() {
- // Initialize graphical representation of the chessboard
- for (int x = 0; x < 10; x++) {
- for (int y = 0; y < 8; y++) {
- // Update the graphical representation of the chessboard
- DrawPiece(x, y); // Draw the piece or an empty cell at (x, y)
- }
- }
- }
- void DrawPiece(int x, int y) {
- ChessPiece* piece = board->getPiece(x, y);
- if (piece != nullptr) {
- boardPictureBoxes[x, y]->SizeMode = PictureBoxSizeMode::Zoom;
- Image^ image = LoadImageForPiece(piece, x, y);
- if (image != nullptr) {
- // Display the piece on the chessboard
- boardPictureBoxes[x, y]->Image = image;
- }
- }
- else {
- // Display an empty cell on the chessboard
- boardPictureBoxes[x, y]->Image = nullptr;
- boardPictureBoxes[x, y]->BackColor = ((x + y) % 2 == 0) ? Color::Bisque : Color::DarkOrange;
- }
- }
- };
- }
Add Comment
Please, Sign In to add comment