import pygame import random # Game window size WIDTH, HEIGHT = 300, 600 # width and height of each square BLOCK_SIZE = 30 # The speed at which the block moves SPEED = 3 class Block: """Block class""" def __init__(self, x, y, shape): self.x = x self.y = y self.color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) self.shape = shape self.rotation = 0 def draw(self, surface): """Draw a square""" for row in range(len(self. shape)): for col in range(len(self. shape[0])): if self. shape[row][col] == 1: pygame.draw.rect(surface, self.color, (self.x + col * BLOCK_SIZE, self.y + row * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE), 0) def move(self, dx, dy): """Block moves""" self.x += dx self.y += dy def rotate(self): """Block rotation""" self.rotation = (self.rotation + 1) % 4 self.shape = [[self.shape[y][x] for y in range(len(self.shape))] for x in range(len(self.shape[0])-1, -1, -1 )] def check_collision(self, grid): """Check block collision with grid""" for row in range(len(self. shape)): for col in range(len(self. shape[0])): if self. shape[row][col] == 1: if self.x + col * BLOCK_SIZE < 0 or self.x + col * BLOCK_SIZE >= WIDTH: return True if self.y + row * BLOCK_SIZE >= HEIGHT: return True if self.y + row * BLOCK_SIZE >= 0 and grid[int((self.y + row * BLOCK_SIZE) / BLOCK_SIZE)][int((self.x + col * BLOCK_SIZE) / BLOCK_SIZE)] != (0, 0,0): return True return False class Game: """Games""" def __init__(self): pygame.init() self.screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Tetris") self. clock = pygame. time. Clock() self.grid = [[(0,0,0) for x in range(WIDTH // BLOCK_SIZE)] for y in range(HEIGHT // BLOCK_SIZE)] self.score = 0 self.level = 1 self.lines = 0 self. current_block = self. new_block() def new_block(self): """Generate a new block""" shapes = [ [[1, 1, 1, 1]], [[1, 0, 0], [1, 1, 1]], [[0, 0, 1], [1, 1, 1]], [[1, 1], [1, 1]], [[0, 1, 1], [1, 1, 0]], [[1, 1, 0], [0, 1, 1]], [[0, 1, 0], [1, 1, 1]] ] shape = random. choice(shapes) return Block(WIDTH // 2 - len(shape[0]) * BLOCK_SIZE // 2, 0, shape) def draw_grid(self): """Draw Grid""" for row in range(len(self. grid)): for col in range(len(self. grid[0])): pygame.draw.rect(self.screen, self.grid[row][col], (col * BLOCK_SIZE, row * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE), 0) def draw_score(self): """Draw Fractions""" font = pygame.font.SysFont("arial", 20) score_label = font.render("Score: {0}".format(self.score), 1, (255, 255, 255)) self.screen.blit(score_label, (10, HEIGHT - 30)) level_label = font.render("Level: {0}".format(self.level), 1, (255, 255, 255)) self.screen.blit(level_label, (WIDTH - 80, HEIGHT - 30)) lines_label = font.render("Lines: {0}".format(self.lines), 1, (255, 255, 255)) self.screen.blit(lines_label, (WIDTH // 2 - 40, HEIGHT - 30)) def check_line(self): """Check if there is a full line""" full_rows = 0 for row in range(len(self. grid)): if (0,0,0) not in self.grid[row]: full_rows += 1 for r in range(row, 0, -1): self.grid[r] = self.grid[r-1].copy() self. grid[0] = [(0,0,0) for x in range(len(self. grid[0]))] if full_rows > 0: self.score += full_rows * 100 self.lines += full_rows self.level = min(self.lines // 10 + 1, 10) def game_over(self): """game over""" font = pygame.font.SysFont("arial", 40) game_over_label = font. render("Game Over", 1, (255, 0, 0)) self.screen.blit(game_over_label, (WIDTH // 2 - 100, HEIGHT // 2 - 20)) pygame.display.update() pygame.time.delay(2000) pygame. quit() quit() def run(self): """Game main loop""" while True: self. clock. tick(60) # Handle events for event in pygame.event.get(): if event.type == pygame.QUIT: pygame. quit() quit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: self. current_block. move(-BLOCK_SIZE, 0) if self.current_block.check_collision(self.grid): self. current_block. move(BLOCK_SIZE, 0) if event.key == pygame.K_RIGHT: self. current_block. move(BLOCK_SIZE, 0) if self.current_block.check_collision(self.grid): self. current_block. move(-BLOCK_SIZE, 0) if event.key == pygame.K_UP: self. current_block. rotate() if self.current_block.check_collision(self.grid): self. current_block. rotate() if event.key == pygame.K_DOWN: self. current_block. move(0, BLOCK_SIZE) if self.current_block.check_collision(self.grid): self.current_block.move(0, -BLOCK_SIZE) # move blocks self. current_block. move(0, SPEED) if self.current_block.check_collision(self.grid): self.current_block.move(0, -SPEED) for row in range(len(self. current_block. shape)): for col in range(len(self. current_block. shape[0])): if self.current_block.shape[row][col] == 1: self.grid[int((self.current_block.y + row * BLOCK_SIZE) / BLOCK_SIZE)][int((self.current_block.x + col * BLOCK_SIZE) / BLOCK_SIZE)] = self.current_block.color self. check_line() self. current_block = self. new_block() if self.current_block.check_collision(self.grid): self. game_over() # draw interface self. screen. fill((0, 0, 0)) self. draw_grid() self. current_block. draw(self. screen) self. draw_score() pygame.display.update() game = Game() game. run()