payhon贪吃蛇tkinter
时间: 2025-01-02 15:34:39 浏览: 9
### 使用 Python 和 Tkinter 实现贪吃蛇游戏
#### 加载所需库
为了创建基于 `Tkinter` 的贪吃蛇游戏,首先需要导入必要的模块。这通常包括 `tkinter` 本身以及用于处理时间延迟的 `time` 模块。
```python
import tkinter as tk
from random import randint
import time
```
#### 初始化窗口和画布
设置主窗口大小并配置背景颜色;接着定义一个 Canvas 组件作为绘图区域,在其中绘制所有的游戏元素。
```python
root = tk.Tk()
root.title("Snake Game with Tkinter")
canvas_width = 600
canvas_height = 400
canvas_bg_color = "black"
game_canvas = tk.Canvas(root, width=canvas_width, height=canvas_height, bg=canvas_bg_color)
game_canvas.pack()
```
#### 定义基本参数
设定网格尺寸、初始方向以及其他一些全局变量以便于后续逻辑操作。
```python
grid_size = 20
directions = {"Up": (-1, 0), "Down": (1, 0), "Left": (0, -1), "Right": (0, 1)}
current_direction = directions["Right"]
snake_body = [(randint(5, canvas_height//grid_size-5)*grid_size,
randint(5, canvas_width//grid_size-5)*grid_size)]
food_position = None
score = 0
speed_delay = 0.1
```
#### 食物生成函数
每当蛇吃到食物后都需要重新随机放置新的食物位置,并确保不会出现在当前蛇体上。
```python
def place_food():
global food_position
while True:
new_x = randint(0, (canvas_width // grid_size)-1) * grid_size
new_y = randint(0, (canvas_height // grid_size)-1) * grid_size
if (new_x, new_y) not in snake_body:
break
food_position = (new_x, new_y)
place_food() # 初始时调用一次以生成第一个食物的位置
```
#### 移动蛇的方法
根据当前的方向更新蛇头的新坐标,并将其加入到身体列表前端。如果撞墙或碰到自己则结束游戏。
```python
def move_snake():
head_x, head_y = snake_body[0]
delta_x, delta_y = current_direction
next_head_pos = ((head_x + delta_x*grid_size)%canvas_width,
(head_y + delta_y*grid_size)%canvas_height)
if next_head_pos in snake_body or \
next_head_pos == tuple(map(lambda i,j:i-j,(next_head_pos),(delta_x*grid_size,delta_y*grid_size))):
game_over()
elif next_head_pos != food_position:
snake_body.pop(-1) # 如果没有吃到食物,则移除最后一节尾巴保持长度不变
else:
global score; score += 1
place_food() # 吃到了食物就要再放一个新的出来哦~
snake_body.insert(0, next_head_pos)
```
#### 更新界面显示
每次移动完成后都要清除旧的画面重绘最新的状态,包括蛇的身体部分还有剩余的食物点位。
```python
def draw_game():
game_canvas.delete(tk.ALL)
for segment in snake_body:
game_canvas.create_rectangle(segment[0], segment[1],
segment[0]+grid_size, segment[1]+grid_size,
fill="green", outline="white")
if food_position is not None:
game_canvas.create_oval(food_position[0], food_position[1],
food_position[0]+grid_size, food_position[1]+grid_size,
fill="red", outline="")
root.update_idletasks()
root.after(int(speed_delay*1000), update_game_state)
```
#### 控制输入监听事件绑定
通过键盘按键改变前进方向,注意防止反向回转的情况发生。
```python
def change_direction(event):
key = event.keysym
opposites = {v:k for k,v in directions.items()}
opposite_dir = opposites.get(current_direction[::-1])
if key in ["w","W"] and opposite_dir!="Up":
set_new_direction(directions["Up"])
elif key in ["a","A"] and opposite_dir!="Left":
set_new_direction(directions["Left"])
elif key in ["d","D"] and opposite_dir!="Right":
set_new_direction(directions["Right"])
elif key in ["s","S"] and opposite_dir!="Down":
set_new_direction(directions["Down"])
def set_new_direction(new_dir):
global current_direction
current_direction = new_dir
```
#### 主循环定时器驱动
利用 `after()` 方法每隔一定毫秒数触发一次回调来进行帧刷新。
```python
def update_game_state():
try:
move_snake()
draw_game()
except Exception as e:
print(f"Game Over! Error occurred: {e}")
exit()
root.bind("<KeyPress>", change_direction)
update_game_state()
root.mainloop()
```
阅读全文