Vla_DOS

chess

Aug 13th, 2023
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 29.98 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <iostream>
  4. #include <vector>
  5. #include <algorithm>
  6.  
  7. #include <Windows.h>
  8. #include "PromotionChoiceForm.h"
  9.  
  10. namespace ChessApplication {
  11.  
  12.     using namespace System;
  13.     using namespace System::ComponentModel;
  14.     using namespace System::Collections;
  15.     using namespace System::Collections::Generic;
  16.  
  17.     using namespace System::Windows::Forms;
  18.     using namespace System::Data;
  19.     using namespace System::Drawing;
  20.  
  21.     // Оголошення класу фігури
  22.     class ChessPiece {
  23.     protected:
  24.  
  25.     public:
  26.         bool isBlack; // true for white pieces, false for black pieces
  27.         int capturedPositionX;
  28.         int capturedPositionY;
  29.         // Constructor to set the color of the piece
  30.         ChessPiece(bool isBlack) : isBlack(isBlack) {}
  31.  
  32.         virtual bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) = 0;
  33.  
  34.         void Capture(int x, int y)
  35.         {
  36.             capturedPositionX = x;
  37.             capturedPositionY = y;
  38.         }
  39.     };
  40.  
  41.     // Оголошення класу фігури Канцлер
  42.     class Chancellor : public ChessPiece {
  43.     public:
  44.         Chancellor(bool isBlack) : ChessPiece(isBlack) {}
  45.  
  46.         bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) {
  47.             // Chancellor moves like a combination of a Rook and a Knight
  48.             int dx = abs(fromX - toX);
  49.             int dy = abs(fromY - toY);
  50.  
  51.             // Check if the move is like a Knight (L-shaped)
  52.             if ((dx == 2 && dy == 1) || (dx == 1 && dy == 2)) {
  53.                 // A Knight-like move is valid, check if the destination cell is empty or has an opponent's piece
  54.                 ChessPiece* targetPiece = board[toX][toY];
  55.                 return targetPiece == nullptr || (targetPiece->isBlack != isBlack);
  56.             }
  57.  
  58.             // Check if the move is like a Rook (horizontally or vertically)
  59.             if ((dx == 0 && dy > 0) || (dx > 0 && dy == 0)) {
  60.                 // A Rook-like move is valid, check for obstacles along the path
  61.                 int stepX = (toX > fromX) ? 1 : (toX < fromX) ? -1 : 0;
  62.                 int stepY = (toY > fromY) ? 1 : (toY < fromY) ? -1 : 0;
  63.  
  64.                 int x = fromX + stepX;
  65.                 int y = fromY + stepY;
  66.  
  67.                 while (x != toX || y != toY) {
  68.                     if (board[x][y] != nullptr) {
  69.                         // There is an obstacle in the way, move is invalid
  70.                         return false;
  71.                     }
  72.                     x += stepX;
  73.                     y += stepY;
  74.                 }
  75.  
  76.                 ChessPiece* targetPiece = board[toX][toY];
  77.                 return targetPiece == nullptr || (targetPiece->isBlack != isBlack);
  78.             }
  79.  
  80.             return false; // Invalid move for the Chancellor
  81.         }
  82.     };
  83.  
  84.     // Оголошення класу фігури Архієпископ
  85.     class Archbishop : public ChessPiece {
  86.     public:
  87.         Archbishop(bool isBlack) : ChessPiece(isBlack) {}
  88.  
  89.         bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) {
  90.             // Archbishop moves like a combination of a Bishop and a Knight
  91.             int dx = abs(fromX - toX);
  92.             int dy = abs(fromY - toY);
  93.  
  94.             // Check if the move is like a Knight (L-shaped)
  95.             if ((dx == 2 && dy == 1) || (dx == 1 && dy == 2)) {
  96.                 // A Knight-like move is valid, check if the destination cell is empty or has an opponent's piece
  97.                 ChessPiece* targetPiece = board[toX][toY];
  98.                 return targetPiece == nullptr || (targetPiece->isBlack != isBlack);
  99.             }
  100.  
  101.             // Check if the move is like a Bishop (diagonally)
  102.             if (dx == dy) {
  103.                 // A Bishop-like move is valid, check for obstacles along the path
  104.                 int stepX = (toX > fromX) ? 1 : (toX < fromX) ? -1 : 0;
  105.                 int stepY = (toY > fromY) ? 1 : (toY < fromY) ? -1 : 0;
  106.  
  107.                 int x = fromX + stepX;
  108.                 int y = fromY + stepY;
  109.  
  110.                 while (x != toX || y != toY) {
  111.                     if (board[x][y] != nullptr) {
  112.                         // There is an obstacle in the way, move is invalid
  113.                         return false;
  114.                     }
  115.                     x += stepX;
  116.                     y += stepY;
  117.                 }
  118.  
  119.                 // Check if the destination cell is empty or has an opponent's piece
  120.                 ChessPiece* targetPiece = board[toX][toY];
  121.                 return targetPiece == nullptr || (targetPiece->isBlack != isBlack);
  122.             }
  123.  
  124.             return false; // Invalid move for the Archbishop
  125.         }
  126.     };
  127.  
  128.     // Оголошення класу фігури Слон
  129.     class Bishop : public ChessPiece {
  130.     public:
  131.         Bishop(bool isBlack) : ChessPiece(isBlack) {}
  132.  
  133.         bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) {
  134.             // Bishop moves diagonally
  135.             int dx = abs(fromX - toX);
  136.             int dy = abs(fromY - toY);
  137.  
  138.             if (dx != dy) {
  139.                 return false; // Bishop can only move diagonally
  140.             }
  141.  
  142.             // Check if there are any pieces in the path
  143.             int xDir = (toX > fromX) ? 1 : -1;
  144.             int yDir = (toY > fromY) ? 1 : -1;
  145.  
  146.             int x = fromX + xDir;
  147.             int y = fromY + yDir;
  148.  
  149.             while (x != toX && y != toY) {
  150.                 if (x < 0 || x >= 10 || y < 0 || y >= 8) {
  151.                     return false; // Out of bounds
  152.                 }
  153.  
  154.                 if (board[x][y] != nullptr) {
  155.                     return false; // There is a piece in the path
  156.                 }
  157.                 x += xDir;
  158.                 y += yDir;
  159.             }
  160.  
  161.             // Check if the destination position is empty or has an opponent's piece
  162.             if (x < 0 || x >= 10 || y < 0 || y >= 8) {
  163.                 return false; // Out of bounds
  164.             }
  165.  
  166.             ChessPiece* destinationPiece = board[x][y];
  167.             if (destinationPiece != nullptr && destinationPiece->isBlack == isBlack) {
  168.                 return false; // Cannot capture own piece
  169.             }
  170.  
  171.             return true;
  172.         }
  173.     };
  174.  
  175.     // Оголошення класу фігури Король
  176.     class King : public ChessPiece {
  177.     public:
  178.         King(bool isBlack) : ChessPiece(isBlack) {}
  179.  
  180.         bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) {
  181.             // King moves one square in any direction
  182.             int dx = abs(fromX - toX);
  183.             int dy = abs(fromY - toY);
  184.  
  185.             return (dx <= 1 && dy <= 1);
  186.         }
  187.     };
  188.  
  189.     // Оголошення класу фігури Королева
  190.     class Queen : public ChessPiece {
  191.     public:
  192.         Queen(bool isBlack) : ChessPiece(isBlack) {}
  193.  
  194.         bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) {
  195.             // Queen moves like a combination of a Rook and a Bishop
  196.             int dx = abs(fromX - toX);
  197.             int dy = abs(fromY - toY);
  198.  
  199.             // Check if the move is along a straight line or diagonal
  200.             if (!((fromX == toX && fromY != toY) || (fromX != toX && fromY == toY) || (dx == dy))) {
  201.                 return false;
  202.             }
  203.  
  204.             // Check for obstacles along the path (straight or diagonal)
  205.             int stepX = (toX == fromX) ? 0 : (toX > fromX) ? 1 : -1;
  206.             int stepY = (toY == fromY) ? 0 : (toY > fromY) ? 1 : -1;
  207.  
  208.             int x = fromX + stepX;
  209.             int y = fromY + stepY;
  210.  
  211.             while (x != toX || y != toY) {
  212.                 if (board[x][y] != nullptr) {
  213.                     // There is an obstacle in the way, move is invalid
  214.                     return false;
  215.                 }
  216.                 x += stepX;
  217.                 y += stepY;
  218.             }
  219.  
  220.             return true;
  221.         }
  222.     };
  223.  
  224.     // Оголошення класу фігури Ладья (Rook)
  225.     class Rook : public ChessPiece {
  226.     public:
  227.         Rook(bool isBlack) : ChessPiece(isBlack) {}
  228.  
  229.         bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) override {
  230.             // Rook moves along a straight line (horizontal or vertical)
  231.             int dx = abs(fromX - toX);
  232.             int dy = abs(fromY - toY);
  233.  
  234.             // Check if the move is along a straight line
  235.             if (!((fromX == toX && fromY != toY) || (fromX != toX && fromY == toY))) {
  236.                 return false;
  237.             }
  238.  
  239.             // Check for obstacles along the path
  240.             int stepX = (toX == fromX) ? 0 : (toX > fromX) ? 1 : -1;
  241.             int stepY = (toY == fromY) ? 0 : (toY > fromY) ? 1 : -1;
  242.  
  243.             int x = fromX + stepX;
  244.             int y = fromY + stepY;
  245.  
  246.             while (x != toX || y != toY) {
  247.                 if (board[x][y] != nullptr) {
  248.                     // There is an obstacle in the way, move is invalid
  249.                     return false;
  250.                 }
  251.                 x += stepX;
  252.                 y += stepY;
  253.             }
  254.  
  255.             return true;
  256.         }
  257.     };
  258.  
  259.     // Оголошення класу фігури Конь (Knight)
  260.     class Knight : public ChessPiece {
  261.     public:
  262.         Knight(bool isBlack) : ChessPiece(isBlack) {}
  263.  
  264.         bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) override {
  265.             // Рух Коня може бути здійснений у вигляді букви "L" (дві клітинки по одній осі і одна по іншій)
  266.             int dx = abs(fromX - toX);
  267.             int dy = abs(fromY - toY);
  268.             return (dx == 2 && dy == 1) || (dx == 1 && dy == 2);
  269.         }
  270.     };
  271.  
  272.     // Оголошення класу фігури Пішак
  273.     class Pawn : public ChessPiece {
  274.     public:
  275.         Pawn(bool isBlack) : ChessPiece(isBlack) {}
  276.  
  277.         bool isValidMove(int fromX, int fromY, int toX, int toY, std::vector<std::vector<ChessPiece*>>& board) {
  278.             int dx = abs(fromX - toX);
  279.             int dy = abs(fromY - toY);
  280.  
  281.             if (board[fromX][fromY] == nullptr) {
  282.                 return false; // No piece to move
  283.             }
  284.  
  285.             if (isBlack) {
  286.                 if (fromX == toX && fromY == toY - 1 && board[toX][toY] == nullptr) {
  287.                     return true; // Move one square forward
  288.                 }
  289.                 if (fromX == toX - 1 && fromY == toY - 1 && board[toX][toY] != nullptr && !board[toX][toY]->isBlack) {
  290.                     return true; // Capture diagonally to the left
  291.                 }
  292.                 if (fromX == toX + 1 && fromY == toY - 1 && board[toX][toY] != nullptr && !board[toX][toY]->isBlack) {
  293.                     return true; // Capture diagonally to the right
  294.                 }
  295.                 if (fromY == 1 && toY == 3 && fromX == toX && board[toX][toY] == nullptr && board[toX][toY - 1] == nullptr) {
  296.                     return true; // Move two squares forward on the first move
  297.                 }
  298.             }
  299.             else {
  300.                 if (fromX == toX && fromY == toY + 1 && board[toX][toY] == nullptr) {
  301.                     return true; // Move one square forward
  302.                 }
  303.                 if (fromX == toX - 1 && fromY == toY + 1 && board[toX][toY] != nullptr && board[toX][toY]->isBlack) {
  304.                     return true; // Capture diagonally to the left
  305.                 }
  306.                 if (fromX == toX + 1 && fromY == toY + 1 && board[toX][toY] != nullptr && board[toX][toY]->isBlack) {
  307.                     return true; // Capture diagonally to the right
  308.                 }
  309.                 if (fromY == 6 && toY == 4 && fromX == toX && board[toX][toY] == nullptr && board[toX][toY + 1] == nullptr) {
  310.                     return true; // Move two squares forward on the first move
  311.                 }
  312.             }
  313.  
  314.             return false;
  315.         }
  316.  
  317.     };
  318.  
  319.     // Оголошення класу дошки
  320.     class ChessBoard {
  321.     private:
  322.         std::vector<std::vector<ChessPiece*>> board;
  323.  
  324.     public:
  325.         ChessBoard() : board(10, std::vector<ChessPiece*>(8, nullptr)) {
  326.             // Початкове розташування фігур на дошці
  327.  
  328.             board[0][0] = new Rook(true); // Ладья
  329.             board[1][0] = new Knight(true); // Конь
  330.             board[2][0] = new Archbishop(true); // Архієпископ
  331.             board[3][0] = new Bishop(true); // Слон
  332.             board[4][0] = new Queen(true); // Королева
  333.             board[5][0] = new King(true); // Король
  334.             board[6][0] = new Bishop(true); // Слон
  335.             board[7][0] = new Chancellor(true); // Канцлер
  336.             board[8][0] = new Knight(true); // Конь
  337.             board[9][0] = new Rook(true); // Ладья
  338.  
  339.             // Вторая линия фигур (белые пешки)
  340.             for (int y = 0; y < 10; y++) {
  341.                 board[y][1] = new Pawn(true); // Пішаки (другая лінія)
  342.             }
  343.  
  344.             // Седьмая линия фигур (черные пешки)
  345.             for (int y = 0; y < 10; y++) {
  346.                 board[y][6] = new Pawn(false); // Пішаки (сьома лінія)
  347.             }
  348.  
  349.             // Восьмая линия фигур (черные фигуры)
  350.             board[0][7] = new Rook(false); // Ладья
  351.             board[1][7] = new Knight(false); // Конь
  352.             board[2][7] = new Archbishop(false); // Архієпископ
  353.             board[3][7] = new Bishop(false); // Слон
  354.             board[4][7] = new Queen(false); // Королева
  355.             board[5][7] = new King(false); // Король
  356.             board[6][7] = new Bishop(false); // Слон
  357.             board[7][7] = new Chancellor(false); // Канцлер
  358.             board[8][7] = new Knight(false); // Конь
  359.             board[9][7] = new Rook(false); // Ладья
  360.  
  361.         }
  362.         bool performCastling(int kingFromX, int kingFromY, int kingToX, int kingToY, int rookFromX, int rookFromY, int rookToX, int rookToY) {
  363.             ChessPiece* king = board[kingFromX][kingFromY];
  364.             ChessPiece* rook = board[rookFromX][rookFromY];
  365.  
  366.             // Перевірка чи фігури король та ладья знаходяться на відповідних позиціях
  367.             if (!king || !rook || !dynamic_cast<King*>(king) || !dynamic_cast<Rook*>(rook)) {
  368.                 return false;
  369.             }
  370.  
  371.             // Перевірка наявності фігур між королем і ладьєю
  372.             int minRookX = System::Math::Min(rookFromX, rookToX);
  373.             int maxRookX = System::Math::Max(rookFromX, rookToX);
  374.             for (int x = minRookX + 1; x < maxRookX; x++) {
  375.                 if (board[x][kingFromY] != nullptr) {
  376.                     return false;
  377.                 }
  378.             }
  379.  
  380.             // Виконуємо рокировку
  381.             board[kingFromX][kingFromY] = nullptr;
  382.             board[rookFromX][rookFromY] = nullptr;
  383.  
  384.             board[kingToX][kingToY] = king;
  385.             board[rookToX][rookToY] = rook;
  386.  
  387.             return true;
  388.         }
  389.  
  390.         ~ChessBoard() {
  391.             // Звільняємо пам'ять від фігур
  392.             for (int i = 0; i < 8; i++) {
  393.                 for (int j = 0; j < 8; j++) {
  394.                     delete board[i][j];
  395.                 }
  396.             }
  397.         }
  398.         bool promotePawn(int x, int y, char pieceType) {
  399.             ChessPiece* piece = board[x][y];
  400.             if (piece != nullptr && dynamic_cast<Pawn*>(piece)) {
  401.                 bool isBlack = piece->isBlack;
  402.                 delete board[x][y];
  403.  
  404.                 ChessPiece* newPiece = nullptr;
  405.                 switch (pieceType) {
  406.                 case 'Q': newPiece = new Queen(isBlack); break;
  407.                 case 'R': newPiece = new Rook(isBlack); break;
  408.                 case 'B': newPiece = new Bishop(isBlack); break;
  409.                 case 'N': newPiece = new Knight(isBlack); break;
  410.                 case 'C': newPiece = new Chancellor(isBlack); break;
  411.                 case 'A': newPiece = new Archbishop(isBlack); break;
  412.  
  413.  
  414.                 }
  415.  
  416.                 if (newPiece != nullptr) {
  417.                     board[x][y] = newPiece;
  418.                     return true;
  419.                 }
  420.             }
  421.             return false;
  422.         }
  423.         ChessPiece* getPiece(int x, int y) {
  424.             // Метод для отримання фігури на позиції (x, y) на дошці
  425.             // Повертає nullptr, якщо клітинка порожня
  426.             if (x >= 0 && x < 10 && y >= 0 && y < 8) {
  427.                 return board[x][y];
  428.             }
  429.             return nullptr;
  430.         }
  431.  
  432.         bool makeMove(int fromX, int fromY, int toX, int toY) {
  433.             // Метод для здійснення ходу
  434.             if (!isValidMove(fromX, fromY, toX, toY)) {
  435.                 return false;
  436.             }
  437.  
  438.             ChessPiece* piece = board[fromX][fromY];
  439.             board[fromX][fromY] = nullptr;
  440.             board[toX][toY] = piece;
  441.             return true;
  442.         }
  443.  
  444.         bool isValidMove(int fromX, int fromY, int toX, int toY) {
  445.             // Метод для перевірки чи дозволений хід фігури з позиції (fromX, fromY) на позицію (toX, toY)
  446.             // Включає логіку перевірки правил руху для конкретної фігури
  447.  
  448.             // Перевірка чи позиції відповідають допустимому діапазону
  449.             if (fromX < 0 || fromX >= 10 || fromY < 0 || fromY >= 8 ||
  450.                 toX < 0 || toX >= 10 || toY < 0 || toY >= 8) {
  451.                 return false;
  452.             }
  453.  
  454.             // Перевірка чи на позиції (fromX, fromY) є фігура
  455.             ChessPiece* piece = board[fromX][fromY];
  456.             if (piece == nullptr) {
  457.                 return false;
  458.             }
  459.  
  460.             // Перевірка чи хід є допустимим для даної фігури
  461.             if (!piece->isValidMove(fromX, fromY, toX, toY, board)) {
  462.                 return false;
  463.             }
  464.             // Перевірка, чи на позиції (toX, toY) є фігура того ж кольору
  465.             ChessPiece* targetPiece = board[toX][toY];
  466.             if (targetPiece != nullptr && targetPiece->isBlack == piece->isBlack) {
  467.                 return false;
  468.             }
  469.  
  470.             return true;
  471.         }
  472.         bool movePiece(int fromX, int fromY, int toX, int toY) {
  473.             // Здійснюємо хід фігурою
  474.             if (fromX < 0 || fromX >= 8 || fromY < 0 || fromY >= 8 || toX < 0 || toX >= 8 || toY < 0 || toY >= 8) {
  475.                 return false; // За межами дошки
  476.             }
  477.  
  478.             ChessPiece* piece = board[fromX][fromY];
  479.  
  480.             if (piece == nullptr) {
  481.                 return false; // Немає фігури для переміщення
  482.             }
  483.  
  484.             if (piece->isValidMove(fromX, fromY, toX, toY, board)) {
  485.                 delete board[toX][toY];
  486.                 board[toX][toY] = piece;
  487.                 board[fromX][fromY] = nullptr;
  488.                 return true;
  489.             }
  490.  
  491.             return false;
  492.         }
  493.     };
  494.  
  495.  
  496.     public ref class MyForm : public System::Windows::Forms::Form
  497.     {
  498.     public:
  499.  
  500.         MyForm(void)
  501.         {
  502.             InitializeComponent();
  503.  
  504.             board = new ChessBoard();
  505.  
  506.             InitializeChessboard();
  507.  
  508.             // Підписка на події кліків по клітинках
  509.             for (int x = 0; x < 10; x++) {
  510.                 for (int y = 0; y < 8; y++) {
  511.                     boardPictureBoxes[x, y]->Click += gcnew EventHandler(this, &MyForm::Cell_Click);
  512.                 }
  513.             }
  514.  
  515.         }
  516.  
  517.     protected:
  518.  
  519.         ~MyForm()
  520.         {
  521.             if (components)
  522.             {
  523.                 delete components;
  524.             }
  525.         }
  526.  
  527.     private:
  528.         System::ComponentModel::Container^ components;
  529.  
  530.         // Графічний інтерфейс
  531.         array<PictureBox^, 2>^ boardPictureBoxes;
  532.         ChessBoard* board;
  533.         Graphics^ g;
  534.         int selectedX = -1; // Stores the X coordinate of the selected piece
  535.         int selectedY = -1; // Stores the Y coordinate of the selected piece
  536.  
  537.         bool validMovesHighlighted = false;
  538.         List<Tuple<int, int>^>^ validMoves = gcnew List<Tuple<int, int>^>();
  539.  
  540.         const int imageWidth = 40; // Зменшені розміри фігур по ширині
  541.         const int imageHeight = 40; // Зменшені розміри фігур по висоті
  542.  
  543.         void InitializeComponent(void)
  544.         {
  545.             this->components = gcnew System::ComponentModel::Container();
  546.             this->Size = System::Drawing::Size(820, 660);
  547.             this->Text = L"Chess";
  548.             this->AutoScaleDimensions = System::Drawing::SizeF(8, 16);
  549.             this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
  550.  
  551.             // Створення PictureBox для клітинок шахівниці
  552.             boardPictureBoxes = gcnew array<PictureBox^, 2>(10, 8);
  553.             for (int x = 0; x < 10; x++) {
  554.                 for (int y = 0; y < 8; y++) {
  555.                     boardPictureBoxes[x, y] = gcnew PictureBox();
  556.                     boardPictureBoxes[x, y]->Size = System::Drawing::Size(60, 60);
  557.                     boardPictureBoxes[x, y]->Location = System::Drawing::Point(x * 60, y * 60);
  558.                     boardPictureBoxes[x, y]->BackColor = ((x + y) % 2 == 0) ? Color::Bisque : Color::DarkOrange;
  559.                     this->Controls->Add(boardPictureBoxes[x, y]);
  560.                 }
  561.             }
  562.         }
  563.  
  564.         Image^ LoadImageForPiece(ChessPiece* piece, int x, int y) {
  565.             Image^ image = nullptr;
  566.  
  567.             if (dynamic_cast<Chancellor*>(piece)) {
  568.                 if (piece->isBlack) {
  569.                     image = Image::FromFile("C:\\chess\\black-chess\\сhancellor.png");
  570.                 }
  571.                 else {
  572.                     image = Image::FromFile("C:\\chess\\white-chess\\сhancellor.png");
  573.                 }
  574.             }
  575.             else if (dynamic_cast<Archbishop*>(piece)) {
  576.                 if (piece->isBlack) {
  577.                     image = Image::FromFile("C:\\chess\\black-chess\\archbishop.png");
  578.                 }
  579.                 else {
  580.                     image = Image::FromFile("C:\\chess\\white-chess\\archbishop.png");
  581.                 }
  582.             }
  583.             else if (dynamic_cast<Pawn*>(piece)) {
  584.                 if (piece->isBlack) {
  585.                     image = Image::FromFile("C:\\chess\\black-chess\\pawn.png");
  586.                 }
  587.                 else {
  588.                     image = Image::FromFile("C:\\chess\\white-chess\\pawn.png");
  589.                 }
  590.             }
  591.             else if (dynamic_cast<Queen*>(piece)) {
  592.                 if (piece->isBlack) {
  593.                     image = Image::FromFile("C:\\chess\\black-chess\\queen.png");
  594.                 }
  595.                 else {
  596.                     image = Image::FromFile("C:\\chess\\white-chess\\queen.png");
  597.                 }
  598.             }
  599.             else if (dynamic_cast<King*>(piece)) {
  600.                 if (piece->isBlack) {
  601.                     image = Image::FromFile("C:\\chess\\black-chess\\king.png");
  602.                 }
  603.                 else {
  604.                     image = Image::FromFile("C:\\chess\\white-chess\\king.png");
  605.                 }
  606.             }
  607.             else if (dynamic_cast<Bishop*>(piece)) {
  608.                 if (piece->isBlack) {
  609.                     image = Image::FromFile("C:\\chess\\black-chess\\bishop.png");
  610.                 }
  611.                 else {
  612.                     image = Image::FromFile("C:\\chess\\white-chess\\bishop.png");
  613.                 }
  614.             }
  615.             else if (dynamic_cast<Knight*>(piece)) {
  616.                 if (piece->isBlack) {
  617.                     image = Image::FromFile("C:\\chess\\black-chess\\knight.png");
  618.                 }
  619.                 else {
  620.                     image = Image::FromFile("C:\\chess\\white-chess\\knight.png");
  621.                 }
  622.             }
  623.             else if (dynamic_cast<Rook*>(piece)) {
  624.                 if (piece->isBlack) {
  625.                     image = Image::FromFile("C:\\chess\\black-chess\\rook.png");
  626.                 }
  627.                 else {
  628.                     image = Image::FromFile("C:\\chess\\white-chess\\rook.png");
  629.                 }
  630.             }
  631.             if (image != nullptr) {
  632.                 // Змініть розмір зображення фігури на imageWidth та imageHeight
  633.                 image = gcnew Bitmap(image, imageWidth, imageHeight);
  634.             }
  635.             return image;
  636.         }
  637.         bool IsInCheck(bool isBlack, ChessBoard* board) {
  638.             // Знаходимо позицію короля поточного гравця
  639.             int kingX = -1;
  640.             int kingY = -1;
  641.  
  642.             for (int x = 0; x < 10; x++) {
  643.                 for (int y = 0; y < 8; y++) {
  644.                     ChessPiece* piece = board->getPiece(x, y);
  645.                     if (piece != nullptr && piece->isBlack == isBlack && dynamic_cast<King*>(piece)) {
  646.                         kingX = x;
  647.                         kingY = y;
  648.                         break;
  649.                     }
  650.                 }
  651.                 if (kingX != -1 && kingY != -1) {
  652.                     break;
  653.                 }
  654.             }
  655.  
  656.             // Перевіряємо, чи є можливі ходи опонента, які можуть атакувати короля
  657.             for (int x = 0; x < 10; x++) {
  658.                 for (int y = 0; y < 8; y++) {
  659.                     ChessPiece* piece = board->getPiece(x, y);
  660.                     if (piece != nullptr && piece->isBlack != isBlack) {
  661.                         if (board->isValidMove(x, y, kingX, kingY)) {
  662.                             return true;
  663.                         }
  664.                     }
  665.                 }
  666.             }
  667.  
  668.             return false;
  669.         }
  670.  
  671.         bool IsCheckmate(bool isBlack, ChessBoard* board) {
  672.             // Перевіряємо, чи король в шаху
  673.             if (!IsInCheck(isBlack, board)) {
  674.                 return false; // Немає шаху, немає мату
  675.             }
  676.  
  677.             // Перевіряємо, чи є можливі ходи для короля
  678.             int kingX = -1;
  679.             int kingY = -1;
  680.  
  681.             for (int x = 0; x < 10; x++) {
  682.                 for (int y = 0; y < 8; y++) {
  683.                     ChessPiece* piece = board->getPiece(x, y);
  684.                     if (piece != nullptr && piece->isBlack == isBlack && dynamic_cast<King*>(piece)) {
  685.                         kingX = x;
  686.                         kingY = y;
  687.                         break;
  688.                     }
  689.                 }
  690.                 if (kingX != -1 && kingY != -1) {
  691.                     break;
  692.                 }
  693.             }
  694.  
  695.             for (int dx = -1; dx <= 1; dx++) {
  696.                 for (int dy = -1; dy <= 1; dy++) {
  697.                     int destX = kingX + dx;
  698.                     int destY = kingY + dy;
  699.  
  700.                     if (board->isValidMove(kingX, kingY, destX, destY) && !IsInCheckAfterMove(kingX, kingY, destX, destY, isBlack, board)) {
  701.                         return false; // Є можливий хід для короля
  702.                     }
  703.                 }
  704.             }
  705.  
  706.             // Шах і немає можливих ходів для короля
  707.             // Перевіряємо, чи можуть інші фігури захистити короля або блокувати атакуючі фігури
  708.  
  709.             for (int x = 0; x < 10; x++) {
  710.                 for (int y = 0; y < 8; y++) {
  711.                     ChessPiece* piece = board->getPiece(x, y);
  712.                     if (piece != nullptr && piece->isBlack == isBlack) {
  713.                         List<Tuple<int, int>^>^ moves = GetValidMoves(x, y, board);
  714.                         for each (Tuple<int, int> ^ move in moves) {
  715.                             int destX = move->Item1;
  716.                             int destY = move->Item2;
  717.  
  718.                             if (!IsInCheckAfterMove(x, y, destX, destY, isBlack, board)) {
  719.                                 return false; // Існує можливий хід для іншої фігури
  720.                             }
  721.                         }
  722.                     }
  723.                 }
  724.             }
  725.  
  726.             return true; // Шах і мат
  727.         }
  728.  
  729.         bool IsInCheckAfterMove(int startX, int startY, int destX, int destY, bool isBlack, ChessBoard* board) {
  730.             // Збережіть фігуру, яку збираєтеся зрушити
  731.             ChessPiece* tempDestPiece = board->getPiece(destX, destY);
  732.  
  733.             // Зробіть хід на тимчасовій дошці
  734.             board->movePiece(startX, startY, destX, destY);
  735.  
  736.             // Перевірте, чи король буде в шаху після цього ходу
  737.             bool result = IsInCheck(isBlack, board);
  738.  
  739.             // Відновіть попередній стан дошки, скасовуючи хід
  740.             board->movePiece(destX, destY, startX, startY);
  741.             //board->setPiece(destX, destY, tempDestPiece);
  742.  
  743.             return result;
  744.         }
  745.  
  746.  
  747.         List<Tuple<int, int>^>^ GetValidMoves(int x, int y, ChessBoard* board) {
  748.             List<Tuple<int, int>^>^ validMoves = gcnew List<Tuple<int, int>^>();
  749.  
  750.             ChessPiece* piece = board->getPiece(x, y);
  751.             if (piece == nullptr) {
  752.                 return validMoves; // Пуста клітинка
  753.             }
  754.  
  755.             // Реалізуйте генерацію можливих ходів для конкретної фігури (пішака, кінь, тощо)
  756.  
  757.             return validMoves;
  758.         }
  759.        
  760.  
  761.  
  762.         bool isBlacksTurn;
  763.  
  764.         void MyForm::Cell_Click(Object^ sender, EventArgs^ e) {
  765.             PictureBox^ pictureBox = (PictureBox^)sender;
  766.             int x = pictureBox->Location.X / 60;
  767.             int y = pictureBox->Location.Y / 60;
  768.  
  769.             // If no piece is currently selected, try to select one
  770.             if (selectedX == -1 && selectedY == -1) {
  771.                 ChessPiece* piece = board->getPiece(x, y);
  772.                 if (piece != nullptr && ((isBlacksTurn && piece->isBlack) || (!isBlacksTurn && !piece->isBlack))) {
  773.                     validMoves = GetValidMoves(x, y);
  774.                     HighlightValidMoves();
  775.                     pictureBox->BorderStyle = BorderStyle::FixedSingle;
  776.  
  777.                     // Update selected coordinates
  778.                     selectedX = x;
  779.                     selectedY = y;
  780.  
  781.                     // Check for promotion for a pawn reaching the last rank
  782.                     if (dynamic_cast<Pawn*>(piece) && ((piece->isBlack && y == 7) || (!piece->isBlack && y == 0))) {
  783.                         // Prompt the user for promotion
  784.                         char pieceType = 'Q'; // Default to Queen
  785.  
  786.                         PromotionChoiceForm^ promotionForm = gcnew PromotionChoiceForm();
  787.                         if (promotionForm->ShowDialog() == System::Windows::Forms::DialogResult::OK) {
  788.                             pieceType = promotionForm->GetSelectedPieceSymbol();
  789.                         }
  790.  
  791.                         bool success = board->promotePawn(x, y, pieceType);
  792.                         if (success) {
  793.                             DrawPiece(x, y);
  794.                         }
  795.                     }
  796.                 }
  797.             }
  798.             else {
  799.                 // A piece is already selected, try to make a move to the clicked cell
  800.                 if (board->isValidMove(selectedX, selectedY, x, y)) {
  801.                     // Attempt to make the move
  802.                     bool moveResult = board->makeMove(selectedX, selectedY, x, y);
  803.  
  804.                     if (moveResult) {
  805.                         // Move was successful, update the graphical representation
  806.                         DrawPiece(selectedX, selectedY); // Clear the source cell
  807.                         DrawPiece(x, y); // Draw the piece on the destination cell
  808.  
  809.                         // Toggle the turn between players
  810.                         isBlacksTurn = !isBlacksTurn;
  811.                     }
  812.                 }
  813.                 // Перевіряємо на шах та мат
  814.                 //bool isBlack = currentPlayer == Player::Black;
  815.  
  816.                 if (IsCheckmate(isBlacksTurn, board)) {
  817.                     // Оголошуємо мат
  818.                     if (isBlacksTurn) {
  819.                         MessageBox::Show("Білий гравець переміг (чорний гравець у маті)!");
  820.                     }
  821.                     else {
  822.                         MessageBox::Show("Чорний гравець переміг (білий гравець у маті)!");
  823.                     }
  824.                 }
  825.                 else if (IsInCheck(isBlacksTurn, board)) {
  826.                     // Попередження про шах
  827.                     MessageBox::Show("Шах!");
  828.                 }
  829.                 validMoves->Clear();
  830.                 UnhighlightValidMoves();
  831.  
  832.                 boardPictureBoxes[selectedX, selectedY]->BorderStyle = BorderStyle::None;
  833.  
  834.                 // Reset selected coordinates
  835.                 selectedX = -1;
  836.                 selectedY = -1;
  837.             }
  838.         }
  839.  
  840.  
  841.  
  842.         List<Tuple<int, int>^>^ GetValidMoves(int x, int y) {
  843.             List<Tuple<int, int>^>^ moves = gcnew List<Tuple<int, int>^>();
  844.  
  845.             ChessPiece* piece = board->getPiece(x, y);
  846.             if (piece != nullptr) {
  847.                 for (int destX = 0; destX < 10; destX++) {
  848.                     for (int destY = 0; destY < 8; destY++) {
  849.                         if (board->isValidMove(x, y, destX, destY)) {
  850.                             moves->Add(gcnew Tuple<int, int>(destX, destY));
  851.                         }
  852.                     }
  853.                 }
  854.             }
  855.  
  856.             return moves;
  857.         }
  858.  
  859.         void HighlightValidMoves() {
  860.             Color highlightColor = Color::Green;
  861.  
  862.             for each (Tuple<int, int> ^ move in validMoves) {
  863.                 int x = move->Item1;
  864.                 int y = move->Item2;
  865.  
  866.                 // Create a new Pen with the highlight color and thickness
  867.                 Pen^ highlightPen = gcnew Pen(highlightColor, 3);
  868.  
  869.                 // Draw a rectangle (outline) around the PictureBox to highlight it
  870.                 Graphics^ g = boardPictureBoxes[x, y]->CreateGraphics();
  871.                 g->DrawRectangle(highlightPen, 0, 0, boardPictureBoxes[x, y]->Width - 1, boardPictureBoxes[x, y]->Height - 1);
  872.  
  873.                 // Dispose of the Pen to release resources
  874.                 delete highlightPen;
  875.             }
  876.         }
  877.  
  878.  
  879.         void UnhighlightValidMoves() {
  880.             for (int x = 0; x < 10; x++) {
  881.                 for (int y = 0; y < 8; y++) {
  882.                     if ((x + y) % 2 == 0) {
  883.                         Pen^ highlightPen = gcnew Pen(Color::Bisque, 3);
  884.  
  885.                         // Draw a rectangle (outline) around the PictureBox to highlight it
  886.                         Graphics^ g = boardPictureBoxes[x, y]->CreateGraphics();
  887.                         g->DrawRectangle(highlightPen, 0, 0, boardPictureBoxes[x, y]->Width - 1, boardPictureBoxes[x, y]->Height - 1);
  888.  
  889.                         // Dispose of the Pen to release resources
  890.                         delete highlightPen;
  891.                     }
  892.                     else {
  893.                         //boardPictureBoxes[x, y]->BackColor = Color::DarkOrange;
  894.                         Pen^ highlightPen = gcnew Pen(Color::DarkOrange, 3);
  895.  
  896.                         // Draw a rectangle (outline) around the PictureBox to highlight it
  897.                         Graphics^ g = boardPictureBoxes[x, y]->CreateGraphics();
  898.                         g->DrawRectangle(highlightPen, 0, 0, boardPictureBoxes[x, y]->Width - 1, boardPictureBoxes[x, y]->Height - 1);
  899.  
  900.                         // Dispose of the Pen to release resources
  901.                         delete highlightPen;
  902.                     }
  903.                 }
  904.             }
  905.         }
  906.  
  907.         void InitializeChessboard() {
  908.             // Initialize graphical representation of the chessboard
  909.             for (int x = 0; x < 10; x++) {
  910.                 for (int y = 0; y < 8; y++) {
  911.                     // Update the graphical representation of the chessboard
  912.                     DrawPiece(x, y); // Draw the piece or an empty cell at (x, y)
  913.                 }
  914.             }
  915.         }
  916.  
  917.         void DrawPiece(int x, int y) {
  918.             ChessPiece* piece = board->getPiece(x, y);
  919.             if (piece != nullptr) {
  920.                 boardPictureBoxes[x, y]->SizeMode = PictureBoxSizeMode::Zoom;
  921.  
  922.                 Image^ image = LoadImageForPiece(piece, x, y);
  923.                 if (image != nullptr) {
  924.                     // Display the piece on the chessboard
  925.                     boardPictureBoxes[x, y]->Image = image;
  926.                 }
  927.             }
  928.             else {
  929.                 // Display an empty cell on the chessboard
  930.                 boardPictureBoxes[x, y]->Image = nullptr;
  931.                 boardPictureBoxes[x, y]->BackColor = ((x + y) % 2 == 0) ? Color::Bisque : Color::DarkOrange;
  932.             }
  933.         }
  934.     };
  935. }
  936.  
Add Comment
Please, Sign In to add comment