欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > 【Python】用Python写一个俄罗斯方块玩玩

【Python】用Python写一个俄罗斯方块玩玩

2025/4/24 15:18:34 来源:https://blog.csdn.net/weixin_41613094/article/details/147305593  浏览:    关键词:【Python】用Python写一个俄罗斯方块玩玩

【Python】用Python写一个俄罗斯方块玩玩

  • 一、引言
    • 1.成品效果展示
  • 二、思考准备
    • 1.思考设计
    • 2.代码设计
      • 2.1 游戏页面
      • 2.2 控件设计
        • 2.2.1 方块生成
        • 2.2.2 方块碰撞
        • 2.2.3 方块消融
        • 2.2.4 游戏主循环
        • 2.2.5 游戏窗口
  • 三、游戏完整版

一、引言

  • 今日看到侄子在玩游戏,凑近一看,原来是俄罗斯方块。熟悉又怀念,童年的记忆瞬间涌上心头。小时候觉得这游戏老厉害了,现在想想,好像就是数组的组合和消融,便想着自己写一个试试。说干就干,冲!

1.成品效果展示

俄罗斯方块实现过程

二、思考准备

1.思考设计

在这里插入图片描述

  • 俄罗斯方块作为风靡一时的游戏,由俄罗斯人阿列克谢·帕基特诺夫于1984年6月发明的休闲游戏,主要是通过方块的组合、消融完成的;
  • 所以得先设计有哪些方块、方块如何组合、完成一行时方块消融并下降一行、方块组合还得回旋转,单次90°等等,考虑中ing…

2.代码设计

2.1 游戏页面

  • 游戏首先得有个操控页面,所以得设计一个
# 设计游戏窗口尺寸
SCREEN_WIDTH, SCREEN_HEIGHT = 300, 600  
# 方块大小
GRID_SIZE = 30     
# 各种图形颜色 可自定义调整                    
COLORS = [            # 颜色配置(含背景色+7种方块色)(0, 0, 0),        # 0: 黑色背景(255, 0, 0),      # 1: 红色-I型(0, 255, 0),      # 2: 绿色-T型(0, 0, 255),      # 3: 蓝色-J型(255, 165, 0),    # 4: 橙色-L型(255, 255, 0),    # 5: 黄色-O型(128, 0, 128),    # 6: 紫色-S型(0, 255, 255)     # 7: 青色-Z型
]

2.2 控件设计

2.2.1 方块生成
  • 游戏开始最上方会有方块掉落,随机形状和颜色

