Python写个小游戏:速算24点(下)



前言

大家好,最近实在是有点忙,下篇迟迟没有动笔。上一篇文章也结束得很匆忙,实在抱歉。代码部分其实早已写好,但是问哥还是想尽力将其拆解、讲解清楚,所以并不是直接分享代码。当然,如果想跳过问哥啰嗦的废话,直接参考代码,也可以跳到文章末尾查阅。

废话不多说,马上进入我们剩下的部分:

上篇 —— 游戏界面搭建
下篇 —— 功能代码实现


速算24点

1. 玩法简介

游戏规则比较简单:找一副扑克牌,去掉大小王,52张牌,每次随机抽取四张牌,运用加减乘除四种计算方法,看看谁能最快计算出24点。虽说是单机游戏,没有比赛的压力,但还是增加了计时功能:如果90秒内未能找出答案,则视为当前测试失败,自动进入下一关。同时,为了降低难度,提供了提示功能:闯关过程中,共有三次机会获得提示参考答案。

游戏截图:
在这里插入图片描述

2. 游戏流程

速算24点的简易流程图如下:

No
Yes
Yes
No
Yes
No 更换下一组
No
Yes
游戏开始
牌堆是否为0
抽取4张牌
计算该组合是否有解
倒计时开始
玩家输入答案
判断答案是否正确
停止倒计时
是否进入下一局
游戏结束
洗牌
有三次机会使用提示
时间用完,自动进入下一局

3. 剩下的部分

上篇内容里讲解了大部分界面的搭建,还有两个小地方,一个是关卡信息,一个是提示按钮。

1). 关卡 / 分数信息

IntVar类

上篇我们引入了StringVar类,实例了变量后,用来和标签绑定,可以直接将变量的内容显示在标签上,从而省去了不少麻烦。而StringVar是针对字符串,对于纯粹的数字,tkinter还提供了类似功能的IntVar类。同样地,将其和标签或其他组件绑定,即可直接将IntVar类实例的值显示出来。与StringVar相区别的是,IntVar是整数(int),可以直接参与计算,所以,用来记录玩家已测试的关卡数,以及通过的关卡(分数),也是十分方便的。

于是,我们先定义两个变量,实例化IntVar类:

level=IntVar()
score=IntVar()

再创建4个标签,两个用来显示固定字符“已测试”、“已通过”,另外两个用来和变量level、score绑定,以动态显示当前的关卡和分数。

cv.create_text(600,350,text='已测试:',font =('方正楷体简体',16,'bold'))
cv.create_text(600,400,text='已通过:',font =('方正楷体简体',16,'bold'))
level_lable = Label(root,text='',font=('微软雅黑',15),textvariable=level,bg='lightyellow')
cv_level = cv.create_window(670,350,window=level_lable)
score_lable = Label(root,text='',font=('微软雅黑',15),textvariable=score,bg='lightyellow')
cv_score = cv.create_window(670,400,window=score_lable)

实现效果如下图:
在这里插入图片描述

2). 提示按钮

提示按钮区域还分了两部分,一部分是按钮,另一部分是小灯泡的图片,用来表示玩家还剩多少次机会。

图片

问哥从网上找到的小灯泡的图片,将它改成png格式,然后命名为idea。
在这里插入图片描述
先定义一个常量HINT,用来表示玩家可以有多少次提示机会。默认是3次,当然你也可以改成5次,更多或更少。然后再通过for循环,在指定的位置绘制3个灯泡图片,并将这些绘制的组件放在一个列表ideas里。

HINT = 3
idea = PhotoImage(file=r"image\poker\idea.png")
ideas = []
for i in range(HINT):
    ideas.append(cv.create_image(450+i*25,450,image = idea))

为什么放进列表呢?因为可以方便我们在按下提示按钮后,自动减少图片并在画布上刷新。

按钮

按钮的创建很简单,我们之前也介绍过。问哥为了加速完成这个小项目,就不使用特效了,于是默认使用tkinter的Button组件。

btn = Button(root,text='提示',width=5,command=hint)
cv_btn = cv.create_window(400,450,window=btn)

关键是我们需要为这个按钮绑定一个回调函数,起名叫hint,在该函数里,我们要完成以下三个功能:

  1. 获取正确答案right_answer,并显示在标签上
  2. 将按钮禁用,以防止玩家不小心点击了多次,从而浪费了提示次数
  3. 减少一个“小灯泡”

