2025-05-04

Manual of NalMok

내가 구상하고 chatGPT 도움 받아 파이썬으로 만든 날목 프로그램을 만들었다. 그 소스 코드를 Gemini에게 주고 설명해달라고 했더니 아래와 같이 답함.  

This experimental model uses your Search history. Some features aren't available.

파이썬 날목 게임 프로그램 설명

제공된 파이썬 코드는 PyQt5 라이브러리를 사용하여 그래픽 사용자 인터페이스(GUI)로 구현된 "날목"이라는 게임입니다. 이 게임은 오목과 유사하지만, 돌이 움직이는 방식에 차이가 있는 것으로 보입니다 (나이트 이동 방향 참고).

프로그램 구조:

프로그램은 크게 두 개의 클래스로 구성됩니다.

FirstTurnDialog(QDialog):

게임 시작 시 누가 먼저 둘 것인지(사람 또는 컴퓨터)를 묻는 대화 상자를 생성합니다.

두 개의 버튼("사람"과 "컴퓨터")을 제공하여 사용자의 선택을 받습니다.

choice 속성에 사용자의 선택("human_first" 또는 "computer_first")을 저장하고, 사용자가 선택을 완료하면 대화 상자를 닫습니다.

NalmokGame(QWidget):

실제 날목 게임 화면과 로직을 구현하는 메인 위젯입니다.

FirstTurnDialog 클래스 상세 설명:

__init__(self):

FirstTurnDialog 클래스의 생성자입니다.

대화 상자의 제목을 "누가 먼저 시작할까요?"로 설정합니다.

choice 속성을 None으로 초기화합니다.

수직 레이아웃(QVBoxLayout)을 생성하여 위젯들을 배치합니다.

"누가 먼저 시작할까요?"라는 질문 레이블을 레이아웃에 추가합니다.

"사람"(btn_human)과 "컴퓨터"(btn_computer) 두 개의 푸시 버튼을 생성하여 레이아웃에 추가합니다.

각 버튼의 clicked 시그널을 해당 슬롯 함수(choose_human, choose_computer)에 연결합니다.

대화 상자의 레이아웃을 설정합니다.

choose_human(self):

"사람" 버튼이 클릭되었을 때 호출되는 함수입니다.

choice 속성을 "human_first"로 설정하고, 대화 상자를 성공적으로 종료(accept())합니다.

choose_computer(self):

"컴퓨터" 버튼이 클릭되었을 때 호출되는 함수입니다.

choice 속성을 "computer_first"로 설정하고, 대화 상자를 성공적으로 종료(accept())합니다.

NalmokGame 클래스 상세 설명:

__init__(self, first_turn_mode):

NalmokGame 클래스의 생성자입니다.

게임 창의 제목을 "날목"으로 설정합니다.

게임 창의 크기를 가로 및 세로 BOARD_SIZE (19) x CELL_SIZE (30) 픽셀로 고정합니다.

board: 게임 판의 상태를 나타내는 2차원 리스트입니다. 각 셀은 EMPTY (0), BLACK (1), 또는 WHITE (2) 값을 가집니다.

move_history: 착수 기록을 저장하는 리스트입니다. 각 요소는 (x, y, stone) 형태의 튜플입니다.

game_over_flag: 게임 종료 여부를 나타내는 플래그입니다. 초기값은 False입니다.

last_black_move, last_white_move: 마지막으로 착수한 검은 돌과 흰 돌의 좌표를 저장합니다.

"Undo" 버튼을 생성하고 위치를 설정하며, 클릭 시 undo_move 함수를 호출하도록 연결합니다.

first_turn_mode에 따라 누가 먼저 시작할지 결정합니다.

"computer_first"인 경우: 컴퓨터(흑돌)가 중앙에 첫 수를 놓고, 사용자의 턴(백돌)으로 시작합니다.

"human_first"인 경우: 사용자의 턴(흑돌)으로 시작합니다.

그 외의 경우: 사용자의 턴(흑돌)으로 시작합니다.

게임 창을 화면에 표시합니다.

paintEvent(self, event):

QWidget의 이벤트 처리 함수로, 위젯을 다시 그릴 필요가 있을 때 자동으로 호출됩니다.

QPainter 객체를 생성하여 그림을 그립니다.

draw_board와 draw_stones 함수를 호출하여 각각 바둑판과 돌을 그립니다.

draw_board(self, qp):

실제 바둑판 배경과 선을 그리는 함수입니다.

연한 갈색(QColor(222, 184, 135))으로 바둑판 배경을 칠합니다.

검은색 펜으로 바둑판의 가로선과 세로선을 그립니다.

바둑판에 점(별)들을 표시합니다.

draw_stones(self, qp):

바둑판 위에 돌을 그리는 함수입니다.

self.board 상태를 순회하며 각 위치에 놓인 돌의 색깔에 따라 검은색 또는 흰색 원을 그립니다.

마지막으로 둔 돌의 위치에 초록색 테두리를 표시하여 시각적으로 강조합니다.

mousePressEvent(self, event):

QWidget의 이벤트 처리 함수로, 마우스 버튼이 눌렸을 때 자동으로 호출됩니다.

게임이 종료되었거나 현재 컴퓨터의 턴(self.turn != WHITE)인 경우에는 아무런 동작도 하지 않습니다.

마우스 클릭 좌표를 바둑판의 행과 열 인덱스로 변환합니다.

클릭된 위치가 유효한 범위 내에 있고 비어있는 셀인 경우:

흰 돌을 해당 위치에 놓습니다(self.place_stone).

흰 돌을 놓음으로써 승리했는지 확인하고, 승리했다면 게임 종료 메시지를 표시하고 함수를 종료합니다.

