作者 | 李秋键

责编 | Carol

出品 | AI科技大本营(ID:rgznai100)

如果说这几年网络上最为常见的词语,其中必然会提到的便是人工智能。

人工智能的发展已经影响到了我们的日常生活,像我们生活中的刷脸支付是用的是计算机视觉中的人脸识别;网购时商品的推荐和阅读新闻时话题的推荐也是基于用户使用记录进行搜索智能优化;以及包括电脑代替游戏玩家进行游戏等等。

而其中AI游戏常用的方法实际上并不是神经网络首当其冲,因为神经网络对于复杂游戏而言需要对电脑服务器等要求较高,且优化复杂。那么针对特定的游戏搭建机器学习算法便显得尤为重要。

在我们生活中经常会遇到机器学习搭建AI游戏的例子。其中《模拟人生》系列就是最好的例子。没错,在这个游戏中,你细致的设置过角色的星座、性格、喜好后,它会按照设定进行自我行动,配上游戏题材,几乎和人类无疑。

做到这一点,依靠的是“行为树”。行为树和此前介绍过的决策树非常相似,通过状态枚举、流程控制来设计游戏中人物的行为。只是相比决策树单纯的通过各个节点进行IF,THEN的判断,行为树中充满了条件节点动作节点选择节点顺序节点等等更复杂的东西。再加上一些随机动作,行为树下的NPC几乎可以以假乱真。

如下图可见:

如上图所示,黄色矩形为执行节点,白色字体为条件节点。模拟人生人物在“吃饭”这一组合节点中,首先要判断自己是否饥饿、冰箱里是否有食物,如果结果都是“是”,就会执行做饭这一行为。

这只是针对这一个游戏而言,但是其原理是差不多的。比如我们要做的智能贪吃蛇,我们要做的就是首先判断果实的位置,然后根据蛇的头部位置可以判断出果实在哪个方位,从而决策出各种往哪个方向行动多少格即可,说白了也就是简单的加减计算而已。

介绍到这里,那么下面我们开始动手搭建我们的智能游戏。

实验前的准备

首先我们使用的python版本是3.6.5所用到的库有random,目的很明显,用来随机生成果实位置;pygame是用来搭建游戏框架实现游戏整体可运行;sys是为了方便操作电脑系统的框架,因为其中电脑需要执行动作需要有操作权限。

搭建游戏框架

1、初始化变量和导入库:

游戏框架所涉及到的必然参数有游戏窗口的大小,方向的定义、以及用来存储蛇身体长度的变量等等。详细代码如下:

import randomimport pygameimport sysfrom pygame.locals import *# 错误码ERR = -404# 屏幕大小Window_Width = 800Window_Height = 500# 刷新频率Display_Clock = 17# 一块蛇身大小Cell_Size = 20assert Window_Width % Cell_Size == 0assert Window_Height % Cell_Size == 0# 等价的运动区域大小Cell_W = int(Window_Width/Cell_Size)Cell_H = int(Window_Height/Cell_Size)FIELD_SIZE = Cell_W * Cell_H# 背景颜色Background_Color = (0, 0, 0)# 蛇头索引Head_index = 0# 运动方向best_move = ERR# 不同东西在矩阵里用不同的数字表示FOOD = 0FREE_PLACE = (Cell_W+1) * (Cell_H+1)SNAKE_PLACE = 2 * FREE_PLACE# 运动方向字典move_directions = {'left': -1,'right': 1,'up': -Cell_W,'down': Cell_W}

2、游戏框架函数:

这部分函数和游戏的智能性无关,仅仅是游戏框架必要的函数。其中用到的函数为了方便调用,我们需要预先设定好。其中必然需要的是关闭界面函数;得分更新函数;获取果实位置等等功能的函数,详细代码如下:

# 关闭游戏界面def close_game():pygame.quit()sys.exit()# 检测玩家的按键def Check_PressKey():if len(pygame.event.get(QUIT)) > 0:close_game()KeyUp_Events = pygame.event.get(KEYUP)if len(KeyUp_Events) == 0:return Noneelif KeyUp_Events[0].key == K_ESCAPE:close_game()return KeyUp_Events[0].key# 显示当前得分def Show_Score(score):score_Content = Main_Font.render('得分:%s' % (score), True, (255, 255, 255))score_Rect = score_Content.get_rect()score_Rect.topleft = (Window_Width-120, 10)Main_Display.blit(score_Content, score_Rect)# 获得果实位置def Get_Apple_Location(snake_Coords):flag = Truewhile flag:apple_location = {'x': random.randint(0, Cell_W-1), 'y': random.randint(0, Cell_H-1)}if apple_location not in snake_Coords:flag = Falsereturn apple_location# 显示果实def Show_Apple(coord):x = coord['x'] * Cell_Sizey = coord['y'] * Cell_Sizeapple_Rect = pygame.Rect(x, y, Cell_Size, Cell_Size)pygame.draw.rect(Main_Display, (255, 0, 0), apple_Rect)# 显示蛇def Show_Snake(coords):x = coords[0]['x'] * Cell_Sizey = coords[0]['y'] * Cell_SizeSnake_head_Rect = pygame.Rect(x, y, Cell_Size, Cell_Size)pygame.draw.rect(Main_Display, (0, 80, 255), Snake_head_Rect)Snake_head_Inner_Rect = pygame.Rect(x+4, y+4, Cell_Size-8, Cell_Size-8)pygame.draw.rect(Main_Display, (0, 80, 255), Snake_head_Inner_Rect)for coord in coords[1:]:x = coord['x'] * Cell_Sizey = coord['y'] * Cell_SizeSnake_part_Rect = pygame.Rect(x, y, Cell_Size, Cell_Size)pygame.draw.rect(Main_Display, (0, 155, 0), Snake_part_Rect)Snake_part_Inner_Rect = pygame.Rect(x+4, y+4, Cell_Size-8, Cell_Size-8)pygame.draw.rect(Main_Display, (0, 255, 0), Snake_part_Inner_Rect)# 画网格def draw_Grid():# 垂直方向for x in range(0, Window_Width, Cell_Size):pygame.draw.line(Main_Display, (40, 40, 40), (x, 0), (x, Window_Height))# 水平方向for y in range(0, Window_Height, Cell_Size):pygame.draw.line(Main_Display, (40, 40, 40), (0, y), (Window_Width, y))# 显示开始界面def Show_Start_Interface():title_Font = pygame.font.Font('simkai.ttf', 100)title_content = title_Font.render('贪吃蛇', True, (255, 255, 255), (0, 0, 160))angle = 0while True:Main_Display.fill(Background_Color)rotated_title = pygame.transform.rotate(title_content, angle)rotated_title_Rect = rotated_title.get_rect()rotated_title_Rect.center = (Window_Width/2, Window_Height/2)Main_Display.blit(rotated_title, rotated_title_Rect)pressKey_content = Main_Font.render('按任意键开始游戏!', True, (255, 255, 255))pressKey_Rect = pressKey_content.get_rect()pressKey_Rect.topleft = (Window_Width-200, Window_Height-30)Main_Display.blit(pressKey_content, pressKey_Rect)if Check_PressKey():# 清除事件队列pygame.event.get()returnpygame.display.update()Snake_Clock.tick(Display_Clock)angle -= 5# 显示结束界面def Show_End_Interface():title_Font = pygame.font.Font('simkai.ttf', 100)title_game = title_Font.render('Game', True, (233, 150, 122))title_over = title_Font.render('Over', True, (233, 150, 122))game_Rect = title_game.get_rect()over_Rect = title_over.get_rect()game_Rect.midtop = (Window_Width/2, 70)over_Rect.midtop = (Window_Width/2, game_Rect.height+70+25)Main_Display.blit(title_game, game_Rect)Main_Display.blit(title_over, over_Rect)pygame.display.update()pygame.time.wait(500)while True:for event in pygame.event.get():if event.type == QUIT:close_game()elif event.type == KEYDOWN:if event.key == K_ESCAPE:close_game()# 判断该位置是否为空def Is_Cell_Free(idx, psnake):location_x = idx % Cell_Wlocation_y = idx // Cell_Widx = {'x': location_x, 'y': location_y}return (idx not in psnake)

游戏智能性设计

1、根据果实位置判断执行方向:

# 检查位置idx是否可以向当前move方向运动def is_move_possible(idx, move_direction):flag = Falseif move_direction == 'left':if idx%Cell_W > 0:flag = Trueelse:flag = Falseelif move_direction == 'right':if idx%Cell_W < Cell_W-1:flag = Trueelse:flag = Falseelif move_direction == 'up':if idx > Cell_W-1:flag = Trueelse:flag = Falseelif move_direction == 'down':if idx < FIELD_SIZE - Cell_W:flag = Trueelse:flag = Falsereturn flag

2、最短路径的选择:

到达果实的位置道路是千万条的,我们需要做的是最有效的方法,即需要找到最短的路径。

详细定义函数如下:

