AI 탐구노트

[코딩] 초간단 청기 백기 게임 만들어보기 본문

DIY 테스트

[코딩] 초간단 청기 백기 게임 만들어보기

42morrow 2025. 4. 3. 18:39

 

 

지난 번에 바이브 코딩을 통해 청기백기 게임을 만들어 보려고 했었죠. 하지만 DeepSite에서 사용한 DeepSeek가 아마도 청기백기 게임은 경험이 없었는지 상세하게 설명을 달아주지 않으면 생성을 못하는 것 같았습니다. 다른 것들은 정말 아주 짧은 한마디만으로도 멋드러지게 만들어줬는데 말이죠.

 

그래서, 청기백기 게임을 간단하게 만들어 보기로 했습니다. 

 

먼저 청기백기 게임의 로직을 한번 만들어 봤습니다. 처음에는 깃발 구분, 액션 구분, 둘 간의 연결 등 개별적으로 따로 구조를 만들고 이를 조합하는 방식으로 구현하려고 했었는데 판정하는 것도 번거롭고 굳이 그럴 필요까지는 없을 것 같았습니다. 그래서, 나올 수 있는 지시어를 전부 명시하는 방식으로 접근했습니다. 

 

청기백기 게임의 기본 로직 구현

나올 수 있는 지시어에 따라 요구되는 키값과 금지 키값을 지정하는 방식으로 진행했습니다. 이렇게 하지 않으면 요구 키값 외의 다른 키 입력을 걸러내는 것이 어렵기 때문에 이렇게 했는데 다른 방법도 있겠죠. 

 

import random 

actions = [
    {'청기 올려':'4,125'}, {'청기 내려':'1,245'}, {'청기 올리지마':',1245'},{'청기 내리지마':',1245'},
    {'백기 올려':'5,124'}, {'백기 내려':'2,145'}, {'백기 올리지마':',1245'},{'백기 내리지마':',1245'},
    {'청기 올리고 백기 올려':'45,12'}, {'청기 올리고 백기 내려':'42,15'}, {'청기 올리고 백기 내리지마':'4,125'},{'청기 올리고 백기 올리지마':'4,125'},
    {'청기 내리고 백기 올려':'15,24'}, {'청기 내리고 백기 내려':'12,45'}, {'청기 내리고 백기 내리지마':'1,245'},{'청기 내리고 백기 올리지마':'1,245'},
    {'청기 올리지말고 백기 올려':'5,124'}, {'청기 올리지말고 백기 내려':'2,145'}, {'청기 올리지말고 백기 내리지마':',1245'},{'청기 올리지말고 백기 올리지마':',1245'},
    {'청기 내리지말고 백기 올려':'5,124'}, {'청기 내리지말고 백기 내려':'2,145'}, {'청기 내리지말고 백기 내리지마':',1245'},{'청기 내리지말고 백기 올리지마':',1245'},
]

# 지시어 생성 (무작위 선택)
selected_action = random.choice(actions)

# key와 value 추출
command, value = list(selected_action.items())[0]

required_set = set()
prohibited_set = set()

# ','로 값 분리 
parts = value.split(',')
if parts[0]: required_set.update(parts[0])
if len(parts) > 1 and parts[1]: prohibited_set.update(parts[1])

print(f"명령어: {command}")
print(f"정답키: {required_set}")
print(f"금지키: {prohibited_set}")

 

 

이제 키보드를 동시 입력을 받고 콘솔에 남기지 않도록 하기 위해 pygame을 이용합니다. 그리고, 정답키가 아무 것도 누르지 않아야 하는 상황 (예: '청기 올리지말고 백기 내리지 마')에서는 시간이 지나고 판정을 하는 대신 '0' 키를 누르는 것으로 변경했습니다. 그래야 게임이 속도감 있게 진행될 수 있을 것 같아서였습니다. 

 

Pygame을 이용해 청기백기 게임 구현

이렇게 해서 만들어진 코드는 다음과 같습니다. 몇 가지 특징을 나열하면 아래와 같습니다. 

  • 숫자 키패드 사용 : 여기서 키보드 입력은 104 호한 키보드에서 숫자 키패드의 키보드를 이용합니다. 예를 들어 청기를 올리고 내리는 것은 각각 '4', '1' 키를 누르는 것으로 매핑되는 것이죠. 아래에 numpad_map은 이 때문에 필요합니다. 
  • 한글 처리 : 기본 시스템 폰트를 사용하면 한글이 깨져서 설치된 나눔고딕 폰트를 이용하도록 변경했습니다. 
  • 작동 확인 : 제대로 동작하는지 확인하는 디버깅 용도로 '정답키', '금지키', '입력키'를 표시하도록 했습니다. 나중에 빼면 됩니다. 
import pygame
import random

pygame.init()

# 화면 설정
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("청기백기 게임")
clock = pygame.time.Clock()

# 폰트 설정
font_path = '/usr/share/fonts/truetype/nanum/NanumGothic.ttf'
font_large = pygame.font.Font(font_path, 50)
font_small = pygame.font.Font(font_path, 30)

