python实现贪吃蛇AI寻路

运行过程:

伪代码:
python实现贪吃蛇AI寻路_第1张图片
代码:
写的比较乱,没有整理过

import copy
import pygame, sys, random, time
from pygame.locals import *

######################################################################
#初始化Pygame库
pygame.init()
#初始化一个游戏界面窗口
DISPLAY = pygame.display.set_mode((300, 300))
#设置游戏窗口的标题
pygame.display.set_caption('贪吃蛇')
#定义一个变量来控制游戏速度
FPSCLOCK = pygame.time.Clock()
#初始化游戏界面内使用的字体
BASICFONT = pygame.font.SysFont("SIMYOU.TTF", 80)
font = pygame.font.SysFont('simsunnsimsun', 80)
BLACK = pygame.Color(0, 0, 0)
WHITE = pygame.Color(255, 255, 255)
RED = pygame.Color(255, 0, 0)
GREY = pygame.Color(150, 150, 150)
GREEN = pygame.Color(0, 255, 255)
YELLOW = pygame.Color(255, 255, 0)
FORESTGREEN = pygame.Color(34, 139, 34)
Purple3 = pygame.Color(125, 38, 205)
######################################################################
#贪吃蛇的的初始位置
snake_Head = [100, 100]
#初始化贪吃蛇的长度 (注:这里以20*20为一个标准小格子)
snake_Body = [[80, 100], [60, 100], [40, 100]]
#指定蛇初始前进的方向,向右
direction = "RIGHT"


def randomfood(snake_Body):
    # 随机生成x, y
    x = random.randrange(1, 15)
    y = random.randrange(1, 15)
    Position = [int(x * 20), int(y * 20)]
    while Position in snake_Body:
        x = random.randrange(1, 15)
        y = random.randrange(1, 15)
        Position = [int(x * 20), int(y * 20)]
    return Position


#随机出现第一个食物
food_Position = randomfood(snake_Body)
food_flag = 1


def GameOver():
    # 设置GameOver的显示颜色
    if (len(snake_Body) - 3) <= 10:
        GameOver_Surf = font.render('太菜了', True, GREY)
    elif 10 <= (len(snake_Body) - 3) <= 20:
        GameOver_Surf = font.render('一般般', True, GREY)
    else:
        GameOver_Surf = font.render('很棒!', True, GREY)
    # 设置GameOver的位置
    GameOver_Rect = GameOver_Surf.get_rect()
    GameOver_Rect.midtop = (320, 200)
    # 绑定以上设置到句柄
    DISPLAY.blit(GameOver_Surf, GameOver_Rect)

    pygame.display.flip()
    # 等待3秒
    time.sleep(3)
    # 退出游戏
    pygame.quit()
    # 退出程序
    sys.exit()


def walkable(location0, snake_body0):
    l = []
    if location0[0] + 20 < 300 and [location0[0] + 20, location0[1]] not in snake_body0:
        l.append([location0[0] + 20, location0[1]])

    if location0[0] - 20 >= 0 and [location0[0] - 20, location0[1]] not in snake_body0:
        l.append([location0[0] - 20, location0[1]])

    if location0[1] + 20 < 300 and [location0[0], location0[1] + 20] not in snake_body0:
        l.append([location0[0], location0[1] + 20])

    if location0[1] - 20 >= 0 and [location0[0], location0[1] - 20] not in snake_body0:
        l.append([location0[0], location0[1] - 20])

    return l


def changexy(position0):
    position = position0.copy()
    return position[1] * 15 + position[0]


def BFS(food_position0, snake_body0):
    food_position = food_position0.copy()
    snake_body = snake_body0.copy()
    flag = 0
    path = []
    search_stack = []
    visited_dict = {}
    search_stack.append([snake_body[0][0], snake_body[0][1]])
    visited_dict[changexy([snake_body[0][0], snake_body[0][1]])] = -1
    while len(search_stack) > 0:
        currentlocation = search_stack.pop(0)
        if currentlocation != food_position:
            l1 = walkable(currentlocation, snake_body)
            # print(l)
            for i in l1:
                if visited_dict.get(changexy(i)) == None:
                    search_stack.append(i)
                    visited_dict[changexy(i)] = currentlocation
        else:
            flag = 1
            break

    path.append(currentlocation)
    while visited_dict[changexy(currentlocation)] != -1:
        currentlocation = visited_dict[changexy(currentlocation)]
        path.append(currentlocation)
    path.reverse()

    return path, flag


def tailBFS(tail_position0, snake_body0):
    tail_position = tail_position0.copy()
    snake_body = snake_body0.copy()
    flag = 0
    path = []
    search_stack = []
    visited_dict = {}
    search_stack.append([snake_body[0][0], snake_body[0][1]])
    visited_dict[changexy([snake_body[0][0], snake_body[0][1]])] = -1
    while len(search_stack) > 0:
        currentlocation = search_stack.pop(0)
        if currentlocation != tail_position:
            tail = snake_body.pop()
            l1 = walkable(currentlocation, snake_body)
            snake_body.append(tail)
            # print(l)
            for i1 in l1:
                if visited_dict.get(changexy(i1)) == None:
                    search_stack.append(i1)
                    visited_dict[changexy(i1)] = currentlocation
        else:
            flag = 1
            break

    return flag


def exploretheway(food_position0, snake_body0):
    snake_body = snake_body0.copy()
    food_position = food_position0.copy()
    while True:
        path, flag1 = BFS(food_position, snake_body)
        snake_body.insert(0, path[1])
        if snake_body[0][0] == food_position[0] and snake_body[0][1] == food_position[1]:
            flag2 = tailBFS(snake_body[-1], snake_body)

            break
        else:
            snake_body.pop()
    return flag2


