智能蛇

在写完一条普通的贪吃蛇之后,我们的老师有增大了学习难度,要写出一条“有脑子的”蛇,通过算法,让小蛇具有 “感知 - 决策 - 行动” 的能力。其实,这也是锻炼我们自顶向下分析能力的很好机会。

这一条小蛇可以绕过类似枪一样的障碍物,变得“聪明”,这样子,就能实现一条智能蛇与人力蛇争抢食物,这将又会是人工智能与人的一次大比拼。

这里写图片描述

首先,利用自顶向下的思想,大致写出这个程序主要部分的伪代码,也就是决定蛇行走的方向函数的伪代码:

// Hx,Hy: 头的位置
    // Fx,Fy:食物的位置
    function whereGoNext(Hx,Hy,Fx,Fy) {
    // 用数组movable[3]={“a”,”d”,”w”,”s”} 记录可走的方向
    // 用数组distance[3]={0,0,0,0} 记录离食物的距离
    // 分别计算蛇头周边四个位置到食物的距离。H头的位置,F食物位置
    //     例如:假设输入”a” 则distance[0] = |Fx – (Hx-1)| + |Fy – Hy|
    //           如果 Hx-1,Hy 位置不是Blank,则 distance[0] = 9999
    // 选择distance中存最小距离的下标p,注意最小距离不能是9999
    // 返回 movable[p]
    }

然后是智能蛇的程序框架:

输出字符矩阵
    WHILE not 游戏结束 DO
        wait(time)
        ch=whereGoNext(Hx,Hy,Fx,Fy)
        CASE ch DO
        ‘A’:左前进一步,break 
        ‘D’:右前进一步,break    
        ‘W’:上前进一步,break    
        ‘S’:下前进一步,break    
        END CASE
        输出字符矩阵
    END WHILE
    输出 The game is over! 

最后,再结合之前写的贪吃蛇代码,就能弄出一条智能蛇啦