# 숫자 키패드 매핑
numpad_map = {
    pygame.K_KP0: "0",
    pygame.K_KP1: "1",
    pygame.K_KP2: "2",
    pygame.K_KP4: "4",
    pygame.K_KP5: "5"
}

# 동작 리스트
actions = [
    {'청기 올려':'4,125'}, {'청기 내려':'1,245'}, {'청기 올리지마':',1245'},{'청기 내리지마':',1245'},
    {'백기 올려':'5,124'}, {'백기 내려':'2,145'}, {'백기 올리지마':',1245'},{'백기 내리지마':',1245'},
    {'청기 올리고 백기 올려':'45,12'}, {'청기 올리고 백기 내려':'42,15'}, {'청기 올리고 백기 내리지마':'4,125'},{'청기 올리고 백기 올리지마':'4,125'},
    {'청기 내리고 백기 올려':'15,24'}, {'청기 내리고 백기 내려':'12,45'}, {'청기 내리고 백기 내리지마':'1,245'},{'청기 내리고 백기 올리지마':'1,245'},
    {'청기 올리지말고 백기 올려':'5,124'}, {'청기 올리지말고 백기 내려':'2,145'}, {'청기 올리지말고 백기 내리지마':',1245'},{'청기 올리지말고 백기 올리지마':',1245'},
    {'청기 내리지말고 백기 올려':'5,124'}, {'청기 내리지말고 백기 내려':'2,145'}, {'청기 내리지말고 백기 내리지마':',1245'},{'청기 내리지말고 백기 올리지마':',1245'},
]

score = 0
input_keys = set()
input_timer_started = False
input_start_time = 0
result_text = ""
result_color = (0, 0, 0)
paused = False

command = ""
required_set = set()
prohibited_set = set()

last_command_time = 0
command_interval = 3000
judged = False

running = True
while running:
    now = pygame.time.get_ticks()

    if not paused and now - last_command_time >= command_interval:
        selected_action = random.choice(actions)
        command, value = list(selected_action.items())[0]
        required_set = set()
        prohibited_set = set()

        parts = value.split(',')
        if parts[0]: required_set.update(parts[0])
        if len(parts) > 1 and parts[1]: prohibited_set.update(parts[1])

        input_keys = set()
        input_timer_started = False
        last_command_time = now
        result_text = ""
        judged = False

    # 화면 출력
    screen.fill((255, 255, 255))
    screen.blit(font_large.render(f"지시어: {command}", True, (0, 0, 255)), (50, 100))
    screen.blit(font_small.render(f"정답 키: {' + '.join(sorted(required_set)) if required_set else '0 (정지 상태)'}", True, (0, 100, 0)), (50, 180))
    screen.blit(font_small.render(f"금지 키: {' + '.join(sorted(prohibited_set)) if prohibited_set else '-'}", True, (200, 0, 0)), (50, 220))
    screen.blit(font_small.render(f"입력 키: {' + '.join(sorted(input_keys)) if input_keys else '-'}", True, (100, 100, 0)), (50, 260))
    screen.blit(font_small.render(result_text, True, result_color), (50, 310))
    screen.blit(font_small.render(f"점수: {score}", True, (0, 128, 0)), (50, 360))
    if paused:
        screen.blit(font_small.render("[일시정지 상태 - 스페이스바로 재시작]", True, (128, 0, 0)), (50, 410))
    pygame.display.flip()

    # 이벤트 처리
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                paused = not paused
            if paused:
                continue
            if event.key in numpad_map:
                key = numpad_map[event.key]
                if not input_timer_started:
                    input_start_time = pygame.time.get_ticks()
                    input_timer_started = True
                input_keys.add(key)

    # 판정
    if not paused and not judged:
        elapsed_input = pygame.time.get_ticks() - input_start_time
        elapsed_command = pygame.time.get_ticks() - last_command_time

        if (input_timer_started and elapsed_input > 200) or (not input_timer_started and elapsed_command > command_interval):
            if not required_set:
                success = input_keys == {"0"}  # '0'만 누르면 성공
            else:
                success = required_set.issubset(input_keys) and input_keys.isdisjoint(prohibited_set)

            if success:
                result_text = "성공!"
                result_color = (0, 100, 255)
                score += 1
            else:
                result_text = "실패!"
                result_color = (255, 0, 0)
                score -= 1
            input_keys = set()
            input_timer_started = False
            judged = True

    clock.tick(60)

pygame.quit()

 

 

청기백기 게임 실행 결과 

아래는 청기를 내려야 하므로 정답 키는 '1'만 눌러야 합니다. 실제로 누르고 '성공!' 판정을 받은 상태에서 스페이스바를 눌러 정지 상태로 캡처를 한 화면입니다. 일단 작동은 제대로 하는 것을 확인했네요.

 

그림 : pygame을 이용해 만들어본 단순 청기백기 게임

 


정리하며...

간단한 청기백기 게임 하나 만드는 것도 이렇게 고민이 필요했습니다. ChatGPT나 DeepSeek를 코딩에 잘 사용할 줄 알게 된다면 이런 수고도 필요 없겠지만 제가 그런 수준은 아니기 때문이죠.