from tkinter import *
import random
class SnakeGame:
def __init__(self):
# moving step for snake and food
self.step = 15
# game score
self.gamescore = -10
self.level = 0
# to initialize the snake in the range of (x1,y1,x2,y2)
r = random.randrange(400, 600, self.step)
self.snakeX = [r, r + self.step, r + self.step * 2]
self.snakeY = [r, r, r]
# to initialize the moving direction
self.snakeDirection = 'left'
self.snakeMove = [-1, 0]
# to draw the game frame
window = Tk()
window.geometry("600x400+10+10")
window.maxsize(600, 400)
window.minsize(600, 400)
window.title("Snake game")
self.frame1 = Frame(window, height=371, width=600)
self.frame2 = Frame(window, width=600, height=371, bg="white")
self.canvas = Canvas(self.frame1, width=600, height=371, bg="grey")
self.score_label = Label(self.frame2, text="Score:")
self.frame1.pack()
self.frame2.pack(fill=BOTH)
self.score_label.pack(side=LEFT)
self.canvas.pack(fill=BOTH)
self.draw_wall()
self.draw_score()
self.draw_food()
self.draw_snake()
self.play()
window.mainloop()
"=== View Part ==="
def draw_wall(self):
self.canvas.create_line(10, 10, 582, 10, fill='blue', width=5)
self.canvas.create_line(10, 359, 582, 359, fill='blue', width=5)
self.canvas.create_line(10, 10, 10, 359, fill='blue', width=5)
self.canvas.create_line(582, 10, 582, 359, fill='blue', width=5)
def draw_score(self):
self.score() # score model
self.score_label.config(self.score_label,
text="Score: " + str(self.gamescore) + " level: " + str(self.level))
def draw_food(self):
self.canvas.delete("food")
self.foodx, self.foody = self.random_food() # food model
self.canvas.create_rectangle(self.foodx, self.foody, self.foodx + 15, self.foody + 15, fill="red", tags="food")
def draw_snake(self):
self.canvas.delete("snake")
x, y = self.snake() # snake model
for i in range(len(x)): # snake view
self.canvas.create_rectangle(x[i], y[i], x[i] + self.step, y[i] + self.step, fill="orange", tags='snake')
"=== Model Part ==="
# food model
def random_food(self):
return random.randrange(11, 570, self.step), random.randrange(11, 340, self.step)
# snake model
def snake(self):
for i in range(len(self.snakeX) - 1, 0, -1):
self.snakeX[i] = self.snakeX[i - 1]
self.snakeY[i] = self.snakeY[i - 1]
self.snakeX[0] += self.snakeMove[0] * self.step
self.snakeY[0] += self.snakeMove[1] * self.step
return self.snakeX, self.snakeY
# score model
def score(self):
self.gamescore = self.gamescore + 10
if self.gamescore % 100 == 0:
self.level = self.gamescore // 100 + 1
return self.score, self.level
"=== Control Part ==="
def iseated(self):
if self.snakeX[0] == self.foodx and self.snakeY[0] == self.foody:
return True
else:
return False
def isdead(self):
# 判断是否头触墙以及是否咬到自身
if self.snakeX[0] < 8 or self.snakeX[0] > 580 or self.snakeY[0] < 8 or self.snakeY[0] > 350:
return self.gameover
for i in range(1, len(self.snakeX)):
if self.snakeX[0] == self.snakeX[i] and self.snakeY[0] == self.snakeY[i]:
return self.gameover
else:
return False
def move(self, event):
# left:[-1,0],right:[1,0],up:[0,1],down:[0,-1]
if (event.keycode == 39 or event.keycode == 68) and self.snakeDirection != 'left':
self.snakeMove = [1, 0]
self.snakeDirection = "right"
elif (event.keycode == 38 or event.keycode == 87) and self.snakeDirection != 'down':
self.snakeMove = [0, -1]
self.snakeDirection = "up"
elif (event.keycode == 37 or event.keycode == 65) and self.snakeDirection != 'right':
self.snakeMove = [-1, 0]
self.snakeDirection = "left"
elif (event.keycode == 40 or event.keycode == 83) and self.snakeDirection != 'up':
self.snakeMove = [0, 1]
self.snakeDirection = "down"
else:
pass
# above codes can be insteaded by the following codes
# if (event.keysym == 'Right' or event.keysym == 'd') and self.snakeDirection != 'left':
# self.snakeMove = [1,0]
# self.snakeDirection = "right"
# elif (event.keysym == 'Up' or event.keysym == 'w') and self.snakeDirection != 'down':
# self.snakeMove = [0,-1]
# self.snakeDirection = "up"
# elif (event.keysym == 'Left' or event.keysym == 'a') and self.snakeDirection != 'right':
# self.snakeMove = [-1,0]
# self.snakeDirection = "left"
# elif (event.keysym == 'Down' or event.keysym == 's') and self.snakeDirection != 'up':
# self.snakeMove = [0,1]
# self.snakeDirection = "down"
# else:
# pass
def play(self):
self.canvas.bind_all("" , self.move)
self.canvas.focus_set()
while True:
if self.isdead():
self.gameover()
break
elif self.iseated():
self.snakeX[0] += self.snakeMove[0] * self.step
self.snakeY[0] += self.snakeMove[1] * self.step
self.snakeX.insert(1, self.foodx)
self.snakeY.insert(1, self.foody)
self.draw_score()
self.draw_food()
self.draw_snake()
else:
self.draw_snake()
self.canvas.after(200)
self.canvas.update()
def gameover(self):
# self.canvas.delete("food","snake")
self.canvas.unbind_all("" )
self.canvas.bind_all("" , self.restart)
self.canvas.create_text(270, 180, text=" Game Over!\n \
Press any key to continue", font='Helvetica -30 bold', tags='text')
def restart(self, event):
self.canvas.delete("food", "snake", "text")
self.canvas.unbind_all('' )
# to initialize the snake in the range of (191,191,341,341)
r = random.randrange(191, 191 + 15 * 10, self.step)
self.snakeX = [r, r + self.step, r + self.step * 2]
self.snakeY = [r, r, r]
# to initialize the moving direction
self.snakeDirection = 'left'
self.snakeMove = [-1, 0]
# reset the score to zero
self.gamescore = -10
self.draw_score()
# to initialize the game (food and snake)
self.draw_food()
self.draw_snake()
# to play the game
self.play()
SnakeGame()
值得注意的是关于Python3中tkinter将键绑定到按钮的方式
#python 3.x
#键盘事件
canvas.bind_all("" ,echo_event)
#如果绑定指定的键盘,则"" 或者""都可以,具体到指定键的话后面加入下划线和指定的键就好了,如:绑定小写字母t和Left键
canvas.bind_all("" ,echo_event)
canvas.bind_all("" ,echo_event)
#鼠标事件
canvas.bind_all("" ,echo_event)
canvas.bind_all("" ,echo_event)
canvas.bind_all("" ,echo_event)
canvas.bind_all("" ,echo_event)
详细绑定信息可以看Python Tkinter command和bind事件处理(绑定)用法详解