# 从蛇头周围4个领域点中选择最短路径def choose_shortest_safe_move(psnake, pboard):best_move = ERRmin_distance = SNAKE_PLACEfor move_direction in ['left', 'right', 'up', 'down']:idx = psnake[Head_index]['x'] + psnake[Head_index]['y']*Cell_Wif is_move_possible(idx, move_direction) and (pboard[idx+move_directions[move_direction]]<min_distance):min_distance = pboard[idx+move_directions[move_direction]]best_move = move_directionreturn best_move# 找到移动后蛇头的位置def find_snake_head(snake_Coords, direction):if direction == 'up':newHead = {'x': snake_Coords[Head_index]['x'],'y': snake_Coords[Head_index]['y']-1}elif direction == 'down':newHead = {'x': snake_Coords[Head_index]['x'],'y': snake_Coords[Head_index]['y']+1}elif direction == 'left':newHead = {'x': snake_Coords[Head_index]['x']-1,'y': snake_Coords[Head_index]['y']}elif direction == 'right':newHead = {'x': snake_Coords[Head_index]['x']+1,'y': snake_Coords[Head_index]['y']}return newHead

3、决策优化:

当蛇身过长等问题出现时可能会导致程序找不到合适的解决方案,故我们需要对此进行处理,即找不到合适的行为吃到果实。代码如下:

# 如果蛇和食物间有路径# 则需要找一条安全的路径def find_safe_way(psnake, pboard, pfood):safe_move = ERRreal_snake = psnake[:]real_board = pboard[:]v_psnake, v_pboard = virtual_move(psnake, pboard, pfood)# 如果虚拟运行后,蛇头蛇尾间有通路,则选最短路运行if is_tail_inside(v_psnake, v_pboard, pfood):safe_move = choose_shortest_safe_move(real_snake, real_board)else:safe_move = follow_tail(real_snake, real_board, pfood)return safe_move# 各种方案均无效时,随便走一步def any_possible_move(psnake, pboard, pfood):best_move = ERRreset_board = board_reset(psnake, pboard, pfood)pboard = reset_boardresult, refresh_board = board_refresh(psnake, pfood, pboard)pboard = refresh_boardmin_distance = SNAKE_PLACEfor move_direction in ['left', 'right', 'up', 'down']:idx = psnake[Head_index]['x'] + psnake[Head_index]['y']*Cell_Wif is_move_possible(idx, move_direction) and (pboard[idx+move_directions[move_direction]]<min_distance):min_distance = pboard[idx+move_directions[move_direction]]best_move = move_directionreturn best_move

游戏运行

调用主函数初始化运行即可:

# 主函数def main():global Main_Display, Main_Font, Snake_Clockpygame.init()Snake_Clock = pygame.time.Clock()Main_Display = pygame.display.set_mode((Window_Width, Window_Height))Main_Font = pygame.font.Font('simkai.ttf', 18)pygame.display.set_caption('AI_snake')Show_Start_Interface()while True:Run_Game()Show_End_Interface()if __name__ == '__main__':main()

最终效果图如下可见:

到此就完成了,如果你感兴趣的话不妨试试看,欢迎在评论区和我一起讨论!

作者介绍:

李秋键,CSDN 博客专家,CSDN达人课作者。硕士在读于中国矿业大学,开发有taptap安卓武侠游戏一部,vip视频解析,文意转换工具,写作机器人等项目,发表论文若干,多次高数竞赛获奖等等。

推荐阅读

  • 那个分分钟处理 10 亿节点图计算的 Plato,现在怎么样了?

  • 黑客用上机器学习你慌不慌?这 7 种窃取数据的新手段快来认识一下!

  • 大促下的智能运维挑战:阿里如何抗住“双11猫晚”?

  • “谷歌杀手”发明者,科学天才 Wolfram

  • 数据库激荡 40 年,深入解析 PostgreSQL、NewSQL 演进历程

  • 超详细!一文告诉你 SparkStreaming 如何整合 Kafka !附代码可实践

  • 5分钟!就能学会以太坊 JSON API 基础知识!

  • 你点的每个“在看”,我都认真当成了AI