def new_piece(self):"""生成新方块,随机形状和颜色"""shape = random.choice(SHAPES)return {'shape': shape,                                        # 方块形状矩阵'x': (SCREEN_WIDTH//GRID_SIZE - len(shape[0])) // 2,   # 初始水平居中'y': 0,                                                # 初始垂直位置'color': random.randint(1, len(COLORS)-1)              # 随机颜色(排除背景色)}
2.2.2 方块碰撞
  • 方块会一直下降,碰撞,下降时还要符合可以多次旋转

def check_collision(self, dx=0, dy=0, rotate=False):"""碰撞检测函数:param dx: 水平移动偏移量:param dy: 垂直移动偏移量:param rotate: 是否正在旋转:return: 是否发生碰撞"""shape = self.current_piece['shape']# 旋转时生成临时形状if rotate:         shape = [list(row[::-1]) for row in zip(*shape)]  # 矩阵旋转算法:先转置再反转每行(顺时针90度)for y, row in enumerate(shape):for x, cell in enumerate(row):if cell:                        # 仅检测实体方块new_x = self.current_piece['x'] + x + dxnew_y = self.current_piece['y'] + y + dy# 边界检测(左右越界/触底/与其他方块重叠)if not (0 <= new_x < len(self.grid[0])) or new_y >= len(self.grid):return Trueif new_y >=0 and self.grid[new_y][new_x]:return Truereturn False
2.2.3 方块消融
  • 方块接触时,合适的会消融、不合适的会叠加,消融了计算分数,消融的还要剔除
def merge_piece(self):"""将当前方块合并到游戏网格,并触发消行检测"""for y, row in enumerate(self.current_piece['shape']):for x, cell in enumerate(row):if cell:# 将方块颜色写入网格对应位置self.grid[self.current_piece['y']+y][self.current_piece['x']+x] = self.current_piece['color']# 消行并更新分数lines = self.clear_lines()self.score += lines * 100def clear_lines(self):"""消除满行并返回消除行数"""lines = 0# 从底部向上扫描for i, row in enumerate(self.grid):if all(cell !=0 for cell in row):       # 检测整行填满del self.grid[i]                    # 删除该行self.grid.insert(0, [0]*len(row))   # 在顶部插入新空行lines +=1return lines
2.2.4 游戏主循环
  • 游戏主体逻辑写入,方块的处理时间、操作事项和刷新等

def run(self):"""游戏主循环"""fall_time = 0       # 下落时间累计器while True:self.screen.fill(COLORS[0])            # 用背景色清屏# 计时系统(控制自动下落速度)fall_time += self.clock.get_rawtime()self.clock.tick()        # 保持帧率稳定# 自动下落逻辑(每800ms下落一格)if fall_time >= 800:if not self.check_collision(dy=1):self.current_piece['y'] +=1                 # 正常下落else:self.merge_piece()                          # 触底合并self.current_piece = self.new_piece()       # 生成新方块# 游戏结束检测(新方块无法放置)if self.check_collision():print("Game Over 你完蛋啦! Score:", self.score)returnfall_time =0   # 重置计时器# 事件处理(适配Mac键盘布局)for event in pygame.event.get():if event.type == QUIT:pygame.quit()returnif event.type == KEYDOWN:# 左右移动(带碰撞检测)if event.key == K_LEFT and not self.check_collision(dx=-1):self.current_piece['x'] -=1elif event.key == K_RIGHT and not self.check_collision(dx=1):self.current_piece['x'] +=1# 软下落(手动加速)elif event.key == K_DOWN:if not self.check_collision(dy=1):self.current_piece['y'] +=1# 旋转方块(带碰撞检测)elif event.key == K_UP and not self.check_collision(rotate=True):self.current_piece['shape'] = [list(row[::-1]) for row in zip(*self.current_piece['shape'])]# 硬下落(空格键一键到底)    elif event.key == K_SPACE:  while not self.check_collision(dy=1):self.current_piece['y'] +=1# 绘制逻辑,游戏网格for y, row in enumerate(self.grid):for x, color in enumerate(row):if color:# 绘制已落下方块(留1像素间隙)pygame.draw.rect(self.screen, COLORS[color], (x*GRID_SIZE, y*GRID_SIZE, GRID_SIZE-1, GRID_SIZE-1))# 绘制当前操作方块for y, row in enumerate(self.current_piece['shape']):for x, cell in enumerate(row):if cell:pygame.draw.rect(self.screen, COLORS[self.current_piece['color']],((self.current_piece['x']+x)*GRID_SIZE, (self.current_piece['y']+y)*GRID_SIZE, GRID_SIZE-1, GRID_SIZE-1))# 刷新画面pygame.display.flip()  
2.2.5 游戏窗口
  • 最后,游戏设计好了,必须有个游戏窗口来展示

def __init__(self):# 初始化游戏窗口self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))pygame.display.set_caption("Mac M1俄罗斯方块")self.clock = pygame.time.Clock()   # 游戏时钟控制帧率# 游戏状态初始化self.grid = [[0]*(SCREEN_WIDTH//GRID_SIZE) for _ in range(SCREEN_HEIGHT//GRID_SIZE)]              # 20x10游戏网格self.current_piece = self.new_piece()     # 当前操作方块self.score = 0                           

三、游戏完整版


# 俄罗斯方块设计
# -*- coding: utf-8 -*-  
"""
功能:俄罗斯方块,童年的回忆
作者:看海的四叔
最后更新:2025-04-16
"""import pygame
import random
from pygame.locals import *# 初始化配置
pygame.init()                           
SCREEN_WIDTH, SCREEN_HEIGHT = 300, 600  
GRID_SIZE = 30                          
COLORS = [            (0, 0, 0),        (255, 0, 0),      (0, 255, 0),      (0, 0, 255),      (255, 165, 0),    (255, 255, 0),    (128, 0, 128),    (0, 255, 255)     
]SHAPES = [[[1,1,1,1]],                [[1,1],[1,1]],              [[0,1,0], [1,1,1]],         [[1,1,1], [1,0,0]],         [[1,1,1], [0,0,1]],         [[0,1,1], [1,1,0]],         [[1,1,0], [0,1,1]]          
]class Tetris:"""游戏主控制类,处理游戏逻辑与渲染"""def __init__(self):self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))pygame.display.set_caption("Mac M1俄罗斯方块")self.clock = pygame.time.Clock()  self.grid = [[0]*(SCREEN_WIDTH//GRID_SIZE) for _ in range(SCREEN_HEIGHT//GRID_SIZE)] self.current_piece = self.new_piece()    self.score = 0                           def new_piece(self):"""生成新方块(随机形状和颜色)"""shape = random.choice(SHAPES)return {'shape': shape,                                        'x': (SCREEN_WIDTH//GRID_SIZE - len(shape[0])) // 2,   'y': 0,                                                'color': random.randint(1, len(COLORS)-1)              }def check_collision(self, dx=0, dy=0, rotate=False):"""碰撞检测函数:param dx: 水平移动偏移量:param dy: 垂直移动偏移量:param rotate: 是否正在旋转:return: 是否发生碰撞"""shape = self.current_piece['shape']if rotate:         shape = [list(row[::-1]) for row in zip(*shape)]  for y, row in enumerate(shape):for x, cell in enumerate(row):if cell:                       new_x = self.current_piece['x'] + x + dxnew_y = self.current_piece['y'] + y + dyif not (0 <= new_x < len(self.grid[0])) or new_y >= len(self.grid):return Trueif new_y >=0 and self.grid[new_y][new_x]:return Truereturn Falsedef merge_piece(self):"""将当前方块合并到游戏网格,并触发消行检测"""for y, row in enumerate(self.current_piece['shape']):for x, cell in enumerate(row):if cell:self.grid[self.current_piece['y']+y][self.current_piece['x']+x] = self.current_piece['color']lines = self.clear_lines()self.score += lines * 100def clear_lines(self):"""消除满行并返回消除行数"""lines = 0for i, row in enumerate(self.grid):if all(cell !=0 for cell in row):       del self.grid[i]                    self.grid.insert(0, [0]*len(row))   lines +=1return linesdef run(self):"""游戏主循环"""fall_time = 0      while True:self.screen.fill(COLORS[0])           fall_time += self.clock.get_rawtime()self.clock.tick()       if fall_time >= 800:if not self.check_collision(dy=1):self.current_piece['y'] +=1                 # 正常下落else:self.merge_piece()                          self.current_piece = self.new_piece()       # 游戏结束检测(新方块无法放置)if self.check_collision():print("Game Over 你完蛋啦! Score:", self.score)returnfall_time =0   # 重置计时器for event in pygame.event.get():if event.type == QUIT:pygame.quit()returnif event.type == KEYDOWN:if event.key == K_LEFT and not self.check_collision(dx=-1):self.current_piece['x'] -=1elif event.key == K_RIGHT and not self.check_collision(dx=1):self.current_piece['x'] +=1elif event.key == K_DOWN:if not self.check_collision(dy=1):self.current_piece['y'] +=1elif event.key == K_UP and not self.check_collision(rotate=True):self.current_piece['shape'] = [list(row[::-1]) for row in zip(*self.current_piece['shape'])]elif event.key == K_SPACE:  while not self.check_collision(dy=1):self.current_piece['y'] +=1for y, row in enumerate(self.grid):for x, color in enumerate(row):if color:pygame.draw.rect(self.screen, COLORS[color], (x*GRID_SIZE, y*GRID_SIZE, GRID_SIZE-1, GRID_SIZE-1))for y, row in enumerate(self.current_piece['shape']):for x, cell in enumerate(row):if cell:pygame.draw.rect(self.screen, COLORS[self.current_piece['color']],((self.current_piece['x']+x)*GRID_SIZE, (self.current_piece['y']+y)*GRID_SIZE, GRID_SIZE-1, GRID_SIZE-1))pygame.display.flip()  if __name__ == "__main__":game = Tetris()game.run()

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词