第2章:环境搭建——Python环境配置、NumPy与Matplotlib库安装、基础地图数据结构设计

好,咱们正式开始动手了。

这一章说白了就是「磨刀不误砍柴工」。你想想看,后面我们要写A*、要写Dijkstra,如果连Python环境都没配好,或者连个地图都画不出来,那还谈什么路径规划?

我个人习惯是先把环境搞利索了再写代码。以前我带团队的时候,经常有新人一上来就写算法,结果跑起来报错,查半天发现是numpy版本不对。嗯,这种坑我踩过不止一次。

2.1 Python环境配置

我建议你用Python 3.8以上版本。为什么?因为后面我们要用的一些库,对低版本的支持已经越来越差了。你如果还在用Python 2.7,那真的该升级了。

安装方式很简单,去官网下载安装包就行。但我个人推荐用Anaconda——它自带了很多科学计算库,省得你一个一个装。

小提示: 如果你用的是Mac或者Linux,记得用 python3 而不是 python 命令。Windows用户一般直接 python 就行。

验证安装是否成功,打开终端或命令行,输入:

python --version

如果看到类似 Python 3.9.7 的输出,那就对了。

2.2 NumPy与Matplotlib库安装

这两个库是我们的左膀右臂。NumPy负责矩阵运算和数组操作,Matplotlib负责把地图和路径画出来。

安装命令很简单:

pip install numpy matplotlib

如果你用的是Anaconda,那大概率已经装好了。验证一下:

python -c "import numpy; print(numpy.__version__)"
python -c "import matplotlib; print(matplotlib.__version__)"

不报错就说明装好了。

注意: 我曾经遇到过一个问题——Matplotlib在Mac上显示中文乱码。解决方案是设置中文字体:plt.rcParams['font.sans-serif'] = ['SimHei']。Windows和Linux一般没这个问题。

2.3 基础地图数据结构设计

好,环境搞定了,接下来咱们聊聊地图。

路径规划里的地图,说白了就是一个二维网格。每个格子要么是「可通行」,要么是「障碍物」。你想想看,这跟迷宫是不是很像?

我习惯用NumPy的二维数组来表示地图。0表示可通行,1表示障碍物。举个例子:

import numpy as np

# 创建一个5x5的地图
# 0: 可通行, 1: 障碍物
map_data = np.array([
    [0, 0, 0, 0, 1],
    [0, 1, 1, 0, 1],
    [0, 0, 0, 0, 0],
    [1, 0, 1, 1, 0],
    [0, 0, 0, 0, 0]
])

print("地图大小:", map_data.shape)
print("障碍物数量:", np.sum(map_data == 1))

你看,这样设计是不是很直观?

但光有数据还不够,我们得能把它画出来。用Matplotlib把地图可视化:

import matplotlib.pyplot as plt

def plot_map(map_data):
    plt.figure(figsize=(6, 6))
    # 用imshow显示地图,cmap='gray'表示灰度图
    plt.imshow(map_data, cmap='gray', origin='upper')
    plt.title("基础地图")
    plt.colorbar(label='0: 可通行, 1: 障碍物')
    plt.grid(True, linestyle='--', alpha=0.7)
    plt.show()

plot_map(map_data)

运行这段代码,你会看到一个5x5的网格图。黑色格子是障碍物,白色格子是可通行区域。

核心要点: 地图数据结构的核心就是「二维数组 + 可视化」。后面所有的路径规划算法,都是在这个基础上运行的。

2.4 地图类的封装

在实际项目中,我习惯把地图封装成一个类。这样代码更整洁,也方便扩展。

class GridMap:
    def __init__(self, width, height, obstacle_ratio=0.2):
        self.width = width
        self.height = height
        # 随机生成地图,obstacle_ratio控制障碍物比例
        self.data = np.random.choice([0, 1], 
                                     size=(height, width), 
                                     p=[1-obstacle_ratio, obstacle_ratio])
    
    def is_obstacle(self, x, y):
        """判断某个格子是否是障碍物"""
        if x < 0 or x >= self.width or y < 0 or y >= self.height:
            return True  # 超出边界视为障碍物
        return self.data[y, x] == 1
    
    def plot(self):
        """可视化地图"""
        plt.figure(figsize=(8, 8))
        plt.imshow(self.data, cmap='gray', origin='upper')
        plt.title(f"地图大小: {self.width}x{self.height}")
        plt.grid(True, linestyle='--', alpha=0.5)
        plt.show()

# 使用示例
my_map = GridMap(10, 10, obstacle_ratio=0.3)
my_map.plot()

你看,这样封装之后,后面写A*算法的时候,直接调用 my_map.is_obstacle(x, y) 就能判断能不能走了,多方便。

避坑指南: 我曾经在项目里把x和y搞反了——地图数组是 data[y, x] 而不是 data[x, y]。因为NumPy数组的第一维是行(y方向),第二维是列(x方向)。这个细节不注意,后面画路径的时候会歪掉。

2.5 本章小结

嗯,这一章的内容就这些。总结一下:

  • Python环境用3.8+,推荐Anaconda
  • NumPy和Matplotlib是必备库,pip一键安装
  • 地图用二维数组表示,0可通行,1障碍物
  • 封装成类,方便后续算法调用

下一章我们就要开始写真正的路径规划算法了。Dijkstra和A*,你准备好了吗?

对了,如果你在安装环境时遇到任何问题,欢迎来找我交流。毕竟这些坑,我都替你踩过了。