Skip to content

Commit 58e0f62

Browse files
committed
분할
1 parent f30b871 commit 58e0f62

File tree

5 files changed

+488
-435
lines changed

5 files changed

+488
-435
lines changed

CMakeLists.txt

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,37 @@
1-
cmake_minimum_required(VERSION 3.28)
1+
cmake_minimum_required(VERSION 3.29)
22
project(ChessPrj LANGUAGES CXX)
33

4+
set(CMAKE_CXX_STANDARD 20)
45
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
56

7+
# SFML 라이브러리 가져오기
68
include(FetchContent)
79
FetchContent_Declare(SFML
8-
GIT_REPOSITORY https://github.com/SFML/SFML.git
9-
GIT_TAG 3.0.1
10-
GIT_SHALLOW ON
11-
EXCLUDE_FROM_ALL
12-
SYSTEM)
10+
GIT_REPOSITORY https://github.com/SFML/SFML.git
11+
GIT_TAG 3.0.1
12+
GIT_SHALLOW ON
13+
EXCLUDE_FROM_ALL
14+
SYSTEM)
1315
FetchContent_MakeAvailable(SFML)
1416

15-
add_executable(main src/main.cpp)
16-
target_compile_features(main PRIVATE cxx_std_17)
17-
target_link_libraries(main PRIVATE SFML::Graphics)
17+
# Boost 라이브러리 찾기
18+
find_package(Boost REQUIRED COMPONENTS system thread)
19+
20+
# 소스 파일 추가
21+
add_executable(${PROJECT_NAME} src/main.cpp
22+
src/GameData.hpp
23+
src/GameLogic.hpp
24+
src/GameLogic.cpp
25+
)
26+
27+
# C++ 표준 설정
28+
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
29+
30+
# 헤더 파일 경로와 라이브러리 링크
31+
if(Boost_FOUND)
32+
target_include_directories(${PROJECT_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
33+
target_link_libraries(${PROJECT_NAME} PRIVATE ${Boost_LIBRARIES})
34+
endif()
35+
36+
# SFML 라이브러리 링크
37+
target_link_libraries(${PROJECT_NAME} PRIVATE SFML::Graphics)

src/GameData.hpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#ifndef GAMEDATA_HPP
2+
#define GAMEDATA_HPP
3+
4+
#include <SFML/Graphics.hpp> // sf::Sprite, sf::Time 때문
5+
#include <string>
6+
#include <vector>
7+
#include <array>
8+
#include <optional>
9+
#include <map>
10+
11+
// 전역 상수 정의
12+
const int TILE_SIZE = 100;
13+
const int BOARD_WIDTH = 8 * TILE_SIZE;
14+
const int BOARD_HEIGHT = 8 * TILE_SIZE;
15+
const int BUTTON_PANEL_WIDTH = 300;
16+
const int WINDOW_WIDTH = BOARD_WIDTH + BUTTON_PANEL_WIDTH;
17+
const int WINDOW_HEIGHT = BOARD_HEIGHT;
18+
const float INITIAL_TIME_SECONDS = 60.f;
19+
// 서버 관련 상수는 네트워크 기능 추가 시 다시 포함 예정
20+
// const std::string SERVER_IP = "10.2.3.147";
21+
// const short SERVER_PORT = 1234;
22+
23+
// 열거형 정의
24+
enum class PieceType { King, Queen, Rook, Bishop, Knight, Pawn, None };
25+
enum class PieceColor { White, Black, None };
26+
enum class GameState { ChoosingPlayer, Playing, GameOver };
27+
28+
// Piece 구조체 정의
29+
struct Piece {
30+
PieceType type;
31+
PieceColor color;
32+
sf::Sprite sprite;
33+
34+
Piece(PieceType t, PieceColor c, sf::Sprite s) : type(t), color(c), sprite(std::move(s)) {}
35+
};
36+
37+
#endif // GAMEDATA_HPP

src/GameLogic.cpp

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
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+
}

src/GameLogic.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef GAMELOGIC_HPP
2+
#define GAMELOGIC_HPP
3+
4+
#include "GameData.hpp" // Piece, PieceType, PieceColor 등 사용
5+
6+
// 함수 선언 (board_state를 const 참조로 받음)
7+
std::vector<sf::Vector2i> getPossibleMoves(const std::array<std::array<std::optional<Piece>, 8>, 8>& board, int row, int col);
8+
sf::Vector2i findKing(const std::array<std::array<std::optional<Piece>, 8>, 8>& board, PieceColor kingColor);
9+
bool isKingInCheck(const std::array<std::array<std::optional<Piece>, 8>, 8>& board, PieceColor kingColor);
10+
bool isCheckmate(const std::array<std::array<std::optional<Piece>, 8>, 8>& board, PieceColor currentColor);
11+
12+
#endif // GAMELOGIC_HPP

0 commit comments

Comments
 (0)