实现代码如下:

def hint():
    answer.set(right_answer)
    btn['state']=DISABLED
    idea = ideas.pop()
    cv.delete(idea)

同样的道理,为了防止玩家误操作(你永远无法完全预见玩家或用户大开脑洞的操作),也为了减少程序的可能,我们规定该按钮只允许在被点击的时候启用,换句话说,除了倒计时开始,玩家开始答题时,而且提示次数没有用完(ideas>0),按钮的状态是NORMAL,其他时间该按钮都应该处于DISABLED状态。

于是,我们分别在其他位置做以下更新:

def initialize():
    # 省略代码
    btn['state']=DISABLED

def draw_card():
    # 省略代码
    if len(ideas)>0: btn['state']=NORMAL

测试效果基本OK:

在这里插入图片描述

3). 重新发牌

代码写到这里,除了还没有让电脑替我们找出正确答案,已经实现基本的输入、判断等功能了。试着运行一下:
在这里插入图片描述
发现回答正确、在选择继续下一局后,桌面上的发牌混乱了,不知道新的四张牌跑到哪里去了,这是怎么回事?

原来,我们在上篇用了一个数组cv_card来储存抽出来的四张牌,并使用for循环将这四张牌显示在桌面上,但是没有考虑到当一局游戏结束,需要重新抽四张牌的情况。在这种情况下,我们需要把桌面上的4张牌从画布上擦去,用代码的话主要是两步:

  1. 删除图片
  2. 清空列表

为了避免重复操作,我们再定义一个子程序来完成清除clear的操作:

def clear(cv_card):
    for i in cv_card:
        cv.delete(i)
    cv_card.clear()

然后,我们再把该函数放在抓牌函数的开始,这样,每次开始抓牌前,我们都先清除(如果有的话)上一轮的四张牌,从而保证代码对新的四张牌依然适用。

def draw_card():
    clear(cv_card)

同样的理由,我们在重新开始下一局后,答案标签的内容也需要清空,所以我们需要在initialize函数以及myanswer函数里添加以下代码:

def initialize():
    answer.set('')
    # 省略代码
def myanswer(event):
    # 省略代码
    if s=='BackSpace':
        txt=txt[:-1]
    elif s=='Return':
        if is_right(txt):
            root.after_cancel(cd)
            c = tm.askyesno(message='继续下一局吗?')
            if c:
                # 省略代码
                return # 添加 return,表示进入下一局后就不继续显示标签

经测试,在没有电脑帮助的情况下,已经可以成功地“自食其力”进行闯关了。可问题是,常常会出现这种情况:抽出四张牌,却很难写出答案,因为我们也无法确定是我们没有想出答案,还是这四张牌根本没有答案。所以,我们需要设计一个方法,让电脑替我们先算好答案,保存在变量right_answer里,如果没有答案的话,就自动更换下一组。有了right_answer,提示按钮也就可以发挥作用了。

4. 让电脑计算24点

算起来,这部分其实是相对独立的代码,因为我们可以把要解决的问题从这个游戏里抽离出来,转换为“给定4个数,计算出能否通过排列组合,使得这四个数组成的算式运算结果等于24。”

1). 表达式的特征

为了解决这个问题,我们观察一下四个数字组成的算术表达式的特征:

  1. 不考虑小括号的情况(也相当于一对小括号把四个数字包起来)。算式的形式为:(a+b+c+d),其中有4个数字,3个运算符(这里加号+只是代表运算符,可以是加减乘除的任意一种)。
  2. 考虑小括号的情况又分为两种:
第一种情况:一对小括号第二种情况:两对小括号
(a+b)+c+d(a+b)+(c+d)
a+(b+c)+d((a+b)+c)+d
a+b+(c+d)(a+(b+c))+d
(a+b+c)+da+((b+c)+d)
a+(b+c+d)a+(b+(c+d))
  1. 再进一步观察可以发现,就像(a+b+c+d)的括号可以省略一样,(a+b+c)+d,a+(b+c+d)也一定与两对括号的情况重复:(a+b+c)+d 必定等价于 ((a+b)+c)+d 或 (a+(b+c))+d;a+(b+c+d) 必定等价于 a+((b+c)+d) 或 a+(b+(c+d))。所以最终,我们只需要考虑8种情况:
    (a+b)+c+d
    a+(b+c)+d
    a+b+(c+d)
    (a+b)+(c+d)
    ((a+b)+c)+d
    (a+(b+c))+d
    a+((b+c)+d)
    a+(b+(c+d))
    当然,这里仍然存在较大重复计算的可能性,假如三个运算符都是加法或乘法的话,上面八个表达式都是等价的,所以这并不是一个最优的算法。