턴을 검은 돌(컴퓨터)으로 변경하고 화면을 업데이트합니다.

0.5초 후에 컴퓨터의 수를 두도록 computer_move 함수를 호출합니다.

place_stone(self, x, y, stone):

지정된 좌표(x, y)에 주어진 색깔(stone)의 돌을 놓는 함수입니다.

self.board를 업데이트하고, 착수 기록(self.move_history)에 추가합니다.

마지막으로 둔 돌의 좌표를 업데이트합니다.

undo_move(self):

"Undo" 버튼 클릭 시 호출되는 함수입니다.

최소 두 번의 착수가 기록되어 있다면 (사용자, 컴퓨터 순서로 되돌리기 위해):

최근 두 번의 착수 기록을 self.move_history에서 제거합니다.

해당 위치의 돌을 self.board에서 EMPTY로 되돌립니다.

마지막 착수 좌표 정보를 초기화합니다.

턴을 사용자(흰 돌)로 되돌리고 화면을 업데이트합니다.

check_win(self, x, y, stone):

현재 돌을 놓은 위치(x, y)를 기준으로 해당 색깔(stone)의 돌이 가로, 세로, 대각선 방향으로 5개 이상 연속되었는지 확인하는 함수입니다.

NALMOK_DIRECTIONS에 정의된 8가지 나이트 이동 방향을 기준으로 5개 연속 여부를 확인합니다.

5개 이상 연속된 경우 True를 반환하고, 그렇지 않으면 False를 반환합니다.

should_block_nalmok(self, x, y, stone, length):

특정 방향으로 주어진 길이(length)만큼 상대방의 돌(stone)이 연속될 가능성이 있는지 확인하고, 양쪽 끝이 열려있는 경우에만 막아야 할 상황으로 판단하는 함수입니다. 이는 날목 게임의 특성(5개 연속 시 승리)을 고려한 로직으로 보입니다.

주어진 좌표에서 NALMOK_DIRECTIONS의 각 방향으로 length만큼 떨어진 위치에 상대방의 돌이 연속되어 있는지 확인합니다.

연속된 돌의 양쪽 끝이 비어있는 경우 (blocked_ends == 0) True를 반환합니다.

computer_move(self):

컴퓨터의 수를 결정하고 두는 함수입니다.

게임이 종료된 경우에는 아무런 동작도 하지 않습니다.

AI 로직:

사용자(백)의 다음 수로 승리하는 경우를 막기: 모든 빈 셀을 순회하며 가상으로 흰 돌을 놓아보고, 사용자가 다음 수로 승리할 수 있는 위치라면 그곳에 검은 돌을 놓아 막습니다.

컴퓨터 승리 수: 컴퓨터(흑돌)가 다음 수로 승리할 수 있는 경우 (열린 4), 해당 위치에 검은 돌을 놓아 승리합니다.

컴퓨터 공격 - 열린 3 만들기: 컴퓨터가 다음에 4를 만들 수 있도록 열린 3을 만드는 위치에 검은 돌을 놓습니다.

상대 열린 4 차단: 사용자가 다음에 승리할 수 있는 열린 4를 만드는 위치를 찾아 검은 돌로 막습니다.

상대 열린 3 차단 (막힌 3은 무시): 사용자가 다음에 열린 4를 만들 수 있는 열린 3을 만드는 위치를 찾아 검은 돌로 막습니다.

중앙 혹은 임의 착수: 위에서 언급된 전략적인 위치가 없다면, 마지막으로 둔 검은 돌 주변 또는 바둑판 중앙의 비어있는 임의의 위치에 검은 돌을 놓습니다.

돌을 놓은 후 승리 여부를 확인하고, 승리했다면 게임 종료 메시지를 표시합니다.

턴을 사용자(흰 돌)로 변경하고 화면을 업데이트합니다.

더 이상 둘 곳이 없다면 무승부 처리합니다.

game_over(self, message):

게임 종료 메시지를 표시하는 함수입니다.

game_over_flag를 True로 설정하고, 메시지 박스를 통해 게임 종료 메시지를 사용자에게 보여줍니다.

게임 창을 닫습니다.

게임 실행:


if __name__ == "__main__": 블록은 스크립트가 직접 실행될 때만 코드를 실행하도록 합니다.

QApplication(sys.argv)를 통해 PyQt5 애플리케이션 객체를 생성합니다.

FirstTurnDialog()를 생성하고 exec_() 메서드를 호출하여 대화 상자를 표시합니다.

대화 상자가 닫히고 사용자가 선택을 완료(QDialog.Accepted)했다면, 사용자의 선택에 따라 NalmokGame 객체를 생성하여 게임을 시작합니다.

sys.exit(app.exec_())는 PyQt5 애플리케이션의 이벤트 루프를 시작하고, 애플리케이션이 종료될 때까지 실행되도록 합니다.

주요 특징:


PyQt5를 사용한 GUI 구현

사용자와 컴퓨터 간의 날목 게임

나이트 이동 방향(NALMOK_DIRECTIONS)을 활용한 게임 규칙 (일반적인 오목과 차이점)

간단한 AI를 구현하여 컴퓨터가 수를 둡니다.

마지막 착수 위치 시각적 강조

Undo 기능 제공

승리 판정 및 게임 종료 처리

이 코드는 PyQt5를 이용하여 날목 게임을 구현한 것으로, GUI 프로그래밍과 간단한 게임 로직 구현의 예시를 보여줍니다. 특히 NALMOK_DIRECTIONS를 통해 일반적인 오목과는 다른 움직임 규칙을 가진 게임을 만들었다는 점이 흥미롭습니다.

댓글 없음:

댓글 쓰기