<think>我们使用Pygame来编写一个简单的贪吃游戏,并加入一些智能元素,比如自动寻路(使用A*算法)来让自动寻找食物。 由于贪吃游戏本身逻辑较为复杂,我们分步骤实现: 1. 初始化游戏和Pygame。 2. 定义和食物的类。 3. 实现手动控制和自动控制(智能)两种模式。 4. 实现A*算法用于自动寻找食物(注意:贪吃的寻路问题有其特殊性,因为的身体是障碍物,而且在移动时身体也会移动,因此传统的A*可能不是最优,我们可以考虑使用一些启发式方法,或者使用寻路到食物的路径,同时避免走入死胡同)。 考虑到时间,我们将实现一个基础版本,其中可以自动寻找食物,但可能不是完美的(因为完美的贪吃AI是一个复杂问题)。我们将使用A*算法来寻找从头到食物的最短路径,但是要注意的身体是动态障碍物。 注意:在贪吃中,如果直接使用A*找到的路径,可能会在路径中出现身移动后变成障碍物的情况。因此,我们这里采用一个简化版:只考虑当前帧的障碍物(身),不考虑未来移动时身体的变化。这样在不长的情况下可以工作,但当很长时可能会陷入死胡同。 我们将实现: - 游戏循环 - 的移动(包括自动和手动) - 食物的随机生成 - 碰撞检测(与边界、与自身) - 使用A*算法自动寻路 由于代码较长,我们将逐步构建。 步骤: 1. 初始化pygame,设置窗口大小等。 2. 定义颜色。 3. 创建类,包含身体(列表),方向,以及移动方法。 4. 创建食物类,随机位置生成。 5. 游戏主循环:处理事件,更新的位置,检查是否吃到食物,检查碰撞,绘制。 6. 在自动模式下,每一步都计算从头到食物的路径(使用A*),然后设置的方向为路径的第一步。 注意:A*算法需要网格地图,我们将游戏区域划分为网格(比如每个格子20x20像素)。 我们先实现手动模式,然后再加入自动模式。 由于贪吃游戏代码较长,我们将分块实现。 注意:由于我们使用A*,我们需要定义网格地图,每个格子可以是障碍(身)或自由(空或食物)。食物所在位置也是自由的,因为头可以到达。 这里我们假设网格大小为20x20,但实际游戏区域大小由窗口大小和网格大小决定。 我们设定窗口大小为800x600,网格大小为20,那么网格列数为40,行数为30。 下面开始写代码。 </think>### Python实现智能贪吃游戏 下面是一个使用Python和Pygame库实现的智能贪吃游戏。这个版本包含自动寻路算法,会自动寻找食物并避开障碍物。 ```python import pygame import sys import random import heapq import math # 初始化pygame pygame.init() # 游戏常量 WIDTH, HEIGHT = 600, 600 GRID_SIZE = 20 GRID_WIDTH = WIDTH // GRID_SIZE GRID_HEIGHT = HEIGHT // GRID_SIZE FPS = 10 # 颜色定义 BLACK = (0, 0, 0) WHITE = (255, 255, 255) GREEN = (0, 255, 0) RED = (255, 0, 0) BLUE = (0, 120, 255) YELLOW = (255, 255, 0) BACKGROUND = (40, 40, 40) # 方向常量 UP = (0, -1) DOWN = (0, 1) LEFT = (-1, 0) RIGHT = (1, 0) class Node: """A*算法节点类""" def __init__(self, position, parent=None): self.position = position self.parent = parent self.g = 0 # 从起点到当前节点的实际代价 self.h = 0 # 从当前节点到终点的估计代价 self.f = 0 # 总代价 (g + h) def __eq__(self, other): return self.position == other.position def __lt__(self, other): return self.f < other.f class Snake: """贪吃类""" def __init__(self): self.reset() def reset(self): """重置的状态""" self.length = 3 self.positions = [(GRID_WIDTH // 2, GRID_HEIGHT // 2)] self.direction = random.choice([UP, DOWN, LEFT, RIGHT]) self.score = 0 self.grow_to = 3 def get_head_position(self): """获取头位置""" return self.positions[0] def update(self): """更新的位置""" head = self.get_head_position() x, y = self.direction new_position = ((head[0] + x) % GRID_WIDTH, (head[1] + y) % GRID_HEIGHT) # 检查是否撞到自己 if new_position in self.positions[1:]: self.reset() return False self.positions.insert(0, new_position) # 检查是否需要增长 if len(self.positions) > self.grow_to: self.positions.pop() return True def render(self, surface): """绘制""" for i, p in enumerate(self.positions): color = GREEN if i == 0 else BLUE # 头绿色,身蓝色 rect = pygame.Rect((p[0] * GRID_SIZE, p[1] * GRID_SIZE), (GRID_SIZE, GRID_SIZE)) pygame.draw.rect(surface, color, rect) pygame.draw.rect(surface, BLACK, rect, 1) class Food: """食物类""" def __init__(self, snake): self.position = (0, 0) self.randomize_position(snake) def randomize_position(self, snake): """随机生成食物位置""" while True: self.position = (random.randint(0, GRID_WIDTH - 1), random.randint(0, GRID_HEIGHT - 1)) if self.position not in snake.positions: break def render(self, surface): """绘制食物""" rect = pygame.Rect((self.position[0] * GRID_SIZE, self.position[1] * GRID_SIZE), (GRID_SIZE, GRID_SIZE)) pygame.draw.rect(surface, RED, rect) pygame.draw.rect(surface, BLACK, rect, 1) def heuristic(a, b): """A*算法的启发式函数(曼哈顿距离)""" return abs(a[0] - b[0]) + abs(a[1] - b[1]) def a_star_search(snake, food, obstacles): """A*寻路算法实现""" start = snake.get_head_position() end = food.position # 创建开始和结束节点 start_node = Node(start) end_node = Node(end) # 初始化开放列表和关闭列表 open_list = [] closed_list = [] # 添加起始节点 heapq.heappush(open_list, (start_node.f, start_node)) # 循环直到找到路径 while open_list: # 获取当前节点 current_node = heapq.heappop(open_list)[1] closed_list.append(current_node) # 找到目标 if current_node == end_node: path = [] current = current_node while current is not None: path.append(current.position) current = current.parent return path[::-1] # 反转路径 # 生成邻居节点 neighbors = [] for new_direction in [UP, DOWN, LEFT, RIGHT]: node_position = ( (current_node.position[0] + new_direction[0]) % GRID_WIDTH, (current_node.position[1] + new_direction[1]) % GRID_HEIGHT ) # 检查是否在障碍物中(身或边界障碍) if node_position in obstacles: continue new_node = Node(node_position, current_node) neighbors.append(new_node) # 遍历所有邻居 for neighbor in neighbors: # 邻居在关闭列表中则跳过 if any(neighbor.position == closed_node.position for closed_node in closed_list): continue # 计算新的g值 neighbor.g = current_node.g + 1 neighbor.h = heuristic(neighbor.position, end) neighbor.f = neighbor.g + neighbor.h # 如果已经在开放列表中且有更低的g值则跳过 if any(neighbor.f > open_node[1].f and neighbor.position == open_node[1].position for open_node in open_list): continue heapq.heappush(open_list, (neighbor.f, neighbor)) return [] # 未找到路径 def draw_grid(surface): """绘制网格线""" for x in range(0, WIDTH, GRID_SIZE): pygame.draw.line(surface, (60, 60, 60), (x, 0), (x, HEIGHT)) for y in range(0, HEIGHT, GRID_SIZE): pygame.draw.line(surface, (60, 60, 60), (0, y), (WIDTH, y)) def draw_score(surface, score): """绘制分数""" font = pygame.font.SysFont('Arial', 20) text = font.render(f'Score: {score}', True, YELLOW) surface.blit(text, (5, 5)) def main(): """主游戏函数""" screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption('AI贪吃') clock = pygame.time.Clock() snake = Snake() food = Food(snake) manual_mode = False while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() sys.exit() elif event.key == pygame.K_m: manual_mode = not manual_mode elif manual_mode: # 手动模式控制 if event.key == pygame.K_UP and snake.direction != DOWN: snake.direction = UP elif event.key == pygame.K_DOWN and snake.direction != UP: snake.direction = DOWN elif event.key == pygame.K_LEFT and snake.direction != RIGHT: snake.direction = LEFT elif event.key == pygame.K_RIGHT and snake.direction != LEFT: snake.direction = RIGHT # 如果是自动模式,使用A*算法寻找路径 if not manual_mode: obstacles = snake.positions[1:] # 身作为障碍物 path = a_star_search(snake, food, obstacles) # 如果有有效路径,设置方向 if path and len(path) > 1: next_pos = path[1] head_pos = snake.get_head_position() snake.direction = ( (next_pos[0] - head_pos[0]) % GRID_WIDTH, (next_pos[1] - head_pos[1]) % GRID_HEIGHT ) # 更新的位置 if not snake.update(): food.randomize_position(snake) # 检查是否吃到食物 if snake.get_head_position() == food.position: snake.grow_to += 1 snake.score += 10 food.randomize_position(snake) # 绘制游戏界面 screen.fill(BACKGROUND) draw_grid(screen) snake.render(screen) food.render(screen) draw_score(screen, snake.score) # 显示当前模式 font = pygame.font.SysFont('Arial', 18) mode_text = font.render(f'Mode: {"Manual" if manual_mode else "AI"} (Press M to toggle)', True, YELLOW) screen.blit(mode_text, (WIDTH - mode_text.get_width() - 10, 5)) pygame.display.update() clock.tick(FPS) if __name__ == "__main__": main() ``` ### 代码解释 1. **游戏结构**: - `Snake`类:管理的位置、方向和增长逻辑 - `Food`类:负责食物的生成和绘制 - `Node`类:A*算法使用的节点结构 2. **核心功能**: - **A*寻路算法**:`a_star_search()`函数实现了智能寻路 - 使用曼哈顿距离作为启发函数 - 考虑身作为动态障碍物 - 支持边界穿越(可以从一边穿到另一边) - **双模式控制**: - AI模式:自动寻找食物 - 手动模式:使用方向键控制(按M键切换) - **碰撞检测**: - 检测头是否撞到自身 - 吃到食物后身增长 3. **游戏特性**: - 网格化游戏区域(20×20网格) - 头为绿色,身为蓝色 - 实时显示分数和当前模式 - 可以穿越边界(从一边到另一边) 4. **控制方式**: - 方向键:手动控制的方向 - M键:切换手动/AI模式 - ESC键:退出游戏 ### 运行说明 1. 需要安装Pygame库:`pip install pygame` 2. 运行后默认为AI模式,会自动寻找食物 3. 按M键切换手动控制模式 4. 在手动模式下使用方向键控制的移动方向 游戏界面会实时显示当前分数和操作模式。吃到食物后分数增加,身变长。当撞到自己时,游戏会自动重置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值