迷宫世界的最终演示效果如图。
黑色为墙不可通行,白色为道路可通行,黄色为出口。
# 环境测试
import gym
import random
import time
env=gym.make('MazeWorld-v0')
env.reset()
reward=0
while True:
action = env.actions[int(random.random()*len(env.actions))]
next_state,r,is_terminal,info = env.step(action)
env.render()
reward += r
if is_terminal == True:
print("reward:",reward)
break
time.sleep(0.2)
方法请参考我的上一篇博客链接: 建立自己的gym环境并调用.
import gym
from numpy import random
import time
class MazeEnv(gym.Env):
def __init__(self):
self.viewer = None
# 状态空间
self.states = [1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15,
16, 17, 18, 19, 20,
21, 22, 23, 24, 25]
# 动作空间
self.actions = ['n', 'e', 's', 'w']
# 回报函数
self.rewards = dict()
self.rewards['10_s'] = 10
self.rewards['14_e'] = 10
self.rewards['20_n'] = 10
# 状态转移概率,用状态_动作的模式存入字典
self.t = dict()
self.t['1_s'] = 6
self.t['1_e'] = 2
self.t['2_w'] = 1
self.t['2_s'] = 7
self.t['2_e'] = 3
self.t['3_w'] = 2
self.t['3_s'] = 8
self.t['5_s'] = 10
self.t['6_n'] = 1
self.t['6_e'] = 7
self.t['7_w'] = 6
self.t['7_n'] = 2
self.t['7_e'] = 8
self.t['8_w'] = 7
self.t['8_n'] = 3
self.t['8_s'] = 13
self.t['10_n'] = 5
self.t['10_s'] = 15
self.t['13_n'] = 8
self.t['13_e'] = 14
self.t['13_s'] = 18
self.t['14_w'] = 13
self.t['14_e'] = 15
self.t['14_s'] = 19
self.t['16_e'] = 17
self.t['16_s'] = 21
self.t['17_w'] = 16
self.t['17_e'] = 18
self.t['17_s'] = 22
self.t['18_w'] = 17
self.t['18_e'] = 19
self.t['18_n'] = 13
self.t['19_w'] = 18
self.t['19_n'] = 14
self.t['19_e'] = 20
self.t['20_w'] = 19
self.t['20_n'] = 15
self.t['21_n'] = 16
self.t['21_e'] = 22
self.t['22_w'] = 21
self.t['22_n'] = 17
def step(self, action):
#系统当前状态
state = self.state
#将状态和动作组成的字典的键值
key = "%d_%s" % (state, action)
#状态转移
#self.t是状态转移表,如果键值在表中,则通过表选出下一状态
if key in self.t:
next_state = self.t[key]
# 动作的下一刻是黑色墙壁的不在状态转移表中
#如果键值不在状态转移表中,则维持当前状态
else:
next_state = state
self.state = next_state
#出口判断,初值为FALSE
is_terminal = False
#self.rewards为回报函数表,即下一状态为出口的的状态和动作
#如果键值在回报函数表里,则出口判断函数is_terminal = True,奖励为10
if key in self.rewards:
r = 10
is_terminal = True
#如果键值不在回报函数里,则出口判断函数保持false值,奖励为-1
else:
r = -1
return next_state, r, is_terminal, {}
def reset(self):
s = [4, 9, 11, 12, 23, 24, 25]
self.state = self.states[int(random.random() * (len(self.states) ))]
while self.state in s:
self.state = self.states[int(random.random() * (len(self.states) - 1))]
return self.state
def close(self):
if self.viewer:
self.viewer.close()
self.viewer = None
def render(self, mode="human"):
from gym.envs.classic_control import rendering
width = 60
height = 40
edge_x = 0
edge_y = 0
if self.viewer is None:
self.viewer = rendering.Viewer(300, 200)
# 右下角 用黑色表示墙
self.viewer.draw_polygon([(0, 0), (0, height), (width, height), (width, 0)], filled=True,
color=(0, 0, 0)).add_attr(
rendering.Transform((edge_x + width * 2, edge_y + height * 1)))
self.viewer.draw_polygon([(0, 0), (0, height), (width, height), (width, 0)], filled=True,
color=(0, 0, 0)).add_attr(
rendering.Transform((edge_x + width * 3, edge_y + height * 1)))
self.viewer.draw_polygon([(0, 0), (0, height), (width, height), (width, 0)], filled=True,
color=(0, 0, 0)).add_attr(
rendering.Transform((edge_x + width * 4, edge_y + height * 1)))
# 左边
self.viewer.draw_polygon([(0, 0), (0, height), (width, height), (width, 0)], filled=True,
color=(0, 0, 0)).add_attr(rendering.Transform((edge_x, edge_y + height * 3)))
self.viewer.draw_polygon([(0, 0), (0, height), (width, height), (width, 0)], filled=True,
color=(0, 0, 0)).add_attr(
rendering.Transform((edge_x + width * 1, edge_y + height * 3)))
# 上边
self.viewer.draw_polygon([(0, 0), (0, height), (width, height), (width, 0)], filled=True,
color=(0, 0, 0)).add_attr(
rendering.Transform((edge_x + width * 3, edge_y + height * 4)))
self.viewer.draw_polygon([(0, 0), (0, height), (width, height), (width, 0)], filled=True,
color=(0, 0, 0)).add_attr(
rendering.Transform((edge_x + width * 3, edge_y + height * 5)))
# 出口,用黄色表示出口
self.viewer.draw_polygon([(0, 0), (0, height), (width, height), (width, 0)], filled=True,
color=(1, 0.9, 0)).add_attr(
rendering.Transform((edge_x + width * 4, edge_y + height * 3)))
# 画网格
for i in range(1, 7):
self.viewer.draw_line((edge_x, edge_y + height * i), (edge_x + 5 * width, edge_y + height * i)) # 横线
self.viewer.draw_line((edge_x + width * (i - 1), edge_y + height),
(edge_x + width * (i - 1), edge_y + height * 6)) # 竖线
# 人的像素位置
self.x = [edge_x + width * 0.5, edge_x + width * 1.5, edge_x + width * 2.5, 0, edge_x + width * 4.5,
edge_x + width * 0.5, edge_x + width * 1.5, edge_x + width * 2.5, 0, edge_x + width * 4.5,
0, 0, edge_x + width * 2.5, edge_x + width * 3.5, edge_x + width * 4.5,
edge_x + width * 0.5, edge_x + width * 1.5, edge_x + width * 2.5, edge_x + width * 3.5,
edge_x + width * 4.5,
edge_x + width * 0.5, edge_x + width * 1.5, 0, 0, 0]
self.y = [edge_y + height * 5.5, edge_y + height * 5.5, edge_y + height * 5.5, 0, edge_y + height * 5.5,
edge_y + height * 4.5, edge_y + height * 4.5, edge_y + height * 4.5, 0, edge_y + height * 4.5,
0, 0, edge_y + height * 3.5, edge_y + height * 3.5, edge_y + height * 3.5,
edge_y + height * 2.5, edge_y + height * 2.5, edge_y + height * 2.5, edge_y + height * 2.5,
edge_y + height * 2.5,
edge_y + height * 1.5, edge_y + height * 1.5, 0, 0, 0]
# 用圆表示人
# self.viewer.draw_circle(18,color=(0.8,0.6,0.4)).add_attr(rendering.Transform(translation=(edge_x+width/2,edge_y+height*1.5)))
self.viewer.draw_circle(18, color=(0.8, 0.6, 0.4)).add_attr(
rendering.Transform(translation=(self.x[self.state - 1], self.y[self.state - 1])))
return self.viewer.render(return_rgb_array=mode == 'rgb_array')