三、生成随机方块,Python基于thinker实现的简单的俄罗斯方块小游戏

article/2025/8/21 5:53:25

文章目录

  • 生成
    • 第一步:随机生成方块对象
    • 第二步:修改游戏运行方法
  • 固定
    • 第一步:记录固定的方块
    • 第二步:修改check_move方法
  • 左右移动
    • 第一步:左右移动方块
    • 第二步:绑定键盘
  • 旋转
    • 第一步:添加旋转方法
    • 第二步:添加加速到底方法
    • 第三步:绑定键盘

生成

**功能:**每次运行都随机生成一个方块

思路分析:

基本逻辑:随机生成一个方块对象 >> 绘制方块对象 >> 移动方块对象

第一步:随机生成方块对象

首先我们需要删除原来的位于game_loop方法上面的a_block = … 和*draw_block_move(canvas, a_block)*这2行代码(这两行代码俄罗斯方块是在固定位置,按照指定形状生成的,需要删掉这部分代码)

然后再在原来的这2行代码所在位置,添加一个随机生成俄罗斯方块的方法generate_new_block

def generate_new_block():# 随机生成新的俄罗斯方块kind = random.choice(list(SHAPES.keys()))# 对应横纵坐标,以左上角为原点,水平向右为x轴正方向,# 竖直向下为y轴正方向,x对应横坐标,y对应纵坐标cr = [C // 2, 0]new_block = {'kind': kind,  # 对应俄罗斯方块的类型'cell_list': SHAPES[kind],'cr': cr}return new_block

第二步:修改游戏运行方法

再将游戏运行方法game_loop修改成如下:

其中,将当前的俄罗斯方块对象通过全局变量来存储,

并在game_loop方法下面设置初始的俄罗斯方块为空(None)

此时每次运行代码都会发现生成了随机的俄罗斯方块

def game_loop():win.update()global current_blockif current_block is None:new_block = generate_new_block()# 新生成的俄罗斯方块需要先在生成位置绘制出来draw_block_move(canvas, new_block)current_block = new_blockelse:draw_block_move(canvas, current_block, [0, 1])win.after(FPS, game_loop)current_block = None

运行结果如下:

image-20230208171120035

当然,此时还有问题没有解决,就是俄罗斯方块生成后,会一直往下移动,就算出了可视范围还是会往下移动(只是这时再也看不到了)。

所以接下来我们要实现的是:当俄罗斯方块落地的时候,将它固定住,然后再去生成新的

固定

**功能:**落到底部的方块固定住不动

思路分析:

判断俄罗斯方块落地的原则是,该方块是否可以继续向下移动

这里我们首先需要的是一个方法check_move需要判断俄罗斯方块是否可以向指定位置移动

def check_move(block, direction=[0, 0]):"""判断俄罗斯方块是否可以朝制定方向移动:param block: 俄罗斯方块对象:param direction: 俄罗斯方块移动方向:return: boolean 是否可以朝制定方向移动"""cc, cr = block['cr']cell_list = block['cell_list']for cell in cell_list:cell_c, cell_r = cellc = cell_c + cc + direction[0]r = cell_r + cr + direction[1]# 判断该位置是否超出左右边界,以及下边界# 一般不判断上边界,因为俄罗斯方块生成的时候,可能有一部分在上边界之上还没有出来if c < 0 or c >= C or r >= R:return Falsereturn True

再将游戏运行方法game_loop修改成如下,便可以每次俄罗斯方块落地后都会生成新的

def game_loop():win.update()global current_blockif current_block is None:new_block = generate_new_block()# 新生成的俄罗斯方块需要先在生成位置绘制出来draw_block_move(canvas, new_block)current_block = new_blockelse:if check_move(current_block, [0, 1]):draw_block_move(canvas, current_block, [0, 1])else:current_block = Nonewin.after(FPS, game_loop)

运行结果如下:

图片

此时仍然有个问题:就是老的俄罗斯方块会被新的落地的俄罗斯方块覆盖,这个需要处理

思路分析:

当俄罗斯方块发现下面有已固定的俄罗斯方块时,也不能移动

当俄罗斯方块发现下面有已固定的俄罗斯方块时,也不能移动首先

解决方案:

第一步:记录固定的方块

我们需要添加一个变量block_list来记录已固定的俄罗斯方块

在原代码draw_blank_board(canvas)的位置的下面,添加如下代码

