1、主要功能
- 自定义食物
- 障碍物设置
- 游戏难度控制
- 游戏记录
- AI对战
- AI版发射炮弹
2、游戏截图
3、游戏代码
1.启动器部分
from tkinter import *
import os, sys
from tkinter import messagebox
import pygame
import ctypes
import tkinter as tk
pygame.init()
root = Tk()
root.title('启动程序')
sw = root.winfo_screenwidth()
sh = root.winfo_screenheight()
ww = 400
wh = 900
x = (sw-ww) / 2
y = (sh-wh) / 2
ctypes.windll.shcore.SetProcessDpiAwareness(1)
ScaleFactor=ctypes.windll.shcore.GetScaleFactorForDevice(0)
root.tk.call('tk', 'scaling', ScaleFactor/75)
root.geometry("%dx%d+%d+%d" %(ww,wh,x,y))
C = Canvas(root, bg='white', height=300, width=400)
filename = PhotoImage(file='x.png')
background_label = Label(root, image=filename)
background_label.place(x=0, y=0, relwidth=1, relheight=0.3)
C.pack()
l1 = Label(root, text="食物数量:1~50")
l1.pack()
xls_text = StringVar()
xls = Entry(root, textvariable = xls_text)
xls_text.set(" ")
xls.pack()
def open_app(app_dir):
os.startfile(app_dir)
def setnum():
x = xls_text.get()
if x == ' ':
x=1
file_handle1 = open('date2.txt', mode='w')
file_handle1.write('%d' % int(x))
file_handle1.close()
def x():
app_dir = 'snake.py'
open_app(app_dir)
def renji():
app_dir = 'PythonAISnake.py'
open_app(app_dir)
def date():
while True:
f = open('date.txt', 'r')
str1 = f.read()
f.close
return str1
def h():
window1 = Tk()
window1.title('游戏记录')
label = Label(window1, text=date())
label.pack()
m8 = Button(window1, text='清空数据', font=('KaiTi', 10, 'bold'), bg='white', fg='black', bd=2, width=10, command=clear_date)
m8.pack()
window1.mainloop()
#open("date.txt",'w').close()
def clear_date():
x = messagebox.askquestion('提示','确定清除?')
print(x)
if x == 'yes' :
open("date.txt",'w').close()
def m():
try:
setnum()
window2 = Tk()
window2.title('游戏选项')
sw = window2.winfo_screenwidth()
sh = window2.winfo_screenheight()
ww = 400
wh = 400
x = (sw-ww) / 2
y = (sh-wh) / 2
window2.geometry("%dx%d+%d+%d" %(ww,wh,x,y))
m1 = Button(window2, text='简单', font=('KaiTi', 36, 'bold'), bg='white', fg='black', bd=2, width=10, command=(lambda : xf(s=1)))
m2 = Button(window2, text='中等', font=('KaiTi', 36, 'bold'), bg='white', fg='black', bd=2, width=10, command=(lambda : xf(s=2)))
m3 = Button(window2, text='困难', font=('KaiTi', 36, 'bold'), bg='white', fg='black', bd=2, width=10, command=(lambda : xf(s=3)))
m1.pack()
m2.pack()
m3.pack()
window2.mainloop()
except ValueError:
messagebox.showinfo("提示","请输入整数")
def xf(s):
if s == 1:
x = 5
else:
if s == 2:
x = 10
else:
x = 15
file_handle = open('date1.txt', mode='w')
file_handle.write('%s' % str(x))
file_handle.close()
app_dir = 'snake.py'
open_app(app_dir)
b = Button(root, text='开始游戏', font=('KaiTi', 36, 'bold'), bg='white', fg='black', bd=2, width=10, command=m)
c = Button(root, text='退出游戏', font=('KaiTi', 36, 'bold'), bg='white', fg='black', bd=2, width=10, command=(root.quit))
d = Button(root, text='游戏记录', font=('KaiTi', 36, 'bold'), bg='white', fg='black', bd=2, width=10, command=h)
k = Button(root, text='人机对战', font=('KaiTi', 36, 'bold'), bg='white', fg='black', bd=2, width=10, command=renji)
b.pack()
c.pack()
d.pack()
k.pack()
root.mainloop()
2.普通版部分
## 导入相关模块
import random
import pygame
import sys
import time
from pygame.locals import *
snake_speed = 15 #贪吃蛇的速度
number = 11
f = open('date1.txt', 'r')
str1 = f.read()
f.close
snake_speed = int(str1)#通过读取date1.txt文件中的数据实现游戏难度的控制
fl = open('date2.txt','r')
str2 = fl.read()
fl.close
if str2 == '':
str2 = 1
number =int(str2)
if (number < 1 or number > 50):
number = 1
windows_width = 800
windows_height = 600 #游戏窗口的大小
cell_size = 20 #贪吃蛇身体方块大小,注意身体大小必须能被窗口长宽整除
''' #初始化区
由于我们的贪吃蛇是有大小尺寸的, 因此地图的实际尺寸是相对于贪吃蛇的大小尺寸而言的
'''
map_width = int(windows_width / cell_size)
map_height = int(windows_height / cell_size)
# 颜色定义
white = (255, 255, 255)
black = (0, 0, 0)
gray = (230, 230, 230)
dark_gray = (40, 40, 40)
DARKGreen = (0, 155, 0)
Green = (0, 255, 0)
Red = (255, 0, 0)
blue = (0, 0, 255)
dark_blue =(0,0, 139)
champagne = (255,255,153)
BG_COLOR = white #游戏背景颜色
pygame.mixer.init()
music = pygame.mixer.Sound("2.wav")
# 定义方向
UP = 1
DOWN = 2
LEFT = 3
RIGHT = 4
HEAD = 0 #贪吃蛇头部下标
#主函数
def main():
pygame.init()
snake_speed_clock = pygame.time.Clock()
screen = pygame.display.set_mode((windows_width, windows_height)) #
screen.fill(white)
pygame.display.set_caption(r"Python 贪吃蛇小游戏")
show_start_info(screen)
while True:
pygame.mixer.music.load("1.mp3")
pygame.mixer.music.play(-1)
running_game(screen, snake_speed_clock)
show_gameover_info(screen)
def running_game(screen,snake_speed_clock):
startx = random.randint(3, map_width - 8) #开始位置
starty = random.randint(3, map_height - 8)
snake_coords = [{'x': startx, 'y': starty}, #初始贪吃蛇
{'x': startx - 1, 'y': starty},
{'x': startx - 2, 'y': starty}]
direction = RIGHT # 开始时向右移动
food = []
a=number
while a>0:
food.append(get_random_location())
a=a-1
Barrier = []
Barrier.append({'x':8,'y':21})
Barrier.append({'x': 12, 'y': 21})
Barrier.append({'x': 16, 'y': 21})
Barrier.append({'x': 20, 'y': 21})
Barrier.append({'x': 24, 'y': 21})
Barrier.append({'x': 28, 'y': 21})
Barrier.append({'x': 32, 'y': 21})
Barrier.append({'x': 8, 'y': 17})
Barrier.append({'x': 8, 'y': 13})
Barrier.append({'x': 8, 'y': 9})
Barrier.append({'x': 32, 'y': 17})
Barrier.append({'x': 32, 'y': 13})
Barrier.append({'x': 32, 'y': 9})
Barrier.append({'x': 12, 'y': 9})
Barrier.append({'x': 16, 'y': 9})
Barrier.append({'x': 20, 'y': 9})
Barrier.append({'x': 24, 'y': 9})
Barrier.append({'x': 28, 'y': 9})
# print(Barrier)
# Barrier.append({'x':Barrier[0][x]+1, 'y':Barrier[0][y]})
# Barrier.append(Barrier[1] + 1)
# Barrier.append(Barrier[2] + 1)
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
elif event.type == KEYDOWN:
if (event.key == K_LEFT or event.key == K_a) and direction != RIGHT:
direction = LEFT
elif (event.key == K_RIGHT or event.key == K_d) and direction != LEFT:
direction = RIGHT
elif (event.key == K_UP or event.key == K_w) and direction != DOWN:
direction = UP
elif (event.key == K_DOWN or event.key == K_s) and direction != UP:
direction = DOWN
elif event.key == K_ESCAPE:
terminate()
move_snake(direction, snake_coords) #移动蛇
ret = snake_is_alive(snake_coords,Barrier)
mx(int(ret), len(snake_coords) - 4)#这个是排行榜
if not ret:
break #蛇跪了. 游戏结束
# snake_is_eat_food(snake_coords, food1, food2) #判断蛇是否吃到食物
# snake_is_eat_food(snake_coords, food3, food4)
screen.fill(BG_COLOR)
draw_grid(screen)
draw_snake(screen, snake_coords)
for i in range(18):
draw_barrier(screen, Barrier[i-1])
# draw_food(screen, food1, food2)
# draw_food(screen, food3, food4)
b=number
while b>0:
draw_food(screen,food[b-1])
b=b-1
draw_score(screen, len(snake_coords) - 4)
snake_is_eat_food(snake_coords, food, Barrier)
pygame.display.update()
snake_speed_clock.tick(snake_speed) #控制fps
def draw_barrier(screen , Barrier):
x = Barrier['x'] * cell_size
y = Barrier['y'] * cell_size
BarrierRect = pygame.Rect(x, y, cell_size, cell_size)
pygame.draw.rect(screen, black, BarrierRect)
def mx(x, s):#排行榜函数
if x != 1:
str1 = time.strftime('%Y.%m.%d %H:%M:%S', time.localtime(time.time()))
file_handle = open('date.txt', mode='a+')
if int(s) < 10:
file_handle.write('得分:0%s 日期: %s\n' % (s, str1))
else:
file_handle.write('得分:%s 日期: %s\n' % (s, str1))
file_handle.close()
def draw_food(screen, food):#把食物画出来,两个食物
x = food['x'] * cell_size
y = food['y'] * cell_size
appleRect = pygame.Rect(x, y, cell_size, cell_size)
pygame.draw.rect(screen, Red, appleRect)
#将贪吃蛇画出来
def draw_snake(screen, snake_coords):
for coord in snake_coords:
x = coord['x'] * cell_size
y = coord['y'] * cell_size
wormSegmentRect = pygame.Rect(x, y, cell_size, cell_size)
pygame.draw.rect(screen, dark_blue, wormSegmentRect)
wormInnerSegmentRect = pygame.Rect( #蛇身子里面的第二层亮绿色
x + 4, y + 4, cell_size - 8, cell_size - 8)
pygame.draw.rect(screen, blue, wormInnerSegmentRect)
#画网格(可选)
def draw_grid(screen):
for x in range(0, windows_width, cell_size): # draw 水平 lines
pygame.draw.line(screen, dark_gray, (x, 0), (x, windows_height))
for y in range(0, windows_height, cell_size): # draw 垂直 lines
pygame.draw.line(screen, dark_gray, (0, y), (windows_width, y))
#移动贪吃蛇
def move_snake(direction, snake_coords):
if direction == UP:
newHead = {'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y'] - 1}
elif direction == DOWN:
newHead = {'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y'] + 1}
elif direction == LEFT:
newHead = {'x': snake_coords[HEAD]['x'] - 1, 'y': snake_coords[HEAD]['y']}
elif direction == RIGHT:
newHead = {'x': snake_coords[HEAD]['x'] + 1, 'y': snake_coords[HEAD]['y']}
snake_coords.insert(0, newHead)
#判断蛇死了没
def snake_is_alive(snake_coords,Barrier):
tag = True
if snake_coords[HEAD]['x'] == -1 or snake_coords[HEAD]['x'] == map_width or snake_coords[HEAD]['y'] == -1 or \
snake_coords[HEAD]['y'] == map_height:
tag = False # 蛇碰壁啦
if ({'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y']} in Barrier):
tag = False
for snake_body in snake_coords[1:]:
if snake_body['x'] == snake_coords[HEAD]['x'] and snake_body['y'] == snake_coords[HEAD]['y']:
tag = False # 蛇碰到自己身体啦
return tag
def snake_is_eat_food(snake_coords, food, Barrier): #如果是列表或字典,那么函数内修改参数内容,就会影响到函数体外的对象。
if ({'x':snake_coords[HEAD]['x'], 'y':snake_coords[HEAD]['y']} in food):
music.play()
x = food.index({'x':snake_coords[HEAD]['x'], 'y':snake_coords[HEAD]['y']})
food[x]['x'] = random.randint(0, map_width - 1)
food[x]['y'] = random.randint(0, map_height - 1)
while ({'x':food[x]['x'],'y':food[x]['y']} in Barrier):
food[x]['x'] = random.randint(0, map_width -1)
food[x]['y'] = random.randint(0, map_height - 1)
else:
del snake_coords[-1] # 如果没有吃到实物, 就向前移动, 那么尾部一格删掉
#食物随机生成
def get_random_location():
return {'x': random.randint(0, map_width - 1), 'y': random.randint(0, map_height - 1)}
#开始信息显示
def show_start_info(screen):
font = pygame.font.Font('myfont.ttf', 40)
tip = font.render('按任意键开始游戏~~~', True, (65, 105, 225))
x = random.randint(0,100)
x = x % 3
if x == 0:
gamestart = pygame.image.load('gamestart1.png')
elif x == 1 :
gamestart = pygame.image.load('gamestart2.png')
else :
gamestart = pygame.image.load('gamestart3.png')
screen.blit(gamestart, (140, 30))
screen.blit(tip, (240, 550))
pygame.display.update()
while True: #键盘监听事件
for event in pygame.event.get(): # event handling loop
if event.type == QUIT:
terminate() #终止程序
elif event.type == KEYDOWN:
if (event.key == K_ESCAPE): #终止程序
terminate() #终止程序
else:
return #结束此函数, 开始游戏
#游戏结束信息显示
def show_gameover_info(screen):
pygame.mixer.music.load("3.mp3")
pygame.mixer.music.play()
font = pygame.font.Font('myfont.ttf', 40)
tip = font.render('按Q或者ESC退出游戏, 按M键重新开始游戏~', True, (65, 105, 225))
x = random.randint(0,100)
x = x % 3
if x == 0 :
gamestart = pygame.image.load('gameover1.png')
elif x == 1 :
gamestart = pygame.image.load('gameover2.png')
else :
gamestart = pygame.image.load('gameover3.png')
screen.blit(gamestart, (60, 0))
screen.blit(tip, (80, 300))
pygame.display.update()
while True: #键盘监听事件
for event in pygame.event.get(): # event handling loop
if event.type == QUIT:
terminate() #终止程序
elif event.type == KEYDOWN:
if event.key == K_ESCAPE or event.key == K_q: #终止程序
terminate() #终止程序
if event.key == K_m:
return #结束此函数, 重新开始游戏
#画成绩
def draw_score(screen,score):
font = pygame.font.Font('myfont.ttf', 30)
scoreSurf = font.render('得分: %s' % score, True, Green)
scoreRect = scoreSurf.get_rect()
scoreRect.topleft = (windows_width - 120, 10)
screen.blit(scoreSurf, scoreRect)
#程序终止
def terminate():
pygame.quit()
sys.exit()
main()
3.AI版
#1.添加音乐、吃到食物音效
#2.添加多个食物(5个)
#**3.修改对抗规则:玩家控制蛇撞到电脑控制蛇会死亡
#4.修改电脑获取食物坐标机制,暂时定于计算机遍历每个坐标与食物坐标对比获得
#5.修改游戏规则,谁先到达一定长度谁赢
######################################################################
####################*************************#########################
######################################################################
import random
import pygame
import sys
from pygame.locals import *
snake_speed = 10 #贪吃蛇的速度
windows_width = 800
windows_height = 600 #游戏窗口的大小
cell_size = 20 #贪吃蛇身体方块大小,注意身体大小必须能被窗口长宽整除
assert windows_width % cell_size == 0
assert windows_height % cell_size == 0
''' #初始化区
由于我们的贪吃蛇是有大小尺寸的, 因此地图的实际尺寸是相对于贪吃蛇的大小尺寸而言的
'''
map_width = int(windows_width / cell_size)
map_height = int(windows_height / cell_size)
# 颜色定义
white = (255, 255, 255)
black = (0, 0, 0)
gray = (230, 230, 230)
dark_gray = (40, 40, 40)
DARKGreen = (0, 155, 0)
Green = (0, 255, 0)
Red = (255, 0, 0)
blue = (0, 0, 255)
dark_blue =(0,0, 139)
BG_COLOR = black #游戏背景颜色
pygame.mixer.init()
music = pygame.mixer.Sound("2.wav")
UP = 1
DOWN = 2
LEFT = 3
RIGHT = 4
HEAD = 0
#主函数
def main():
pygame.init()
snake_speed_clock = pygame.time.Clock()
screen = pygame.display.set_mode((windows_width, windows_height)) #
screen.fill(white)
pygame.display.set_caption("Python 贪吃蛇小游戏")
show_start_info(screen)
while True:
pygame.mixer.music.load("1.mp3")
pygame.mixer.music.play(-1)
running_game(screen, snake_speed_clock)
#run_game_AI(screen, snake_speed_clock)
#上1下2左3右4
#游戏运行主体
def running_game(screen,snake_speed_clock):
board = [0] * FIELD_SIZE
startx = 3
starty = 5
snake_coords1 = [{'x': startx, 'y': starty},
{'x': startx - 1, 'y': starty},
{'x': startx - 2, 'y': starty}]
snake_coords = [{'x': startx, 'y': starty+10}, #人控制的
{'x': startx - 1, 'y': starty},
{'x': startx - 2, 'y': starty}]
direction = RIGHT
direction1 = RIGHT
food = []
a = 5
shoot = False
bongLocate = snake_coords1[HEAD]
bongDirection = LEFT
live = True
while a>0:
food.append(get_random_location())
a=a-1
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
elif event.type == KEYDOWN:
if (event.key == K_LEFT or event.key == K_a) and direction1 != RIGHT:
direction1 = LEFT
elif (event.key == K_RIGHT or event.key == K_d) and direction1 != LEFT:
direction1 = RIGHT
elif (event.key == K_UP or event.key == K_w) and direction1 != DOWN:
direction1 = UP
elif (event.key == K_DOWN or event.key == K_s) and direction1 != UP:
direction1 = DOWN
elif event.key == K_ESCAPE:
terminate()
elif event.key == K_SPACE:
if shoot == False and len(snake_coords1) > 3:
shoot = True
del snake_coords1[-1]
bongDirection = direction1
if bongDirection == 1 :
bongLocate['x'] = snake_coords1[HEAD]['x']
bongLocate['y'] = snake_coords1[HEAD]['y'] - 2
if bongDirection == 2 :
bongLocate['x'] = snake_coords1[HEAD]['x']
bongLocate['y'] = snake_coords1[HEAD]['y'] + 2
if bongDirection == 3 :
bongLocate['x'] = snake_coords1[HEAD]['x'] - 2
bongLocate['y'] = snake_coords1[HEAD]['y']
if bongDirection == 4 :
bongLocate['x'] = snake_coords1[HEAD]['x'] + 2
bongLocate['y'] = snake_coords1[HEAD]['y']
food_location = find_food(food)
#if len(snake_coords) > 9:
# live = False
if not live and len(snake_coords) > 4:
#board[head_idx] = SNAKE_PLACE
#board[end_idx] = FREE_PLACE
del snake_coords[-1]
del snake_coords[-1]
del snake_coords[-1]
del snake_coords[-1]
#del snake_coords[-1]
shoot = False
live = True
# print(food_location)
reset_board = board_reset(snake_coords, board, food_location)
board = reset_board
result, refresh_board = board_refresh(snake_coords, food_location, board)
board = refresh_board
# 如果蛇可以吃到食物
if result:
best_move = find_safe_way(snake_coords, board, food_location)
else:
best_move = follow_tail(snake_coords, board, food_location)
if best_move == ERR:
best_move = any_possible_move(snake_coords, board, food_location)
if best_move != ERR:
newHead = find_snake_head(snake_coords, best_move)
snake_coords.insert(0, newHead)
head_idx = snake_coords[HEAD]['x'] + snake_coords[HEAD]['y']*map_width
end_idx = snake_coords[-1]['x'] + snake_coords[-1]['y']*map_width
if ({'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y']} in food):
board[head_idx] = SNAKE_PLACE
if len(snake_coords) < FIELD_SIZE:
xx = food.index({'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y']})
food[xx]['x'] = random.randint(0, map_width - 1)
food[xx]['y'] = random.randint(0, map_height - 1)
else:
board[head_idx] = SNAKE_PLACE
board[end_idx] = FREE_PLACE
del snake_coords[-1]
else:
return
move_snake(direction1, snake_coords1) #移动蛇
# print(snake_speed)
# print(food_location)
# print(m)
snake_is_eat_food(snake_coords1, food) #判断蛇是否吃到食物
screen.fill(BG_COLOR)
#print(bongDirection)
if shoot:
#print(bongLocate)
draw_bong(screen, bongLocate)
if bongDirection == 1 :
bongLocate['y'] = bongLocate['y'] - 1
elif bongDirection == 2 :
bongLocate['y'] = bongLocate['y'] + 1
elif bongDirection == 3:
bongLocate['x'] = bongLocate['x'] - 1
elif bongDirection == 4 :
bongLocate['x'] = bongLocate['x'] + 1
live = AIanake_is_alive(snake_coords,bongLocate)#判断AI贪吃蛇死了没
if bongLocate['x'] <= -1 or bongLocate['x'] >= map_width or bongLocate['y'] <= -1 or bongLocate['y'] >= map_height :
shoot = False
# del snake_coords[-5]
#gameover(screen)
#break
draw_score(screen, len(snake_coords) - 3, len(snake_coords1)-3)
#print(len(snake_coords))
ret = snake_is_alive(snake_coords1, snake_coords)
#ret = True
if not ret or len(snake_coords)-3 == 30 or len(snake_coords1)-3 == 30:
show_gameover_info(screen, len(snake_coords) -3, len(snake_coords1)-3,ret)
break # 蛇跪了. 游戏结束
draw_snake(screen, snake_coords)
draw_snake1(screen, snake_coords1)
a=5
while a>0:
draw_food(screen, food[a-1])
a=a-1
pygame.display.update()
snake_speed_clock.tick(10)
def draw_bong(screen, bong):
x = bong['x'] * cell_size
y = bong['y'] * cell_size
bongRect = pygame.Rect(x, y, cell_size, cell_size)
pygame.draw.rect(screen, Green, bongRect)
def find_food(food):
for x in range(windows_height):
for y in range(windows_width):
if ({'x':x, 'y':y} in food):
m = food.index({'x': x, 'y': y})
return food[m]
def draw_food(screen, food):
x = food['x'] * cell_size
y = food['y'] * cell_size
appleRect = pygame.Rect(x, y, cell_size, cell_size)
pygame.draw.rect(screen, Red, appleRect)
#将贪吃蛇画出来
def draw_snake(screen, snake_coords):
for coord in snake_coords:
x = coord['x'] * cell_size
y = coord['y'] * cell_size
wormSegmentRect = pygame.Rect(x, y, cell_size, cell_size)
pygame.draw.rect(screen, dark_blue, wormSegmentRect)
wormInnerSegmentRect = pygame.Rect(
x + 4, y + 4, cell_size - 8, cell_size - 8)
pygame.draw.rect(screen, blue, wormInnerSegmentRect)
def draw_snake1(screen, snake_coords):
for coord in snake_coords:
x = coord['x'] * cell_size
y = coord['y'] * cell_size
wormSegmentRect = pygame.Rect(x, y, cell_size, cell_size)
pygame.draw.rect(screen, dark_blue, wormSegmentRect)
wormInnerSegmentRect = pygame.Rect(
x + 4, y + 4, cell_size - 8, cell_size - 8)
pygame.draw.rect(screen, Red, wormInnerSegmentRect)
#移动贪吃蛇
def move_snake(direction, snake_coords):
if direction == UP:
newHead = {'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y'] - 1}
elif direction == DOWN:
newHead = {'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y'] + 1}
elif direction == LEFT:
newHead = {'x': snake_coords[HEAD]['x'] - 1, 'y': snake_coords[HEAD]['y']}
elif direction == RIGHT:
newHead = {'x': snake_coords[HEAD]['x'] + 1, 'y': snake_coords[HEAD]['y']}
snake_coords.insert(0, newHead)
def AIanake_is_alive(snake,bong):
tag = True
for snake_body in snake[1:]:
if snake_body['x'] == bong['x'] and snake_body['y'] == bong['y']:
#print('被打到了')
#print(len(snake))
#del snake[-5]
tag = False
return tag
#判断蛇死了没
def snake_is_alive(snake_coords1,snake_coords):
tag = True
if snake_coords1[HEAD]['x'] == -1 or snake_coords1[HEAD]['x'] == map_width or snake_coords1[HEAD]['y'] == -1 or \
snake_coords1[HEAD]['y'] == map_height:
tag = False # 蛇碰壁啦
for snake_body in snake_coords1[1:]:
if snake_body['x'] == snake_coords1[HEAD]['x'] and snake_body['y'] == snake_coords1[HEAD]['y']:
tag = False # 蛇碰到自己身体啦
for snake_body in snake_coords[1:]:
if snake_body['x'] == snake_coords1[HEAD]['x'] and snake_body['y'] == snake_coords1[HEAD]['y']:
tag = False
return tag
#判断贪吃蛇是否吃到食物
def snake_is_eat_food(snake_coords, food):
if ({'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y']} in food):
music.play()
x = food.index({'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y']})
food[x]['x'] = random.randint(0, map_width - 1)
food[x]['y'] = random.randint(0, map_height - 1)
else:
del snake_coords[-1] # 如果没有吃到实物, 就向前移动, 那么尾部一格删掉
#食物随机生成
def get_random_location():
return {'x': random.randint(0, map_width -1), 'y': random.randint(0, map_height -1)}
def show_start_info(screen):
font = pygame.font.Font('myfont.ttf', 40)
tip = font.render('按任意键开始游戏~~~', True, (65, 105, 225))
x = random.randint(0,100)
x = x % 3
if x == 0:
gamestart = pygame.image.load('gamestart1.png')
elif x == 1:
gamestart = pygame.image.load('gamestart2.png')
else :
gamestart = pygame.image.load('gamestart3.png')
#print(x%3)
screen.blit(gamestart, (140, 30))
screen.blit(tip, (240, 550))
pygame.display.update()
while True: #键盘监听事件
for event in pygame.event.get():
if event.type == QUIT:
terminate() #终止程序
elif event.type == KEYDOWN:
if (event.key == K_ESCAPE): #终止程序
terminate() #终止程序
else:
return #结束此函数, 开始游戏
#游戏结束信息显示
def show_gameover_info(screen,s1,s2,ret):
font = pygame.font.Font('myfont.ttf', 40)
font_x=pygame.font.Font('myfont.ttf',80)
if s1<s2 and ret:
tips = font_x.render('玩家胜利',True,Red)
pygame.mixer.music.load("4.mp3")
pygame.mixer.music.play()
elif s1==s2 and ret:
tips = font_x.render('平局',True,Red)
pygame.mixer.music.load("4.mp3")
pygame.mixer.music.play()
else:
tips = font_x.render('计算机胜利',True,Red)
pygame.mixer.music.load("3.mp3")
pygame.mixer.music.play()
tip = font.render('按Q或者ESC退出游戏, 按任意键重新开始游戏~', True, (65, 105, 225))
x = random.randint(0,100)
x = x % 3
if x == 0:
gamestart = pygame.image.load('gameover1.png')
elif x == 1:
gamestart = pygame.image.load('gameover2.png')
else :
gamestart = pygame.image.load('gameover3.png')
screen.blit(gamestart, (60, 0))
screen.blit(tip, (80, 300))
screen.blit(tips, (300, 200))
pygame.display.update()
while True: #键盘监听事件
for event in pygame.event.get(): # event handling loop
if event.type == QUIT:
terminate() #终止程序
elif event.type == KEYDOWN:
if event.key == K_ESCAPE or event.key == K_q: #终止程序
terminate() #终止程序
else:
return #结束此函数, 重新开始游戏
#画成绩
def draw_score(screen,score1,score2):
font = pygame.font.Font('myfont.ttf', 30)
scoreSurf1 = font.render('计算机得分: %s' % score1, True, Green)
scoreSurf2 = font.render("玩家得分:%s" % score2, True , Green)
scoreRect1 = scoreSurf1.get_rect()
scoreRect2 = scoreSurf2.get_rect()
scoreRect1.topright = (windows_width - 600, 10)
scoreRect2.topleft = (windows_width -180,10)
# scoreRect.topleft
screen.blit(scoreSurf1, scoreRect1)
screen.blit(scoreSurf2,scoreRect2)
#程序终止
def terminate():
pygame.quit()
sys.exit()
# 运动方向字典
move_directions = {
'left': -1,
'right': 1,
'up': -map_width,
'down': map_width
}
def Is_Cell_Free(idx, psnake):
location_x = idx % map_width
location_y = idx // map_width
idx = {'x': location_x, 'y': location_y}
return (idx not in psnake)
# 检查位置idx是否可以向当前move方向运动
def is_move_possible(idx, move_direction):
flag = False
if move_direction == 'left':
if idx % map_width > 0:
flag = True
else:
flag = False
elif move_direction == 'right':
if idx % map_width < map_width-1:
flag = True
else:
flag = False
elif move_direction == 'up':
if idx > map_width-1:
flag = True
else:
flag = False
elif move_direction == 'down':
if idx < FIELD_SIZE - map_width:
flag = True
else:
flag = False
return flag
# 广度优先搜索遍历整个board
# 计算出board中每个非SNAKE_PLACE元素到达食物的路径长度
def board_refresh(psnake, pfood, pboard):
temp_board = pboard[:]
pfood_idx = pfood['x'] + pfood['y'] * map_width
queue = []
queue.append(pfood_idx)
inqueue = [0] * FIELD_SIZE
found = False
while len(queue) != 0:
idx = queue.pop(0)
if inqueue[idx] == 1:
continue
inqueue[idx] = 1
for move_direction in ['left', 'right', 'up', 'down']:
if is_move_possible(idx, move_direction):
if (idx+move_directions[move_direction]) == (psnake[HEAD]['x'] + psnake[HEAD]['y']*map_width):
found = True
# 该点不是蛇身(食物是0才可以这样子写)
if temp_board[idx+move_directions[move_direction]] < SNAKE_PLACE:
if temp_board[idx+move_directions[move_direction]] > temp_board[idx]+1:
temp_board[idx+move_directions[move_direction]] = temp_board[idx] + 1
if inqueue[idx+move_directions[move_direction]] == 0:
queue.append(idx+move_directions[move_direction])
return (found, temp_board)
# 根据board中元素值
# 从蛇头周围4个领域点中选择最短路径
def choose_shortest_safe_move(psnake, pboard):
best_move = ERR
min_distance = SNAKE_PLACE
for move_direction in ['left', 'right', 'up', 'down']:
idx = psnake[HEAD]['x'] + psnake[HEAD]['y']*map_width
if is_move_possible(idx, move_direction) and (pboard[idx+move_directions[move_direction]]<min_distance):
min_distance = pboard[idx+move_directions[move_direction]]
best_move = move_direction
return best_move
# 找到移动后蛇头的位置
def find_snake_head(snake_Coords, direction):
if direction == 'up':
newHead = {'x': snake_Coords[HEAD]['x'],
'y': snake_Coords[HEAD]['y']-1}
elif direction == 'down':
newHead = {'x': snake_Coords[HEAD]['x'],
'y': snake_Coords[HEAD]['y']+1}
elif direction == 'left':
newHead = {'x': snake_Coords[HEAD]['x']-1,
'y': snake_Coords[HEAD]['y']}
elif direction == 'right':
newHead = {'x': snake_Coords[HEAD]['x']+1,
'y': snake_Coords[HEAD]['y']}
return newHead
# 虚拟地运行一次
def virtual_move(psnake, pboard, pfood):
temp_snake = psnake[:]
temp_board = pboard[:]
reset_tboard = board_reset(temp_snake, temp_board, pfood)
temp_board = reset_tboard
food_eated = False
while not food_eated:
refresh_tboard = board_refresh(temp_snake, pfood, temp_board)[1]
temp_board = refresh_tboard
move_direction = choose_shortest_safe_move(temp_snake, temp_board)
snake_Coords = temp_snake[:]
temp_snake.insert(0, find_snake_head(snake_Coords, move_direction))
# 如果新的蛇头正好是食物的位置
if temp_snake[HEAD] == pfood:
reset_tboard = board_reset(temp_snake, temp_board, pfood)
temp_board = reset_tboard
pfood_idx = pfood['x'] + pfood['y'] * map_width
temp_board[pfood_idx] = SNAKE_PLACE
food_eated = True
else:
newHead_idx = temp_snake[0]['x'] + temp_snake[0]['y'] * map_width
temp_board[newHead_idx] = SNAKE_PLACE
end_idx = temp_snake[-1]['x'] + temp_snake[-1]['y'] * map_width
temp_board[end_idx] = FREE_PLACE
del temp_snake[-1]
return temp_snake, temp_board
# 检查蛇头和蛇尾间是有路径的
# 避免蛇陷入死路
def is_tail_inside(psnake, pboard, pfood):
temp_board = pboard[:]
temp_snake = psnake[:]
# 将蛇尾看作食物
end_idx = temp_snake[-1]['x'] + temp_snake[-1]['y'] * map_width
temp_board[end_idx] = FOOD
v_food = temp_snake[-1]
# 食物看作蛇身(重复赋值了)
pfood_idx = pfood['x'] + pfood['y'] * map_width
temp_board[pfood_idx] = SNAKE_PLACE
# 求得每个位置到蛇尾的路径长度
result, refresh_tboard = board_refresh(temp_snake, v_food, temp_board)
temp_board = refresh_tboard
for move_direction in ['left', 'right', 'up', 'down']:
idx = temp_snake[HEAD]['x'] + temp_snake[HEAD]['y']*map_width
end_idx = temp_snake[-1]['x'] + temp_snake[-1]['y']*map_width
if is_move_possible(idx, move_direction) and (idx+move_directions[move_direction] == end_idx) and (len(temp_snake)>3):
result = False
return result
# 根据board中元素值
# 从蛇头周围4个领域点中选择最远路径
def choose_longest_safe_move(psnake, pboard):
best_move = ERR
max_distance = -1
for move_direction in ['left', 'right', 'up', 'down']:
idx = psnake[HEAD]['x'] + psnake[HEAD]['y']*map_width
if is_move_possible(idx, move_direction) and (pboard[idx+move_directions[move_direction]]>max_distance) and (pboard[idx+move_directions[move_direction]]<FREE_PLACE):
max_distance = pboard[idx+move_directions[move_direction]]
best_move = move_direction
return best_move
# 让蛇头朝着蛇尾运行一步
def follow_tail(psnake, pboard, pfood):
temp_snake = psnake[:]
temp_board = board_reset(temp_snake, pboard, pfood)
# 将蛇尾看作食物
end_idx = temp_snake[-1]['x'] + temp_snake[-1]['y'] * map_width
temp_board[end_idx] = FOOD
v_food = temp_snake[-1]
# 食物看作蛇身
pfood_idx = pfood['x'] + pfood['y'] * map_width
temp_board[pfood_idx] = SNAKE_PLACE
# 求得每个位置到蛇尾的路径长度
result, refresh_tboard = board_refresh(temp_snake, v_food, temp_board)
temp_board = refresh_tboard
# 还原
temp_board[end_idx] = SNAKE_PLACE
# temp_board[pfood_idx] = FOOD
return choose_longest_safe_move(temp_snake, temp_board)
# 如果蛇和食物间有路径
# 则需要找一条安全的路径
def find_safe_way(psnake, pboard, pfood):
safe_move = ERR
real_snake = psnake[:]
real_board = pboard[:]
v_psnake, v_pboard = virtual_move(psnake, pboard, pfood)
# 如果虚拟运行后,蛇头蛇尾间有通路,则选最短路运行
if is_tail_inside(v_psnake, v_pboard, pfood):
safe_move = choose_shortest_safe_move(real_snake, real_board)
else:
safe_move = follow_tail(real_snake, real_board, pfood)
return safe_move
# 各种方案均无效时,随便走一步
def any_possible_move(psnake, pboard, pfood):
best_move = ERR
reset_board = board_reset(psnake, pboard, pfood)
pboard = reset_board
result, refresh_board = board_refresh(psnake, pfood, pboard)
pboard = refresh_board
min_distance = SNAKE_PLACE
for move_direction in ['left', 'right', 'up', 'down']:
idx = psnake[HEAD]['x'] + psnake[HEAD]['y']*map_width
if is_move_possible(idx, move_direction) and (pboard[idx+move_directions[move_direction]]<min_distance):
min_distance = pboard[idx+move_directions[move_direction]]
best_move = move_direction
return best_move
# 重置board
def board_reset(psnake, pboard, pfood):
temp_board = pboard[:]
pfood_idx = pfood['x'] + pfood['y'] * map_width
for i in range(FIELD_SIZE):
if i == pfood_idx:
temp_board[i] = FOOD
elif Is_Cell_Free(i, psnake):
temp_board[i] = FREE_PLACE
else:
temp_board[i] = SNAKE_PLACE
return temp_board
# 错误码
ERR = -404
FIELD_SIZE = map_width * map_height
# 运动方向
best_move = ERR
# 不同东西在矩阵里用不同的数字表示
FOOD = 0
FREE_PLACE = (map_width+1) * (map_height+1)
SNAKE_PLACE = 2 * FREE_PLACE
if __name__ == '__main__':
main()