본문 바로가기

코딩 공부/파이썬

파이썬 테트리스 코드 정리 (다운로드 포함)

파이썬 테트리스 코드 정리 (+다운로드 포함)

목차

1. 파이썬 테트리스 코드 정리
2. 테트리스 다운로드
3. 테트리스 코드 후기

 

이코드는 2024 12 03 일 작성한 코드입니다.

 

제 모든 파이썬 코드들은 학습용으로 지인을 통해 만들게 되었으며 제가 기획하는 부분은 디테일 하게 짤 수 있으나 코드를 구현할 줄 몰라 ai의 힘을 많이 빌린 작품들 입니다.

 

이번 테트리스 작품의 중요 포인트는 3가지로 구성을 하였습니다.

 

1. 정상작동 하는 테트리스 블록들

2. 1줄이 클리어 되었을때 나오는 스코어

3. 배경음악과 효과음


 

 

파이썬 테트리스 코드

 

파이썬 테트리스 코드

 

import pygame
import random

# 기본 설정
pygame.init()
pygame.mixer.init()  # 믹서 초기화
width, height = 300, 600  # 게임판 크기 (10x20 타일 크기)
block_size = 30  # 각 블럭의 픽셀 크기
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Tetris with Sound")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 36)

# 색상 설정
colors = [
    (0, 0, 0),  # 빈 공간
    (0, 240, 240),  # I 블럭
    (0, 0, 240),    # J 블럭
    (240, 160, 0),  # L 블럭
    (240, 240, 0),  # O 블럭
    (0, 240, 0),    # S 블럭
    (160, 0, 240),  # T 블럭
    (240, 0, 0)     # Z 블럭
]

# 블럭 모양 정의 (4x4 그리드)
shapes = [
    [[1, 1, 1, 1]],  # I
    [[1, 0, 0], [1, 1, 1]],  # J
    [[0, 0, 1], [1, 1, 1]],  # L
    [[1, 1], [1, 1]],  # O
    [[0, 1, 1], [1, 1, 0]],  # S
    [[0, 1, 0], [1, 1, 1]],  # T
    [[1, 1, 0], [0, 1, 1]]   # Z
]

# 블럭 클래스
class Block:
    def __init__(self, shape, x, y):
        self.shape = shape
        self.x = x
        self.y = y
        self.color = colors[shapes.index(shape) + 1]

    def rotate(self):
        # 시계 방향으로 블럭 회전
        self.shape = [list(row) for row in zip(*self.shape[::-1])]

    def draw(self, surface):
        # 블럭을 화면에 그리기
        for y, row in enumerate(self.shape):
            for x, cell in enumerate(row):
                if cell:
                    pygame.draw.rect(
                        surface,
                        self.color,
                        (self.x + x * block_size, self.y + y * block_size, block_size, block_size),
                        0
                    )

