728x90

7강에서 할 일
7강에서는 스네이크 게임의 핵심인 “몸”을 만듭니다.
- 뱀을 좌표 1개가 아니라 좌표 리스트로 관리합니다
- 이동할 때 몸이 따라오게 합니다
- 먹이를 먹으면 꼬리를 지우지 않아서 길이가 늘어나게 합니다
- 먹이 생성 시 뱀 몸 전체와 겹치지 않게 합니다
1) 뱀을 리스트로 관리합니다
지금까지는 머리 좌표 snake_x, snake_y만 있었습니다.
이제부터는 뱀 전체를 다음처럼 리스트로 관리합니다.
예시:
snake = [(5, 5), (4, 5), (3, 5)]
- 리스트의 첫 번째가 머리입니다
- 뒤로 갈수록 몸/꼬리입니다
우선 시작은 머리 1개로 합니다.
기존의 snake_x, snake_y는 계속 쓰되, 뱀 리스트를 추가합니다.
게임 루프 밖(초기화 부분)에 넣습니다.
snake = [(snake_x, snake_y)]
2) 먹이 생성 함수가 몸 전체를 피하도록 바꿉니다
이제는 “머리만 피하기”가 아니라, “몸 전체를 피하기”가 필요합니다.
기존 함수:
- spawn_food(snake_x, snake_y) 형태였습니다.
이제는 리스트를 받도록 바꿉니다.
def spawn_food(snake):
while True:
x = random.randint(0, GRID_SIZE - 1)
y = random.randint(0, GRID_SIZE - 1)
if (x, y) not in snake:
return x, y
그리고 먹이 생성 호출도 바꿉니다.
food_x, food_y = spawn_food(snake)
3) 이동할 때 “머리 추가 + 꼬리 제거”를 합니다
스네이크 이동은 원리가 단순합니다.
- 머리가 한 칸 앞으로 나갑니다(새 머리 좌표 생성)
- 몸 리스트 맨 앞에 새 머리를 넣습니다
- 길이가 유지되려면 꼬리를 1칸 제거합니다
즉, “앞에 추가하고 뒤를 자른다” 입니다.
새 머리 좌표 계산
방향에 따라 새 머리를 만듭니다.
head_x, head_y = snake[0]
new_head = (head_x, head_y)
if direction == "UP":
new_head = (head_x, head_y - 1)
elif direction == "DOWN":
new_head = (head_x, head_y + 1)
elif direction == "LEFT":
new_head = (head_x - 1, head_y)
elif direction == "RIGHT":
new_head = (head_x + 1, head_y)
머리를 리스트 맨 앞에 넣습니다
snake.insert(0, new_head)
먹이를 안 먹었으면 꼬리를 제거합니다
snake.pop()
4) 먹이를 먹으면 “꼬리를 제거하지 않습니다”
먹이를 먹으면 길이가 늘어나야 합니다.
원리는 간단합니다.
- 평소에는 pop()을 해서 길이를 유지합니다
- 먹었을 때는 pop()을 하지 않아서 길이가 1 늘어납니다
즉, 먹었는지 먼저 판단하고 분기합니다.
ate_food = (new_head[0] == food_x and new_head[1] == food_y)
if ate_food:
score += 1
food_x, food_y = spawn_food(snake)
else:
snake.pop()
5) 벽 충돌도 “새 머리” 기준으로 검사합니다
이제는 snake_x, snake_y 대신 new_head로 벽 충돌을 검사합니다.
if (
new_head[0] < 0 or new_head[0] >= GRID_SIZE or
new_head[1] < 0 or new_head[1] >= GRID_SIZE
):
pygame.quit()
sys.exit()
6) 화면에 뱀 “전체”를 그립니다
이제는 머리만 그리면 안 됩니다.
리스트의 모든 좌표를 그립니다.
for x, y in snake:
rect = pygame.Rect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE)
pygame.draw.rect(screen, GREEN, rect)
7강 정리
이번 강의에서 배운 핵심입니다.
- 스네이크는 리스트로 관리합니다
- 이동은 “머리 추가 + (안 먹었으면) 꼬리 제거” 입니다
- 먹으면 꼬리를 제거하지 않아서 길이가 늘어납니다
- 먹이 생성은 몸 전체와 겹치지 않게 합니다
전체 코드
더보기
import pygame
import sys
import random
pygame.init()
# =========================
# 기본 설정
# =========================
CELL_SIZE = 40
GRID_SIZE = 10
SCREEN_SIZE = CELL_SIZE * GRID_SIZE
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
# =========================
# 화면 설정
# =========================
screen = pygame.display.set_mode((SCREEN_SIZE, SCREEN_SIZE))
pygame.display.set_caption("10x10 Snake Game")
clock = pygame.time.Clock()
# =========================
# 점수 및 폰트
# =========================
score = 0
font = pygame.font.SysFont(None, 36)
# =========================
# 먹이 생성 함수 (몸 전체와 겹침 방지)
# =========================
def spawn_food(snake):
while True:
x = random.randint(0, GRID_SIZE - 1)
y = random.randint(0, GRID_SIZE - 1)
if (x, y) not in snake:
return x, y
# =========================
# 뱀 초기 위치
# =========================
snake_x = 5
snake_y = 5
snake = [(snake_x, snake_y)] # (x, y) 좌표 리스트, 0번이 머리
# =========================
# 방향 설정
# =========================
direction = "RIGHT"
next_direction = direction
# =========================
# 이동 제어
# =========================
move_delay = 1
move_counter = 0
# =========================
# 먹이 초기 생성
# =========================
food_x, food_y = spawn_food(snake)
# =========================
# 게임 루프
# =========================
while True:
# 이벤트 처리
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# 방향키 입력
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP and direction != "DOWN":
next_direction = "UP"
elif event.key == pygame.K_DOWN and direction != "UP":
next_direction = "DOWN"
elif event.key == pygame.K_LEFT and direction != "RIGHT":
next_direction = "LEFT"
elif event.key == pygame.K_RIGHT and direction != "LEFT":
next_direction = "RIGHT"
# 이동 타이밍
move_counter += 1
if move_counter >= move_delay:
move_counter = 0
direction = next_direction
# 현재 머리
head_x, head_y = snake[0]
# 새 머리 계산
if direction == "UP":
new_head = (head_x, head_y - 1)
elif direction == "DOWN":
new_head = (head_x, head_y + 1)
elif direction == "LEFT":
new_head = (head_x - 1, head_y)
else: # RIGHT
new_head = (head_x + 1, head_y)
# 벽 충돌 (새 머리 기준)
if (
new_head[0] < 0 or new_head[0] >= GRID_SIZE or
new_head[1] < 0 or new_head[1] >= GRID_SIZE
):
pygame.quit()
sys.exit()
# 머리 추가
snake.insert(0, new_head)
# 먹이 먹기 판정
ate_food = (new_head[0] == food_x and new_head[1] == food_y)
if ate_food:
score += 1
food_x, food_y = spawn_food(snake)
else:
# 먹이 안 먹었으면 꼬리 제거(길이 유지)
snake.pop()
# 배경
screen.fill(BLACK)
# 점수 표시
score_text = font.render(f"Score: {score}", True, WHITE)
screen.blit(score_text, (10, 10))
# 뱀 전체 그리기
for x, y in snake:
rect = pygame.Rect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE)
pygame.draw.rect(screen, GREEN, rect)
# 먹이 그리기
food_rect = pygame.Rect(
food_x * CELL_SIZE,
food_y * CELL_SIZE,
CELL_SIZE,
CELL_SIZE
)
pygame.draw.rect(screen, YELLOW, food_rect)
# 화면 갱신
pygame.display.update()
clock.tick(10)
728x90
'⚙️ Python > 🎮 Pygame 실전' 카테고리의 다른 글
| [Pygame] 🐍 스네이크 게임 만들기 9강 | 게임 오버 화면 + R키로 재시작 (0) | 2026.01.09 |
|---|---|
| [Pygame] 🐍 스네이크 게임 만들기 8강 | 자기 몸 충돌 처리하기 (0) | 2026.01.08 |
| [Pygame] 🐍 스네이크 게임 만들기 6강 | 먹이 처리 + 점수 (0) | 2026.01.06 |
| [Pygame] 🐍 스네이크 게임 만들기 5강 | 먹이 생성하기 (랜덤위치) (0) | 2026.01.05 |
| [Pygame] 🐍 스네이크 게임 만들기 4강 | 벽 충돌 처리하기 (게임 오버) (0) | 2026.01.04 |