2). 代码的实现

虽然存在很多重复计算,但在不考虑时间复杂度,以及运算量并不算大的情况下,完全可以让电脑进行穷举运算,把所有的可能性都检查一遍。于是我们可以把代码的实现过程分成三步:

  1. 找出4个数字所有不重复的排列组合,最多有24种可能(4!)
  2. 找出3个运算符(加减乘除)的排列组合,因为运算符可重复使用,所以是4^3=64种可能。(这里面有一些组合是不可能计算出24点的,比如连续三个减号或除号,但是如果添加小括号使得计算顺序发生改变的话,结果将有所不同。为了省事,这里就把所有排列组合都考虑了)
  3. 在算式的不同位置添加小括号。根据前面列举的,总共有8种可能。

于是,不考虑存在重复的情况下,最多总共有 24*64*8 = 12288 种可能。这点计算量对人类来说可能望而却步,但是对电脑来说简直不值一提。更何况,我们并不用找出所有正确答案,而是只要找到一个即可。

下面我们开始写代码:

将扑克牌转换成数字

我们首先要做的,就是把抽取的4张牌转化为数字。因为扑克牌的数字是从0到51,但是所代表的用于计算的数字却是从1到13,这其实可以通过简单的求余运算来实现。

于是,我们定义一个函数:

def calnum(n):
    global nums
    nums=[i%13+1 for i in n]
    formula=form(nums)

这个函数接收一个变量n,代表含有4张牌的列表,然后通过列表生成式(或称为推导式)将其转换成一个实际用于计算的数字的列表nums。然后再调用另一个自定义函数form()将这个列表通过排列组合转化成含有最多12288个表达式的列表,保存为formula。

需要注意的是,我们还要将nums声明成全局变量。这样做的唯一目的,是为了在判断玩家输入的时候,是否只使用了给定的4个数字。于是,我们顺便将判断玩家输入的函数 is_right() 也更新如下:

def is_right(txt):
    # 省略代码
    if sorted(txt)!=sorted(nums):
        tm.showinfo(message='请使用给定的数字!')
        return False
    # 省略代码

下面我们接着写form()函数。

数字的排列组合

为了不重复制造轮子,我们可以直接使用Python提供的内置模块来计算排列组合。

from itertools import permutations
def form(nums):
    numlist=set(permutations(nums))

从itertools模块中导入permutations函数以后,就可以使用它来计算列表的排列组合了。这个函数接收两个参数,第一个是列表等可迭代对象,第二个是数字,表示从前面的列表里取出几个元素进行排列组合,可以省略,如果省略的话,则表示默认对所有元素进行排列组合。于是在这里,我们可以省略第二个参数,直接将含有4个数字的nums列表交给permutations函数,返回一个可迭代对象。同时,为了去重,比如四张牌里有重复的数字,3,3,4,4这种,我们可以将这个结果转换为集合set,最终将结果保存在numlist里。

在控制台测试结果:

>>> from itertools import permutations
>>> nums = [1,2,3,4]
>>> numlist = permutations(nums)
>>> type(numlist)
<class 'itertools.permutations'>
>>> for i in numlist: print(i,end=' ')
(1, 2, 3, 4) (1, 2, 4, 3) (1, 3, 2, 4) (1, 3, 4, 2) (1, 4, 2, 3) (1, 4, 3, 2) (2, 1, 3, 4) (2, 1, 4, 3) (2, 3, 1, 4) (2, 3, 4, 1) (2, 4, 1, 3) (2, 4, 3, 1) (3, 1, 2, 4) (3, 1, 4, 2) (3, 2, 1, 4) (3, 2, 4, 1) (3, 4, 1, 2) (3, 4, 2, 1) (4, 1, 2, 3) (4, 1, 3, 2) (4, 2, 1, 3) (4, 2, 3, 1) (4, 3, 1, 2) (4, 3, 2, 1) 
>>> 

可以看到,如我们所预想的,4个不重复的数字可以组成最多24个互不重复的组合。

添加运算符

接下来,我们需要在这四个数字中间插入三个运算符,当然,我们首先要找到运算符组成的64种组合,使用三层循环即可实现,并将结果保存在列表operations里。

