Тема: тетріс + алгоритм який його проходетиме
Привіт!
Побачив відео як алгоритм грає в тетріс, захотілось і собі такий зробити. (так як програмувати трішки умію)
Ну до алгоритма мені ще далеко поки роблю тетріс.
(тема була створена для того що якщо кому буде потрбен погано зроблений тетріс, щоб виглядало як його робив неумілий студент, нехай беруть (код тетріса під спойлером))
▼тетріс на pygame
import pygame
from copy import deepcopy
from random import choice
#config
W, H = 10, 20
TILE = 30
GAME_RES = W * TILE, H * TILE
FPS = 120
SECOND_IN_MINUTE = 60
ANIMATION_SPEED = FPS * SECOND_IN_MINUTE #for y
COLOR = pygame.Color(30, 30, 30) #figure color
FIGURES_POS = [[(-1, 0), (-2, 0), ( 0, 0), ( 1, 0)],
[( 0, -1), (-1, -1), (-1, 0), ( 0, 0)],
[(-1, 0), (-1, 1), ( 0, 0), ( 0, -1)],
[( 0, 0), (-1, 0), ( 0, 1), (-1, -1)],
[( 0, 0), ( 0, -1), ( 0, 1), (-1, -1)],
[( 0, 0), ( 0, -1), ( 0, 1), ( 1, -1)],
[( 0, 0), ( 0, -1), ( 0, 1), (-1, 0)]]
FIGURES = [[pygame.Rect(x + W // 2, y + 1, 1, 1) for x, y in fig_pos] for fig_pos in FIGURES_POS]
class Tetris:
def __init__(self):
pygame.init()
self.sc = pygame.display.set_mode(GAME_RES)
self.clock = pygame.time.Clock()
self.grid = [pygame.Rect(x * TILE, y * TILE, TILE, TILE) for x in range(W) for y in range(H)]
self.figure_rect = pygame.Rect(0, 0, TILE - 2, TILE - 2)
self.figure, self.next_figure = deepcopy(choice(FIGURES)), deepcopy(choice(FIGURES))
def check_borders(self, i):
if self.figure[i].x < 0 or self.figure[i].x > W - 1:
return False
elif self.figure[i].y > H - 1 or self.field[self.figure[i].y][self.figure[i].x]:
return False
return True
def control(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT : self.dx = -1
elif event.key == pygame.K_RIGHT: self.dx = 1
elif event.key == pygame.K_DOWN : self.anim_limit = -1
elif event.key == pygame.K_UP : self.rotate_check = True
def move_x(self):
self.figure_old = deepcopy(self.figure)
for i in range(4):
self.figure[i].x += self.dx
if not self.check_borders(i):
self.figure = deepcopy(self.figure_old)
break
self.dx = 0
def move_y(self):
self.anim_count, self.figure_old = 0, deepcopy(self.figure)
for i in range(4):
self.figure[i].y += 1
if not self.check_borders(i):
for i in range(4):
self.field[self.figure_old[i].y][self.figure_old[i].x] = COLOR
self.figure, self.next_figure = self.next_figure, deepcopy(choice(FIGURES))
self.anim_limit = ANIMATION_SPEED
break
def rotate(self):
self.figure_old = deepcopy(self.figure)
center = self.figure[0]
for i in range(4):
x = self.figure[i].y - center.y
y = self.figure[i].x - center.x
self.figure[i].x = center.x - x
self.figure[i].y = center.y + y
if not self.check_borders(i):
self.figure = deepcopy(self.figure_old)
break
self.rotate_check = False
def check_lines(self):
line = H - 1
for row in range(H - 1, -1, -1):
count = 0
for i in range(W):
if self.field[row][i]:
count += 1
self.field[line][i] = self.field[row][i]
if count < W: line -= 1
def restart_game(self):
self.field = [[0 for i in range(W)] for i in range(H)]
self.anim_count, self.anim_speed, self.anim_limit, self.dx, self.rotate_check = 0, FPS, ANIMATION_SPEED, 0, False
def run(self):
self.restart_game()
while 1:
self.sc.fill(pygame.Color("black"))
[pygame.draw.rect(self.sc, (20, 20, 20), i_rect, 1) for i_rect in self.grid] #draw gride
self.anim_count += self.anim_speed
self.control()
# dx = 1 -> move right | dx = -1 -> move left
if self.dx != 0 : self.move_x()
if self.anim_count > self.anim_limit : self.move_y()
if self.rotate_check : self.rotate()
self.check_lines() #check and delete full lines
# draw figure
for i in range(4):
self.figure_rect.x = self.figure[i].x * TILE
self.figure_rect.y = self.figure[i].y * TILE
pygame.draw.rect(self.sc, COLOR, self.figure_rect)
# draw field
for y, raw in enumerate(self.field):
for x, col in enumerate(raw):
if col:
self.figure_rect.x, self.figure_rect.y = x * TILE, y * TILE
pygame.draw.rect(self.sc, col, self.figure_rect)
# game over
for i in range(W):
if self.field[1][i]:
self.restart_game()
pygame.display.flip()
self.clock.tick(FPS)
def main():
tetris = Tetris()
tetris.run()
if __name__ == "__main__":
main()
ну тетріс ніби зробив час для алгоритму...
upd1:
щось той алгоритм погано працює, вчора проблему шукав...
ну незнаю, потім напишу якщо знайду
upd2: алгоритм буде працювати на основі цього:
▼всі можливі позиції фігурки в тетрісі які може зробити людине (не враховуючи повільний спуск)
u - поворот, r - рух в право, l - рух в ліво, d - моментальний спуск
offsets = [
['d'],
['r', 'd'],
['l', 'd'],
['r', 'r', 'd'],
['l', 'l', 'd'],
['r', 'r', 'r', 'd'],
['l', 'l', 'l', 'd'],
['r', 'r', 'r', 'r', 'd'],
['l', 'l', 'l', 'l', 'd'],
['u', 'd'],
['u', 'r', 'd'],
['u', 'l', 'd'],
['u', 'r', 'r', 'd'],
['u', 'l', 'l', 'd'],
['u', 'r', 'r', 'r', 'd'],
['u', 'l', 'l', 'l', 'd'],
['u', 'r', 'r', 'r', 'r', 'd'],
['u', 'l', 'l', 'l', 'l', 'd'],
['u', 'u', 'd'],
['u', 'u', 'r', 'd'],
['u', 'u', 'l', 'd'],
['u', 'u', 'r', 'r', 'd'],
['u', 'u', 'l', 'l', 'd'],
['u', 'u', 'r', 'r', 'r', 'd'],
['u', 'u', 'l', 'l', 'l', 'd'],
['u', 'u', 'r', 'r', 'r', 'r', 'd'],
['u', 'u', 'l', 'l', 'l', 'l', 'd'],
['u', 'u', 'u', 'd'],
['u', 'u', 'u', 'r', 'd'],
['u', 'u', 'u', 'l', 'd'],
['u', 'u', 'u', 'r', 'r', 'd'],
['u', 'u', 'u', 'l', 'l', 'd'],
['u', 'u', 'u', 'r', 'r', 'r', 'd'],
['u', 'u', 'u', 'l', 'l', 'l', 'd'],
['u', 'u', 'u', 'r', 'r', 'r', 'r', 'd'],
['u', 'u', 'u', 'l', 'l', 'l', 'l', 'd'],
]