block_list = []
for i in range(R):i_row = ['' for j in range(C)]block_list.append(i_row)

然后再在固定俄罗斯方块的时候记录进去,所以

  • 一要添加一个save_block_to_list方法,将无法移动的俄罗斯方块记录进去
  • 二要修改game_loop
def save_block_to_list(block):shape_type = block['kind']cc, cr = block['cr']cell_list = block['cell_list']for cell in cell_list:cell_c, cell_r = cellc = cell_c + ccr = cell_r + cr# block_list 在对应位置记下其类型block_list[r][c] = shape_typedef game_loop():win.update()global current_blockif current_block is None:new_block = generate_new_block()# 新生成的俄罗斯方块需要先在生成位置绘制出来draw_block_move(canvas, new_block)current_block = new_blockelse:if check_move(current_block, [0, 1]):draw_block_move(canvas, current_block, [0, 1])else:# 无法移动,记入 block_list 中save_block_to_list(current_block)current_block = Nonewin.after(FPS, game_loop)

第二步:修改check_move方法

然后还要再修改原来的check_move方法,就是发现下面有已固定的俄罗斯方块时,也不能移动,具体如下

def check_move(block, direction=[0, 0]):"""判断俄罗斯方块是否可以朝制定方向移动:param block: 俄罗斯方块对象:param direction: 俄罗斯方块移动方向:return: boolean 是否可以朝制定方向移动"""cc, cr = block['cr']cell_list = block['cell_list']for cell in cell_list:cell_c, cell_r = cellc = cell_c + cc + direction[0]r = cell_r + cr + direction[1]# 判断该位置是否超出左右边界,以及下边界# 一般不判断上边界,因为俄罗斯方块生成的时候,可能有一部分在上边界之上还没有出来if c < 0 or c >= C or r >= R:return False# 必须要判断r不小于0才行,具体原因你可以不加这个判断,试试会出现什么效果if r >= 0 and block_list[r][c]:return Falsereturn True

运行结果如下:

图片

左右移动

**功能:**左右移动方块

思路分析:

我们需要新建一个左右移动俄罗斯方块的方法horizontal_move_block,其中的参数event对应键鼠事件

在save_block_to_list方法下面添加horizontal_move_block方法的代码如下:

第一步:左右移动方块

def horizontal_move_block(event):"""左右水平移动俄罗斯方块"""direction = [0, 0]if event.keysym == 'Left':direction = [-1, 0]elif event.keysym == 'Right':direction = [1, 0]else:returnglobal current_blockif current_block is not None and check_move(current_block, direction):draw_block_move(canvas, current_block, direction)

第二步:绑定键盘

canvas.focus_set() # 聚焦到canvas画板对象上
canvas.bind("<KeyPress-Left>", horizontal_move_block)
canvas.bind("<KeyPress-Right>", horizontal_move_block)

现在可以左右移动方块了

旋转

**功能:**按下键盘⬆️表示顺时针旋转90度;按下键盘⬇️表示方块加速到底

思路分析:

第一步:添加旋转方法