“我想玩游戏!” 大佬:玩啥游戏,教你做一个智能贪吃蛇游戏!相关推荐

  1. 手把手教你做一个Java贪吃蛇小游戏

    大家好,我是孙不坚1208,这篇博客给大家分享一下:如何做一个贪吃蛇小游戏(Java版)的exe应用程序,希望能给需要帮助的朋友带来方便. 手把手教你做一个Java贪吃蛇小游戏的exe应用程序 一.J ...

  2. java毕业设计——基于java+J2ME的贪吃蛇游戏设计与实现(毕业论文+程序源码)——贪吃蛇游戏

    基于java+J2ME的贪吃蛇游戏设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+J2ME的贪吃蛇游戏设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦.需要下载开题报告P ...

  3. 回忆经典,九叔教你用Python制作贪吃蛇游戏

    众所周知Python除了不能生孩子啥都行. 咱们今天就说一下如何利用Python写一个简易的小游戏. 所以呀咱们今天就用Python写大家都玩过的小游戏--贪吃蛇. 用Python写游戏就得用到pyg ...

  4. Java贪吃蛇暂停怎么做_Java实现贪吃蛇游戏(1小时学会)

    今天就来拿贪吃蛇小游戏来练练手吧! 贪吃蛇游戏规则: 1.按下空格键(游戏未结束)则游戏暂停或开始: 2.按下空格键(游戏结束后)则游戏重新开始: 3.当贪吃蛇的头部撞到身体时则贪吃蛇死亡(游戏结束) ...

  5. 手把手教你使用 Python 制作贪吃蛇游戏

    贪吃蛇游戏是有史以来最受欢迎的街机游戏之一.在这个游戏中,玩家的主要目标是在不撞墙或不撞墙的情况下抓住最大数量的水果.在学习 Python 或 Pygame 时,可以将创建蛇游戏视为一项挑战.这是每个 ...

  6. 手把手教你使用 Python 制作贪吃蛇游戏,才发现原来制作起来很简单ǃ

    贪吃蛇游戏是有史以来最受欢迎的街机游戏之一.在这个游戏中,玩家的主要目标是在不撞墙或不撞墙的情况下抓住最大数量的水果.在学习 Python 或 Pygame 时,可以将创建蛇游戏视为一项挑战.这是每个 ...

  7. python逢7过小游戏_while循环拓展:用python做一个逢七过小游戏

    不知道各位同学和小伙伴在一起无聊的时候有没有玩过逢七过的游戏. 可能有的同学玩过,有的同学有点懵.逢七过是个什么游戏?那不管有没有玩过这个游戏,我们都来讲一下游戏规则. 游戏规则 逢七过游戏规则:最少 ...

  8. 贪吃蛇python小白_面向 python 小白的贪吃蛇游戏

    代码和教程详见微信公众号:Python高效编程 效果图 图片 代码和教程详见微信公众号:Python高效编程 文字部分: 引言 作为python 小白,总是觉得自己要做好百分之二百的准备,才能开始写程 ...

  9. 面向 python 小白的贪吃蛇游戏

    引言 作为python 小白,总是觉得自己要做好百分之二百的准备,才能开始写程序.以至于常常整天在那看各种语法教程,学了几个月还是只会print('hello world'). 这样做效率太低,正确的 ...

最新文章

  1. 一份520页的机器学习笔记!附下载链接
  2. Windows 7 IIS (HTTP Error 500.21 - Internal Server Error)解决
  3. 使用RoundedBitmapDrawable快速生成圆角和圆形图片
  4. 【转载】OI生涯结束……在逸夫楼那些的日子里
  5. 无网络访问权限怎么办_解决无Internet访问权限
  6. 设计模式C++实现(7)——观察者模式
  7. 我最喜欢的Java高级开发人员书籍
  8. MySQL并发复制系列一:binlog组提交 (转载)
  9. python创意实用案例-精心整理!9个 Python 实用案例分享
  10. ai生成图片是什么技术_什么是生成型AI?
  11. 简易c语言编程软件,c语言开发工具下载
  12. PMP第六版备考笔记练习题答疑(持续更新)
  13. 深度学习?不一定非得搞“黑箱”
  14. android viewholder模式,为什么在ViewHolder模式中ViewHolder类应该是静态的?
  15. NetSarang旗下网络通讯系列产品v5版本更新合集丨附下载
  16. 3D打印-切片软件简介
  17. 【算法】格雷码(Gray Code)与8421二进制码之间的转换算法 (LeetCode89)
  18. ppt压缩文件怎么压缩?
  19. 新元宇宙每周连载《地球人奇游天球记》第十八回冥王遇鬼
  20. WPS 表格 身份证 提取生日 判断性别 计算年龄 15位身份证与18位身份证转换 18位身份证号校验

热门文章

  1. Django计算机毕业设计创意摄影交流平台python(源码程序+lw+远程部署)
  2. 【python】网站接口整理
  3. ambari 2.7.4搭建过程
  4. LAN、WAN和WLAN介绍
  5. C语言:菜鸟教程经典100例题(1-50)
  6. sqlite 打开扩展名为.DB 文件
  7. Java:SpringBoot给Controller添加统一路由前缀
  8. 用计算机说唱什么歌,最近不知道喜欢上了说唱求大家给点词呗~
  9. JAVA基础类库(第四周)(三只松鼠,奥利给)
  10. EasyARM-i.MX280A—Linux系统开发板(开发日记1-登录开发板)