Vla_DOS

chess2.0

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