def rotate_block(event):"""该函数用于实现方块旋转,当current_block有值时,遍历其cell_list,将每个cell顺时针旋转90度,放入rotate_list中,新生成旋转后的block,并判断是否超出边界,如果不超出边界,把新block覆盖原来的block。"""global current_blockif current_block is None:returncell_list = current_block['cell_list']rotate_list = []for cell in cell_list:cell_c, cell_r = cellrotate_cell = [cell_r, -cell_c]rotate_list.append(rotate_cell)block_after_rotate = {'kind': current_block['kind'],  # 对应俄罗斯方块的类型'cell_list': rotate_list,'cr': current_block['cr']}if check_move(block_after_rotate):cc, cr= current_block['cr']draw_cells(canvas, cc, cr, current_block['cell_list'])draw_cells(canvas, cc, cr, rotate_list,SHAPESCOLOR[current_block['kind']])current_block = block_after_rotate

第二步:添加加速到底方法

def land(event):"""该函数的功能是让当前正在运行的方块移动到最低的可能高度。它遍历当前块所有单元格的位置,然后找出方块单元格距离下面块的最小高度,并将其保存到min_height中,最后调用check_move函数以及draw_block_move函数来处理并将方块移动到最低的可能高度。"""global current_blockif current_block is None:returncell_list = current_block['cell_list']cc, cr = current_block['cr']min_height = Rfor cell in cell_list:cell_c, cell_r = cellc, r = cell_c + cc, cell_r + crif r>=0 and block_list[r][c]:returnh = 0for ri in range(r+1, R):if block_list[ri][c]:breakelse:h += 1if h < min_height:min_height = hdown = [0, min_height]if check_move(current_block, down):draw_block_move(canvas, current_block, down)

第三步:绑定键盘

canvas.bind("<KeyPress-Up>", rotate_block)
canvas.bind("<KeyPress-Down>", land)

运行结果如下:

image-20230208232322856

完整代码下载地址:Python基于thinker实现的简单的俄罗斯方块小游戏源代码


http://chatgpt.dhexx.cn/article/1iKQF9uw.shtml

相关文章

【G-thinker】G-thinker部分源码解析

一、main 子图匹配程序run.cpp中主要使用到worker.h和comper.h分别对应线程和进程单位&#xff0c;接下来我们从main函数入手解析源码 从主函数可以看到&#xff0c;子图匹配程序中GMatchWorker继承了worker&#xff0c;主函数声明了workerparams并且传入了路径和线程参数&am…

python用thinker库制作一个进制转换器(可打包exe)

进制类型分为&#xff1a; 二进制 字母B表示 八进制 字母O表示 十进制 字母D表示 十六机制 字母H表示 进制转换之间很麻烦&#xff0c;还得计算&#xff0c;如果可以做一个进制转换器多nice&#xff0c;其实也不难&#xff0c;就利用一个tkinter库就能制作&#xff0c;废话不多…

Thinker Board 2开发板上使用奥比中光 astra 深度相机

Thinker Board 2 国产开发板 arm架构 上使用奥比中光 astra 深度相机 准备工作 1、下载astraSDK 选择linux_arm 下载 https://developer.orbbec.com.cn/download.html?id53 2、下载openNI https://dl.orbbec3d.com/dist/openni2/OpenNI_2.3.0.66.zip 开始安装 1、安装fre…

think

我167&#xff0c;97斤&#xff0c;胸d&#xff0c;腰很细&#xff0c;反手轻松摸肚脐那种&#xff0c;骨架小&#xff0c;总结就是身高刚好人瘦胸大屁股大腿细腰细肤白。走路腰杆能挺到天上&#xff0c;气质挺好。漂亮女生太多了&#xff0c;想取胜只能从气质下手了。脸呢&…

Python基于thinker实现的简单的俄罗斯方块小游戏源代码:一、搭建界面

文章目录 一、搭建界面搭建基础窗体第一步&#xff1a;创建画板大小第二步&#xff1a;在画板上作画 绘制俄罗斯方块第一步&#xff1a;绘制o形俄罗斯方块第二步&#xff1a;绘制其他形状方块 记录俄罗斯方块小游戏的游戏思路和过程 一、搭建界面 **目标&#xff1a;**搭建基础…

thinker board s debian系统安装配置

thinker board s debian系统安装配置 好多年前买了一块thinker board s&#xff0c;装安卓系统来用&#xff0c;结果经常性卡死不知道为啥&#xff0c;可能是供电问题&#xff0c;也可能是系统bug&#xff0c;之后就吃灰不怎么用了&#xff0c;最近想装一个计算服务器&#xff…

python利用thinker制作多页面切换的桌面应用实例教程

本篇文章主要讲解&#xff0c;python利用thinker制作多页面的桌面实例教程。可以在一个主界面中相互进行切换和设置相关的表单信息&#xff0c;布局等方法 代码片段的实际效果 视频演示&#xff1a; python使用thinker制作多窗口代码片段实例效果 gif动态图&#xff1a; 构建…

模型思维-THE MODEL THINKER

序言这本书是怎样写成的 Part1为什么需要模型思维 01做一个多模型思考者 使用模型来思考能够带给你的&#xff0c;远远不仅仅是工作绩效的提高。它还会使你成为一个更优秀的人&#xff0c;让你拥有更强的思考能力。你将更擅长评估层出不穷的经济事件和政治事件&#xff0c;更能…

展示一下用thinker做小软件的UI

有一个大坑给大家分享一下。ttk.Treeview可以改变列宽&#xff0c;却不能改变某一行的行高&#xff08;可以改变整体的行高&#xff09;&#xff0c;其实就是Treeview没有自动换行功能&#xff0c;很痛苦&#xff0c;很折磨&#xff0c;......我一度放弃thinker&#xff0c;因为…

Python Thinker GUI的组件的简单总结

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Label二、Button三、Entry四、Text五、CheckButton六、RadioButton七、Menu八、Canvas九、Scale 前言 例如&#xff1a;随之前学过Java的基础&#xff0c;…

Thinker 使用详解

文章目录 Tinker基本介绍它主要包含以下几部分&#xff1a;为什么使用 Tinker Tinker 执行原理及流程简单的使用 Tinker1,在项目的gradle.properties 中添加2,在项目的 gradle中添加&#xff1a;3,在 app 中的 gradle 中添加&#xff1a;4,接着进行初始化&#xff0c;新建一个类…

python界面编程-thinker

一、介绍 thinker是python内置界面库不需要额外安装 二、控件使用 1、窗口 import tkintertop tkinter.Tk()#创建窗口 top.mainloop()#消息循环2、按钮 from tkinter import *def button_event():print("按钮按下\n")return#创建窗口 main_window Tk() #设置窗口…

python thinker(菜单,滚动条,回调函数,对话框)

菜单menu from tkinter import * root Tk() def lab():label0Label(root,text"hello world")label0.grid(column0) root.geometry("800x480")#窗口大小menu0Menu(root)#参数是父级控件 for x in [文件,编辑,视图]:menu0.add_command(labelx,commandlab)#…

永恒之蓝(勒索病毒)

1、要有一台靶机和一台攻击机&#xff0c;这里的攻击机为kali&#xff0c;靶机为Windows2008。 2、添加一个新的网卡&#xff0c;防止病毒传播到主机。 1、添加网卡&#xff1a; 注意&#xff1a;这里添加的子网ip不能和前面的重复。 3、给虚拟机设置网卡。 两台虚拟机要设置为…

老生常谈,永恒之蓝-winxp

老生常谈&#xff0c;永恒之蓝-winxp 环境说明&#xff1a; 攻击机&#xff1a;kali 靶机&#xff1a;windows xp sp2 靶机开放服务&#xff1a;无&#xff0c;IE浏览器版本 6.0 信息收集&#xff1a; 扫描当前网段存活主机&#xff0c;发现目标主机&#xff1a;IP&#xf…

msf渗透测试学习-与永恒之蓝漏洞案例

MSF是Metasploit Framework的缩写&#xff0c;是一款广泛使用的渗透测试工具&#xff0c;具有强大的攻击功能。它提供了一个模块化的平台&#xff0c;通过将各种攻击载荷、漏洞利用和辅助工具组装在一起&#xff0c;可用于模拟各种攻击&#xff0c;测试系统安全性&#xff0c;也…

永恒之蓝--Windows7

永恒之蓝是在Windows的SMB服务处理SMB v1请求时发生的漏洞&#xff0c;这个漏洞导致攻击者在目标系统上可以执行任意代码。通过永恒之蓝漏洞会扫描开放445文件共享端口的Windows机器&#xff0c;无需用户任何操作&#xff0c;只要开机上网&#xff0c;不法分子就能在电脑和服务…

win7永恒之蓝

一 使用msfconsole命令开启MSF&#xff0c;并使用search命令搜索永恒之蓝模块 search ms17-010 二 &#xff1a;使用搜索出来的第三个模块来进行探测目标是否存在永恒之蓝漏洞&#xff0c;并设置好以下参数进行扫描测试 >>>use auxiliary/scanner/smb/smb_ms17_010 …

永恒之蓝从渗透的复现

永恒之蓝又称为勒索病毒&#xff0c;同样这个漏洞成为了黑客现在训练的好方式&#xff08;记住千万不可以攻击别人的电脑&#xff09;&#xff0c;这个漏洞在win7中十分常见&#xff0c;而永恒之蓝对应的是445端口&#xff0c;所以说我们将用win7虚拟机&#xff08;受害者&…

永恒之蓝(Eternal Blue)复现

永恒之蓝介绍 什么是永恒之蓝 永恒之蓝&#xff08;Eternal Blue&#xff09;爆发于2017年4月14日晚&#xff0c;是一种利用Windows系统的SMB协议漏洞来获取系统的最高权限&#xff0c;以此来控制被入侵的计算机。甚至于2017年5月12日&#xff0c; 不法分子通过改造“永恒之蓝…