def longest_tail_path(snake_body0):
    snake_body = snake_body0.copy()
    tail = snake_body.pop()
    l0 = walkable(snake_body[0], snake_body)
    snake_body.append(tail)
    longest = -1

    for i0 in l0:
        flag = 0
        path = []
        search_stack = []
        visited_dict = {}

        search_stack.append(i0)

        visited_dict[changexy(i0)] = -1
        while len(search_stack) > 0:
            currentlocation = search_stack.pop(0)
            if currentlocation != snake_body[-1]:
                tail = snake_body.pop()
                l1 = walkable(currentlocation, snake_body)
                snake_body.append(tail)
                for j in l1:
                    if visited_dict.get(changexy(j)) == None:
                        search_stack.append(j)
                        visited_dict[changexy(j)] = currentlocation

            else:
                flag = 1
                break
        path.append(currentlocation)
        while visited_dict[changexy(currentlocation)] != -1:
            currentlocation = visited_dict[changexy(currentlocation)]
            path.append(currentlocation)
        path.reverse()

        if flag == 1:

            if len(path) > longest:
                longest = len(path)
                longest_path = path
    return longest_path


##漫步函数,随机选择蛇头周围四个方向中可走的方向走一步
def wander(snake_body0):
    l = walkable(snake_body0[0], snake_body0)
    if len(l) > 1:
        x = random.randrange(0, len(l))
    elif len(l) == 1:
        x = 0
    else:
        return l
    return l[x]

#######################################################################################################################
#######################################################################################################################
while True:
    food_path, food_flag = BFS(food_Position, snake_Body)
    tail_flag = tailBFS(snake_Body[-1], snake_Body)
    if food_flag == 1: ##当前布局能找到吃food_path
        virtual_tail_flag = exploretheway(food_Position, snake_Body) ##虚拟蛇探路,吃到食物后如果能找到tail_path则返回1
        if virtual_tail_flag == 1:##虚拟蛇吃完食物后找得到tail_path
            print("安全路径吃食物")
            ######真实的蛇沿最短路径向食物走一步######
            snake_Body.insert(0, food_path[1])
            if snake_Body[0][0] == food_Position[0] and snake_Body[0][1] == food_Position[1]:
                food_Position = randomfood(snake_Body)
            else:
                snake_Body.pop()
            #######################################

        else:  ##虚拟蛇吃完食物后找不到tail_path
            print("直接吃不安全,找蛇尾")
            ######真实的蛇沿最长路径向蛇尾走一步######
            longest_path = longest_tail_path(snake_Body)
            snake_Body.insert(0, longest_path[0])
            if snake_Body[0][0] == food_Position[0] and snake_Body[0][1] == food_Position[1]:
                food_Position = randomfood(snake_Body)
            else:
                snake_Body.pop()
            #######################################

    elif tail_flag == 1:##当前布局能找到tail_path(找不到food_path)
        print("找到蛇尾")
        ######真实的蛇沿最长路径向蛇尾走一步######
        longest_path = longest_tail_path(snake_Body)
        snake_Body.insert(0, longest_path[0])
        snake_Body.pop()
        #######################################

    elif food_flag != 1 and tail_flag != 1: ##找不到food_path也找不到tail_path时。随机走一步
        print("找不到食物也找不到蛇尾")
        if len(wander(snake_Body)) == 0:
            print("走投无路")
            GameOver()
            break
        else:
            snake_Body.insert(0, wander(snake_Body))
            snake_Body.pop()


#######################################################################################################################
#######################################################################################################################

    def drawSnake(snake_body0):
        pygame.draw.rect(DISPLAY, Purple3, Rect(snake_body0[0][0], snake_body0[0][1], 20, 20))
        for j in range(1, len(snake_body0)-1):
            pygame.draw.rect(DISPLAY, FORESTGREEN, Rect(snake_body0[j][0], snake_body0[j][1], 20, 20))
        pygame.draw.rect(DISPLAY, GREEN, Rect(snake_body0[-1][0], snake_body0[-1][1], 20, 20))


    def drawFood(food_position0):
        pygame.draw.rect(DISPLAY, RED, Rect(food_position0[0], food_position0[1], 20, 20))


    def drawScore(score):
        # 设置分数的显示颜色
        score_Surf = BASICFONT.render('%s' % (score), True, GREY)
        # 设置分数的位置
        score_Rect = score_Surf.get_rect()
        score_Rect.midtop = (50, 20)
        # 绑定以上设置到句柄
        DISPLAY.blit(score_Surf, score_Rect)


    DISPLAY.fill(BLACK)
    # 画出贪吃蛇
    drawSnake(snake_Body)
    # 画出食物的位置
    drawFood(food_Position)
    # 打印出玩家的分数
    drawScore(len(snake_Body) - 3)
    # 刷新Pygame的显示层,贪吃蛇与食物的每一次移动,都会进行刷新显示层的操作来显示。
    pygame.display.flip()
    # 控制游戏速度
    FPSCLOCK.tick(20)

    if snake_Body[0][0] < 0 or snake_Body[0][0] > 300:
        GameOver()
    if snake_Body[0][1] < 0 or snake_Body[0][1] > 300:
        GameOver()
    # 贪吃蛇触碰到自己
    for i in snake_Body[1:]:
        if snake_Body[0][0] == i[0] and snake_Body[0][1] == i[1]:
            GameOver()

最后结果:
运行到这里就不能继续吃到食物了。但是蛇也不会死,蛇头一直追着蛇尾跑,一直循环下去。
python实现贪吃蛇AI寻路_第2张图片

参考资料:
Hawstein. Snake AI. 2013 http://www.hawstein.com/posts/snake-ai.html
bilibili:幽蓝依梦 cv677066

你可能感兴趣的:(python实现贪吃蛇AI寻路)