Command line python tetris

andreasPython CodeGames2 months ago94 Views

Here is a complete console-based Tetris game in Python with increasing difficulty as the score increases. The controls are:

  • W = Rotate
  • A = Move Left
  • D = Move Right
  • S = Drop

The game increases in speed as your score rises. You can run this in a Windows console (due to the use of msvcrt for keyboard input).

import os
import random
import time
import threading
import msvcrt

# Board dimensions
WIDTH = 10
HEIGHT = 20

# Tetromino shapes
SHAPES = {
    'I': [[1, 1, 1, 1]],
    'O': [[1, 1], [1, 1]],
    'T': [[0, 1, 0], [1, 1, 1]],
    'S': [[0, 1, 1], [1, 1, 0]],
    'Z': [[1, 1, 0], [0, 1, 1]],
    'J': [[1, 0, 0], [1, 1, 1]],
    'L': [[0, 0, 1], [1, 1, 1]]
}

class Tetromino:
    def __init__(self, shape):
        self.shape = SHAPES[shape]
        self.x = WIDTH // 2 - len(self.shape[0]) // 2
        self.y = 0

    def rotate(self):
        self.shape = [list(row) for row in zip(*self.shape[::-1])]

class Tetris:
    def __init__(self):
        self.board = [[0] * WIDTH for _ in range(HEIGHT)]
        self.score = 0
        self.level = 1
        self.tetromino = self.new_tetromino()
        self.running = True

    def new_tetromino(self):
        return Tetromino(random.choice(list(SHAPES.keys())))

    def valid_position(self, shape, offset_x, offset_y):
        for y, row in enumerate(shape):
            for x, cell in enumerate(row):
                if cell:
                    new_x = offset_x + x
                    new_y = offset_y + y
                    if new_x < 0 or new_x >= WIDTH or new_y >= HEIGHT:
                        return False
                    if new_y >= 0 and self.board[new_y][new_x]:
                        return False
        return True

    def merge(self):
        for y, row in enumerate(self.tetromino.shape):
            for x, cell in enumerate(row):
                if cell:
                    self.board[self.tetromino.y + y][self.tetromino.x + x] = 1

    def clear_lines(self):
        new_board = [row for row in self.board if any(cell == 0 for cell in row)]
        lines_cleared = HEIGHT - len(new_board)
        self.score += lines_cleared * 100
        self.level = self.score // 500 + 1
        while len(new_board) < HEIGHT:
            new_board.insert(0, [0] * WIDTH)
        self.board = new_board

    def drop(self):
        if self.valid_position(self.tetromino.shape, self.tetromino.x, self.tetromino.y + 1):
            self.tetromino.y += 1
        else:
            self.merge()
            self.clear_lines()
            self.tetromino = self.new_tetromino()
            if not self.valid_position(self.tetromino.shape, self.tetromino.x, self.tetromino.y):
                self.running = False

    def move(self, dx):
        if self.valid_position(self.tetromino.shape, self.tetromino.x + dx, self.tetromino.y):
            self.tetromino.x += dx

    def rotate(self):
        old_shape = self.tetromino.shape
        self.tetromino.rotate()
        if not self.valid_position(self.tetromino.shape, self.tetromino.x, self.tetromino.y):
            self.tetromino.shape = old_shape

    def render(self):
        os.system('cls' if os.name == 'nt' else 'clear')
        temp_board = [row[:] for row in self.board]
        for y, row in enumerate(self.tetromino.shape):
            for x, cell in enumerate(row):
                if cell and 0 <= y + self.tetromino.y < HEIGHT and 0 <= x + self.tetromino.x < WIDTH:
                    temp_board[y + self.tetromino.y][x + self.tetromino.x] = 1
        print("Score:", self.score, "Level:", self.level)
        for row in temp_board:
            print(''.join(['#' if cell else '.' for cell in row]))

    def input_loop(self):
        while self.running:
            if msvcrt.kbhit():
                key = msvcrt.getch()
                if key == b'a':
                    self.move(-1)
                elif key == b'd':
                    self.move(1)
                elif key == b's':
                    self.drop()
                elif key == b'w':
                    self.rotate()

    def run(self):
        threading.Thread(target=self.input_loop, daemon=True).start()
        while self.running:
            self.render()
            self.drop()
            time.sleep(max(0.1, 1.0 - (self.level - 1) * 0.1))
        self.render()
        print("Game Over! Final Score:", self.score)

if __name__ == '__main__':
    Tetris().run()

0 Votes: 0 Upvotes, 0 Downvotes (0 Points)

Leave a reply

Previous Post

Next Post

Loading Next Post...
Loading

Signing-in 3 seconds...