ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

贪吃蛇的Gym环境搭建

2021-12-08 22:31:19  阅读:255  来源: 互联网

标签:return Gym gym 贪吃蛇 snake Size self def 搭建


写个贪吃蛇拿来入门实践深度强化学习感觉上是再合适不过了,不过得先把贪吃蛇写出来

一.游戏规则

也无意搞得多复杂,游戏规则就概括为两句话:

1.头部碰到边界或者身体游戏结束

2.吃到食物长度加一

二.准备文件

1.安装好gym和pygame

2.安装好之后,可以在anaconda prompt界面用pip show gym命令找到gym安装目录

3.新建文件Greedy_Snake.py放在gym\envs\classic_control中,方便调用同文件夹中的rendering.py文件.

4.在gym\envs目录下的_init_.py文件中加入:

register (
    id= 'GreedySnake-v0',# id是调用所构建的环境的时候起的名字
    entry_point='gym.envs.classic_control:SnakeEnv',# entry_point是环境文件所在的位置
    max_episode_steps=200,
    reward_threshold=100.0,
)

5.在gym\envs\classic_control目录下的__init__.py文件中加入:

from gym.envs.classic_control.Greedy_Snake import SnakeEnv

在这一切都准备好了后,就要开始在Greedy_Snake.py文件中写SnakeEnv类来实现我们的Gym环境了。

6.在Greedy_Snake.py准备好Gym的标准框架:

class SnakeEnv(gym.Env):
    metadata = {# 元数据
        'render.modes': ['human', 'rgb_array'],
        'video.frames_per_second': 2
    }
	
    # 初始化
    def __init__(self):
     
    #动力函数 最重要的部分
    def step(self, action):# 输入为动作
        return state, rewards, done, info# 输出为 状态, 反馈, 终结标志, 调试信息
    
    # 将状态重置为初始状态
    def reset(self):
        return state# 返回初始状态
    
    # 图形化的函数部分
    def render(self, mode='human'):
    
    # 关闭GUI的
    def close(self):

三.编写贪吃蛇

终于开始写贪吃蛇了,别看上面的部分只有一点点(虽然确实只有一点点),但是查了好久的资料才理解和捋顺了的(可能是人傻)。

1.编写__init__:

贪吃蛇的构造函数主要需要初始化两部分:一个是环境信息,一个是GUI信息

环境信息主要包括环境的行为空间和观测空间。

GUI信息主要包括pygame的初始化以及蛇的颜色和食物颜色以及像素大小和游戏边框等等

  def __init__(self):
        #游戏环境初始化
        self.Size = 15
        self.height = 50  # 高度
        self.width = 60  # 宽度
        self.bodyColor = (0,225,0)
        self.foodColor = (0,0,225)
        #环境初始化
        self.action_space = spaces.Discrete(4) # 0:上 1:下 2:左 3:右
        self.observation_space = spaces.Discrete(self.height * self.width) # 观测空间是整个游戏棋盘


惊讶的发现写出来后居然只有两句话就概括了,写的时候因为要考虑全局还是思考了有一会的。

2.编写step:

这个函数是重中之重,基本上贪吃蛇的所有东西都在这个里面实现。

其逻辑是输入一个行动(在贪吃蛇里就是方向)。然后蛇就要跟着这个方向移动,同时如果吃到了食物,蛇的长度会加一,分数加一百,食物也会随机的重新生成,如果存活则分数加一(生存是第一准则嘛)。最后返回更新后的状态值,分数和是否结束游戏的标志。

放代码:

    def step(self, action):
        self.move(action)
        self.eat()
        self.state = self.getState()
        self.score += 1
        return self.state, self.score, self.is_done(), {}

然后我们把每段逻辑分成函数逐个实现。

2.1move

贪吃蛇的移动可以通过一个列表来存放每个身体的位置,列表首端就是蛇头,末端就是蛇尾,移动就是列表的首端插入移动后的蛇头位置,同时弹出末尾。

在移动的同时还要注意不能往反方向移动

    def move(self,direction):
        """
        移动
        """
        # 上走height减一
        if direction == 0 and self.direction != 1:
            self.snake.insert(0,[self.snake[0][0] - 1,self.snake[0][1]])
            self.snake.pop()
        # 下走height加一
        elif direction == 1 and self.direction != 0:
            self.snake.insert(0, [self.snake[0][0] + 1, self.snake[0][1]])
            self.snake.pop()
        # 左走width减一
        elif direction == 2 and self.direction != 3:
            self.snake.insert(0, [self.snake[0][0], self.snake[0][1] - 1])
            self.snake.pop()
        # 右走width加一
        elif direction == 3 and self.direction != 2:
            self.snake.insert(0, [self.snake[0][0], self.snake[0][1] + 1])
            self.snake.pop()