operations=[]
for i in '+-*/':
    for j in '+-*/':
        for k in '+-*/':
            operation = i+j+k
            operations.append(operation)

因为这个列表会被频繁调用(每发四张牌,就要插入运算符),所以我们可以将它放在主程序里,这样只要在游戏开始时运算一次,在函数里就可以一直调用(而不修改)。

接着,在函数form里,我们同样使用for循环来将3个运算符插入到4个数字之间:

def form(nums):
    numlist=set(permutations(nums))
    combo=[]
    for num in numlist:
        for i in operations:
            temp=[]
            for j in range(3):
                temp+=[str(num[j]),i[j]]
            temp.append(str(num[j+1]))
            combo.append(temp)

因为最终我们需要将表达式转换成字符串,所以在这里我们就可以使用str函数将数字转换成字符串,保存在列表combo里。根据之前计算的,combo里最多应该存在 24*64 = 1536 个元素,代表了1536个表达式。但是现在它们任然是单个的字符,因为我们还需要插入小括号。

插入小括号

小括号用于提升运算等级、改变运算顺序。根据前面所分析的,由于默认计算顺序为先乘除、后加减、从左到右依次运算,所以不包含小括号的情况(a+b+c+d)一定等价于某种使用小括号的情况。所以最终我们只需要考虑8种小括号的情况:三种一对小括号的情况,和五种两对小括号的情况。但是该怎样插入呢?

通过之前的计算,我们得到的combo二维列表里的表达式列表应该类似这个样子:
[‘1’, ‘+’, ‘2’, ‘+’, ‘3’, ‘+’, ‘4’]

可见,每个表达式都是包含7个字符串元素(4个数字、3个运算符)的列表。于是,我们只要事先找到需要添加小括号的位置(索引),就可以通过循环添加了。

通过比较,我们将两种情况(一对和两对小括号)的左右小括号的位置索引找到,并创建列表如下:

    one=[(3,0),(5,2),(7,4)]
    two=[(7,3,5,0),(5,3,0,0),(5,5,2,0),(7,5,2,2),(7,7,4,2)]

需要注意的是,我们要先插入右边的小括号,再插入左边小括号。因为插入元素以后,列表的长度改变,为了方便计算,先插入右边小括号可以最大程度保持相对位置。在两对小括号的时候也是如此(先插入右侧的括号),只需要注意其中一种情况:(a+b)+(c+d)。在这种情况下,插入两个右括号之后,夹在两个右括号中间的左括号位置发生了变化,只要记录新的位置即可。

于是,通过索引列表,我们可以将form函数补全:

def form(nums):
    numlist=set(permutations(nums))
    combo=[]
    for num in numlist:
        for i in operations:
            temp=[]
            for j in range(3):
                temp+=[str(num[j]),i[j]]
            temp.append(str(num[j+1]))
            combo.append(temp)
    one=[(3,0),(5,2),(7,4)]
    two=[(7,3,5,0),(5,3,0,0),(5,5,2,0),(7,5,2,2),(7,7,4,2)]
    formula=[]
    for i in combo:
        for j in one:
            temp=i[:]
            temp.insert(j[0],')')
            temp.insert(j[1],'(')
            formula.append(''.join(temp)) # 将列表转化为字符串
        for j in two:
            temp=i[:]
            temp.insert(j[0],')')
            temp.insert(j[1],')')
            temp.insert(j[2],'(')
            temp.insert(j[3],'(')
            formula.append(''.join(temp)) # 将列表转化为字符串
    return formula
返回运算结果

最后,我们得到包含最多12288个表达式的列表formula,并返回到函数calnum里使用eval函数进行计算。

def calnum(n):
    # 省略代码
    formula=form(nums)
    for i in formula:
        try:
            result = eval(i)
        except:
            continue
        if math.isclose(result,24):
            return i
    return 'None'

通过for循环遍历formula列表,依次计算结果是否等于24。如果正确,则把正确答案(表达式)返回,如果遍历所有12288种可能都没有结果,则返回字符串None。

3). 调用计算函数

按照我们之前的逻辑,在每次抓取4张牌之后,我们都需要电脑帮忙计算,看看当前4张牌能否计算出24点,如果不能,则自动进入下一局(重新抓牌),如果可以,则将答案保存在变量right_answer里,方便提示(hint)按钮调用。于是,我们更新相应部位的代码即可:

