以下为完整代码:
import tkinter as tk
import random
import time
background = 'gray'
egg_color = 'red'
snake_color = 'black'
score = 0
gameover = False
grid_size = 20
grid_num = 30
width = grid_size * grid_num + 150
height = grid_size * grid_num
# 创建蛇
class Snake(object):
def __init__(self, canvas, x, y, distx=0, disty=1, length=1, color='black'):
self.canvas = canvas
self.length = length
self.color = color
self.x = x
self.y = y
self.head = canvas.create_rectangle(self.x * grid_size, self.y * grid_size, (self.x + 1) * grid_size,
(self.y + 1) * grid_size, fill=self.color)
# 蛇的整个身体
self.section = [[self.head, self.x, self.y]]
# 移动的方向
self.distx = distx
self.disty = disty
self.grid()
self.canvas.bind_all("" , self.move)
self.canvas.bind_all("" , self.move)
self.canvas.bind_all("" , self.move)
self.canvas.bind_all("" , self.move)
self.draw()
self.collision()
def grid(self):
"""
画格子
:return:
"""
for i in range(grid_num + 1):
self.canvas.create_line(grid_size * i, 0, grid_size * i, height)
self.canvas.create_line(0, grid_size * i, width - 150, grid_size * i)
def draw(self):
"""
画整个蛇
:return:
"""
# 更新头部
# self.canvas.move(self.head, self.distx * grid_size, self.disty * grid_size)
# self.upforward()
# self.x += self.distx
# self.y += self.disty
print('头部位置:', self.x, self.y)
idx = len(self.section) - 1
while idx > 0:
curItem = self.section[idx]
lastItem = self.section[idx - 1]
# print('身体移动:', curItem, '-->',lastItem)
# 把curItem移動到lastItem的位置,並且變換座標
dx = lastItem[1] - curItem[1]
dy = lastItem[2] - curItem[2]
self.canvas.move(curItem[0], dx * grid_size, dy * grid_size)
curItem[1] = lastItem[1]
curItem[2] = lastItem[2]
idx -= 1
# 更新頭部
head = self.section[0]
self.canvas.move(self.head, self.distx * grid_size, self.disty * grid_size)
self.x += self.distx
self.y += self.disty
head[1] = self.x
head[2] = self.y
self.collision()
def lengthen(self):
"""
蛇变长
:return:
"""
x = self.section[-1][1]
y = self.section[-1][2] + 1
idn = self.canvas.create_rectangle(x * grid_size, y * grid_size, (x + 1) * grid_size, (y + 1) * grid_size,
fill=self.color)
self.section.append([idn, x, y])
# print('idn', idn, '初始位置:', x, y)
self.length += 1
def move(self, event):
"""
按钮按下的事件处理函数
:param event:
:return:
"""
if self.distx==0 and self.disty==-1:
if event.keysym == "Up":
self.distx = 0
self.disty = -1
elif event.keysym == "Left":
self.distx = -1
self.disty = 0
elif event.keysym == "Right":
self.distx = 1
self.disty = 0
else:
pass
if self.distx==0 and self.disty==1:
if event.keysym == "Left":
self.distx = -1
self.disty = 0
elif event.keysym == "Down":
self.distx = 0
self.disty = 1
elif event.keysym == "Right":
self.distx = 1
self.disty = 0
else:
pass
if self.distx==-1 and self.disty==0:
if event.keysym == "Left":
self.distx = -1
self.disty = 0
elif event.keysym == "Down":
self.distx = 0
self.disty = 1
elif event.keysym == "Up":
self.distx = 0
self.disty = -1
else:
pass
if self.distx==1 and self.disty==0:
if event.keysym == "Up":
self.distx = 0
self.disty = -1
elif event.keysym == "Down":
self.distx = 0
self.disty = 1
elif event.keysym == "Right":
self.distx = 1
self.disty = 0
else:
pass
def collision(self):
"""
撞墙 及是否咬到自己 判断
:return:
"""
global gameover
if (self.x == 0 and self.distx == -1) or (self.x == grid_num - 1 and self.distx == 1) or (
self.y == 0 and self.disty == -1) or (self.y == grid_num - 1 and self.disty == 1):
gameover = True
cnt=len(self.section)-1
while cnt>0:
curItem=self.section[cnt]
# print('cunItem:', curItem)
if self.x==curItem[1] and self.y==curItem[2]:
gameover = True
break
cnt -=1
class Egg(object):
def __init__(self, canvas, x, y, color='red'):
self.cvs = canvas
self.x = x
self.y = y
# print('egg: ', self.x, self.y)
self.color = color
# self.draw(self.color)
self.id=self.cvs.create_rectangle(grid_size * self.x, grid_size * self.y, grid_size * (self.x + 1),
grid_size * (self.y + 1),
fill=color)
# def draw(self, color):
# self.cvs.create_rectangle(grid_size * self.x, grid_size * self.y, grid_size * (self.x + 1),
# grid_size * (self.y + 1),
# fill=color)
def new_egg(self):
# self.draw('gray')
x = random.randint(1, grid_num - 2)
y = random.randint(1, grid_num - 2)
dx=x-self.x
dy=y-self.y
# print('移动: ', dx, dy)
self.cvs.move(self.id, dx * grid_size, dy * grid_size)
self.x = x
self.y = y
# print('egg: ',self.x, self.y)
def scored(x):
global background
# 计分区刷新
cvs.create_rectangle(width - 150, 0, width, 200, fill=background)
cvs.create_text(670, 100, text=['score:', str(x)],
fill='black', font=('Courier', 16))
def eat_egg(snake_x, snake_y, egg_x, egg_y):
global score
if snake_x == egg_x and snake_y == egg_y:
score += 1
scored(score)
egg.new_egg()
snake.lengthen()
root = tk.Tk()
root.title('snake')
root.geometry(
'%dx%d+%d+%d' % (width, height, (root.winfo_screenwidth() - width) / 2, (root.winfo_screenheight() - height) / 2))
# 窗口最大值
root.maxsize(width, height)
# 窗口最小值
root.minsize(width, height)
cvs = tk.Canvas(root, width=width, height=height, bg='grey')
cvs.pack()
root.update()
snake = Snake(cvs, 5, 5)
egg = Egg(cvs, 10, 10)
idx = 0
while not (gameover):
if idx % 20 == 0:
snake.draw()
eat_egg(snake.x, snake.y, egg.x, egg.y)
root.update_idletasks()
root.update()
time.sleep(0.01)
idx += 1
cvs.create_text(670, 400, text='GameOver!',
fill='red', font=('Courier', 16))
root.mainloop()