通过Q-Learning强化学习实现AI走迷宫
学习numpy的时候突发奇想借助AI工具完成了这一有趣的代码。首先是需要的库import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation然后随机迷宫的生成是通过修改康威生命游戏的代码得到的这里我们假定“0”代表路“1”代表墙生成一个的迷宫rows, cols 100, 100 temp_world np.random.choice([0, 1], size(rows, cols), p[0.55, 0.45]) for _ in range(8): N np.roll(temp_world, shift1, axis0) S np.roll(temp_world, shift-1, axis0) E np.roll(temp_world, shift-1, axis1) W np.roll(temp_world, shift1, axis1) NW np.roll(N, shift1, axis1) NE np.roll(N, shift-1, axis1) SW np.roll(S, shift1, axis1) SE np.roll(S, shift-1, axis1) neighbors_count N S E W NW NE SW SE become_wall (neighbors_count 5) stay_wall (temp_world 1) (neighbors_count 4) temp_world (become_wall | stay_wall).astype(int) world_map temp_world.copy()通过roll函数实现平移来快速得到东西南北左邻右舍的坐标。然后随机生成起点与终点floor_positions np.argwhere(world_map 0) if len(floor_positions) 2: print(地图拥挤) exit() start_end_indices np.random.choice(len(floor_positions), size2, replaceFalse) start_pos floor_positions[start_end_indices[0]] end_pos floor_positions[start_end_indices[1]]而为了让AI经过很多很多次走迷宫后能够得到训练我们采用Q-Learning的强化学习方法。简单来说就是我们给AI的每次行进打分AI将每次的行进方式得到的分数记录在一个表中我们称之为Q表在训练完成后AI会查阅这个Q表然后按照分数最高的线路行进。这一方法的核心原理是贝尔曼更新公式其中代表在状态下执行动作的期望则是在下一状态中所有动作可能得到的最大值是学习率即AI接受新经验的比例学习率太大会导致模型摈弃旧经验浮动大太小又会导致模型迭代缓慢一般而言我们设定为0.1是折扣因子即AI对眼前还是长远利益分数的把握权重折扣因子过小则会导致AI专注眼前分数忽视未来分数过大会导致AI只在意未来分数一般而言我们设定为0.9则是状态下执行动作所获得的分数。贝尔曼更新公式来源于马尔可夫决策过程这里博主不懂所以不做展开说明。我们直接建立分数机制惩罚机制和Q表# 初始化 Q 表形状为 (行, 列, 4个方向) Q_table np.zeros((rows, cols, 4)) actions [(-1, 0), (1, 0), (0, -1), (0, 1)] # 0:上, 1:下, 2:左, 3:右 alpha 0.1 # 学习率 gamma 0.9 # 折扣因子 epsilon 0.1 # 探索率 episodes 100000 # 训练回合数 for episode in range(episodes): current_r, current_c start_pos[0], start_pos[1] step_count 0 # 防止进入无解的死胡同卡死限制每回合最多走 10000 步 while (current_r, current_c) ! (end_pos[0], end_pos[1]) and step_count 10000: step_count 1 # epsilon-greedy 策略选择动作 if np.random.rand() epsilon: action_idx np.random.randint(4) #探索 else: action_idx np.argmax(Q_table[current_r, current_c]) #经验 dr, dc actions[action_idx] next_r, next_c current_r dr, current_c dc # 边界与碰撞检测 if not (0 next_r rows and 0 next_c cols) or world_map[next_r, next_c] 1: # 撞墙严厉惩罚 reward -10 best_future_q np.max(Q_table[current_r, current_c]) Q_table[current_r, current_c, action_idx] alpha * (reward gamma * best_future_q - Q_table[current_r, current_c, action_idx]) # 位置不变 (留在原地) elif (next_r, next_c) (end_pos[0], end_pos[1]): # 到达终点 reward 100 # 终点没有未来了直接更新 Q_table[current_r, current_c, action_idx] alpha * (reward - Q_table[current_r, current_c, action_idx]) break # 结束这回合的重生 else: # 普通平地轻微惩罚以催促它找捷径 reward -0.1 best_future_q np.max(Q_table[next_r, next_c]) Q_table[current_r, current_c, action_idx] alpha * (reward gamma * best_future_q - Q_table[current_r, current_c, action_idx]) # 移动到新位置 current_r, current_c next_r, next_c训练结束后可以用matplotlib来展现训练成功的AI走迷宫的动画#中文显示 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False fig, ax plt.subplots(figsize(8, 6)) ax.set_title(AI训练成果展示, fontsize14) ax.axis(off) ax.imshow(world_map, cmapbinary_r) ax.scatter(end_pos[1], end_pos[0], cgold, s150, marker*, label终点) ax.scatter(start_pos[1], start_pos[0], cgreen, s50, label起点) explorer_dot ax.scatter(start_pos[1], start_pos[0], cred, s50, label训练后AI) ax.legend(locupper right) anim_pos [start_pos[0], start_pos[1]] def update_explorer(frame): global anim_pos if (anim_pos[0], anim_pos[1]) (end_pos[0], end_pos[1]): ax.set_title(规划完美, fontsize16, colororange) return [explorer_dot] # 完全顺着最大的 Q 值走 best_action_idx np.argmax(Q_table[anim_pos[0], anim_pos[1]]) dr, dc actions[best_action_idx] new_row anim_pos[0] dr new_col anim_pos[1] dc # 如果没撞墙万一没训练完全就往前走 if (0 new_row rows) and (0 new_col cols) and world_map[new_row, new_col] 0: anim_pos [new_row, new_col] explorer_dot.set_offsets([[anim_pos[1], anim_pos[0]]]) return [explorer_dot] ani animation.FuncAnimation(fig, update_explorer, frames300, interval150, blitFalse) plt.show()成果展示屏幕录制 2026-07-28 215732博主是编程新手如有问题还请大家指出同时也欢迎留言分享您的建议与观点谢谢