def draw_card():
    global cv_card, right_answer    
    invalid=True
    while invalid:
        clear(cv_card)
        draw=[]
        if len(cardnum)==0:
            tm.showinfo(message='牌堆已用完,为您重新洗牌')
            shuffle_card()
        for i in range(4):
            draw.append(cardnum.pop())
            cv_card.append(cv.create_image(100,200,image=card[draw[i]]))
            if len(cardnum)==0:cv.delete(cv_back)
            for _ in range(150*(i+1)):
                cv.move(cv_card[i],1,0)
                cv.update()
        right_answer = calnum(draw) # 调用函数计算12288种可能
        if right_answer=='None':
            tm.showinfo(message='本组数字无解,为您自动更换下一组')
        else:
            countdown()
            if len(ideas)>0: btn['state']=NORMAL
            invalid=False

如果4张牌无法计算24点,就需要一直重新抽牌,直到可以计算为止。于是这里使用一个while循环,并给定一个标记 invalid 假定当前组合无法计算24点。只有当得到答案时(right_answer的值不是None),invalid变为False,结束while循环,开始计时等后续程序。

5. 知识点回顾

  1. Canvas的delete方法
  2. IntVar类型
  3. permutations函数

到这里,我们这个“速算24点”的小游戏就做好了。大家可以继续在里面添加其他想要的功能,改变布局、颜色等等。最终运行效果如下:
在这里插入图片描述


完整代码

from tkinter import *
import tkinter.messagebox as tm
import random
import math
from itertools import permutations

def shuffle_card():
    global cardnum, back, cv_back
    cardnum = list(range(52))
    random.shuffle(cardnum)
    back = PhotoImage(file=r"image\poker\back1.png")
    cv_back = cv.create_image(100,200,image = back)

def clear(cv_card):
    for i in cv_card:
        cv.delete(i)
    cv_card.clear()

def draw_card():
    global cv_card, right_answer    
    invalid=True
    while invalid:
        clear(cv_card)
        draw=[]
        if len(cardnum)==0:
            tm.showinfo(message='牌堆已用完,为您重新洗牌')
            shuffle_card()
        for i in range(4):
            draw.append(cardnum.pop())
            cv_card.append(cv.create_image(100,200,image=card[draw[i]]))
            if len(cardnum)==0:cv.delete(cv_back)
            for _ in range(150*(i+1)):
                cv.move(cv_card[i],1,0)
                cv.update()
        right_answer = calnum(draw)
        if right_answer=='None':
            tm.showinfo(message='本组数字无解,为您自动更换下一组')
        else:
            countdown()
            if len(ideas)>0: btn['state']=NORMAL
            invalid=False

def initialize():
    global angle,count,cv_arc,cv_inner,cv_text
    count=90
    angle=360
    btn['state']=DISABLED
    answer.set('')
    cv_arc=cv.create_oval(100,330,200,430,fill='red',outline='yellow')
    cv_inner=cv.create_oval(120,350,180,410,fill='yellow',outline='yellow')
    cv_text=cv.create_text(150,380,text=count,font =('微软雅黑',20,'bold'),fill='red')
    draw_card()

def countdown():
    global angle,count,cv_arc,cv_inner,cv_text,cd
    if angle == 360:
        angle -= 1
    else:
        cv.delete(cv_arc)
        cv.delete(cv_inner)
        cv.delete(cv_text)
        cv_arc=cv.create_arc(100,330,200,430,start=90,extent=angle,fill="red",outline='yellow')
        angle -= 1
        if angle%4 == 0: count-=1
        cv_inner=cv.create_oval(120,350,180,410,fill='yellow',outline='yellow')
        cv_text=cv.create_text(150,380,text=count,font =('微软雅黑',20,'bold'),fill='red')
    if count==0:
        tm.showinfo(message='倒计时结束!自动进入下一局')
        level.set(int(level.get())+1)
        cv.delete(cv_arc)
        cv.delete(cv_inner)
        cv.delete(cv_text)
        initialize()
    else:
        cd = root.after(250,countdown)   

def myanswer(event):
    s=event.keysym
    txt=answer.get()
    if s=='BackSpace':
        txt=txt[:-1]
    elif s=='Return':
        if is_right(txt):
            level.set(int(level.get())+1)
            score.set(int(score.get())+1)
            root.after_cancel(cd)
            c = tm.askyesno(message='继续下一局吗?')
            if c:
                cv.delete(cv_arc)
                cv.delete(cv_inner)
                cv.delete(cv_text)
                initialize()
                return
            else:root.destroy()
        else:
            txt=''
    elif s.isnumeric():
        txt+=s
    elif s in trans:
        txt+=trans[s]
    answer.set(txt)

