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()