[Python] 자동 테트리스 알고리즘

‍허진·2023년 2월 27일
0

Programming

목록 보기
6/10
post-thumbnail

> 과제 요구사항

pygame 라이브러리를 이용하여 자동으로 테트리스 게임을 하는 알고리즘을 만들어본다.

> 출력 예시

> 코드

import pygame
import random

import copy

point=0
def check2(lasttable,table):
    RES=0
    A=E=F=G=0
    for row in range(1,20):
        for col in range(10):
            if(lasttable[row][col]!=table[row][col]):
                lasttable[row][col]=9
    for row in range(1,20):
        for col in range(10):
            if(lasttable[row][col]==9):
                if(row==19):
                    G+=1
                if(row!=19):
                    if(0<lasttable[row-1][col]<9):
                        E+=1
                    if(0<lasttable[row+1][col]<9):
                        E+=1
                if(col==0 or col==9):
                    F+=1
                if(0<col<9):
                    if(0<lasttable[row][col-1]<9):
                        E+=1
                    if(0<lasttable[row][col+1]<9):
                        E+=1
                        
    RES+=(6.5)*E+(4)*F+6*G
    
    A=0
    for col in range(10):
        tmp=0
        a=20 
        for row in range(1,20):
            if lasttable[row][col]==9:
                tmp=a
            if tmp!=0: break
            a-=1
        A+=tmp
    RES+=A*(-3.78)
    return RES

def check(table):
    RES=0
    A=B=C=D=0
    
    for col in range(10): # col
        tmp=0
        tmp2=0
        for row in range(1,20):
            if(tmp!=0 and table[row][col]==0):
                tmp2=1
                B+=1
            elif(table[row][col]!=0):
                tmp+=1
            if(tmp2==1 and table[row][col]!=0):
                C+=tmp
                tmp=1
                tmp2=0
    RES+=B*(-20)
    RES+=C*(-5)
   
    lines = 0
    for i in range(1, 20):
        zeros = 0
        for j in range(10):
            if table[i][j] == 0:
                zeros += 1
        if zeros == 0:
            lines += 1
            for i1 in range(i, 1, -1):
                for j in range(10):
                    table[i1][j] = table[i1 - 1][j]
    D+= lines
    RES+=D*(200)
    return RES



colors = [
    (0, 0, 0),
    (120, 37, 179),
    (100, 179, 179),
    (80, 34, 22),
    (80, 134, 22),
    (180, 34, 22),
    (180, 34, 122),
]


class Figure:
    x = 0
    y = 0

    figures = [
        [[1, 5, 9, 13], [4, 5, 6, 7]],
        [[4, 5, 9, 10], [2, 6, 5, 9]],
        [[6, 7, 9, 10], [1, 5, 6, 10]],
        [[1, 2, 5, 9], [0, 4, 5, 6], [1, 5, 9, 8], [4, 5, 6, 10]],
        [[1, 2, 6, 10], [5, 6, 7, 9], [2, 6, 10, 11], [3, 5, 6, 7]],
        [[1, 4, 5, 6], [1, 4, 5, 9], [4, 5, 6, 9], [1, 5, 6, 9]],
        [[1, 2, 5, 6]],
    ]

    def __init__(self, x, y): 
        self.x = x
        self.y = y
        self.type = random.randint(0, len(self.figures) - 1)
        self.color = random.randint(1, len(colors) - 1)
        self.rotation = 0

    def image(self): 
        return self.figures[self.type][self.rotation]

    def rotate(self):
        self.rotation = (self.rotation + 1) % len(self.figures[self.type])


