Python

[나도코딩] 파이썬 실전 프로젝트 | 기억력 테스트 게임, 침팬지를 이겨라

짱짱이_ 2023. 12. 6. 22:59
import pygame
from random import *

def setup(level): # 레벨에 맞게 설정
    global display_time
    display_time = 5 - (level // 3) # 숫자를 얼마의 시간동안 보여줄지
    display_time = max(display_time, 1) # 1초 미만이면 1초로 처리
    number_count = (level // 3) + 5
    number_count = min(number_count, 20) # 최대수가 20이 되게 설정
    shuffle_grid(number_count) # grid 형태로 숫자를 랜덤 배치

def shuffle_grid(number_count):
    rows = 5
    columns = 9
    cell_size = 130 # 각 Grid cell 별 가로, 세로 크기
    button_size = 110 # Grid cell 내에 실제로 그려질 버튼 크기
    screen_left_margin = 55 # 전체 스크린 왼쪽 여백
    screen_top_margin = 20 # 전체 스크린 위쪽 여백

    # [0, 0, 0, 0, 0, 0, 0, 0, 0] 가 5줄 만들어지게 설정
    grid = [[0 for col in range(columns)] for row in range(rows)]
    
    number = 1 # 시작 숫자 1부터 number_count까지 랜덤으로 배치
    while number <= number_count:
        row_idx = randrange(0, rows) # 0이상 5미만 랜덤으로 수 뽑음
        col_idx = randrange(0, columns) # 0이상 8미만 랜덤 수
        
        if grid[row_idx][col_idx] == 0:
            grid[row_idx][col_idx] = number # 슷자 지정
            number += 1

            # 현재 grid cell 위치 기준으로 x, y 위치를 구함
            center_x = screen_left_margin + (col_idx * cell_size) + (cell_size / 2)
            center_y = screen_top_margin + (row_idx * cell_size) + (cell_size / 2)

            # 숫자 버튼 만들기
            button = pygame.Rect(0, 0, button_size, button_size)
            button.center = (center_x, center_y)
            number_bottons.append(button)
            
    print(grid) # 배치된 숫자 위치 확인

def display_start_screen():
    pygame.draw.circle(screen, WHITE, start_button.center, 60, 5) # 흰색 동그라미를 그림, 중심은 start_button의 중심좌표, 반지름은 60, 선 두께는 5
   
    msg = game_font.render(f"{curr_level}", True, WHITE)
    msg_rect = msg.get_rect(center=start_button.center)
    screen.blit(msg, msg_rect)

def display_game_screen():
    global hidden

    if not hidden:
        elapsed_time = (pygame.time.get_ticks() - start_ticks) / 1000 # ms를 s로
        if elapsed_time > display_time:
            hidden = True
    for idx, rect in enumerate(number_bottons, start =1):
        if hidden:
            pygame.draw.rect(screen, BLUE, rect) # 버튼 사각형을 그리기

        else:
            # 숫자 텍스트 추가
            cell_text = game_font.render(str(idx), True, WHITE)
            text_rect = cell_text.get_rect(center=rect.center)
            screen.blit(cell_text, text_rect)

def check_buttons(pos):
    global start, start_ticks # global을 이용해 전역변수임을 알려주어야 함 (아래 if문에서 사용하기 위해)
    
    if start: # 게임이 시작했으면?
        check_number_buttons(pos)
    
    elif start_button.collidepoint(pos): # start_button 안에 클릭 좌표가 있다면
        start = True
        start_ticks = pygame.time.get_ticks() # 타이머 시작, 현재 시간 저장

def check_number_buttons(pos):
    global hidden, start, curr_level

    for button in number_bottons:
        if button.collidepoint(pos):
            if button == number_bottons[0]:
                print("Correct")
                del number_bottons[0]
                if not hidden:
                    hidden = True # 숫자 숨김 처리
            else:
                game_over()
            break

    # 모든 숫자를 다 맞췄다면 다음 레벨로, 다시 시작 화면으로 감
    if len(number_bottons) == 0:
        start = False
        hidden = False
        curr_level += 1
        setup(curr_level)

def game_over(): # 게임 종료 처리, 메시지 보여줌
    global running
    running = False
    msg = game_font.render(f"Your level is {curr_level}", True, WHITE)
    msg_rect = msg.get_rect(center=(screen_width/2, screen_height/2))
    screen.fill(BLACK)
    screen.blit(msg, msg_rect)
    

pygame.init()

# 화면 크기 설정
screen_width = 1280
screen_height = 720
screen = pygame.display.set_mode((screen_width, screen_height))   # (screen_width, screen_height) 는 튜플 이용
pygame.display.set_caption("Memory Game")
game_font = pygame.font.Font(None, 120)

# 시작 버튼
start_button = pygame.Rect(0, 0, 120, 120)
start_button.center = (120, screen_height-120)

# 색깔
BLACK = (0 , 0, 0) # RGB
WHITE = (255, 255, 255)
BLUE = (176, 224, 230)

number_bottons = [] # 플레이어가 눌러야 하는 버튼들
curr_level = 1 # 현재 레벨
display_time = None # 숫자를 보여주는 시간
start_ticks = None # 시간 계산 (현재 시간 정보 저장)

# 게임 시작 여부
start = False
# 숫자 숨김 여부 (사용자가 1을 클릭했거나 보여주는 시간을 초과했을 때)
hidden = False
# 게임 시작 전 셋업
setup(curr_level)

# 게임 실행 루프
running = True # 게임이 실행 중인지 판별하는 변수
while running:
    click_pos = None
    for event in pygame.event.get(): # 어떤 이벤트가 발생했는가?
        if event.type == pygame.QUIT: # 창이 닫히는 이벤트
            running = False
        elif event.type == pygame.MOUSEBUTTONUP: # 마우스 버튼이 클릭되면
            click_pos = pygame.mouse.get_pos() # 클릭 좌표 정보 얻음
            print(click_pos)

    # 화면 전체를 까맣게
    screen.fill(BLACK)

    if start:
        display_game_screen() # 게임 화면 표시
    else:
        display_start_screen() # 시작 화면 표시
    pygame.display.update() # 화면 업데이트

    # 사용자가 클릭한 좌표값이 생기면 (클릭을 하면)
    if click_pos:
        check_buttons(click_pos)
    pygame.display.update()

pygame.time.delay(3000) # 3초 정도 보여줌
pygame.quit() # 게임 종료