1 Востаннє редагувалося mamkin haker (24.11.2021 15:54:59)

Тема: тетріс + алгоритм який його проходетиме

Привіт!
Побачив відео як алгоритм грає в тетріс, захотілось і собі такий зробити. (так як програмувати трішки умію)
Ну до алгоритма мені ще далеко поки роблю тетріс.

(тема була створена для того що якщо кому буде потрбен погано зроблений тетріс, щоб виглядало як його робив неумілий студент, нехай беруть (код тетріса під спойлером))

тетріс на 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'],
]
Подякували: koala, Arete, leofun013

2 Востаннє редагувалося mamkin haker (25.11.2021 16:02:17)

Re: тетріс + алгоритм який його проходетиме

ось, +- робоча версія, може очищати аж до 14 ліній за 1 життя :) (кількість ліній залежать від рандома)
код надто великий, тому прикріплю :3
запускати main.py
(код трішки нище, на гіт хабі лежить)

3 Востаннє редагувалося mamkin haker (25.11.2021 00:23:16)

Re: тетріс + алгоритм який його проходетиме

.

4 Востаннє редагувалося mamkin haker (23.01.2022 19:30:27)

Re: тетріс + алгоритм який його проходетиме

.