找回密码
 立即注册
楼主: 嵌入式之路

51单片机的2048游戏机讨论

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:472
  • 最近打卡:2025-06-30 18:00:53

17

主题

533

回帖

1424

积分

金牌会员

积分
1424
发表于 2024-9-23 22:32:46 | 显示全部楼层
C语言上面的代码已经写好了, 如果移植到单片机上就是需要控制随机数的生成和使用IO控制移动,以及驱动WS2812就行. WS2812 我已经实现了基本的驱动
自信就会温和,温和就会坚定!
回复 支持 1 反对 0

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:483
  • 最近打卡:2025-07-01 00:06:00
已绑定手机

81

主题

5242

回帖

9377

积分

超级版主

DebugLab

积分
9377
发表于 2024-9-24 00:13:34 | 显示全部楼层
Python源码:

  1. import random
  2. import math
  3. __mataclass__ = type  # 使用新式类
  4. # 此类为地图模块封装的类
  5. class map2048():
  6.     # 重新设置游戏数据
  7.     def reset(self):
  8.         self.__row = 4  # 行数
  9.         self.__col = 4  # 列数
  10.         self.data = [
  11.             [0 for x in range(self.__col)]
  12.             for y in range(self.__row)
  13.         ]
  14.         # self.data = [[x + 4 * y for x in range(self.__col)]
  15.         #              for y in range(self.__row)]
  16.         # self.data = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
  17.         self.fill2()
  18.         self.fill2()
  19.     def __init__(self):
  20.         self.reset()
  21.     # 获取没有数字的位置的个数
  22.     def get_space_count(self):
  23.         """
  24.         获取没有数字的方格的数量
  25.         """
  26.         count = 0
  27.         for r in self.data:
  28.             count += r.count(0)
  29.         return count
  30.     # 获取游戏的得数。
  31.     def get_score(self):
  32.         s = 0
  33.         for r in self.data:
  34.             for c in r:
  35.                 s += 0 if c < 4 else c * int((math.log(c, 2) - 1.0))
  36.         return s
  37.     # 填充2到空位置,如果填度成功返回True,如果已满,则返回False,
  38.     def fill2(self):
  39.         blank_count = self.get_space_count()
  40.         if 0 == blank_count:
  41.             return False
  42.         # 生成随机位置
  43.         pos = random.randrange(0, blank_count)
  44.         offset = 0
  45.         for r in self.data:
  46.             for ci in range(self.__col):
  47.                 if 0 == r[ci]:
  48.                     if offset == pos:
  49.                         r[ci] = 2
  50.                         return True
  51.                     offset += 1
  52.     # 判断游戏是否结束
  53.     def is_gameover(self):
  54.         for r in self.data:
  55.             # 如果水平方向还有0,则游戏没有结束
  56.             if r.count(0):
  57.                 return False
  58.             # 水平方向如果有两个相邻的元素相同,则没有游戏结束
  59.             for i in range(self.__col - 1):
  60.                 if r[i] == r[i + 1]:
  61.                     return False
  62.         for c in range(self.__col - 1):
  63.             # 竖直方向如果有两个相邻的元素相同,则没有游戏结束
  64.             for r in range(self.__row - 1):
  65.                 if self.data[r][c] == self.data[r + 1][c]:
  66.                     return False
  67.         # 以上都没有,则游戏结束
  68.         return True
  69.     # 2048游戏的左移动 (采用"贾琳倩"美女老师的方法进行移动)
  70.     def left(self):
  71.         # moveflag 是否成功移动数字标志位,如果有移动则为真值,原地图不变则为假值
  72.         moveflag = False
  73.         # 将所有数字向左移动来填补左侧空格
  74.         for times in range(self.__col - 1):
  75.             for r in self.data:
  76.                 for c in range(self.__col - 1):
  77.                     if 0 == r[c]:
  78.                         moveflag = True
  79.                         r[c] = r[c + 1]
  80.                         r[c + 1] = 0
  81.         # 判断是否发生碰幢,如果有碰撞则合并,合并结果靠左,右则填充空格
  82.         for r in self.data:
  83.             for c in range(self.__col - 1):
  84.                 if r[c] == r[c + 1]:
  85.                     moveflag = True
  86.                     r[c] *= 2
  87.                     r[c + 1] = 0
  88.         # 再将所有数字向左移动来填补左侧空格
  89.         for times in range(self.__col - 1):
  90.             for r in self.data:
  91.                 for c in range(self.__col - 1):
  92.                     if 0 == r[c]:
  93.                         moveflag = True
  94.                         r[c] = r[c + 1]
  95.                         r[c + 1] = 0
  96.         return moveflag
  97.     # 游戏右移操作
  98.     def right(self):
  99.         for r in self.data:
  100.             r.reverse()
  101.         moveflag = self.left()
  102.         for r in self.data:
  103.             r.reverse()
  104.         return moveflag
  105.     # 游戏上移操作
  106.     def up(self):
  107.         # moveflag 是否成功移动数字标志位,如果有移动则为真值,原地图不变则为假值
  108.         moveflag = False
  109.         # 将所有数字向上移动来填补上面空格
  110.         for times in range(self.__row - 1):
  111.             for c in range(self.__col):
  112.                 for r in range(self.__row - 1):
  113.                     if 0 == self.data[r][c]:
  114.                         moveflag = True
  115.                         self.data[r][c] = self.data[r + 1][c]
  116.                         self.data[r + 1][c] = 0
  117.         # 判断是否发生碰幢,如果有碰撞则合并,合并结果靠上,下面填充空格
  118.         for c in range(self.__col):
  119.             for r in range(self.__row - 1):
  120.                 if self.data[r][c] == self.data[r + 1][c]:
  121.                     moveflag = True
  122.                     self.data[r][c] *= 2
  123.                     self.data[r + 1][c] = 0
  124.         # 再将所有数字向上移动来填补上面空格
  125.         for times in range(self.__row - 1):
  126.             for c in range(self.__col):
  127.                 for r in range(self.__row - 1):
  128.                     if 0 == self.data[r][c]:
  129.                         moveflag = True
  130.                         self.data[r][c] = self.data[r + 1][c]
  131.                         self.data[r + 1][c] = 0
  132.         return moveflag
  133.     # 游戏下移操作
  134.     def down(self):
  135.         self.data.reverse()
  136.         moveflag = self.up()
  137.         self.data.reverse()
  138.         return moveflag
  139. import sys
  140. if (sys.version_info > (3, 0)):
  141.     from tkinter import *
  142.     from tkinter import messagebox
  143. else:
  144.     from Tkinter import *
  145. game = map2048()
  146. keymap = {
  147.     'a': game.left,
  148.     'd': game.right,
  149.     'w': game.up,
  150.     's': game.down,
  151.     'Left': game.left,
  152.     'Right': game.right,
  153.     'Up': game.up,
  154.     'Down': game.down,
  155.     'q': exit,
  156. }
  157. game_bg_color = "#bbada0"
  158. mapcolor = {
  159.     0: ("#cdc1b4", "#776e65"),
  160.     2: ("#eee4da", "#776e65"),
  161.     4: ("#ede0c8", "#f9f6f2"),
  162.     8: ("#f2b179", "#f9f6f2"),
  163.     16: ("#f59563", "#f9f6f2"),
  164.     32: ("#f67c5f", "#f9f6f2"),
  165.     64: ("#f65e3b", "#f9f6f2"),
  166.     128: ("#edcf72", "#f9f6f2"),
  167.     256: ("#edcc61", "#f9f6f2"),
  168.     512: ("#e4c02a", "#f9f6f2"),
  169.     1024: ("#e2ba13", "#f9f6f2"),
  170.     2048: ("#ecc400", "#f9f6f2"),
  171.     4096: ("#ae84a8", "#f9f6f2"),
  172.     8192: ("#b06ca8", "#f9f6f2"),
  173. }
  174. # 游戏各方块的lable数据
  175. map_labels = []
  176. # 鼠标按下处理函数
  177. def on_mouse_down(event):
  178.     print("clicked at", event.x, event.y)
  179. # 键盘按下处理函数
  180. def on_key_down(event):
  181.     keysym = event.keysym
  182.     if keysym in keymap:
  183.         if keymap[keysym]():
  184.             game.fill2()
  185.     update_ui()
  186.     if game.is_gameover():
  187.         mb = messagebox.askyesno(title="gameover", message="游戏结束!\n是否退出游戏!")
  188.         if mb:
  189.             exit()
  190.         else:
  191.             game.reset()
  192.             update_ui()
  193. # 刷新界面函数
  194. def update_ui():
  195.     # 更改各个Label的设置
  196.     for r in range(len(game.data)):
  197.         for c in range(len(game.data[0])):
  198.             number = game.data[r][c]
  199.             label = map_labels[r][c]
  200.             label['text'] = str(number) if number else ''
  201.             label['bg'] = mapcolor[number][0]
  202.             label['foreground'] = mapcolor[number][1]
  203.     label_score['text'] = str(game.get_score())
  204. # 以下为2048的界面
  205. root = Tk()
  206. root.title('2048')
  207. # root.iconbitmap('./favicon.ico')  # 48x48 ico bitmap
  208. frame = Frame(root, width=300, height=300, bg=game_bg_color)
  209. frame.grid(sticky=N+E+W+S)
  210. # 按键事件见:http://blog.csdn.net/qq_25600055/article/details/46942035
  211. # 设置焦点能接收按键事件
  212. frame.focus_set()
  213. frame.bind("<Key>", on_key_down)
  214. # 以下绑定鼠标按下事件
  215. # frame.bind("<Button-1>", on_mouse_down)
  216. # 以下绑定鼠标移动事件
  217. # frame.bind("<Motion>", on_mouse_down)
  218. # 以下绑定鼠标抬起事件
  219. frame.bind("<ButtonRelease-1>", on_mouse_down)
  220. # 见 :http://blog.csdn.net/wjciayf/article/details/50550947
  221. # 初始化图形界面
  222. for r in range(len(game.data)):
  223.     row = []
  224.     for c in range(len(game.data[0])):
  225.         value = game.data[r][c]
  226.         text = '' if 0 == value else str(value)
  227.         label = Label(frame, text=text, width=4, height=2,
  228.                       font=("黑体", 30, "bold"))
  229.         label.grid(row=r, column=c, padx=5, pady=5, sticky=N+E+W+S)
  230.         row.append(label)
  231.     map_labels.append(row)
  232. bottom_row = len(game.data)
  233. print("button", str(bottom_row))
  234. label = Label(frame, text='分数', font=("黑体", 30, "bold"),
  235.               bg="#bbada0", fg="#eee4da")
  236. label.grid(row=bottom_row, column=0, padx=5, pady=5)
  237. label_score = Label(frame, text='0', font=("黑体", 30, "bold"),
  238.                     bg="#bbada0", fg="#ffffff")
  239. label_score.grid(row=bottom_row, columnspan=2, column=1, padx=5, pady=5)
  240. def reset_game():
  241.     game.reset()
  242.     update_ui()
  243. # restart_button = Button(frame, text='重新开始', command=reset_game)
  244. restart_button = Button(frame, text='重新开始', font=("黑体", 16, "bold"),
  245.                         # width=4, height=2,
  246.                         bg="#8f7a66", fg="#f9f6f2", command=reset_game)
  247. restart_button.grid(row=bottom_row, column=3, padx=5, pady=5)
  248. update_ui()
  249. root.mainloop()
复制代码


DebugLab
回复 支持 1 反对 0

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:561
  • 最近打卡:2025-07-01 07:57:52
已绑定手机

1

主题

838

回帖

1747

积分

金牌会员

积分
1747
发表于 2024-9-24 07:56:15 | 显示全部楼层
嵌入*** 发表于 2024-9-23 22:30
成本其实真的不高, 那个ws2812 如果选好的雾面的一个5毛 16个也就是8元. 我估计成本也就15元左右 ...

利润高,可以搞一搞
靡不有初,鲜克有终
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:482
  • 最近打卡:2025-07-01 00:52:47
已绑定手机

19

主题

3233

回帖

5355

积分

论坛元老

积分
5355
发表于 2024-9-24 08:29:14 来自手机 | 显示全部楼层
DebugLab 发表于 2024-9-24 00:13
Python源码:

还带gui的啊
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-7-1 16:25 , Processed in 0.110867 second(s), 63 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表