(三)、python程序--俄罗斯方块游戏

一、绪论

1、采用pygame模块写的游戏界面;

2、左右移动,上变形;

3、一行叠满消除;

二、代码分享

1、main.py

import pygame
import sys
import shape as c_shape


def game_over():
    pygame.quit()
    sys.exit()


def game_start():
    window_title = 'tetris'
    window_size = (300, 640)
    grid_num = (15, 32)  # 15列,32行
    grid_size = (20, 20)

    pygame.init()
    pg_clock = pygame.time.Clock()

    main_window = pygame.display.set_mode(window_size)
    pygame.display.set_caption(window_title)

    SHAPE = c_shape.SHAPE(grid_num)

    while True:

        for event in pygame.event.get():

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    SHAPE.rota_shape()
                elif event.key == pygame.K_DOWN:
                    pass
                elif event.key == pygame.K_LEFT:
                    SHAPE.move_step('left')
                elif event.key == pygame.K_RIGHT:
                    SHAPE.move_step('right')

            elif event.type == pygame.QUIT:
                game_over()

        SHAPE.move_step('down')

        main_window.fill((0, 0, 0))
        SHAPE.draw_shape(main_window, grid_size, )
        pygame.display.update()
        pg_clock.tick(3)


if __name__ == '__main__':
    game_start()

2、shape.py

import numpy as np
import pygame


class SHAPE(object):

    def __init__(self, grid_num):
        self.npl = grid_num[0]  # 列数
        self.nph = grid_num[1]  # 行数
        self.grid_np = np.zeros((self.nph, self.npl), dtype='int8')

        self.shape_np = np.array([[[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1],  #oooo
                                  [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 4],
                                  [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1],
                                  [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 4]],

                                 [[1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2],  #oo
                                  [1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2],  #oo
                                  [1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2],
                                  [1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2]],

                                  [[0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2],  # o
                                   [1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 3],  #ooo
                                   [1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2],
                                   [0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 3]],

                                  [[1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2],  # oo
                                   [0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 3],  #  oo
                                   [1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2],
                                   [0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 3]],

                                  [[0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2],  #  oo
                                   [1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 3],  # oo
                                   [0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2],
                                   [1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 3]],

                                  [[1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2],  # ooo
                                   [1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 3],  # o
                                   [0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2],
                                   [1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 2, 3]],

                                  [[1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2],  # ooo
                                   [0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 2, 3],  #   o
                                   [1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2],
                                   [1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 3]]
                                  ], dtype='int8')
        self.shape_vertex = [int(self.npl/2), 0]          # 列、行
        self.shape_type_num = self.shape_np.shape[0]
        self.shape_rota_num = self.shape_np.shape[1]
        self.shape_type_index = np.random.randint(0, self.shape_type_num)
        self.shape_rota_index = np.random.randint(0, self.shape_rota_num)

        self.shape_color = pygame.Color(145, 145, 145)
        self.grid_color = pygame.Color(255, 255, 255)

    def reset_shape(self):
        """重置形状"""
        self.grid_np = np.zeros((self.nph, self.npl))
        self.shape_vertex = [int(self.npl / 2), 0]
        self.shape_type_index = np.random.randint(0, self.shape_type_num)
        self.shape_rota_index = np.random.randint(0, self.shape_rota_num)

    def chiose_shape(self):
        """选择形状,如果一出来就撞到其它,说明游戏结束"""
        self.shape_vertex = [int(self.npl / 2), 0]
        self.shape_type_index = np.random.randint(0, self.shape_type_num)
        self.shape_rota_index = np.random.randint(0, self.shape_rota_num)
        if self.check_hill_other(self.shape_vertex[0], self.shape_vertex[1]) == 1:
            self.reset_shape()

    def rota_shape(self):
        """转动形状"""
        # 转动序号加一.不能大于等于4,需要回到0
        self.shape_rota_index += 1
        if self.shape_rota_index == 4:
            self.shape_rota_index = 0
        # 如果旋转会撞到墙或者撞到其它方块,则不旋转
        if self.check_hill_wo(self.shape_vertex[0]) == 1:
            self.shape_rota_index -= 1

    def move_step(self, action):
        """往下掉、左边、右边一步"""
        l, h = self.shape_vertex
        if action == 'down':
            if self.check_hill_bo(h+1) == 0:
                h += 1
            else:
                self.merge_shape_grid()
                self.cut_h()
                self.chiose_shape()
                return
        elif action == 'right':
            if self.check_hill_wo(l+1) == 0:
                l += 1
        elif action == 'left':
            if self.check_hill_wo(l-1) == 0:
                l -= 1
        self.shape_vertex = [l, h]

    def check_hill_other(self, l, h):
        #  hill the other
        shape_data = self.shape_np[self.shape_type_index][self.shape_rota_index]
        shape_data = shape_data[0:-2].reshape((4, 4))
        x = np.where(shape_data == 1)[0] + h
        y = np.where(shape_data == 1)[1] + l
        if np.max(x) >= self.nph:
            return 1
        if np.sum(self.grid_np[x, y]) >= 1:
            return 1
        else:
            return 0

    def check_hill_wo(self, l):
        """检查是否左右撞墙"""
        # hill the wall
        sl = self.shape_np[self.shape_type_index][self.shape_rota_index][-2]
        if l < 0 or (l + sl) > self.npl:
            return 1
        # hill other
        else:
            return self.check_hill_other(l, self.shape_vertex[1])

    def check_hill_bo(self, h):
        """检查是否撞到底部的东西,需要合并"""
        # hill the bottom
        sh = self.shape_np[self.shape_type_index][self.shape_rota_index][-1]
        if (h + sh) > self.nph:
            print('hill the bottom')
            return 1
        # hill other
        else:
            return self.check_hill_other(self.shape_vertex[0], h)

    def merge_shape_grid(self):
        """合并形状和棋盘"""
        shape_data = self.shape_np[self.shape_type_index][self.shape_rota_index]
        shape_data = shape_data[0:-2].reshape((4, 4))
        x = np.where(shape_data == 1)[0] + self.shape_vertex[1]
        y = np.where(shape_data == 1)[1] + self.shape_vertex[0]
        self.grid_np[x, y] = 1

    def cut_h(self):
        """一行满,则该行消失"""
        sum = np.sum(self.grid_np, axis=1)
        cut_position = np.where(sum == self.npl)
        if len(cut_position[0]) > 0:
            for index in cut_position[0]:
                self.grid_np = np.delete(self.grid_np, index, axis=0)
                self.grid_np = np.insert(self.grid_np, 0, np.zeros(self.npl), axis=0)

    def draw_shape(self, window, grid_size):
        """画形状和棋盘"""
        # 画
        for zl in range(self.npl):
            for zh in range(self.nph):
                if self.grid_np[zh][zl] == 1:
                    x = zl * grid_size[0]
                    y = zh * grid_size[1]
                    rec = (x+1, y+1, grid_size[0]-2, grid_size[1]-2)
                    pygame.draw.rect(window, self.grid_color, rec)
        # 画
        shape_data = self.shape_np[self.shape_type_index][self.shape_rota_index]
        for index, data in enumerate(shape_data):
            if index <= 15 and data == 1:
                x = ((index % 4) + self.shape_vertex[0]) * grid_size[0]  # 列
                y = (int(index / 4) + self.shape_vertex[1]) * grid_size[1]
                rec = (x+1, y+1, grid_size[0]-2, grid_size[1]-2)
                pygame.draw.rect(window, self.shape_color, rec)

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的俄罗斯方块 Python 程序示例,使用 Pygame 模块实现: ```python import pygame import random # 定义方块的形状及颜色 block_shapes = [ [[1, 1, 1], [0, 1, 0]], [[0, 2, 2], [2, 2, 0]], [[3, 3, 0], [0, 3, 3]], [[4, 0, 0], [4, 4, 4]], [[0, 0, 5], [5, 5, 5]], [[6, 6, 6, 6]], [[7, 7], [7, 7]] ] block_colors = [ (255, 0, 0), # 红色 (0, 255, 0), # 绿色 (0, 0, 255), # 蓝色 (255, 255, 0), # 黄色 (0, 255, 255), # 青色 (255, 0, 255), # 紫色 (255, 255, 255) # 白色 ] # 初始化 Pygame pygame.init() # 定义游戏窗口 screen_width = 800 screen_height = 600 screen = pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption("俄罗斯方块") # 定义游戏参数 block_size = 30 board_width = 10 board_height = 20 board_top = 50 board_left = (screen_width - block_size * board_width) // 2 fps = 30 score = 0 # 定义游戏区域 board = [[0] * board_width for i in range(board_height)] # 绘制游戏区域 def draw_board(): for i in range(board_height): for j in range(board_width): if board[i][j] > 0: pygame.draw.rect(screen, block_colors[board[i][j] - 1], (board_left + j * block_size, board_top + i * block_size, block_size, block_size), 0) pygame.draw.rect(screen, (255, 255, 255), (board_left + j * block_size, board_top + i * block_size, block_size, block_size), 1) # 绘制方块 def draw_block(block, x, y): for i in range(len(block)): for j in range(len(block[i])): if block[i][j] > 0: pygame.draw.rect(screen, block_colors[block[i][j] - 1], (board_left + (x + j) * block_size, board_top + (y + i) * block_size, block_size, block_size), 0) pygame.draw.rect(screen, (255, 255, 255), (board_left + (x + j) * block_size, board_top + (y + i) * block_size, block_size, block_size), 1) # 判断方块是否越界或与已有方块重叠 def is_valid_position(block, x, y): for i in range(len(block)): for j in range(len(block[i])): if block[i][j] > 0: if x + j < 0 or x + j >= board_width or y + i < 0 or y + i >= board_height or board[y + i][x + j] > 0: return False return True # 随机生成一个方块 def get_random_block(): shape = random.choice(block_shapes) block = [] for i in range(len(shape)): row = [] for j in range(len(shape[i])): if shape[i][j] > 0: row.append(len(block_colors)) else: row.append(0) block.append(row) return block # 将方块加入游戏区域 def add_block_to_board(block, x, y): for i in range(len(block)): for j in range(len(block[i])): if block[i][j] > 0: board[y + i][x + j] = block[i][j] # 消除整行 def remove_complete_lines(): global score num_lines_removed = 0 i = board_height - 1 while i >= 0: if all(board[i]): for j in range(i, 0, -1): for k in range(board_width): board[j][k] = board[j - 1][k] for k in range(board_width): board[0][k] = 0 num_lines_removed += 1 score += 10 else: i -= 1 return num_lines_removed # 绘制得分 def draw_score(): font = pygame.font.Font(None, 36) text = font.render("Score: " + str(score), 1, (255, 255, 255)) screen.blit(text, (10, 10)) # 主函数 def main(): global score clock = pygame.time.Clock() # 随机生成第一个方块 current_block = get_random_block() current_x = board_width // 2 - len(current_block[0]) // 2 current_y = -len(current_block) next_block = get_random_block() while True: # 处理游戏事件 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: if is_valid_position(current_block, current_x - 1, current_y): current_x -= 1 elif event.key == pygame.K_RIGHT: if is_valid_position(current_block, current_x + 1, current_y): current_x += 1 elif event.key == pygame.K_UP: rotated_block = [[current_block[j][i] for j in range(len(current_block))] for i in range(len(current_block[0]) - 1, -1, -1)] if is_valid_position(rotated_block, current_x, current_y): current_block = rotated_block elif event.key == pygame.K_DOWN: if is_valid_position(current_block, current_x, current_y + 1): current_y += 1 # 绘制游戏界面 screen.fill((0, 0, 0)) draw_board() draw_block(current_block, current_x, current_y) draw_score() # 移动方块 if is_valid_position(current_block, current_x, current_y + 1): current_y += 1 else: add_block_to_board(current_block, current_x, current_y) num_lines_removed = remove_complete_lines() score += num_lines_removed ** 2 current_block = next_block current_x = board_width // 2 - len(current_block[0]) // 2 current_y = -len(current_block) next_block = get_random_block() if not is_valid_position(current_block, current_x, current_y): pygame.quit() quit() # 更新屏幕 pygame.display.update() # 控制帧率 clock.tick(fps) # 启动程序 if __name__ == '__main__': main() ``` 这个程序实现了一个基本的俄罗斯方块游戏,玩家可以通过方向键控制方块的移动和旋转,将方块放置在游戏区域中,消除整行并得分。程序中使用 Pygame 模块实现了游戏窗口、方块和游戏区域的绘制,以及方块的移动、旋转和放置等游戏逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值