A brief explanation

80, 90 after the small partners have played “Tetris”, the kind of “all-powerful” scene occasionally flashed in my mind is really too cool; If you don’t have time to play, this time you can really make your own

This example uses Python3 (Python3.5, 3.6, 3.7…., of course + PyGame

To run the pyGame module, install the following command

pip install pygame -i https://mirrors.aliyun.com/pypi/simple/
Copy the code

Two, the operation effect

Complete code

The following code, use the font file yh. The vera.ttf, download address www.itprojects.cn/detail.html…

The file main.py looks like this:

For more project examples, please visit: www.itprojects.cn """

import random
import sys
import time

import pygame

from blocks import block_s, block_i, block_j, block_l, block_o, block_t, block_z

SCREEN_WIDTH, SCREEN_HEIGHT = 450.750
BG_COLOR = (40.40.60)  # the background color
BLOCK_COL_NUM = 10  # Number of squares per row
SIZE = 30  # Size of each small square
BLOCK_ROW_NUM = 25  # Number of squares per column
BORDER_WIDTH = 4  # Game area border width
RED = (200.30.30)  # red, the font color for GAME OVER


def judge_game_over(stop_all_block_list) :
    """ Determine if the game is over """
    if "O" in stop_all_block_list[0] :return True


def change_speed(score) :
    speed_level = [("1".0.5.0.20), ("2".0.4.21.50), ("3".0.3.51.100), ("4".0.2.101.200), ("5".0.1.201.None)]
    for speed_info, speed, score_start, score_stop in speed_level:
        if score_stop and score_start <= score <= score_stop:
            return speed_info, speed
        elif score_stop is None and score >= score_start:
            return speed_info, speed


def judge_lines(stop_all_block_list) :
    """ Determine if there are squares in the same row, and eliminate """
    Record the number of rows just eliminated
    move_row_list = list(a)# Eliminate full rows
    for row, line in enumerate(stop_all_block_list):
        if "." not in line:
            # If this line doesn't. So that means that all of them are O, so that eliminates this row
            stop_all_block_list[row] = ['. ' for _ in range(len(line))]
            move_row_list.append(row)

    End this function if there are no full rows
    if not move_row_list:
        return 0

    Move the remaining rows to the next row
    for row in move_row_list:
        stop_all_block_list.pop(row)
        stop_all_block_list.insert(0['. ' for _ in range(len(line))])

    return len(move_row_list) * 10


def add_to_stop_all_block_list(stop_all_block_list, current_block, current_block_start_row, current_block_start_col) :
    """ Adds the currently stopped block to the list """
    for row, line in enumerate(current_block):
        for col, block in enumerate(line):
            ifblock ! ='. ':
                stop_all_block_list[current_block_start_row + row][current_block_start_col + col] = "O"


def change_current_block_style(current_block) :
    """ Change the style of the graphic """
    Figure out which graph the current graphic style belongs to
    current_block_style_list = None
    for block_style_list in [block_s, block_i, block_j, block_l, block_o, block_t, block_z]:
        if current_block in block_style_list:
            current_block_style_list = block_style_list

    # get the index (subscript) of the graph currently in use
    index = current_block_style_list.index(current_block)
    # index of its next graph
    index += 1
    # Prevent crossing boundaries
    index = index % len(current_block_style_list)
    # Return to the next graph
    return current_block_style_list[index]


def judge_move_right(current_block, current_block_start_col) :
    """ Determine if you can move to the right. """
    Columns are judged from right to left
    for col in range(len(current_block[0]) - 1, -1, -1) :Get all the elements of column 1
        col_list = [line[col] for line in current_block]
        Check if the right boundary is encountered
        if 'O' in col_list and current_block_start_col + col >= BLOCK_COL_NUM:
            return False
    return True


def judge_move_left(current_block, current_block_start_col) :
    """ Determine if you can move to the left. ""
    Columns are judged from left to right
    for col in range(len(current_block[0)) :Get all the elements of column 1
        col_list = [line[col] for line in current_block]
        Check if the right boundary is encountered
        if 'O' in col_list and current_block_start_col + col < 0:
            return False
    return True


def judge_move_down(current_block, current_block_start_row, current_block_start_col, stop_all_block_list) :
    "" determine whether to collide with other shapes or bottom boundaries. ""
    # Get all coordinates of other graphs
    stop_all_block_position = list(a)for row, line in enumerate(stop_all_block_list):
        for col, block in enumerate(line):
            ifblock ! =".":
                stop_all_block_position.append((row, col))
    # print(stop_all_block_position)

    # Determine collision
    for row, line in enumerate(current_block):
        if 'O' in line and current_block_start_row + row >= BLOCK_ROW_NUM:
            If the current row has 0 and counting from the starting row + the number of rows currently displayed exceeds the total number of rows, then the bottom is considered to be reached
            return False
        for col, block in enumerate(line):
            ifblock ! ="." and (current_block_start_row + row, current_block_start_col + col) in stop_all_block_position:
                return False

    return True


def get_block() :
    """
    创建一个图形
    """
    block_style_list = random.choice([block_s, block_i, block_j, block_l, block_o, block_t, block_z])
    return random.choice(block_style_list)


def main() :
    pygame.init()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption(tetris)

    current_block = get_block()  # current graphics
    current_block_start_row = -2  # Where does the current image start to display the graph
    current_block_start_col = 4  # From which column the current graph is displayed
    next_block = get_block()  # Next graphic
    last_time = time.time()
    speed = 0.5  # Speed of descent
    speed_info = '1'  # Display speed level

    # define a list of all shapes that have stopped moving
    stop_all_block_list = [['. ' for i in range(BLOCK_COL_NUM)] for j in range(BLOCK_ROW_NUM)]

    # font
    font = pygame.font.Font('yh.ttf'.24)  # blackbody 24
    game_over_font = pygame.font.Font("yh.ttf".72)
    game_over_font_width, game_over_font_height = game_over_font.size('GAME OVER')
    game_again_font_width, game_again_font_height = font.size('Mouse click anywhere, play again.')

    # score
    score = 0

    # Flag if the game is over
    game_over = False

    # Create timer (prevent while loop too fast, use too much CPU)
    clock = pygame.time.Clock()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    if judge_move_left(current_block, current_block_start_col - 1):
                        current_block_start_col -= 1
                elif event.key == pygame.K_RIGHT:
                    if judge_move_right(current_block, current_block_start_col + 1):
                        current_block_start_col += 1
                elif event.key == pygame.K_UP:
                    current_block_next_style = change_current_block_style(current_block)
                    if judge_move_left(current_block_next_style, current_block_start_col) and \
                            judge_move_right(current_block_next_style, current_block_start_col) and \
                            judge_move_down(current_block, current_block_start_row, current_block_start_col, stop_all_block_list):
                        # Determine if the new style does not cross the line
                        current_block = current_block_next_style
                elif event.key == pygame.K_DOWN:
                    # Determine whether you can move down, if you hit the bottom or other graphics can not move
                    if judge_move_down(current_block, current_block_start_row + 1, current_block_start_col, stop_all_block_list):
                        current_block_start_row += 1
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button:
                if game_over:
                    Reset the variables used in the game
                    current_block = get_block()  # current graphics
                    current_block_start_row = -2  # Where does the current image start to display the graph
                    current_block_start_col = 4  # From which column the current graph is displayed
                    next_block = get_block()  # Next graphic
                    stop_all_block_list = [['. ' for i in range(BLOCK_COL_NUM)] for j in range(BLOCK_ROW_NUM)]
                    score = 0
                    game_over = False

        Determine whether to modify the start line of the current graphic display
        if not game_over and time.time() - last_time > speed:
            last_time = time.time()
            # Determine whether you can move down, if you hit the bottom or other graphics can not move
            if judge_move_down(current_block, current_block_start_row + 1, current_block_start_col, stop_all_block_list):
                current_block_start_row += 1
            else:
                # Store the graph in a unified list so it is easy to determine if it is a row
                add_to_stop_all_block_list(stop_all_block_list, current_block, current_block_start_row, current_block_start_col)
                # check if there is a row in the same row, if so, eliminate it and add a fraction
                score += judge_lines(stop_all_block_list)
                # Determine if the game is over (if there is an O in the middle of the first line, the game is over)
                game_over = judge_game_over(stop_all_block_list)
                # Adjust speed
                speed_info, speed = change_speed(score)
                # Create a new graphic
                current_block = next_block
                next_block = get_block()
                # reset data
                current_block_start_col = 4
                current_block_start_row = -2

        # Paint background (Fill background color)
        screen.fill(BG_COLOR)

        # Draw a line dividing the game area
        pygame.draw.line(screen, (100.40.200), (SIZE * BLOCK_COL_NUM, 0), (SIZE * BLOCK_COL_NUM, SCREEN_HEIGHT), BORDER_WIDTH)

        # Display the current graphic
        for row, line in enumerate(current_block):
            for col, block in enumerate(line):
                ifblock ! ='. ':
                    pygame.draw.rect(screen, (20.128.200), ((current_block_start_col + col) * SIZE, (current_block_start_row + row) * SIZE, SIZE, SIZE), 0)

        # Show all graphics that have stopped moving
        for row, line in enumerate(stop_all_block_list):
            for col, block in enumerate(line):
                ifblock ! ='. ':
                    pygame.draw.rect(screen, (20.128.200), (col * SIZE, row * SIZE, SIZE, SIZE), 0)

        # Draw grid lines vertical lines
        for x in range(BLOCK_COL_NUM):
            pygame.draw.line(screen, (0.0.0), (x * SIZE, 0), (x * SIZE, SCREEN_HEIGHT), 1)
        # Draw grid lines across
        for y in range(BLOCK_ROW_NUM):
            pygame.draw.line(screen, (0.0.0), (0, y * SIZE), (BLOCK_COL_NUM * SIZE, y * SIZE), 1)

        # Display right side (score, speed, next line graphic)
        # score
        score_show_msg = font.render('Score:'.True, (255.255.255))
        screen.blit(score_show_msg, (BLOCK_COL_NUM * SIZE + 10.10))
        score_show_msg = font.render(str(score), True, (255.255.255))
        screen.blit(score_show_msg, (BLOCK_COL_NUM * SIZE + 10.50))
        # speed
        speed_show_msg = font.render('Speed:'.True, (255.255.255))
        screen.blit(speed_show_msg, (BLOCK_COL_NUM * SIZE + 10.100))
        speed_show_msg = font.render(speed_info, True, (255.255.255))
        screen.blit(speed_show_msg, (BLOCK_COL_NUM * SIZE + 10.150))
        # Next graphic (text prompt)
        next_style_msg = font.render('下一个: '.True, (255.255.255))
        screen.blit(next_style_msg, (BLOCK_COL_NUM * SIZE + 10.200))
        # Next graphic (graphic)
        for row, line in enumerate(next_block):
            for col, block in enumerate(line):
                ifblock ! ='. ':
                    pygame.draw.rect(screen, (20.128.200), (320 + SIZE * col, (BLOCK_COL_NUM + row) * SIZE, SIZE, SIZE), 0)
                    # Displays the color of the four sides of this grid
                    # left
                    pygame.draw.line(screen, (0.0.0), (320 + SIZE * col, (BLOCK_COL_NUM + row) * SIZE), (320 + SIZE * col, (BLOCK_COL_NUM + row + 1) * SIZE), 1)
                    On the #
                    pygame.draw.line(screen, (0.0.0), (320 + SIZE * col, (BLOCK_COL_NUM + row) * SIZE), (320 + SIZE * (col + 1), (BLOCK_COL_NUM + row) * SIZE), 1)
                    Under the #
                    pygame.draw.line(screen, (0.0.0), (320 + SIZE * col, (BLOCK_COL_NUM + row + 1) * SIZE), (320 + SIZE * (col + 1), (BLOCK_COL_NUM + row + 1) * SIZE), 1)
                    # right
                    pygame.draw.line(screen, (0.0.0), (320 + SIZE * (col + 1), (BLOCK_COL_NUM + row) * SIZE), (320 + SIZE * (col + 1), (BLOCK_COL_NUM + row + 1) * SIZE), 1)

        # Display the end of the game screen
        if game_over:
            game_over_tips = game_over_font.render('GAME OVER'.True, RED)
            screen.blit(game_over_tips, ((SCREEN_WIDTH - game_over_font_width) // 2, (SCREEN_HEIGHT - game_over_font_height) // 2))
            # display "Mouse click anywhere, play again"
            game_again = font.render('Mouse click anywhere, play again.'.True, RED)
            screen.blit(game_again, ((SCREEN_WIDTH - game_again_font_width) // 2, (SCREEN_HEIGHT - game_again_font_height) // 2 + 80))

        # refresh the display (at which point the window will actually display)
        pygame.display.update()
        # FPS (number of frames displayed per second)
        clock.tick(60)  # Through a certain delay, to achieve 1 second can cycle 60 times


if __name__ == '__main__':
    main()
Copy the code

The code for file blocks. Py is as follows:

# s-shaped block
block_s = [['.OO'.'OO.'.'... '],
           ['O.. '.'OO.'.'.O.']]
# Z square
block_z = [['OO.'.'.OO'.'... '],
           ['.O.'.'OO.'.'O.. ']]
# i-block
block_i = [['.O.. '.'.O.. '.'.O.. '.'.O.. '],
           ['....'.'....'.'OOOO'.'....']]
# O-block
block_o = [['OO'.'OO']]
# J-block
block_j = [['O.. '.'OOO'.'... '],
           ['.OO'.'.O.'.'.O.'],
           ['... '.'OOO'.'.. O'],
           ['.O.'.'.O.'.'OO.']]
# L-shaped block
block_l = [['.. O'.'OOO'.'... '],
           ['.O.'.'.O.'.'.OO'],
           ['... '.'OOO'.'O.. '],
           ['OO.'.'.O.'.'.O.']]
# T-block
block_t = [['.O.'.'OOO'.'... '],
           ['.O.'.'.OO'.'.O.'],
           ['... '.'OOO'.'.O.'],
           ['.O.'.'OO.'.'.O.']]
Copy the code