# 게임판 클래스
class TetrisGame:
    def __init__(self, line_clear_sound):
        self.board = [[0] * 10 for _ in range(20)]  # 10x20 게임판 초기화
        self.current_block = self.create_new_block()
        self.next_block = self.create_new_block()
        self.score = 0
        self.game_over = False
        self.line_clear_sound = line_clear_sound  # 라인 클리어 소리

    def create_new_block(self):
        shape = random.choice(shapes)
        return Block(shape, 3 * block_size, 0)

    def draw_board(self, surface):
        # 게임판을 화면에 그리기
        for y, row in enumerate(self.board):
            for x, cell in enumerate(row):
                if cell:
                    pygame.draw.rect(
                        surface,
                        colors[cell],
                        (x * block_size, y * block_size, block_size, block_size),
                        0
                    )

    def clear_lines(self):
        # 한 줄이 가득 찼는지 확인하고, 가득 찬 줄을 제거
        new_board = [row for row in self.board if any(cell == 0 for cell in row)]
        cleared_lines = len(self.board) - len(new_board)
        self.score += cleared_lines * 100  # 점수 추가
        self.board = [[0] * 10 for _ in range(cleared_lines)] + new_board
        return cleared_lines  # 클리어된 라인 수를 반환

    def check_collision(self, block, offset_x=0, offset_y=0):
        # 블럭이 벽이나 다른 블럭과 충돌하는지 확인
        for y, row in enumerate(block.shape):
            for x, cell in enumerate(row):
                if cell:
                    new_x = (block.x // block_size) + x + offset_x
                    new_y = (block.y // block_size) + y + offset_y
                    if new_x < 0 or new_x >= 10 or new_y >= 20 or self.board[new_y][new_x]:
                        return True
        return False

    def place_block(self, block):
        # 블럭을 게임판에 고정
        for y, row in enumerate(block.shape):
            for x, cell in enumerate(row):
                if cell:
                    self.board[(block.y // block_size) + y][(block.x // block_size) + x] = colors.index(block.color)
        cleared_lines = self.clear_lines()  # 라인 클리어 후 갱신
        if cleared_lines > 0:
            self.line_clear_sound.play()  # 라인 클리어 효과음
        self.current_block = self.next_block
        self.next_block = self.create_new_block()
        if self.check_collision(self.current_block):
            self.game_over = True

    def move_block_down(self):
        # 블럭을 아래로 한 칸 이동
        if not self.check_collision(self.current_block, offset_y=1):
            self.current_block.y += block_size
        else:
            self.place_block(self.current_block)

    def move_block_sideways(self, dx):
        # 블럭을 좌우로 이동
        if not self.check_collision(self.current_block, offset_x=dx):
            self.current_block.x += dx * block_size

    def drop_block(self):
        # 스페이스바를 눌렀을 때 블럭을 한 번에 내려놓기
        while not self.check_collision(self.current_block, offset_y=1):
            self.current_block.y += block_size
        self.place_block(self.current_block)

    def rotate_block(self):
        # 블럭을 회전
        old_shape = self.current_block.shape[:]
        self.current_block.rotate()
        if self.check_collision(self.current_block):
            self.current_block.shape = old_shape  # 회전 불가능 시 원상 복구

# 게임 실행 함수
def main():
    pygame.mixer.music.load("TM.wav")  # 배경 음악 파일 경로
    pygame.mixer.music.play(-1, 0.0)  # 배경 음악 반복재생
    drop_sound = pygame.mixer.Sound("TD.wav")  # 블록 떨어지는 소리 파일 경로
    line_clear_sound = pygame.mixer.Sound("TL.wav")  # 라인 클리어 소리 파일 경로

    game = TetrisGame(line_clear_sound)  # 라인 클리어 소리를 전달
    fall_time = 0
    speed = 500  # 블럭이 자동으로 떨어지는 속도

    while True:
        screen.fill((0, 0, 0))
        fall_time += clock.get_rawtime()
        clock.tick()

        if game.game_over:
            # 게임 종료 시 배경 음악 중지
            pygame.mixer.music.stop()
           
            # 게임 종료 시 스코어 및 재시작 메시지 출력
            game_over_text = font.render(f"Game Over! Score: {game.score}", True, (255, 255, 255))
            restart_text = font.render("Press R to Restart", True, (255, 255, 255))
            screen.blit(game_over_text, (20, height // 2 - 40))
            screen.blit(restart_text, (20, height // 2))
            pygame.display.update()

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    return
                if event.type == pygame.KEYDOWN and event.key == pygame.K_r:
                    main()  # 게임 재시작
            continue

        if fall_time > speed:
            fall_time = 0
            game.move_block_down()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                return
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    game.move_block_sideways(-1)
                elif event.key == pygame.K_RIGHT:
                    game.move_block_sideways(1)
                elif event.key == pygame.K_DOWN:
                    game.move_block_down()
                elif event.key == pygame.K_UP:
                    game.rotate_block()
                elif event.key == pygame.K_SPACE:
                    game.drop_block()
                    drop_sound.play()  # 블록 떨어지는 소리

        game.draw_board(screen)
        game.current_block.draw(screen)

        # 점수 표시
        score_text = font.render(f"Score: {game.score}", True, (255, 255, 255))
        screen.blit(score_text, (10, 10))

        pygame.display.update()

if __name__ == "__main__":
    main()

 

 


 

 

파이썬 테트리스 코드 다운로드

 

blacksoy 테트리스.zip
10.85MB

 

위 파일을 받으면 파이썬 코드와 함께 효과음 파일이 있습니다 참고하셔서 여러분 만의 코드를 작성해 보시거나 추가를 해보시는 것을 추천드립니다.


 

 

파이썬 테트리스 코드 작성 후기

 

이번 테트리스 게임 개발 과정은 개발자로서의 창의력과 논리적 사고를 동시에 활용할 수 있는 매우 흥미로운 경험이었습니다. 처음에는 게임의 기본 구조를 설계하며 각 구성 요소를 세밀하게 나누는 작업을 진행했습니다. 이를 통해 코드의 유지보수성을 높이고, 추후 확장성을 고려한 구조를 마련할 수 있었습니다.

 

코드를 작성하는 동안 가장 중점을 둔 부분은 게임의 핵심적인 동작인 블록 이동, 회전, 라인 클리어 등의 기능을 효율적으로 구현하는 것이었습니다. 이를 위해 객체 지향 프로그래밍의 장점을 활용해 각 블록과 게임판을 클래스로 정의하고, 이들 간의 상호작용을 명확히 했습니다. 예를 들어, 블록 클래스는 자체적인 회전과 그리기 기능을 담당하며, 게임판 클래스는 블록의 충돌 감지와 고정, 라인 클리어를 처리하도록 설계했습니다. 이러한 구조는 각 기능을 모듈화하여 코드의 가독성과 재사용성을 높이는 데 기여했습니다.

사운드 효과를 추가하는 작업도 매우 흥미로웠습니다. 배경 음악과 블록 이동, 라인 클리어 등의 효과음을 적절히 배치하여 게임의 몰입감을 향상시키는 데 성공했습니다. 특히, 라인 클리어 시 사운드를 재생하도록 구현한 것은 사용자에게 즉각적인 피드백을 제공함으로써 게임의 재미를 한층 더 높이는 요소가 되었습니다. 이 과정에서 Pygame의 믹서 모듈을 사용해 사운드를 관리했으며, 이는 다소 생소한 부분이었지만 결과적으로 성공적으로 구현할 수 있었습니다.

 

개발 중 가장 도전적이었던 부분은 블록의 충돌 감지와 회전 로직이었습니다. 특히, 블록이 벽이나 다른 블록에 닿았을 때 정확히 처리되도록 하는 것은 상당히 신중한 계산이 필요했습니다. 이를 해결하기 위해 다양한 테스트 데이터를 생성하고, 모든 경우의 수를 꼼꼼히 검증하며 문제를 해결해 나갔습니다. 이러한 경험은 문제 해결 능력을 한층 더 향상시키는 계기가 되었습니다.

 

또한, 이번 프로젝트에서는 사용자의 인터랙션에 즉각적으로 반응하는 동작을 구현하는 데 많은 노력을 기울였습니다. 키 입력에 따라 블록이 자연스럽게 움직이고, 회전하거나 떨어지도록 구현하면서 게임의 조작감을 최대한 현실감 있게 만드는 데 집중했습니다. 이 과정에서 Pygame의 이벤트 처리 시스템을 활용했으며, 이를 통해 효율적으로 사용자 입력을 처리할 수 있었습니다.

 

결과적으로, 이번 프로젝트는 단순한 게임 개발을 넘어 코드의 구조화와 효율적인 기능 구현, 사용자 경험을 고려한 설계 등의 다양한 측면에서 많은 것을 배울 수 있는 기회였습니다. 앞으로도 이러한 경험을 바탕으로 더 복잡한 게임이나 애플리케이션을 개발하는 데 도전할 계획입니다. 이번 프로젝트는 저에게 프로그래밍 실력을 키우고 창의성을 발휘할 수 있는 값진 시간이었습니다

반응형