zoukankan      html  css  js  c++  java
  • 用python的TK模块实现猜成语游戏(附源码)

    说明:本游戏使用到的python模块有tkinter,random,hashlib;整个游戏分为四个窗口,一个进入游戏的窗口、一个选关窗口、一个游戏进行窗口和一个游戏结束的窗口。

    源码有两个主要的py文件,mygame.py和setting.py,mygame文件是游戏的主文件,所有的代码逻辑在该文件;setting模块存放游戏的一些资源,如问题、答案、提示等;

    player_answers.txt文件用来记录玩家已经回答过的关卡。

    游戏规则:
      玩家点击按钮进入游戏窗口后,通过点击屏幕下方的按键输入问题的答案,

      答案正确则会生成进入下一关的按钮,否则无法进入下一关。

    游戏扩展:1.目前游戏暂定30关,玩家可自由地添加关数,无需修改任何代码;
    2.在setting模块中按照三个字典的格式直接往里添加新的关数的数据即可,在if __name__ == "__main__"中
    有str1和str2两个变量用来对答案加密和对键盘上的字进行乱序操作。

    实现的功能:1.对所有答案都使用了md5算法加密;源码中无明文答案;
    2.支持自由选关的操作;
    3.支持返回上一关的操作;
    4.支持答案提示操作,提示最多为一个字;
    5.自动永久记录已经回答正确的问题,其选关按钮会由红色变成绿色;如果想要重置,运行
    mygame模块if __name__ == "__main__"中注释的代码或直接修改player_answers.txt文件,
    将里面所有的数据置为0.
    游戏界面图:



    代码说明:
    一、选择关卡的界面的按钮:

     1 __author__ = {'author': 'caiwanpeng',
     2               'Email': '626004181@qq.com',
     3               'Blog': 'http://www.cnblogs.com/cwp-bg/',
     4               'Created': '2017-09-25',
     5               'Version': '1.1'}
     6 
     7 
     8 class ButtonSelect(object):
     9     """创建选择关卡的按钮"""
    10 
    11     def __init__(self, win, num, game_screen, elements, player_answer):
    12         self.win = win
    13         self.name = tk.StringVar(self.win)
    14         self.sum_sc = len(dict_problems)
    15         self.num_sc = num
    16         self.start_game = game_screen
    17         self.eles = elements
    18         self.player_answer = player_answer
    19 
    20     def set_name(self, value):
    21         """设置按钮的数值"""
    22         self.name.set(value)
    23 
    24     def set_bg(self):
    25         """设置按钮的背景色"""
    26         if self.player_answer == "1":
    27             return "green"
    28         return "red"
    29 
    30     def create_button(self, place=(0, 0)):
    31         """创建按钮"""
    32         button = tk.Button(self.win, textvariable=self.name,
    33                            command=self._select_sc,
    34                            bg=self.set_bg(), fg="black",
    35                            activebackground="orange",
    36                            font=("宋体", 16, "bold"))
    37         button.place(width=40, height=40,
    38                      relx=0.1 + place[0] * 0.8,
    39                      rely=0.1 + place[1] * 0.9)
    40         return button
    41 
    42     def _select_sc(self):
    43         """选择按钮响应函数"""
    44         #  改变窗口记录的关数值
    45         self.num_sc[0] = int(self.name.get())
    46         #  清除界面所有的元素
    47         try:
    48             for ele in self.eles:
    49                 ele.destroy()  # 删除所有的元素
    50         except Exception as re:
    51             print(re)
    52         self.eles.clear()  # 清空记录
    53         #  加载游戏窗口
    54         self.start_game()
    
    
    
    二、输入答案的键盘按钮:
     1 class ButtonNew(object):
     2     """创建键盘按钮"""
     3 
     4     def __init__(self, wins, v1, v2, result, screen_num, bg='red',
     5                  fg="green", height=1, width=3,
     6                  font=("宋体", 20, "bold")):
     7         self.win = wins
     8         self.v1 = v1
     9         self.v2 = v2
    10         self.v_name = tk.StringVar(self.win)  # 一个显示按钮文字的标签
    11         self.results = result
    12         self.screen_num = screen_num  # 获得目前的关卡数
    13         # 相关属性
    14         self.bg = bg
    15         self.fg = fg
    16         self.height = height
    17         self.width = width
    18         self.font = font
    19 
    20     def create_button(self, place_b=(0, 0)):
    21         """键盘按钮"""
    22         # 创建按钮,按钮上的标签内容,command点击按钮执行函数,bg背景颜色,fg标签颜色
    23         key_answer = tk.Button(self.win, textvariable=self.v_name,
    24                                command=lambda: self._button_event(self.v_name.get()),
    25                                activebackground="blue",
    26                                bg=self.bg, fg=self.fg,
    27                                height=self.height,
    28                                width=self.width, font=self.font)
    29         # 设置按钮的位置
    30         key_answer.place(x=place_b[0], y=place_b[1])
    31         return key_answer
    32 
    33     def _button_event(self, name1):
    34         """创建一个点击按钮响应的函数"""
    35         # 先清空v2标签
    36         self.v2.set("")
    37         if len(self.v1.get()) < 4:  # 小于成语的长度
    38             self.results.append(name1)
    39         else:
    40             self.results.clear()
    41 
    42         result = ""
    43         for i in self.results:  # 拼接字符串
    44             result += i
    45         self.v1.set(result)
    46 
    47         # 判断答案是否正确
    48         if abt.the_answer is True:
    49             abt.the_answer = False
    50         password = dict_result[str(self.screen_num[0])]
    51         if len(self.results) >= 4 and self.get_md5(result) == password:
    52             abt.the_answer = True  # 将答案开关设置为正确
    53             # print(abt.the_answer)
    54 
    55     @staticmethod
    56     def get_md5(str1):
    57         """对st1字符串MD5加密"""
    58         return hb.md5(str1.encode("utf-8")).hexdigest()
    
    
    
    三、游戏的主窗口:
      1 class GameWindow(object):
      2     """创建游戏运行窗口并加载相关的控件"""
      3 
      4     def __init__(self):
      5         """初始化窗口"""
      6         # 创建一个根窗口
      7         self.win = tk.Tk()
      8         self.win.title("史上最污猜成语")  # 标题
      9         self.win.geometry("500x500+500+100")  # 设置尺寸
     10         self.win.resizable(width=False, height=False)  # 宽高不可变
     11         self.v1 = tk.StringVar(self.win)  # 显示答案的标签
     12         self.v2 = tk.StringVar(self.win)  # 答案是否正确的标签
     13         self.v_screen = tk.StringVar(self.win)  # 显示下一关的标签
     14         self.v_problems = tk.StringVar(self.win)  # 一个显示问题的可变标签
     15         self.results = []  # 创建一个记录答案长度的变量
     16         self.eles = []  # 创建一个记录界面元素的列表
     17         self.list_button = []  # 存放键盘可变文字对象
     18         self.screen_num = [1]  # 记录当前是第几关,使用可变类型将地址引用
     19         self.sum_screen = len(dict_problems)  # 获取当前的总关卡数
     20         self.player_answers = self.player_answer()  # 记录目前已回答的关数的情况
     21 
     22     def create_label(self):
     23         """创建窗口所有的标签"""
     24         # 标签显示第几关
     25         dir1 = tk.Label(self.win, bg="yellow", textvariable=self.v_screen,
     26                         fg="blue", font=("宋体", 20, "bold"))
     27         dir1.pack(side=tk.TOP, fill=tk.X)
     28         self.eles.append(dir1)
     29         # 创建一个标签"答案"
     30         dir2 = tk.Label(self.win, bg="red", text="答案:",
     31                         font=("宋体", 20, "bold"))
     32         dir2.place(x=0, y=200)  # 位置坐标控制
     33         self.eles.append(dir2)
     34         # 创建一个换行标签
     35         dir3 = tk.Label(self.win, bg="#00F000", textvariable=self.v_problems,
     36                         wraplength=400, justify="left",
     37                         fg="blue", font=("宋体", 20, "bold"), height=4)
     38         dir3.pack(fill=tk.X)
     39         self.eles.append(dir3)
     40         # 一个空白的标签等待用户输入答案
     41         dir4 = tk.Label(self.win, bg="green", textvariable=self.v1,
     42                         font=("宋体", 20, "bold"))
     43         dir4.place(x=100, y=200)
     44         self.eles.append(dir4)
     45         # 一个空白标签显示答案错误时
     46         dir5 = tk.Label(self.win, textvariable=self.v2, fg="red",
     47                         font=("宋体", 12, "bold"))
     48         dir5.place(x=100, y=240)
     49         self.eles.append(dir5)
     50 
     51     def create_button(self):
     52         """创建游戏窗口所有的按钮"""
     53         # 采用嵌套循环创建4*8个按钮
     54         for j in range(4):
     55             for g in range(8):
     56                 button1 = ButtonNew(self.win, v1=self.v1,
     57                                     v2=self.v2, result=self.results,
     58                                     screen_num=self.screen_num)
     59                 # 设置按钮的位置
     60                 key_b = button1.create_button(place_b=(30 + g * 54, 280 + j * 45))
     61                 self.list_button.append(button1.v_name)  # 将每一个标签加入列表
     62                 self.eles.append(key_b)  # 所有的按钮加入列表
     63         self._set_key(self.screen_num[0])  # 设置相应关数的值
     64 
     65         # 创建一个用来清除答案的按钮
     66         cls = tk.Button(self.win, text="清除", command=self._cls_function,
     67                         bg="black", fg="white", font=("宋体", 16, "bold"))
     68         cls.place(x=250, y=200)
     69         self.eles.append(cls)
     70         # 创建一个用来提示答案的按钮
     71         pmt = tk.Button(self.win, text="提示",
     72                         command=lambda: self._prompt_button(self.screen_num[0]),
     73                         bg="red", fg="white", font=("宋体", 16, "bold"))
     74         pmt.place(x=320, y=200)
     75         self.eles.append(pmt)
     76         # 创建一个用来确定答案的按钮
     77         istrue = tk.Button(self.win, text="确定", command=self._ensure_button,
     78                            bg="red", fg="white", font=("宋体", 16, "bold"))
     79         istrue.place(x=390, y=200)
     80         self.eles.append(istrue)
     81         # 创建一个返回上一关的按钮
     82         last_sc = tk.Button(self.win, text="上一关", command=self._last_sc_button,
     83                             bg="red", fg="white", font=("宋体", 16, "bold"))
     84         last_sc.place(x=250, y=155)
     85         self.eles.append(last_sc)
     86         # 创建一个返回选关窗口的按钮
     87         return_button = tk.Button(self.win, text="返回选关", command=self._return_lock,
     88                                   bg="red", fg="white", font=("宋体", 16, "bold"))
     89         return_button.place(x=10, y=155)
     90         self.eles.append(return_button)
     91 
     92     def before_screen(self):
     93         """创建一个进入游戏的窗口所有元素"""
     94         # 空白标签
     95         label1 = self.the_label()
     96         # 标签显示"史上最污猜成语"
     97         label2 = self.the_label("史上最污猜成语")
     98         # 空白标签
     99         label3 = self.the_label()
    100         # 显示淡绿色背景
    101         label4 = self.the_label(font=("宋体", 250, "bold"), bg="#00ee00")
    102         # 显示作者“天宇之游”
    103         dirx = tk.Label(self.win, bg="#00ee00", text="----天宇之游",
    104                         fg="blue", font=("宋体", 20, "bold"))
    105         dirx.place(x=250, y=200)
    106         list_labels = [label1, label2, label3, label4, dirx]
    107         # 创建一个进入游戏的按钮
    108         go_game = tk.Button(self.win, text="开启污旅程",
    109                             command=lambda: self._start_game(go_game, *list_labels),
    110                             bg="red", fg="white", activebackground="yellow",
    111                             activeforeground="red", font=("宋体", 30, "bold"))
    112         go_game.place(x=130, y=300)
    113 
    114     def lock_screen(self):
    115         """创建一个展示所有的关卡及关卡解锁的窗口"""
    116         # 空白区域
    117         dir_k = tk.Label(self.win, bg="#3b9dff", font=("宋体", 20, "bold"))
    118         dir_k.pack(fill=tk.X)
    119         self.eles.append(dir_k)
    120         # 显示相关信息
    121         dir1 = tk.Message(self.win, bg="blue", text="选择关卡",
    122                           fg="red", font=("宋体", 20, "bold"),
    123                           width=200)
    124         dir1.pack(fill=tk.X)
    125         self.eles.append(dir1)
    126         # 创建一块画布,所有的元素都放置在画布上
    127         cans = tk.Canvas(self.win,  # 根窗口
    128                          bg="#92dba0",  # 设置画布的颜色
    129                          height=500,
    130                          borderwidth=0)
    131         cans.pack(fill=tk.X)
    132         self.eles.append(cans)  # 添加到列表便于删除
    133 
    134         for i in range(self.sum_screen):  # 按照已有的关卡数生成相应的按钮数量
    135             j = i % 10 / 10.0
    136             k = i // 10 / 10
    137             # 传入当前的关数和加载游戏窗口的函数
    138             bn_st = ButtonSelect(cans, self.screen_num,
    139                                  self._game_go, self.eles,
    140                                  self.player_answers[i])
    141             bn_st.create_button(place=(j, k))
    142             bn_st.set_name(str(i + 1))
    143 
    144     def after_screen(self):
    145         """一个游戏结束的画面窗口"""
    146         self.the_label()  # 空白标签
    147         text1 = "恭喜你!"
    148         text2 = "成功晋升为老司机!"
    149         # 标签显示结束语
    150         self.the_label(text1)
    151         self.the_label(text2)
    152         self.the_label()  # 空白标签
    153         # 创建一个结束的按钮
    154         go_game = tk.Button(self.win, text="再见!",
    155                             command=lambda: exit(),
    156                             bg="red", fg="white",
    157                             activebackground="yellow",
    158                             activeforeground="red",
    159                             font=("宋体", 30, "bold"))
    160         go_game.place(x=170, y=300)
    161 
    162     def the_label(self, text=None, side=tk.TOP,
    163                   font=("宋体", 40, "bold"), bg="green"):
    164         """创建显示标签"""
    165         dir1 = tk.Label(self.win, bg=bg, text=text,
    166                         fg="black", font=font)
    167         dir1.pack(side=side, fill=tk.X)
    168         return dir1
    169 
    170     def _return_lock(self):
    171         """返回选择关卡的界面"""
    172         # 清空标签
    173         self.list_button.clear()
    174         # 清除界面的所有元素
    175         self.clear_screen()
    176         # 清空元素记录列表
    177         self.eles.clear()
    178         # 将关数记录还原到1
    179         self.screen_num[0] = 1
    180         # 调用界面创建函数
    181         self.screen_control(1)
    182 
    183     def clear_screen(self):
    184         """清除界面所有元素的函数"""
    185         try:
    186             for ele in self.eles:
    187                 ele.destroy()  # 删除所有的元素
    188         except Exception as re:
    189             print(re)
    190 
    191     def _set_key(self, num):
    192         """设置所有的按键变量的值"""
    193         listx = rm.sample(dict_key[str(num)], len(dict_key[str(num)]))  # 打乱顺序
    194         #  设置所有的键盘上的文字
    195         for j, k in enumerate(self.list_button):
    196             k.set(listx[j])  # 获取文字设置按键值
    197 
    198     def _next_screen(self):
    199         """当答案正确时生成下一关的按钮"""
    200         # 创建一个用来确定答案的按钮
    201         next_b = tk.Button(self.win, text="下一关", command=lambda: self._next_button(next_b),
    202                            bg="red", fg="white",
    203                            font=("宋体", 16, "bold"))
    204         next_b.place(x=390, y=155)
    205         return next_b
    206 
    207     def _next_button(self, next_b):
    208         """当点击下一关按钮时响应函数"""
    209         try:
    210             # 判断是否已经是最后一关
    211             if self.screen_num[0] >= len(dict_problems):
    212                 # print("这已经是最后一关")
    213                 # 清除界面所有的元素
    214                 self.clear_screen()
    215                 # 加载游戏结束的界面
    216                 self.screen_control(3)
    217             else:
    218                 if abt.the_answer is True:
    219                     self.__update_screen()  # 更新窗口
    220                 else:
    221                     self.v2.set("答案错误!")
    222 
    223             # 将上一关的选关按钮变为绿色
    224             self.player_answers[self.screen_num[0] - 2] = "1"
    225             # 同时将当前的数据同步到文件
    226             file = open("./player_answers.txt", "w")
    227             file.write("".join(self.player_answers))  # 转化成字符串
    228         except Exception as re:
    229             print(re)
    230         else:
    231             # 删除按钮本身
    232             next_b.destroy()
    233         finally:
    234             file.close()
    235 
    236     def _last_sc_button(self):
    237         """上一关按钮的响应函数"""
    238         # 判断目前是不是第一关
    239         if self.screen_num[0] == 1:
    240             self.v2.set("这是第一关!")
    241         else:
    242             self.screen_num[0] -= 2  # 减少一关
    243             self.__update_screen()
    244 
    245     def __update_screen(self):
    246         """更新窗口的的函数"""
    247         # 显示问题
    248         self.v_problems.set(dict_problems[str(self.screen_num[0] + 1)])
    249         self.screen_num[0] += 1  # 指针指向下一关
    250         # 改变关数的标签
    251         self.v_screen.set("" + str(self.screen_num[0]) + "")
    252         # 更新所有的按键值
    253         self._set_key(self.screen_num[0])
    254         # 清除v1和v2标签的内容
    255         self._cls_function()
    256         self.v2.set("")
    257         # print("成功执行!")
    258 
    259     def _start_game(self, *args):
    260         """进入游戏的响应函数"""
    261         try:
    262             for ele in args:
    263                 ele.destroy()  # 删除所有的元素
    264         except Exception as re:
    265             print(re)
    266         self.screen_control(num=1)  # 进入选关界面
    267 
    268     def _game_go(self):
    269         str_num = str(self.screen_num[0])
    270         self.v_screen.set("" + str_num + "")  # 设置第几关标签
    271         self.v_problems.set(dict_problems[str_num])  # 设置问题
    272         self.screen_control(2)  # 进入游戏界面
    273 
    274     def _cls_function(self):
    275         """清除按钮响应事件函数"""
    276         self.results.clear()
    277         self.v1.set("")  # 清空标签
    278 
    279     def _ensure_button(self):
    280         """确定开关的事件函数"""
    281         if abt.the_answer is True:
    282             self.v2.set("答案正确!")
    283             self._next_screen()  # 在窗口创建一个按钮
    284         else:
    285             self.v2.set("答案错误!")
    286 
    287     def _prompt_button(self, key):
    288         """提示开关的事件函数"""
    289         if abt.the_answer is True:  # 将可能打开的开关关闭
    290             abt.the_answer = False
    291         self.results.clear()  # 先清空原来的答案
    292         self.results.append(list_answer[int(key)])  # 加入提示
    293         self.v1.set(list_answer[int(key)])  # 设置提示答案
    294 
    295     def screen_control(self, num=0):
    296         """创建一个窗口控件显示的控制函数"""
    297         if num == 0:
    298             self.before_screen()  # 开始显示游戏进入界面
    299         elif num == 1:
    300             self.lock_screen()  # 进入选关界面
    301         elif num == 2:
    302             self.create_label()  # 传入所有可变的参数创建所有的标签
    303             self.create_button()  # 传入空白标签对象创建所有的按钮
    304         elif num == 3:
    305             self.after_screen()  # 进入游戏结束界面
    306 
    307     def run(self):
    308         self.win.mainloop()  # 窗口运行
    309 
    310     def player_answer(self):
    311         """更新记录的玩家回答的状态"""
    312         # 获取目前的总关数
    313         number1 = self.sum_screen
    314         try:
    315             # 读取文件中的关数信息,如果数目不变则不更新文件,改变则初始化文件
    316             f = open("./player_answers.txt", "r")
    317             str3 = f.read()
    318             # print(str3)
    319         except Exception as re:
    320             print(re)
    321         finally:
    322             f.close()
    323 
    324         if number1 == len(str3):
    325             return list(iter(str3))
    326         else:  # 初始化
    327             str2 = "0" * number1
    328             try:
    329                 f1 = open("./player_answers.txt", "w")
    330                 f1.write(str2)  # 更新信息
    331             except Exception as re:
    332                 print(re)
    333             finally:
    334                 f1.close()
    335             return list(iter(str2))
    336 
    337 
    338 win = GameWindow()
    339 sc = win.screen_control
    340 bs = win.before_screen
    341 as_ = win.after_screen
    342 ls = win.lock_screen
    343 run = win.run
    344 
    345 
    346 def main():
    347     sc()
    348     run()  # 游戏运行
    349 
    350 
    351 if __name__ == "__main__":
    352     main()
    353     # 初始化记录文件
    354     # str2 = "0"*len(dict_key)
    355     # f1 = open("./player_answers.txt", "w")
    356     # f1.write(str2)  # 更新信息
    357     # f1.close()
    
    
    
    四、游戏的setting模块。
    数据资源见源码包。
     1 class AllButton(object):
     2     """创建一个开关类管理所有的开关便于以后的扩展"""
     3 
     4     def __init__(self):
     5         self.the_answer = False  # 设置答案是否正确的开关
     6         self.cls_answer = False  # 设置清空答案的开关
     7         self.start_game = False  # 进入游戏的开关
     8 
     9 
    10 abt = AllButton()
    11 
    12 if __name__ == "__main__":
    13     print(len(dict_key))
    14     str1 = ""  # 用来生成加密的答案
    15     md5_answer = hb.md5(str1.encode("utf-8")).hexdigest()
    16     print(md5_answer)  # 得到加密的答案
    17     str2 = ""
    18     results = rm.sample(str2, len(str2))
    19     results = "".join(results)
    20     print(results)  # 得到乱序后的字列

    游戏源码下载:https://files.cnblogs.com/files/cwp-bg/game_one.zip

    码云
    地址:https://gitee.com/TianYuZhiYou/guess_the_chengyu
    • 作者:天宇之游
    • 出处:http://www.cnblogs.com/cwp-bg/
    • 本文版权归作者和博客园共有,欢迎转载、交流,但未经作者同意必须保留此段声明,且在文章明显位置给出原文链接。
    
    
  • 相关阅读:
    UVa532 Dungeon Master 三维迷宫
    6.4.2 走迷宫
    UVA 439 Knight Moves
    UVa784 Maze Exploration
    UVa657 The die is cast
    UVa572 Oil Deposits DFS求连通块
    UVa10562 Undraw the Trees
    UVa839 Not so Mobile
    327
    UVa699 The Falling Leaves
  • 原文地址:https://www.cnblogs.com/cwp-bg/p/7630166.html
Copyright © 2011-2022 走看看