2.2eat

如果蛇头与食物重合,则视为“吃”,然后通过在尾部插入一个同尾部相同坐标的部分,下次移动时尾部弹出后会呈现未弹出的效果,即达到了增长的效果,吃了后还要生成新的食物。当然如果没得吃的话就什么都不做。

        if self.snake[0] == self.food:
            self.food = self.getFood()
            self.socre += 100
            self.snake.append(self.snake[-1])

2.2.1getFood

生成新食物要注意的就是不能在蛇身处生成,所以还要稍加拒绝,直到生成符合要求的坐标

    def getFood(self):
        """
        获取新的食物位置
        """
        food = [random.randint(0,self.height - 1),random.randint(0,self.width - 1)]
        while food in self.snake:
            food = [random.randint(0, self.height - 1), random.randint(0, self.width - 1)]
        return food

2.3getState

把游戏棋盘抽成一维数组

    def getState(self):
        board = np.array(self.getBoard())
        board = board.reshape(3000)
        return board

2.4is_done

这是用来判断是否为终局

如果蛇头在不该出现的位置就为终局(如蛇身,边界外)

def is_done(self):
    head = self.snake[0]
    if head in self.snake[1:]:
        return True
    if head[0] < 0 or head[0] >= self.height - 1 or head[1] < 0 or head[1] >= self.width - 1:
        return True
    return False

3.编写reset:

reset就是重置环境,主要用于以后训练的时候用(当然我因为懒,所以这里也被我寄予了初始化的重望)

    def reset(self,is_GUI=True):
        self.snake = [[random.randint(0,self.height - 1), random.randint(0,self.width - 1)]] # 蛇的所有身体位置
        self.food = self.getFood() #食物位置
        self.direction = random.choice([0,1,2,3]) #随机方向
        self.score = 0
        self.state = self.getState()
        self.is_GUI = is_GUI
        if is_GUI:
            pygame.init()
            size = self.width * self.Size, self.height * self.Size  # 设置窗口大小
            self.screen = pygame.display.set_mode(size)  # 显示窗口
        return self.state

4.编写render:

这里就是编写图形界面的地方

其逻辑主要就是把屏幕涂黑,然后画出蛇和食物,打印出分数,刷新!

def render(self, mode='human'):
    # 涂黑
    self.screen.fill((0,0,0))
    # 画
    board = self.getBoard()
    for h in range(len(board)):
        for w in range(len(board[0])):
            if board[h][w] == 1:
                pygame.draw.rect(self.screen, self.bodyColor,
                                 [w * self.Size, h * self.Size, self.Size, self.Size], 0)
            elif board[h][w] == 2:
                pygame.draw.rect(self.screen, self.foodColor,
                                 [w * self.Size, h * self.Size, self.Size, self.Size], 0)
    # 分数
    font = pygame.font.SysFont("freesansbold.ttf", 30)  # 30:font size
    text = font.render(str(self.score), True, (225, 225, 225))  # (0,0,0) color of font
    self.screen.blit(text, (10, 10))  # (10,10) rect left top
    # 刷新
    pygame.display.update()
    return None

5.编写close:

这个嘛,我直接没写,没关系!

四.编写测试文件

新建文件env_TEST.py

输入:

import random
import sys
import time

import gym
env = gym.make('GreedySnake-v0')

env.reset()

while True:
    action = random.randint(0,3)
    state, score, is_done, info = env.step(action)
    env.render()
    if is_done:
        print(score)
        sys.exit()
    time.sleep(0.01)

运行之,然后你就能看到一个不受控制傻乎乎的贪吃蛇(还只是一个头,你甚至几乎不能看到变成蛇的样子,因为几乎吃不到食物)

很傻是吗?然而我并不打算做键盘控制(虽然我做了,但是这只是想玩玩而已,对实现目标并无任何裨益)

总之就写出来了,下一步就能准备编写深度强化学习的玩意了。

标签:return,Gym,gym,贪吃蛇,snake,Size,self,def,搭建
来源: https://blog.csdn.net/qq_53776431/article/details/121802736

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有