class Tetris:
    level = 2
    score = 0
    state = "start"
    field = []
    height = 0
    width = 0
    x = 100
    y = 60
    zoom = 20
    figure = None

    def __init__(self, height, width): #20, 10
        self.height = height
        self.width = width
        self.field = []
        self.score = 0
        self.state = "start"
        for i in range(height):
            new_line = []
            for j in range(width):
                new_line.append(0)
            self.field.append(new_line)

    def new_figure(self):
        self.figure = Figure(3, 0)

    def intersects(self):
        intersection = False
        for i in range(4):
            for j in range(4):
                if i * 4 + j in self.figure.image():
                    if i + self.figure.y > self.height - 1 or \
                            j + self.figure.x > self.width - 1 or \
                            j + self.figure.x < 0 or \
                            9> self.field[i + self.figure.y][j + self.figure.x] > 0:
                        intersection = True
        return intersection

    def break_lines(self):
        lines = 0
        for i in range(1, self.height):
            zeros = 0
            for j in range(self.width):
                if self.field[i][j] == 0:
                    zeros += 1
            if zeros == 0:
                lines += 1
                for i1 in range(i, 1, -1):
                    for j in range(self.width):
                        self.field[i1][j] = self.field[i1 - 1][j]
        self.score += lines ** 2

    def go_spacetmp(self):
        while not self.intersects():
            self.figure.y += 1
        self.figure.y -= 1
        self.tmp_freeze()

    def go_space(self):
        while not self.intersects():
            self.figure.y += 1
        self.figure.y -= 1
        self.freeze()

    def go_down(self):
        self.figure.y += 1
        if self.intersects():
            self.figure.y -= 1
            self.freeze()

    def freeze(self):
        for i in range(4):
            for j in range(4):
                if i * 4 + j in self.figure.image():
                    self.field[i + self.figure.y][j + self.figure.x] = self.figure.color
        self.break_lines()
        self.new_figure()
        if self.intersects():
            self.state = "gameover"
            game.__init__(20, 10)


    def tmp_freeze(self):
        for i in range(4):
            for j in range(4):
                if i * 4 + j in self.figure.image():
                    self.field[i + self.figure.y][j + self.figure.x] = self.figure.color

    def go_side(self, dx):
        old_x = self.figure.x
        self.figure.x += dx
        if self.intersects():
            self.figure.x = old_x

    def rotate(self):
        old_rotation = self.figure.rotation
        self.figure.rotate()
        if self.intersects():
            self.figure.rotation = old_rotation

pygame.init()

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (128, 128, 128)

size = (400, 500)
screen = pygame.display.set_mode(size)

pygame.display.set_caption("Tetris")

# Loop until the user clicks the close button.
done = False
clock = pygame.time.Clock()
fps = 25
game = Tetris(20, 10)
counter = 0

pressing_down = False

while not done:
    screen.fill(WHITE)
    
    lasttable=[]
    plaintable=[]
    
    if game.figure is None:
        game.new_figure() 

    lasttable=copy.deepcopy(game.field)
    plaintable=copy.deepcopy(game.field)
        
    counter += 1
    if counter > 100000:
        counter = 0

    if counter % (fps // game.level // 2) == 0 or pressing_down:
        if game.state == "start":
            game.go_down() 
    
    bestlist=[]
    for i in range(10):
        for j in range(len(game.figure.figures[game.figure.type])):
            game.figure.x=3
            game.figure.y=0
            res=0
            game.figure.rotation=j
            game.go_side(i-4)
            
            game.go_spacetmp()
            
            res+=check(game.field)
            res+=check2(lasttable,game.field)
            newlist=[i,j,res]
            bestlist.append(newlist)
            
            lasttable=copy.deepcopy(plaintable)
            game.field=copy.deepcopy(plaintable)
    game.figure.x=3
    game.figure.y=0
    game.figure.rotation=0
    best=bestlist[0]
    for i in bestlist:
        if i[2]>best[2]:
            best=i
    game.figure.rotation=best[1]
    game.go_side(best[0]-4)
    
    game.go_space()

    game.new_figure()

    screen.fill(WHITE)

    for i in range(game.height):
        for j in range(game.width):
            pygame.draw.rect(screen, GRAY, [game.x + game.zoom * j, game.y + game.zoom * i, game.zoom, game.zoom], 1)
            if game.field[i][j] > 0:
                pygame.draw.rect(screen, colors[game.field[i][j]],
                                 [game.x + game.zoom * j + 1, game.y + game.zoom * i + 1, game.zoom - 2, game.zoom - 1])

    if game.figure is not None:
        for i in range(4):
            for j in range(4):
                p = i * 4 + j
                if p in game.figure.image():
                    pygame.draw.rect(screen, colors[game.figure.color],
                                     [game.x + game.zoom * (j + game.figure.x) + 1,
                                      game.y + game.zoom * (i + game.figure.y) + 1,
                                      game.zoom - 2, game.zoom - 2])

    font = pygame.font.SysFont('Calibri', 25, True, False)
    font1 = pygame.font.SysFont('Calibri', 65, True, False)
    text = font.render("Score: " + str(game.score), True, BLACK)
    text_game_over = font1.render("Game Over", True, (255, 125, 0))
    text_game_over1 = font1.render("Press ESC", True, (255, 215, 0))

    screen.blit(text, [0, 0])
    if game.state == "gameover":
        screen.blit(text_game_over, [20, 200])
        screen.blit(text_game_over1, [25, 265])

    pygame.display.flip()
    clock.tick(fps)

pygame.quit()
profile
매일 공부하기 목표 👨‍💻 

0개의 댓글