|
| 1 | +#include "GameLogic.hpp" |
| 2 | +// 필요한 다른 표준 라이브러리가 있다면 여기에 include (예: <iostream> for debugging) |
| 3 | + |
| 4 | +std::vector<sf::Vector2i> getPossibleMoves(const std::array<std::array<std::optional<Piece>, 8>, 8>& board, int row, int col) { |
| 5 | + std::vector<sf::Vector2i> moves; |
| 6 | + // 함수 시작 시 row, col 유효성 검사 및 piece 존재 여부 확인 |
| 7 | + if (row < 0 || row >= 8 || col < 0 || col >= 8 || !board[row][col].has_value()) { |
| 8 | + return moves; |
| 9 | + } |
| 10 | + |
| 11 | + PieceType type = board[row][col]->type; |
| 12 | + PieceColor color = board[row][col]->color; |
| 13 | + |
| 14 | + auto addMovesInDirection = [&](int dr, int dc, bool canMoveMultipleSteps) { |
| 15 | + for (int i = 1; i < 8; ++i) { |
| 16 | + int targetRow = row + dr * i; |
| 17 | + int targetCol = col + dc * i; |
| 18 | + if (targetRow < 0 || targetRow >= 8 || targetCol < 0 || targetCol >= 8) break; |
| 19 | + if (board[targetRow][targetCol].has_value()) { |
| 20 | + if (board[targetRow][targetCol]->color != color) moves.push_back({targetCol, targetRow}); |
| 21 | + break; |
| 22 | + } else { |
| 23 | + moves.push_back({targetCol, targetRow}); |
| 24 | + } |
| 25 | + if (!canMoveMultipleSteps) break; |
| 26 | + } |
| 27 | + }; |
| 28 | + |
| 29 | + if (type == PieceType::Pawn) { |
| 30 | + int direction = (color == PieceColor::White) ? -1 : 1; |
| 31 | + int nextRow = row + direction; |
| 32 | + if (nextRow >= 0 && nextRow < 8 && !board[nextRow][col].has_value()) { |
| 33 | + moves.push_back({col, nextRow}); |
| 34 | + bool isInitialPosition = (color == PieceColor::White && row == 6) || (color == PieceColor::Black && row == 1); |
| 35 | + if (isInitialPosition) { |
| 36 | + int twoStepsRow = row + 2 * direction; |
| 37 | + // 두 칸 전진 시 바로 앞 칸과 두 번째 칸 모두 비어있어야 함 |
| 38 | + if (twoStepsRow >= 0 && twoStepsRow < 8 && !board[row + direction][col].has_value() && !board[twoStepsRow][col].has_value()){ |
| 39 | + moves.push_back({col, twoStepsRow}); |
| 40 | + } |
| 41 | + } |
| 42 | + } |
| 43 | + int attackColLeft = col - 1; int attackRow = row + direction; |
| 44 | + if (attackColLeft >= 0 && attackRow >= 0 && attackRow < 8) { |
| 45 | + if (board[attackRow][attackColLeft].has_value() && board[attackRow][attackColLeft]->color != color) { |
| 46 | + moves.push_back({attackColLeft, attackRow}); |
| 47 | + } |
| 48 | + } |
| 49 | + int attackColRight = col + 1; |
| 50 | + if (attackColRight < 8 && attackRow >= 0 && attackRow < 8) { |
| 51 | + if (board[attackRow][attackColRight].has_value() && board[attackRow][attackColRight]->color != color) { |
| 52 | + moves.push_back({attackColRight, attackRow}); |
| 53 | + } |
| 54 | + } |
| 55 | + } else if (type == PieceType::Rook) { |
| 56 | + addMovesInDirection(1, 0, true); addMovesInDirection(-1, 0, true); addMovesInDirection(0, 1, true); addMovesInDirection(0, -1, true); |
| 57 | + } else if (type == PieceType::Bishop) { |
| 58 | + addMovesInDirection(1, 1, true); addMovesInDirection(1, -1, true); addMovesInDirection(-1, 1, true); addMovesInDirection(-1, -1, true); |
| 59 | + } else if (type == PieceType::Queen) { |
| 60 | + addMovesInDirection(1, 0, true); addMovesInDirection(-1, 0, true); addMovesInDirection(0, 1, true); addMovesInDirection(0, -1, true); |
| 61 | + addMovesInDirection(1, 1, true); addMovesInDirection(1, -1, true); addMovesInDirection(-1, 1, true); addMovesInDirection(-1, -1, true); |
| 62 | + } else if (type == PieceType::Knight) { |
| 63 | + std::vector<std::pair<int, int>> knightMoves = {{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}}; |
| 64 | + for (const auto& move : knightMoves) { |
| 65 | + int targetRow = row + move.first; int targetCol = col + move.second; |
| 66 | + if (targetRow >= 0 && targetRow < 8 && targetCol >= 0 && targetCol < 8) { |
| 67 | + if (!board[targetRow][targetCol].has_value() || board[targetRow][targetCol]->color != color) { |
| 68 | + moves.push_back({targetCol, targetRow}); |
| 69 | + } |
| 70 | + } |
| 71 | + } |
| 72 | + } else if (type == PieceType::King) { |
| 73 | + for (int dr = -1; dr <= 1; ++dr) { |
| 74 | + for (int dc = -1; dc <= 1; ++dc) { |
| 75 | + if (dr==0 && dc==0) continue; |
| 76 | + int targetRow = row + dr; int targetCol = col + dc; |
| 77 | + if (targetRow >=0 && targetRow < 8 && targetCol >=0 && targetCol < 8) { |
| 78 | + if (!board[targetRow][targetCol].has_value() || board[targetRow][targetCol]->color != color) { |
| 79 | + moves.push_back({targetCol, targetRow}); |
| 80 | + } |
| 81 | + } |
| 82 | + } |
| 83 | + } |
| 84 | + } |
| 85 | + return moves; |
| 86 | +} |
| 87 | + |
| 88 | +sf::Vector2i findKing(const std::array<std::array<std::optional<Piece>, 8>, 8>& board, PieceColor kingColor) { |
| 89 | + for (int r=0; r<8; ++r) { |
| 90 | + for (int c=0; c<8; ++c) { |
| 91 | + if (board[r][c].has_value() && board[r][c]->type == PieceType::King && board[r][c]->color == kingColor) { |
| 92 | + return {c, r}; |
| 93 | + } |
| 94 | + } |
| 95 | + } |
| 96 | + return {-1,-1}; // 킹을 찾지 못한 경우 |
| 97 | +} |
| 98 | + |
| 99 | +bool isKingInCheck(const std::array<std::array<std::optional<Piece>, 8>, 8>& board, PieceColor kingColor) { |
| 100 | + sf::Vector2i kingPos = findKing(board, kingColor); |
| 101 | + if (kingPos.x == -1) return false; // 킹이 없으면 체크도 아님 |
| 102 | + |
| 103 | + PieceColor opponentColor = (kingColor == PieceColor::White) ? PieceColor::Black : PieceColor::White; |
| 104 | + for (int r=0; r<8; ++r) { |
| 105 | + for (int c=0; c<8; ++c) { |
| 106 | + if (board[r][c].has_value() && board[r][c]->color == opponentColor) { |
| 107 | + std::vector<sf::Vector2i> opponentMoves = getPossibleMoves(board, r, c); |
| 108 | + for (const auto& move : opponentMoves) { |
| 109 | + if (move.x == kingPos.x && move.y == kingPos.y) return true; |
| 110 | + } |
| 111 | + } |
| 112 | + } |
| 113 | + } |
| 114 | + return false; |
| 115 | +} |
| 116 | + |
| 117 | +bool isCheckmate(const std::array<std::array<std::optional<Piece>, 8>, 8>& board, PieceColor currentColor) { |
| 118 | + if (!isKingInCheck(board, currentColor)) return false; |
| 119 | + |
| 120 | + for (int r=0; r<8; ++r) { |
| 121 | + for (int c=0; c<8; ++c) { |
| 122 | + if (board[r][c].has_value() && board[r][c]->color == currentColor) { |
| 123 | + std::vector<sf::Vector2i> possibleMovesForPiece = getPossibleMoves(board, r, c); |
| 124 | + for (const auto& move : possibleMovesForPiece) { |
| 125 | + std::array<std::array<std::optional<Piece>, 8>, 8> tempBoard = board; // 임시 보드 복사 |
| 126 | + std::optional<Piece> originalPieceOpt = tempBoard[r][c]; |
| 127 | + if (originalPieceOpt.has_value()) { |
| 128 | + // 스프라이트 복사 문제 해결을 위해 Piece 생성자 명시적 호출 |
| 129 | + tempBoard[move.y][move.x] = Piece(originalPieceOpt->type, originalPieceOpt->color, originalPieceOpt->sprite); |
| 130 | + tempBoard[r][c].reset(); // 이전 위치 비우기 |
| 131 | + if (!isKingInCheck(tempBoard, currentColor)) { |
| 132 | + return false; // 체크를 벗어날 수 있는 수가 있다면 체크메이트 아님 |
| 133 | + } |
| 134 | + } |
| 135 | + } |
| 136 | + } |
| 137 | + } |
| 138 | + } |
| 139 | + return true; // 모든 수를 시도해도 체크를 벗어날 수 없으면 체크메이트 |
| 140 | +} |
0 commit comments