(1)蛇每走一步,就使用BFS计算游戏界面中每个位置(蛇身除外)到达食物的最短路径长;
(2)将蛇的安全定义为蛇是否可以跟着蛇尾运动,即蛇头和蛇尾间是否存在路径;
(3)蛇每次行动前先利用虚拟的蛇进行探路,若虚拟的蛇吃完食物后是安全的,真蛇才行动;
(4)若蛇和食物之间不存在路径或者吃完食物后并不安全,就跟着蛇尾走;
(5)若蛇和食物之间、蛇和蛇尾之间均不存在路径,就随便挑一步可行的来走;
(6)保证目标是食物时蛇走最短路径,目标是蛇尾时蛇走最长路径。
部分功能代码如下:
画网格
def drawGrid():
# 垂直方向
for x in range(0, SCREENWIDTH, CELLSIZE):
pygame.draw.line(screen, (40, 40, 40), (x, 0), (x, SCREENHEIGHT))
# 水平方向
for y in range(0, SCREENHEIGHT, CELLSIZE):
pygame.draw.line(screen, (40, 40, 40), (0, y), (SCREENWIDTH, y))
显示蛇
def ShowSnake(coords):
x = coords[0]['x'] * CELLSIZE
y = coords[0]['y'] * CELLSIZE
head_rect = pygame.Rect(x, y, CELLSIZE, CELLSIZE)
pygame.draw.rect(screen, (0, 80, 255), head_rect)
head_inner_rect = pygame.Rect(x + 4, y + 4, CELLSIZE - 8, CELLSIZE - 8)
pygame.draw.rect(screen, (0, 80, 255), head_inner_rect)
for coord in coords[1:]:
x = coord['x'] * CELLSIZE
y = coord['y'] * CELLSIZE
rect = pygame.Rect(x, y, CELLSIZE, CELLSIZE)
pygame.draw.rect(screen, (0, 155, 0), rect)
inner_rect = pygame.Rect(x + 4, y + 4, CELLSIZE - 8, CELLSIZE - 8)
pygame.draw.rect(screen, (0, 255, 0), inner_rect)
显示果实
def ShowApple(coord):
x = coord['x'] * CELLSIZE
y = coord['y'] * CELLSIZE
rect = pygame.Rect(x, y, CELLSIZE, CELLSIZE)
pygame.draw.rect(screen, (255, 0, 0), rect)
显示当前得分
def ShowScore(score):
score_render = default_font.render('得分: %s' % (score), True, (255, 255, 255))
rect = score_render.get_rect()
rect.topleft = (SCREENWIDTH-120, 10)
screen.blit(score_render, rect)
显示结束界面
def ShowEndInterface():
title_font = pygame.font.Font('simkai.ttf', 100)
title_game = title_font.render('Game', True, (233, 150, 122))
title_over = title_font.render('Over', True, (233, 150, 122))
game_rect = title_game.get_rect()
over_rect = title_over.get_rect()
game_rect.midtop = (SCREENWIDTH/2, 70)
over_rect.midtop = (SCREENWIDTH/2, game_rect.height+70+25)
screen.blit(title_game, game_rect)
screen.blit(title_over, over_rect)
pygame.display.update()
pygame.time.wait(500)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
CloseGame()
广度优先遍历, 计算每个非SNAKENUM元素到达食物的路径长度
def RefreshBoard(psnake, pfood, pboard):
temp_board = pboard[:]
pfood_idx = pfood['x'] + pfood['y'] * MATRIX_W
queue = []
queue.append(pfood_idx)
inqueue = [0] * MATRIX_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 isMovePossible(idx, move_direction):
if (idx + MOVEDIRECTIONS[move_direction]) == (psnake[HEADINDEX]['x'] + psnake[HEADINDEX]['y'] * MATRIX_W):
found = True
# 该点不是蛇身(食物是0才可以这样子写)
if temp_board[idx + MOVEDIRECTIONS[move_direction]] < SNAKENUM:
if temp_board[idx + MOVEDIRECTIONS[move_direction]] > temp_board[idx]+1:
temp_board[idx + MOVEDIRECTIONS[move_direction]] = temp_board[idx] + 1
if inqueue[idx + MOVEDIRECTIONS[move_direction]] == 0:
queue.append(idx + MOVEDIRECTIONS[move_direction])
由于食物是随机出现的,若虚拟的蛇跑一遍发现去吃食物是不安全的,真蛇就不会去吃食物,而是选择追着蛇尾跑,若一直如此,就陷入了死循环,蛇一直追着蛇尾跑,直到你终止游戏为止。