tkinter制作的简易贪吃蛇
自己制作的第一个游戏!import tkinter as tk
import random
class Game(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title('Eat Snake')
# 固定边框
self.resizable(False,False)
# 设置边长、像素
self.width = 15
self.height = 16
self.px = 20
# 设置自动移动
self.auto = True
# 创建画布
self.canvas = tk.Canvas(
self, width=self.width*self.px,
height=self.height*self.px)
self.canvas.grid(row=0,column=0,columnspan=2)
# 设置画布的点集(范围)
self.canvas_set = set()
for i in range(0, self.width):
for j in range(0, self.height):
self.canvas_set.add((i,j))
# 绑定按键功能
self.bind("<Key-Right>", self.move_right)
self.bind("<Key-Left>", self.move_left)
self.bind("<Key-Up>", self.move_up)
self.bind("<Key-Down>", self.move_down)
# 运行游戏
self.run_game()
def draw_rect(self,x,y,obj="bg"):
""""绘制像素"""
match obj:
case 'bg':
# 设置背景像素颜色
fill = 'grey'
outline = 'white'
case 'snake':
# 设置蛇身像素颜色
fill = 'green'
outline = 'red'
case 'head':
# 设置蛇头像素颜色
fill = 'yellow'
outline = 'red'
case 'apple':
# 设置Food像素颜色
fill = 'red'
outline = 'yellow'
px = self.px
try:
# 绘制像素
self.canvas.create_rectangle(
x*px,y*px,
(x+1)*px,(y+1)*px,
fill=fill,outline=outline
)
except:
# 如果fill和outline没有定义,打印Error
print("Error")
def initialize(self):
"""初始化界面"""
# 绘制背景
for x,y in list(self.canvas_set):
self.draw_rect(x,y,obj='bg')
# 绘制初始的贪吃蛇
self.snake_list = [(self.width//2 + i,self.height//2) for i in range(3)]
for (i, j) in self.snake_list:
if (i,j) == self.snake_list[-1]:
self.draw_rect(i,j,obj='head')
else:
self.draw_rect(i,j,obj='snake')
# 绘制初始的Food
self.food_set = self.canvas_set.difference(set(self.snake_list))
self.food_x,self.food_y = random.choice(list(self.food_set))
self.draw_rect(self.food_x,self.food_y,obj='apple')
def flip(self,food=False):
"""刷新界面,使画面动起来"""
# 删除画布上所有元素
self.canvas.delete("all")
# 重新绘制当前画布上的元素
for (x,y) in list(self.canvas_set):
self.draw_rect(x,y,obj='bg')
for (i, j) in self.snake_list:
if (i, j) == self.snake_list[-1]:
self.draw_rect(i, j, obj='head')
else:
self.draw_rect(i, j, obj='snake')
if food:
self.food_set = self.canvas_set.difference(set(self.snake_list[-1]))
self.food_x,self.food_y = random.choice(list(self.food_set))
self.draw_rect(self.food_x, self.food_y, obj='apple')
def move_right(self,event):
x, y = self.snake_list[-1]
if x <= self.snake_list[-2] and y == self.snake_list[-2]:
pass
else:
self.run(1,0)
def move_left(self,event):
x, y = self.snake_list[-1]
if x >= self.snake_list[-2] and y == self.snake_list[-2]:
pass
else:
self.run(-1,0)
def move_up(self,event):
x, y = self.snake_list[-1]
if x == self.snake_list[-2] and y >= self.snake_list[-2]:
pass
else:
self.run(0,-1)
def move_down(self,event):
x, y = self.snake_list[-1]
if x == self.snake_list[-2] and y <= self.snake_list[-2]:
pass
else:
self.run(0,1)
def run(self,move_x,move_y):
x, y = self.snake_list[-1]
food = self.eat_food(x + move_x, y + move_y)
if food == False:
self.snake_list.pop(0)
else:
self.food_x, self.food_y = random.choice(list(self.food_set))
print(self.food_x, self.food_y)# 无意义,可删去
if move_x != 0 or move_y != 0:
self.snake_list.append((x + move_x, y + move_y))
if self.is_over(x + move_x, y + move_y):
self.game_over()
else:
self.flip(food)
def eat_food(self,x,y):
if x == self.food_x and y == self.food_y:
return True
else:
return False
def is_over(self,x,y):
ls = len(self.snake_list)
if x < 0 or y < 0 or x >= self.width or y >= self.height:
return True
elif (x, y) in self.snake_list[:ls-1]:
return True
return False
def again(self):
self.destroy()
self.__init__()
def game_over(self):
w = self.width*self.px // 2
h = self.height*self.px // 2
self.canvas.create_text(w, h, text="GAME OVER", fill="red", font=("黑体",50))
qb = tk.Button(self,text="QUIT", font=50, command=self.destroy)
qb.grid(row=1,column=0,sticky="nsew")
rb = tk.Button(self,text="Again", font=50, command=self.again)
rb.grid(row=1,column=1,sticky="nsew")
self.unbind("<Key-Right>")
self.unbind("<Key-Left>")
self.unbind("<Key-Up>")
self.unbind("<Key-Down>")
self.auto = False
# 取消所有后续的自动运行
self.canvas.after_cancel("automatic_run")
def run_game(self):
self.initialize()
if self.auto:
self.automatic_run()
self.mainloop()
def automatic_run(self):
if not hasattr(self, "game_over_called"):
ls = len(self.snake_list)
if self.snake_list == self.snake_list:
if self.snake_list > self.snake_list:
self.run(0,1)
else:
self.run(0,-1)
else:
if self.snake_list > self.snake_list:
self.run(1,0)
else:
self.run(-1,0)
if self.auto:
self.canvas.after(500,self.automatic_run)
if __name__ == '__main__':
game = Game() 代码问题分析与修改建议
这个贪吃蛇程序有几个关键问题需要修复,以下是主要修改点:
[*]1. 初始化蛇身错误
原代码:self.snake_list =
修改为:
self.snake_list = [(5, 8)]# 添加初始坐标
self.snake_dir = (1, 0) # 添加初始移动方向
[*]2. 按键绑定失效
原代码事件字符串为空:
self.bind("", self.move_right)
正确绑定方式:
self.bind("<Right>", self.move_right)
self.bind("<Left>", self.move_left)
self.bind("<Up>", self.move_up)
self.bind("<Down>", self.move_down)
[*]3. 移动逻辑错误
修改移动方法(以move_right为例):
def move_right(self, event):
if self.snake_dir != (-1, 0):# 禁止反向移动
self.snake_dir = (1, 0)
[*]4. 自动移动逻辑重构
修改自动移动方法:
def automatic_run(self):
if self.auto:
head_x, head_y = self.snake_list
food_dx = self.food_x - head_x
food_dy = self.food_y - head_y
# 简单AI自动寻路
if abs(food_dx) > abs(food_dy):
self.snake_dir = (1 if food_dx > 0 else -1, 0)
else:
self.snake_dir = (0, 1 if food_dy > 0 else -1)
self.run(*self.snake_dir)
self.after(200, self.automatic_run)
完整修改建议
# 在__init__方法中添加初始化方向
self.snake_dir = (1, 0)# 初始向右移动
# 修改run方法核心逻辑
def run(self, dx, dy):
new_head = (self.snake_list + dx,
self.snake_list + dy)
if self.is_dead(*new_head):
self.game_over()
return
self.snake_list.insert(0, new_head)
if new_head == (self.food_x, self.food_y):
self.flip(food=True)
else:
self.snake_list.pop()
self.flip()
# 修改碰撞检测
def is_dead(self, x, y):
if (x < 0 or y < 0 or
x >= self.width or y >= self.height or
(x, y) in self.snake_list):
return True
return False
改进建议
[*]添加分数统计功能
[*]实现难度等级(通过调节移动速度)
[*]添加暂停/继续功能(空格键控制)
[*]使用更智能的食物生成算法
这个修改后的版本应该可以正常运行基础贪吃蛇功能,方向键控制移动,自动模式下蛇会追踪食物。建议从基础版本开始逐步添加新功能。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 还不错的 能自己写出来,太强了{:10_254:} 太强了 厉害厉害{:5_106:} 有趣~ {:10_256:} 不二如是 发表于 2025-5-9 11:40
有趣~
这个评分的 C 币怎么加的 sfqxx 发表于 2025-5-10 09:20
这个评分的 C 币怎么加的
发优质内容(帖子、评论),多@我{:10_256:} 不二如是 发表于 2025-5-10 09:32
发优质内容(帖子、评论),多@我
{:10_323:} sfqxx 发表于 2025-5-10 09:35
{:10_256:}{:10_256:}{:10_256:}之前的好贴链接也可以发我 不二如是 发表于 2025-5-10 09:38
之前的好贴链接也可以发我
{:10_323:}
之前的好帖都被您评过了{:10_250:}{:10_275:} nice呀,学习了{:7_130:} 厉害 有时红点会出现在蛇的身上
本帖最后由 pyzyd 于 2025-5-12 16:51 编辑
zxlhbqhxy 发表于 2025-5-12 15:55
有时红点会出现在蛇的身上
哈哈,我以前玩的就是这种,只是不会出现在头上 {:5_101:}非常好 厉害 加油!
页:
[1]
2