def is_right(txt):
    try:
        result = eval(txt)
    except:
        tm.showinfo(message='算式不正确,请重新输入!')
        return False
    for i in '+-*/()':
        txt=txt.replace(i,' ')
    txt=[int(i) for i in txt.split()]
    if sorted(txt)!=sorted(nums):
        tm.showinfo(message='请使用给定的数字!')
        return False
    if math.isclose(result,24):
        tm.showinfo(message='恭喜您!回答正确!')
        return True

def hint():
    answer.set(right_answer)
    btn['state']=DISABLED
    idea = ideas.pop()
    cv.delete(idea)

def calnum(n):
    global nums
    nums=[i%13+1 for i in n]
    formula=form(nums)
    for i in formula:
        try:
            result = eval(i)
        except:
            continue
        if math.isclose(result,24):
            return i
    return 'None'

def form(nums):
    numlist=set(permutations(nums))
    combo=[]
    for num in numlist:
        for i in operations:
            temp=[]
            for j in range(3):
                temp+=[str(num[j]),i[j]]
            temp.append(str(num[j+1]))
            combo.append(temp)
    one=[(3,0),(5,2),(7,4)]
    two=[(7,3,5,0),(5,3,0,0),(5,5,2,0),(7,5,2,2),(7,7,4,2)]
    formula=[]
    for i in combo:
        for j in one:
            temp=i[:]
            temp.insert(j[0],')')
            temp.insert(j[1],'(')
            formula.append(''.join(temp))
        for j in two:
            temp=i[:]
            temp.insert(j[0],')')
            temp.insert(j[1],')')
            temp.insert(j[2],'(')
            temp.insert(j[3],'(')
            formula.append(''.join(temp))
    return formula

# 游戏从这里开始
HINT = 3
operations=[]
for i in '+-*/':
    for j in '+-*/':
        for k in '+-*/':
            operation = i+j+k
            operations.append(operation)
trans={'plus':'+','minus':'-','asterisk':'*','slash':'/','parenleft':'(','parenright':')'}
root = Tk()
root.geometry('800x500+400+200')
root.resizable(0,0)
root.title('速算24点')
# 画布大小和主窗口大小一致
cv = Canvas(root,width=800,height=500)
# 背景图片
bg = PhotoImage(file=r"image\poker\bg.png")
cv_bg = cv.create_image(400,250,image = bg)
# 标题图片
title = PhotoImage(file=r"image\poker\title.png")
cv_title = cv.create_image(400,60,image = title)
# 显示答案及关卡分数等信息
answer=StringVar()
level=IntVar()
score=IntVar()
cv.create_text(400,350,text='请输入您的答案',font =('方正楷体简体',18,'bold'))
lb = Label(root,text='',font=('微软雅黑',15),textvariable=answer,bg='lightyellow')
cv_lb = cv.create_window(400,400,window=lb)
cv.create_text(600,350,text='已测试:',font =('方正楷体简体',16,'bold'))
cv.create_text(600,400,text='已通过:',font =('方正楷体简体',16,'bold'))
level_lable = Label(root,text='',font=('微软雅黑',15),textvariable=level,bg='lightyellow')
cv_level = cv.create_window(670,350,window=level_lable)
score_lable = Label(root,text='',font=('微软雅黑',15),textvariable=score,bg='lightyellow')
cv_score = cv.create_window(670,400,window=score_lable)
# 提示图片及按钮
idea = PhotoImage(file=r"image\poker\idea.png")
ideas = []
for i in range(HINT):
    ideas.append(cv.create_image(450+i*25,450,image = idea))
btn = Button(root,text='提示',width=5,command=hint)
cv_btn = cv.create_window(400,450,window=btn)

# 绑定从键盘获取输入<Key>,并传给自定义函数myanswer
lb.bind('<Key>',myanswer)
# 使标签组件获得焦点,不然无法从键盘输入
lb.focus_set()


card = [PhotoImage(file=f'image/poker/{i:0>2}.png') for i in range(1,53)]
cv_card=[]
cv.pack()
shuffle_card()
initialize()
root.mainloop()
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

请叫我问哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值