数字华容道游戏_用Python tkinter Canvas实现

在博文《用39条Python语句完成“数字华容道”游戏》一文中使用按钮实现该游戏。本文用Python tkinter Canvas实现该游戏,也仅用了46条语句。
游戏用Canvas中的text实例显示数字,简称数字或text实例。text实例显示数字不同,其属性tag值也不同,根据text实例属性tag值,就能找到相应数字(text实例)。为了使鼠标单击数字事件函数知道要移动那个数字,必须用参数将被点击数字(text实例)tag值传递给该事件函数。采用的方法是在Canvas中每创建一个text实例,都令其有不同tag值,同时为该text实例创建一个单击数字事件函数,该函数有参数nTag其默认值是这个text实例的tag值。单击某数字,这个text实例(数字)用自己的事件函数响应,该事件函数找到其参数nTag的默认值指定的text实例(数字),完成对被点击数字的移动和输赢判断。这样每一个text实例都有一个事件函数,占用较多资源。
本游戏不完整,但基本框架已建成,这主要是为了使读者更容易地通过本例深入了解Python tkinter Canvas。有兴趣的读者可在此基础加以扩充,例如,增加重玩按钮,从3x3升级到4x4、5x5,把它们集成到一起等等。
下边是完整程序,有详细注解,应该能读懂代码。比较难理解的可能是事件绑定,如有问题可参考博文“python3.8的tkinter按钮事件函数实现多个参数另一种方法”。

import tkinter as tk
import random
def moveNum(nTag):              #移动被鼠标点击的数字,参数是在Canvas中字符对象的tag
    global X0,Y0,w,gameOver     #空位所在位置的坐标(X0,Y0)
    x,y=w.coords(nTag)          #得到被点击的数字所在位置的坐标
    if abs(x-X0)+abs(y-Y0)==60 and gameOver==False:  #判断被单击数字是否和空白处相邻
        w.move(nTag,X0-x,Y0-y)  #如果和空白处相邻,移动数字到空白处,第2,3参数是移动增量
        X0,Y0=x,y                           #记录新空白处位置坐标
        numbers=list('087654321')
        for y in range(90,270,60):           #y为Canvas的y坐标,90,150,210
            for x in range(90,270,60):       #x为Canvas的x坐标,90,150,210
                m=numbers.pop()
                if m!= '0':                 #如m!= '0',8个数字还未检查完
#tag='1'字符对象显示1,在(90,90)位置正确,tag='2'字符对象显示2,在(150,90)处正确,等等
                    if [x,y]!=w.coords("A"+m):  #如相应字符对象位置不正确,玩家未赢
                        return
                else:                       #如m=='0',8个数字所在位置正确,玩家赢了
                    gameOver=True
                    label['text']="你赢了"
root = tk.Tk()                                #初始化窗口
root.title('数字华容道_用Canvas实现')          #窗口标题
root.geometry("300x260+200+20")#窗口宽300,高=2600,窗口左上点离屏幕左边界200,离屏幕上边界距离20。
root.resizable(width=False,height=False) #设置窗口是否可变,这里宽不可变,高不可变,默认为True
w = tk.Canvas(root, width = 300, height = 260, background = "white")        #建立Canvas对象
w.pack()
gameOver=False
numbers=list('123456780')
random.shuffle(numbers)             #使列表数字和空白随机排列
label=tk.Label(w,text='单击数字移动方块',fg='red',font=("Arial",15))
label.place(x=20,y=10,width=250,height=40)
X0=Y0=0                                #空位所在位置的坐标(X0,Y0)
for x in range(60,300,60):          #画棋盘4条竖线,x为Canvas的x坐标
    w.create_line(x,60,x,240,fill = "black",width = 3)
for y in range(60,300,60):          #画棋盘4条横线,y为Canvas的y坐标
    w.create_line(60,y,240,y,fill = "black",width = 3)
for y in range(90,270,60):           #y为Canvas的y坐标,90,150,210
    for x in range(90,270,60):       #x为Canvas的x坐标,90,150,210
        n=numbers.pop()
        if n!='0':#如n!='0',建立8个数字对象,注意tag有2个值,可通过"R"操作所有数字对象,如删除所有数字
            w.create_text(x,y,text=n,fill="red",tag=("A"+n,"R"),font=("Arial",40))#tag=A1,显示1
            def leftClick(event,nTag="A"+n): #每个按钮都生成一个事件函数,参数默认值是该数字的tag
                moveNum(nTag)            #所有事件函数都调用同一函数
            w.tag_bind("A"+n,'<Button-1>',leftClick)        #绑定左键单击事件
        else:                           #n=0,代表空白,记住无数字的空位的Canvas坐标(x,y)
            X0,Y0=x,y            
root.mainloop()
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值