Python贪吃蛇游戏重启报错:TypeError: next_turn()缺少food参数
Tkinter贪吃蛇游戏重启功能修复:解决TypeError参数缺失问题
问题描述
我用Tkinter开发了一款贪吃蛇游戏,蛇死亡后窗口会显示“Game over”,希望玩家点击窗口就能重启游戏。但尝试点击调用next_turn()函数时出现错误:TypeError: next_turn() missing 1 required positional argument: 'food',就算添加food参数也没解决问题,相关代码如下:
from tkinter import * import random GAME_WIDTH = 700 GAME_HEIGHT = 700 SPEED = 70 SPACE_SIZE = 20 BODY_PARTS = 3 SNAKE_COLOR = "#00FF00" FOOD_COLOR = "#FF0000" BACKGROUND_COLOR = "#000000" class Snake: def __init__(self): self.body_size = BODY_PARTS self.coordinates = [] self.squares = [] for i in range(0, BODY_PARTS): self.coordinates.append([0, 0]) for x, y in self.coordinates: square = canvas.create_rectangle(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=SNAKE_COLOR, tag="snake") self.squares.append(square) class Food: def __init__(self): x = random.randint(0, (GAME_WIDTH / SPACE_SIZE) - 1) * SPACE_SIZE y = random.randint(0, (GAME_HEIGHT / SPACE_SIZE) - 1) * SPACE_SIZE self.coordinates = [x, y] canvas.create_oval(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=FOOD_COLOR, tag="food") def next_turn(snake, food): x, y = snake.coordinates[0] if direction == "up": y -= SPACE_SIZE elif direction == "down": y += SPACE_SIZE elif direction == "left": x -= SPACE_SIZE elif direction == "right": x += SPACE_SIZE snake.coordinates.insert(0, (x, y)) square = canvas.create_rectangle(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=SNAKE_COLOR) snake.squares.insert(0, square) if x == food.coordinates[0] and y == food.coordinates[1]: global score score += 1 label.config(text="Score:{}".format(score)) canvas.delete('food') food = Food() global SPEED SPEED -= 1 else: del snake.coordinates[-1] canvas.delete(snake.squares[-1]) del snake.squares[-1] if check_collisions(snake): game_over() else: window.after(SPEED, next_turn, snake, food) def change_direction(new_direction): global direction if new_direction == 'left': if direction != 'right': direction = new_direction elif new_direction == 'right': if direction != 'left': direction = new_direction elif new_direction == 'up': if direction != 'down': direction = new_direction elif new_direction == 'down': if direction != 'up': direction = new_direction def check_collisions(snake): x, y = snake.coordinates[0] if x < 0 or x >= GAME_WIDTH: return True elif y < 0 or y >= GAME_HEIGHT: return True for body_part in snake.coordinates[1:]: if x == body_part[0] and y == body_part[1]: return True return False def game_over(): canvas.delete(ALL) canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height()/2, font=("consolas", 70), text="GAME OVER", fill="red", tag="gameover") canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height() - 200, font=("consolas", 20), text="click to play", fill="red", tag="para") window.bind('<Button-1>', next_turn) # HERE----------------------------------------------------------- window = Tk() window.title("Snake game") window.resizable(False, False) score = 0 direction = "down" label = Label(window, text="Score:{}".format(score), font=('consolas', 40)) label.pack() canvas = Canvas(window, bg=BACKGROUND_COLOR, height=GAME_HEIGHT, width=GAME_WIDTH) canvas.pack() window.update() window_width = window.winfo_width() window_height = window.winfo_height() screen_width = window.winfo_screenwidth() screen_height = window.winfo_screenheight() x = int((screen_width/2) - (window_width/2)) y = int((screen_height/2) - (window_height/2)) window.geometry(f"{window_width}x{window_height}+{x}+{y}") window.bind('<a>', lambda event: change_direction('left')) window.bind('<d>', lambda event: change_direction('right')) window.bind('<w>', lambda event: change_direction('up')) window.bind('<s>', lambda event: change_direction('down')) snake = Snake() food = Food() next_turn(snake, food) window.mainloop()
错误原因
- 事件回调参数不匹配:Tkinter绑定鼠标点击事件时,会自动把
event对象作为第一个参数传给回调函数,但next_turn需要的是snake和food两个参数,参数数量和类型不匹配,直接触发TypeError。 - 未重置游戏状态:游戏结束后,原有的蛇、食物实例已经失效,直接调用
next_turn无法恢复游戏,必须重置所有核心状态(分数、速度、方向、蛇和食物实例)。
解决方案
步骤1:新增重启游戏函数
创建restart_game函数,负责重置所有游戏状态,创建新的蛇和食物,启动游戏循环:
def restart_game(event=None): global score, direction, SPEED # 重置全局变量 score = 0 direction = "down" SPEED = 70 label.config(text="Score:{}".format(score)) # 清除画布所有内容 canvas.delete(ALL) # 创建新的蛇和食物实例 snake = Snake() food = Food() # 启动游戏循环 next_turn(snake, food) # 解除点击绑定,避免重复触发 window.unbind('<Button-1>')
步骤2:修改game_over函数的事件绑定
把game_over里的绑定改为调用restart_game:
def game_over(): canvas.delete(ALL) canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height()/2, font=("consolas", 70), text="GAME OVER", fill="red", tag="gameover") canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height() - 200, font=("consolas", 20), text="click to play", fill="red", tag="para") # 绑定点击事件到重启函数 window.bind('<Button-1>', restart_game)
修改后的完整代码
from tkinter import * import random GAME_WIDTH = 700 GAME_HEIGHT = 700 SPEED = 70 SPACE_SIZE = 20 BODY_PARTS = 3 SNAKE_COLOR = "#00FF00" FOOD_COLOR = "#FF0000" BACKGROUND_COLOR = "#000000" class Snake: def __init__(self): self.body_size = BODY_PARTS self.coordinates = [] self.squares = [] for i in range(0, BODY_PARTS): self.coordinates.append([0, 0]) for x, y in self.coordinates: square = canvas.create_rectangle(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=SNAKE_COLOR, tag="snake") self.squares.append(square) class Food: def __init__(self): x = random.randint(0, (GAME_WIDTH / SPACE_SIZE) - 1) * SPACE_SIZE y = random.randint(0, (GAME_HEIGHT / SPACE_SIZE) - 1) * SPACE_SIZE self.coordinates = [x, y] canvas.create_oval(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=FOOD_COLOR, tag="food") def next_turn(snake, food): x, y = snake.coordinates[0] if direction == "up": y -= SPACE_SIZE elif direction == "down": y += SPACE_SIZE elif direction == "left": x -= SPACE_SIZE elif direction == "right": x += SPACE_SIZE snake.coordinates.insert(0, (x, y)) square = canvas.create_rectangle(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=SNAKE_COLOR) snake.squares.insert(0, square) if x == food.coordinates[0] and y == food.coordinates[1]: global score, SPEED score += 1 label.config(text="Score:{}".format(score)) canvas.delete('food') food = Food() SPEED -= 1 else: del snake.coordinates[-1] canvas.delete(snake.squares[-1]) del snake.squares[-1] if check_collisions(snake): game_over() else: window.after(SPEED, next_turn, snake, food) def change_direction(new_direction): global direction if new_direction == 'left' and direction != 'right': direction = new_direction elif new_direction == 'right' and direction != 'left': direction = new_direction elif new_direction == 'up' and direction != 'down': direction = new_direction elif new_direction == 'down' and direction != 'up': direction = new_direction def check_collisions(snake): x, y = snake.coordinates[0] if x < 0 or x >= GAME_WIDTH or y < 0 or y >= GAME_HEIGHT: return True for body_part in snake.coordinates[1:]: if x == body_part[0] and y == body_part[1]: return True return False def game_over(): canvas.delete(ALL) canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height()/2, font=("consolas", 70), text="GAME OVER", fill="red", tag="gameover") canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height() - 200, font=("consolas", 20), text="click to play", fill="red", tag="para") window.bind('<Button-1>', restart_game) def restart_game(event=None): global score, direction, SPEED score = 0 direction = "down" SPEED = 70 label.config(text="Score:{}".format(score)) canvas.delete(ALL) snake = Snake() food = Food() next_turn(snake, food) window.unbind('<Button-1>') window = Tk() window.title("Snake game") window.resizable(False, False) score = 0 direction = "down" label = Label(window, text="Score:{}".format(score), font=('consolas', 40)) label.pack() canvas = Canvas(window, bg=BACKGROUND_COLOR, height=GAME_HEIGHT, width=GAME_WIDTH) canvas.pack() window.update() window_width = window.winfo_width() window_height = window.winfo_height() screen_width = window.winfo_screenwidth() screen_height = window.winfo_screenheight() x = int((screen_width/2) - (window_width/2)) y = int((screen_height/2) - (window_height/2)) window.geometry(f"{window_width}x{window_height}+{x}+{y}") window.bind('<a>', lambda event: change_direction('left')) window.bind('<d>', lambda event: change_direction('right')) window.bind('<w>', lambda event: change_direction('up')) window.bind('<s>', lambda event: change_direction('down')) snake = Snake() food = Food() next_turn(snake, food) window.mainloop()
内容的提问来源于stack exchange,提问作者NajwiększyPolskiCrusher
相关产品推荐
相关产品推荐

