[项目分享]我又‘来’了哦~

7097浏览
查看: 7097|回复: 9

[项目分享] 我又‘来’了哦~

[复制链接]
闲着也是闲着,把与老师子一起写的2048分享一下叭;
  (我懒得写教程了,自己康注释吧(我抄老师的注释抄了好久qwq))
  1. import random,sys  # 导入随机模块random,主要用于随机生成新的数字及数字摆方位置
  2. import math  # 导入数学模块,用来计算分数
  3. # _map_data 绑定一个 4 x 4 列表,此列表为2048游戏地图,初始值如下:
  4. _map_data = [
  5.     [0, 0, 0, 0],
  6.     [0, 0, 0, 0],
  7.     [0, 0, 0, 0],
  8.     [0, 0, 0, 0]
  9. ]
  10. def reset():
  11.     '''重新设置游戏数据,将地图恢复为初始状态,并加入两个数据 2 作用初始状态'''
  12.     _map_data[:] = []  # _map_data.clear()
  13.     _map_data.append([0, 0, 0, 0])
  14.     _map_data.append([0, 0, 0, 0])
  15.     _map_data.append([0, 0, 0, 0])
  16.     _map_data.append([0, 0, 0, 0])
  17.     # 在空白地图上填充两个2
  18.     fill2()
  19.     fill2()
  20. def get_space_count():
  21.     """获取没有数字的方格的数量,如果数量为0则说有无法填充新数据,游戏即将结束
  22.     """
  23.     count = 0
  24.     for r in _map_data:
  25.         count += r.count(0)
  26.     return count
  27. def get_score():
  28.     '''获取游戏的分数,得分规则是每次有两个数加在一起则生成相应的分数。
  29.     如 2 和 2 合并后得4分, 8 和 8 分并后得 16分.
  30.     根据一个大于2的数字就可以知道他共合并了多少次,可以直接算出分数:
  31.     如:
  32.        4 一定由两个2合并,得4分
  33.        8 一定由两个4合并,则计:8 + 4 + 4 得32分
  34.        ... 以此类推
  35.     '''
  36.     score = 0
  37.     for r in _map_data:
  38.         for c in r:
  39.             score += 0 if c < 4 else c * int((math.log(c, 2) - 1.0))
  40.     return score  # 导入数学模块
  41. def fill2():
  42.     '''填充2到空位置,如果填度成功返回True,如果已满,则返回False'''
  43.     blank_count = get_space_count()  # 得到地图上空白位置的个数
  44.     if 0 == blank_count:
  45.         return False
  46.     # 生成随机位置, 如,当只有四个空时,则生成0~3的数,代表自左至右,自上而下的空位置
  47.     pos = random.randrange(0, blank_count)
  48.     offset = 0
  49.     for row in _map_data:   # row为行row
  50.         for col in range(4):  # col 为列,column
  51.             if 0 == row[col]:
  52.                 if offset == pos:
  53.                     # 把2填充到第row行,第col列的位置,返回True
  54.                     row[col] = 2
  55.                     return True
  56.                 offset += 1
  57. def is_gameover():
  58.     """判断游戏是否结束,如果结束返回True,否是返回False
  59.     """
  60.     for r in _map_data:
  61.         # 如果水平方向还有0,则游戏没有结束
  62.         if r.count(0):
  63.             return False
  64.         # 水平方向如果有两个相邻的元素相同,应当是可以合并的,则游戏没有结束
  65.         for i in range(3):
  66.             if r[i] == r[i + 1]:
  67.                 return False
  68.     for c in range(4):
  69.         # 竖直方向如果有两个相邻的元素相同,应当可以合并的,则游戏没有结束
  70.         for r in range(3):
  71.             if _map_data[r][c] == _map_data[r + 1][c]:
  72.                 return False
  73.     # 以上都没有,则游戏结束
  74.     return True
  75. # 以下是2048游戏的基本算法,此算法是在达内的美女老师"贾琳倩"提供算法上改进而来
  76. def _left_move_number(line):
  77.     '''左移一行数字,如果有数据移动则返回True,否则返回False:
  78.     此行数据需要左移三次:
  79.      最终结果: line = [4, 8, 0, 0]
  80.     '''
  81.     moveflag = False  # 是否移动的标识,先假设没有移动
  82.     for _ in range(3):  # 重复执行下面算法三次
  83.         for i in range(3):  # i为索引
  84.             if 0 == line[i]:  # 此处有空位,右侧相邻数字向左侧移动,右侧填空白
  85.                 moveflag = True
  86.                 line[i] = line[i + 1]
  87.                 line[i + 1] = 0
  88.     return moveflag
  89. def _left_marge_number(line):
  90.     '''向左侧进行相同单元格合并,合并结果放在左侧,右侧补零
  91.     最终结果: line = [4, 8, 8, 0]
  92.     '''
  93.     for i in range(3):
  94.         if line[i] == line[i + 1]:
  95.             moveflag = True
  96.             line[i] *= 2  # 左侧翻倍
  97.             line[i + 1] = 0  # 右侧归零
  98. def _left_move_aline(line):
  99.     '''左移一行数据,如果有数据移动则返回True,否则返回False:
  100.     左移算法分为三步:
  101.             +---+---+---+---+
  102.         最终结果: line = [4, 8, 0, 0]
  103.     '''
  104.     moveflag = False
  105.     if _left_move_number(line):
  106.         moveflag = True
  107.     if _left_marge_number(line):
  108.         moveflag = True
  109.     if _left_move_number(line):
  110.         moveflag = True
  111.     return moveflag
  112. def left():
  113.     """游戏左键按下时或向左滑动屏幕时的算法"""
  114.     moveflag = False  # moveflag 是否成功移动数字标志位,如果有移动则为真值,原地图不变则为假值
  115.     # 将第一行都向左移动.如果有移动就返回True
  116.     for line in _map_data:
  117.         if _left_move_aline(line):
  118.             moveflag = True
  119.     return moveflag
  120. def right():
  121.     """游戏右键按下时或向右滑动屏幕时的算法
  122.     选将屏幕进行左右对调,对调后,原来的向右滑动即为现在的向左滑动
  123.     滑动完毕后,再次左右对调回来
  124.     """
  125.     # 左右对调
  126.     for r in _map_data:
  127.         r.reverse()
  128.     moveflag = left()  # 向左滑动
  129.     # 再次左右对调
  130.     for r in _map_data:
  131.         r.reverse()
  132.     return moveflag
  133. def up():
  134.     """游戏上键按下时或向上滑动屏幕时的算法
  135.     先把每一列都自上而下放入一个列表中line中,然后执行向滑动,
  136.     滑动完成后再将新位置摆回到原来的一列中
  137.     """
  138.     moveflag = False
  139.     line = [0, 0, 0, 0]  # 先初始化一行,准备放入数据
  140.     for col in range(4):  # 先取出每一列
  141.         # 把一列中的每一行数入放入到line中
  142.         for row in range(4):
  143.             line[row] = _map_data[row][col]
  144.         # 将当前列进行上移,即line 左移
  145.         if (_left_move_aline(line)):
  146.             moveflag = True
  147.         # 把左移后的 line中的数据填充回原来的一列
  148.         for row in range(4):
  149.             _map_data[row][col] = line[row]
  150.     return moveflag
  151. def down():
  152.     """游戏下键按下时或向下滑动屏幕时的算法
  153.     选将屏幕进行上下对调,对调后,原来的向下滑动即为现在的向上滑动
  154.     滑动完毕后,再次上下对调回来
  155.     """
  156.     _map_data.reverse()
  157.     moveflag = up()  # 上滑
  158.     _map_data.reverse()
  159.     return moveflag
  160. if (sys.version_info > (3, 0)):
  161.     from tkinter import *
  162.     from tkinter import messagebox
  163. else:
  164.     from Tkinter import *
  165. def main():
  166.     reset()  # 先重新设置游戏数据
  167.     root = Tk()  # 创建tkinter窗口
  168.     root.title('2048游戏')  # 设置标题文字
  169.     root.resizable(width=False, height=False)  # 固定宽和高
  170.     # 以下是键盘映射
  171.     keymap = {
  172.         'a': left,
  173.         'd': right,
  174.         'w': up,
  175.         's': down,
  176.         'Left': left,
  177.         'Right': right,
  178.         'Up': up,
  179.         'Down': down,
  180.         'q': root.quit,
  181.     }
  182.     game_bg_color = "#bbada0"  # 设置背景颜色
  183.     # 设置游戏中每个数据对应色块的颜色
  184.     mapcolor = {
  185.         0: ("#cdc1b4", "#776e65"),
  186.         2: ("#eee4da", "#776e65"),
  187.         4: ("#ede0c8", "#f9f6f2"),
  188.         8: ("#f2b179", "#f9f6f2"),
  189.         16: ("#f59563", "#f9f6f2"),
  190.         32: ("#f67c5f", "#f9f6f2"),
  191.         64: ("#f65e3b", "#f9f6f2"),
  192.         128: ("#edcf72", "#f9f6f2"),
  193.         256: ("#edcc61", "#f9f6f2"),
  194.         512: ("#e4c02a", "#f9f6f2"),
  195.         1024: ("#e2ba13", "#f9f6f2"),
  196.         2048: ("#ecc400", "#f9f6f2"),
  197.         4096: ("#ae84a8", "#f9f6f2"),
  198.         8192: ("#b06ca8", "#f9f6f2"),
  199.         # ----其它颜色都与8192相同---------
  200.         2**14: ("#b06ca8", "#f9f6f2"),
  201.         2**15: ("#b06ca8", "#f9f6f2"),
  202.         2**16: ("#b06ca8", "#f9f6f2"),
  203.         2**17: ("#b06ca8", "#f9f6f2"),
  204.         2**18: ("#b06ca8", "#f9f6f2"),
  205.         2**19: ("#b06ca8", "#f9f6f2"),
  206.         2**20: ("#b06ca8", "#f9f6f2"),
  207.     }
  208.     def on_key_down(event):
  209.         '键盘按下处理函数'
  210.         keysym = event.keysym
  211.         if keysym in keymap:
  212.             if keymap[keysym]():  # 如果有数字移动
  213.                 fill2()  # 填充一个新的2
  214.         update_ui()
  215.         if is_gameover():
  216.             mb = messagebox.askyesno(
  217.                 title="gameover", message="游戏结束!\n是否退出游戏!")
  218.             if mb:
  219.                 root.quit()
  220.             else:
  221.                 reset()
  222.                 update_ui()
  223.     def update_ui():
  224.         '''刷新界面函数
  225.         根据计算出的f地图数据,更新各个Label的设置
  226.         '''
  227.         for r in range(4):
  228.             for c in range(len(_map_data[0])):
  229.                 number = _map_data[r][c]  # 设置数字
  230.                 label = map_labels[r][c]  # 选中Lable控件
  231.                 label['text'] = str(number) if number else ''
  232.                 label['bg'] = mapcolor[number][0]
  233.                 label['foreground'] = mapcolor[number][1]
  234.         label_score['text'] = str(get_score())  # 重设置分数
  235.     # 创建一个frame窗口,此创建将容纳全部的widget 部件
  236.     frame = Frame(root, bg=game_bg_color)
  237.     frame.grid(sticky=N+E+W+S)
  238.     # 设置焦点能接收按键事件
  239.     frame.focus_set()
  240.     frame.bind("<Key>", on_key_down)
  241.     # 初始化图形界面
  242.     # 创建4x4的数字块
  243.     map_labels = []  # 游戏各方块的lable Widget
  244.     for r in range(4):
  245.         row = []
  246.         for c in range(len(_map_data[0])):
  247.             value = _map_data[r][c]
  248.             text = str(value) if value else ''
  249.             label = Label(frame, text=text, width=4, height=2,
  250.                           font=("黑体", 30, "bold"))
  251.             label.grid(row=r, column=c, padx=5, pady=5, sticky=N+E+W+S)
  252.             row.append(label)
  253.         map_labels.append(row)
  254.     # 设置显示分数的Lable
  255.     label = Label(frame, text='分数', font=("黑体", 30, "bold"),
  256.                   bg="#bbada0", fg="#eee4da")
  257.     label.grid(row=4, column=0, padx=5, pady=5)
  258.     label_score = Label(frame, text='0', font=("黑体", 30, "bold"),
  259.                         bg="#bbada0", fg="#ffffff")
  260.     label_score.grid(row=4, columnspan=2, column=1, padx=5, pady=5)
  261.     # 以下设置重新开始按钮
  262.     def reset_game():
  263.         reset()
  264.         update_ui()
  265.     restart_button = Button(frame, text='重新开始', font=("黑体", 16, "bold"),
  266.                             bg="#8f7a66", fg="#f9f6f2", command=reset_game)
  267.     restart_button.grid(row=4, column=3, padx=5, pady=5)
  268.     update_ui()  # 更新界面
  269.     root.mainloop()  # 进入tkinter主事件循环
  270. main()  # 启动游戏
复制代码
散会!!!


黄添添  见习技师
 楼主|

发表于 2022-4-3 14:23:19

并且我一直懒得写教程
回复

使用道具 举报

hnyzcj  版主

发表于 2022-4-4 07:32:41

哈哈哈
回复

使用道具 举报

bobbi  初级技师

发表于 2022-4-4 21:46:16

哈哈哈哈哈哈
回复

使用道具 举报

赤星三春牛!  初级技神

发表于 2022-4-4 22:22:28

66666666666
回复

使用道具 举报

赤星三春牛!  初级技神

发表于 2022-4-4 22:24:39

哈哈哈哈哈哈
回复

使用道具 举报

赤星三春牛!  初级技神

发表于 2022-4-4 22:25:49

呵呵呵呵
回复

使用道具 举报

赤星三春牛!  初级技神

发表于 2022-4-4 22:27:21

厉害厉害
回复

使用道具 举报

赤星三春牛!  初级技神

发表于 2022-4-4 22:29:47

赞赞赞赞赞赞
回复

使用道具 举报

zschenxi  学徒

发表于 2022-4-6 18:37:55


赞赞赞赞赞赞
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail