鱼C论坛

 找回密码
 立即注册
查看: 92|回复: 12

[作品展示] tkinter制作的简易贪吃蛇

[复制链接]
回帖奖励 69 鱼币 回复本帖可获得 3 鱼币奖励! 每人限 1 次(中奖概率 90%)
发表于 3 天前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
自己制作的第一个游戏!
  1. import tkinter as tk
  2. import random

  3. class Game(tk.Tk):
  4.     def __init__(self):
  5.         tk.Tk.__init__(self)
  6.         self.title('Eat Snake')
  7.         # 固定边框
  8.         self.resizable(False,False)
  9.         # 设置边长、像素
  10.         self.width = 15
  11.         self.height = 16
  12.         self.px = 20
  13.         # 设置自动移动
  14.         self.auto = True
  15.         # 创建画布
  16.         self.canvas = tk.Canvas(
  17.             self, width=self.width*self.px,
  18.             height=self.height*self.px)
  19.         self.canvas.grid(row=0,column=0,columnspan=2)
  20.         # 设置画布的点集(范围)
  21.         self.canvas_set = set()
  22.         for i in range(0, self.width):
  23.             for j in range(0, self.height):
  24.                 self.canvas_set.add((i,j))
  25.         # 绑定按键功能
  26.         self.bind("<Key-Right>", self.move_right)
  27.         self.bind("<Key-Left>", self.move_left)
  28.         self.bind("<Key-Up>", self.move_up)
  29.         self.bind("<Key-Down>", self.move_down)
  30.         # 运行游戏
  31.         self.run_game()

  32.     def draw_rect(self,x,y,obj="bg"):
  33.         """"绘制像素"""
  34.         match obj:
  35.             case 'bg':
  36.                 # 设置背景像素颜色
  37.                 fill = 'grey'
  38.                 outline = 'white'
  39.             case 'snake':
  40.                 # 设置蛇身像素颜色
  41.                 fill = 'green'
  42.                 outline = 'red'
  43.             case 'head':
  44.                 # 设置蛇头像素颜色
  45.                 fill = 'yellow'
  46.                 outline = 'red'
  47.             case 'apple':
  48.                 # 设置Food像素颜色
  49.                 fill = 'red'
  50.                 outline = 'yellow'
  51.         px = self.px
  52.         try:
  53.             # 绘制像素
  54.             self.canvas.create_rectangle(
  55.                 x*px,y*px,
  56.                 (x+1)*px,(y+1)*px,
  57.                 fill=fill,outline=outline
  58.             )
  59.         except:
  60.             # 如果fill和outline没有定义,打印Error
  61.             print("Error")

  62.     def initialize(self):
  63.         """初始化界面"""
  64.         # 绘制背景
  65.         for x,y in list(self.canvas_set):
  66.             self.draw_rect(x,y,obj='bg')
  67.         # 绘制初始的贪吃蛇
  68.         self.snake_list = [(self.width//2 + i,self.height//2) for i in range(3)]
  69.         for (i, j) in self.snake_list:
  70.             if (i,j) == self.snake_list[-1]:
  71.                 self.draw_rect(i,j,obj='head')
  72.             else:
  73.                 self.draw_rect(i,j,obj='snake')
  74.         # 绘制初始的Food
  75.         self.food_set = self.canvas_set.difference(set(self.snake_list))
  76.         self.food_x,self.food_y = random.choice(list(self.food_set))
  77.         self.draw_rect(self.food_x,self.food_y,obj='apple')

  78.     def flip(self,food=False):
  79.         """刷新界面,使画面动起来"""
  80.         # 删除画布上所有元素
  81.         self.canvas.delete("all")
  82.         # 重新绘制当前画布上的元素
  83.         for (x,y) in list(self.canvas_set):
  84.             self.draw_rect(x,y,obj='bg')
  85.         for (i, j) in self.snake_list:
  86.             if (i, j) == self.snake_list[-1]:
  87.                 self.draw_rect(i, j, obj='head')
  88.             else:
  89.                 self.draw_rect(i, j, obj='snake')
  90.         if food:
  91.             self.food_set = self.canvas_set.difference(set(self.snake_list[-1]))
  92.             self.food_x,self.food_y = random.choice(list(self.food_set))
  93.         self.draw_rect(self.food_x, self.food_y, obj='apple')

  94.     def move_right(self,event):
  95.         x, y = self.snake_list[-1]
  96.         if x <= self.snake_list[-2][0] and y == self.snake_list[-2][1]:
  97.             pass
  98.         else:
  99.             self.run(1,0)

  100.     def move_left(self,event):
  101.         x, y = self.snake_list[-1]
  102.         if x >= self.snake_list[-2][0] and y == self.snake_list[-2][1]:
  103.             pass
  104.         else:
  105.             self.run(-1,0)

  106.     def move_up(self,event):
  107.         x, y = self.snake_list[-1]
  108.         if x == self.snake_list[-2][0] and y >= self.snake_list[-2][1]:
  109.             pass
  110.         else:
  111.             self.run(0,-1)

  112.     def move_down(self,event):
  113.         x, y = self.snake_list[-1]
  114.         if x == self.snake_list[-2][0] and y <= self.snake_list[-2][1]:
  115.             pass
  116.         else:
  117.             self.run(0,1)

  118.     def run(self,move_x,move_y):
  119.         x, y = self.snake_list[-1]
  120.         food = self.eat_food(x + move_x, y + move_y)
  121.         if food == False:
  122.             self.snake_list.pop(0)
  123.         else:
  124.             self.food_x, self.food_y = random.choice(list(self.food_set))
  125.             print(self.food_x, self.food_y)  # 无意义,可删去
  126.         if move_x != 0 or move_y != 0:
  127.             self.snake_list.append((x + move_x, y + move_y))
  128.         if self.is_over(x + move_x, y + move_y):
  129.             self.game_over()
  130.         else:
  131.             self.flip(food)

  132.     def eat_food(self,x,y):
  133.         if x == self.food_x and y == self.food_y:
  134.             return True
  135.         else:
  136.             return False

  137.     def is_over(self,x,y):
  138.         ls = len(self.snake_list)
  139.         if x < 0 or y < 0 or x >= self.width or y >= self.height:
  140.             return True
  141.         elif (x, y) in self.snake_list[:ls-1]:
  142.             return True
  143.         return False

  144.     def again(self):
  145.         self.destroy()
  146.         self.__init__()

  147.     def game_over(self):
  148.         w = self.width*self.px // 2
  149.         h = self.height*self.px // 2
  150.         self.canvas.create_text(w, h, text="GAME OVER", fill="red", font=("黑体",50))
  151.         qb = tk.Button(self,text="QUIT", font=50, command=self.destroy)
  152.         qb.grid(row=1,column=0,sticky="nsew")
  153.         rb = tk.Button(self,text="Again", font=50, command=self.again)
  154.         rb.grid(row=1,column=1,sticky="nsew")
  155.         self.unbind("<Key-Right>")
  156.         self.unbind("<Key-Left>")
  157.         self.unbind("<Key-Up>")
  158.         self.unbind("<Key-Down>")
  159.         self.auto = False
  160.         # 取消所有后续的自动运行
  161.         self.canvas.after_cancel("automatic_run")

  162.     def run_game(self):
  163.         self.initialize()
  164.         if self.auto:
  165.             self.automatic_run()
  166.         self.mainloop()

  167.     def automatic_run(self):
  168.         if not hasattr(self, "game_over_called"):
  169.             ls = len(self.snake_list)
  170.             if self.snake_list[ls-1][0] == self.snake_list[ls-2][0]:
  171.                 if self.snake_list[ls-1][1] > self.snake_list[ls-2][1]:
  172.                     self.run(0,1)
  173.                 else:
  174.                     self.run(0,-1)
  175.             else:
  176.                 if self.snake_list[ls-1][0] > self.snake_list[ls-2][0]:
  177.                     self.run(1,0)
  178.                 else:
  179.                     self.run(-1,0)
  180.         if self.auto:
  181.             self.canvas.after(500,self.automatic_run)

  182. if __name__ == '__main__':
  183.     game = Game()
复制代码

评分

参与人数 3荣誉 +10 鱼币 +6 贡献 +7 C币 +4 收起 理由
小甲鱼 + 3 + 3 + 3 + 3 鱼C有你更精彩^_^
sfqxx + 5 + 3
不二如是 + 2 + 3 + 1 + 1 鱼C有你更精彩^_^

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 3 天前 | 显示全部楼层
代码问题分析与修改建议

这个贪吃蛇程序有几个关键问题需要修复,以下是主要修改点:

  • 1. 初始化蛇身错误
    原代码:self.snake_list =
    修改为:

    1. self.snake_list = [(5, 8)]  # 添加初始坐标
    2. self.snake_dir = (1, 0)     # 添加初始移动方向
    复制代码

  • 2. 按键绑定失效
    原代码事件字符串为空:
    self.bind("", self.move_right)
    正确绑定方式:

    1. self.bind("<Right>", self.move_right)
    2. self.bind("<Left>", self.move_left)
    3. self.bind("<Up>", self.move_up)
    4. self.bind("<Down>", self.move_down)
    复制代码

  • 3. 移动逻辑错误
    修改移动方法(以move_right为例):

    1. def move_right(self, event):
    2.     if self.snake_dir != (-1, 0):  # 禁止反向移动
    3.         self.snake_dir = (1, 0)
    复制代码

  • 4. 自动移动逻辑重构
    修改自动移动方法:

    1. def automatic_run(self):
    2.     if self.auto:
    3.         head_x, head_y = self.snake_list[0]
    4.         food_dx = self.food_x - head_x
    5.         food_dy = self.food_y - head_y
    6.         
    7.         # 简单AI自动寻路
    8.         if abs(food_dx) > abs(food_dy):
    9.             self.snake_dir = (1 if food_dx > 0 else -1, 0)
    10.         else:
    11.             self.snake_dir = (0, 1 if food_dy > 0 else -1)
    12.         
    13.         self.run(*self.snake_dir)
    14.         self.after(200, self.automatic_run)
    复制代码



完整修改建议


  1. # 在__init__方法中添加初始化方向
  2. self.snake_dir = (1, 0)  # 初始向右移动

  3. # 修改run方法核心逻辑
  4. def run(self, dx, dy):
  5.     new_head = (self.snake_list[0][0] + dx,
  6.                 self.snake_list[0][1] + dy)
  7.    
  8.     if self.is_dead(*new_head):
  9.         self.game_over()
  10.         return
  11.    
  12.     self.snake_list.insert(0, new_head)
  13.    
  14.     if new_head == (self.food_x, self.food_y):
  15.         self.flip(food=True)
  16.     else:
  17.         self.snake_list.pop()
  18.         self.flip()

  19. # 修改碰撞检测
  20. def is_dead(self, x, y):
  21.     if (x < 0 or y < 0 or
  22.         x >= self.width or y >= self.height or
  23.         (x, y) in self.snake_list):
  24.         return True
  25.     return False
复制代码


改进建议
  • 添加分数统计功能
  • 实现难度等级(通过调节移动速度)
  • 添加暂停/继续功能(空格键控制)
  • 使用更智能的食物生成算法


这个修改后的版本应该可以正常运行基础贪吃蛇功能,方向键控制移动,自动模式下蛇会追踪食物。建议从基础版本开始逐步添加新功能。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 前天 07:11 | 显示全部楼层

回帖奖励 +3 鱼币

还不错的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 前天 08:32 | 显示全部楼层

回帖奖励 +3 鱼币

能自己写出来,太强了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 前天 09:57 | 显示全部楼层

回帖奖励 +3 鱼币

太强了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 前天 10:40 | 显示全部楼层

回帖奖励 +3 鱼币

厉害厉害
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 前天 11:40 | 显示全部楼层

回帖奖励 +3 鱼币

有趣~
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 前天 22:41 | 显示全部楼层

回帖奖励 +3 鱼币

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 昨天 09:20 | 显示全部楼层

回帖奖励 +3 鱼币


这个评分的 C 币怎么加的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 09:32 | 显示全部楼层
sfqxx 发表于 2025-5-10 09:20
这个评分的 C 币怎么加的

发优质内容(帖子、评论),多@我
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 09:35 | 显示全部楼层
不二如是 发表于 2025-5-10 09:32
发优质内容(帖子、评论),多@我

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 09:38 | 显示全部楼层

之前的好贴链接也可以发我
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 10:13 | 显示全部楼层
不二如是 发表于 2025-5-10 09:38
之前的好贴链接也可以发我


之前的好帖都被您评过了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-11 10:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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