AI贪吃蛇(二)
前言
之前写过一篇关于贪吃蛇AI的博客,当时虽然取得了一些成果,但是也存在许多问题,所以最近又花了三天时间重新思考了一下。以下是之前博客存在的一些问题:
- 策略不对,只要存在找不到尾巴的情况就可能失败,所以这次的AI能保证始终找到尾巴。
- 编程思路不对,当时用C语言编写的,原有的游戏规则和AI部分有耦合,所以甚至出现了吃自己身体的状况,这是完全可以避免的。
以上两个问题是最主要的,其他地方也还是有可取之处的。下面是本次的成果。
思路
首先,我在网上找了一份贪吃蛇游戏的成品,然后在此代码的基础之上修改,添加一个AI,在每次游戏刷新时更新方向,这样,只要返回的方向错误,游戏一定会终止。同时,这种思路也比较符合实际:实际中我们玩贪吃蛇游戏其实就是通过键盘向游戏返回一个方向。现在不过是由AI负责返回方向。
AI算法
角度一:路径规划
这也是我本次采用的策略,如果看过上文提到的博客,就应该比较清楚,但是具体的策略有了变化,伪代码如下:
if (蛇身长度 > N && 策略1可行) {
执行策略1;
} else if (策略2可行) {
执行策略2;
} else if (策略3可行){
执行策略三;
}
具体解释一下:策略1
是非常无聊的做法,如下图,只要这样走一定会赢,但是显然没有任何价值,所以 N
越大,AI就越强。
策略2
是游戏早期会采用的一种策略,即利用A*算法 去寻找最短路径,如果按照路径去吃食物后还能找到尾巴就可行。但是也存在一个问题:有时候A*算法是行不通的但是稍微绕点路可能就行了,对于这种情况,我本想再添加一种策略,即遍历出所有路径,然后在策略1
不可行的情况下采用此策略,可是貌似不是目前的主要矛盾就放弃了(还有一部分原因是尝试了一下,没写出来。。。)
策略3
就是策略不可行的时候,采取的追尾策略,但是如何追,看到一些文章说朝离食物最远的方向,可是,我却遭遇了死循环:
最后,我采取的策略是选择合法的方向中,离尾巴最远(DFS距离)的那个方向。
可以看到,无论哪个策略,都是可控的,能找到尾巴的,这也是成功的关键。
角度二:博弈
这部分是我的一些思考,未实践探索。
其实,很多AI问题都可以用博弈的观点来解决,有些很明显:比如五子棋,围棋,有些则不那么明显:比如贪吃蛇。
如何用博弈的观点来看呢(描述可能不严谨):
- 博弈双方甲、乙
- 甲方选择一个空位置放置目标
- 乙方在不撞墙、不撞自身的前提下,在有限步骤内乙方需要吃掉食物。
- 如果乙方吃掉食物,身体长度加一(如何增加有多种方式,比如原代码是吃完增加,我更习惯吃的那一步发生增加)
- 如果甲没有位置放置目标则甲输,如果乙撞墙、撞自己、不能在有限步内吃到目标,任何一种情况发生都算输。
从经典贪吃蛇游戏的规则来看,甲采取的肯定不是最优策略,因为都知道食物是随机放置的,乙是否存在最优呢(这个我还不敢多做评论)
以上是我的一些想法,下图是一副几年前很火的图,图片是处理过的,用了2min,实际用时是13min,从花费的时间来看,我觉得如果这是AI(这个GIF是如何做出来的目前还不清楚,并不一定是AI),那一定得是搜索了博弈树,路径规划花13min是不太可能的:
代码概述
AI我是用JavaScript写的,才看了《JavaScript权威指南》前几章,写的很烂(这也是最后的AI中有一些“不可表述”的奇怪bug的原因),没必要细细分析,说一下大体框架:
aiSetDirection: AI入口
aiSetSituation: 将目标位置等信息存储起来,方便AI使用
aiGetPrePath: 策略1,返回第一种策略可行时的方向
aiGetBestPath: 策略2,使用A*算法返回可行时方向
aiFollowTail: 策略3,追着尾巴跑
aiJudgePath: 判断路径是否可行,策略2传入数组,策略三传入的数组实际只有一个元素
aiDFSPath: 返回蛇头朝四个方向移动(策略3中)时尾巴的DFS深度
aiTurnToDirection:将路径(下一步)转换为方向
贪吃蛇游戏是否存在最优解
目前,我还不能做最终定论,原因有以下几点:
- 目前自己掌握的资料有限,是否有同类问题的学术研究,又或者在哪已经彻底解决了这个问题(目前的倾向是不能保证100%取胜)。所以我觉得自己还需要寻找更多的资料,比如相关的AI比赛也是有的,我目前还没有了解。
- 目前无论用哪种语言,我都没法随心所欲的驾驭,需要用到的几个关键算法及其变种同样也没法熟练的使用。
- 形式化的研究还没有开始,至少目前我想,对于这个问题,我想的还不够抽象。
源代码和在线演示
源代码托管在GitHub上了,欢迎star&fork
在线演示(不能保证每次成功):AI-Snake
视频:优酷(标清);youtube(高清)
总结
花了三天吧,敲了很多垃圾代码。算法不熟练,代码不熟练。事先规划不充分。
可改进之处:
- 可以在早期多按照预定路径走几次,这样可以有效消除空位置。即
身长>N
改为身长>N || (身长>n1 && 身长<N1) || ...
可以视为一种调节机制 - 预定的路径有多种,有时候上文提到的路径可能不行(因为到达N时蛇的形态可能很特殊),所以可以多设置几种
无聊必胜
策略,防止某一策略不可行
参考
- 关于寻路算法的一些思考(1):A*算法介绍,这是第一篇,这个系列是我读的中文里最好的A*算法讲解
- Creating A Snake Game Tutorial With HTML5,我的代码就是在此基础之上建立的,一个很不错的网站,应该是个人网站
- Winning A Snake Game,GIF的视频版
- Snake - Maximum score (tool-assisted),另一个获胜的视频,没上一个那么吓人
- Snake finally beaten,关于那张经典GIF的一则新闻
- The Perfect Snake,同样是关于GIF的一篇短博文
- Смотрим до конца,GIF的出处
- Snake Online,一个关于贪吃蛇游戏的网站
- 如何用Python写一个贪吃蛇AI,国内比较火的AI贪吃蛇博文,博主的项目star数蛮高的
- 贪吃蛇 AI 的实现 snake AI,国内另一篇AI贪吃蛇的博文,比较好的就这两篇了。
- Snake,入门级讲解。
- js实现A*寻路算法,对我一个js菜鸟帮助还是很大的
AI贪吃蛇(二)的更多相关文章
- Python制作AI贪吃蛇
前提:本文实现AI贪吃蛇自行对战,加上人机对战,文章末尾附上源代码以及各位大佬的链接,还有一些实现步骤,读者可再次基础上自行添加电脑VS电脑和玩家VS玩家(其实把人机对战写完,这2个都没什么了,思路都 ...
- AI贪吃蛇前瞻——基于Dijkstra算法的最短路径问题
在贪吃蛇流程结构优化之后,我又不满足于亲自操刀控制这条蠢蠢的蛇,干脆就让它升级成AI,我来看程序自己玩,哈哈. 一.Dijkstra算法原理 作为一种广为人知的单源最短路径算法,Dijkstra用于求 ...
- Python制作AI贪吃蛇,很多很多细节、思路都写下来了!
前提:本文实现AI贪吃蛇自行对战,加上人机对战,读者可再次基础上自行添加电脑VS电脑和玩家VS玩家(其实把人机对战写完,这2个都没什么了,思路都一样) 实现效果: 很多人学习python,不知道从何学 ...
- Python-pygame案例AI贪吃蛇
# coding: utf-8 import pygame,sys,time,random from pygame.locals import * # 定义颜色变量 redColour = pygam ...
- C++ 贪吃蛇二维
#include <iostream> #include <conio.h> #include <windows.h> #include <time.h> ...
- 数据结构算法C语言实现(九)--- 拓展:由迷宫问题引申的AI贪吃蛇
一.简述 [开发中]由于期末时间有限,而且要用到后面的最短路径(可能),所以打算小学期在实现这一部分
- 浅析初等贪吃蛇AI算法
作为小学期程序设计训练大作业的一部分,也是自己之前思考过的一个问题,终于利用小学期完成了贪吃蛇AI的一次尝试,下作一总结. 背景介绍: 首先,我针对贪吃蛇AI这一关键词在百度和google上尽心了检索 ...
- 如何用python制作贪吃蛇以及AI版贪吃蛇
用python制作普通贪吃蛇 哈喽,大家不知道是上午好还是中午好还是下午好还是晚上好! 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很 ...
- 贪吃蛇AI
贪吃蛇AI 作者:CodeNoob 转载请标明作者和出处 序言 前几天在网上看到一张让人涨姿势的图片,这张图片我很早以前看过,当时就觉得肯定是程序实现的,只是当时还比较渣,不会算法.这次学了java也 ...
随机推荐
- ORACLE表空间管理维护
1:表空间概念 在ORACLE数据库中,所有数据从逻辑结构上看都是存放在表空间当中,当然表空间下还有段.区.块等逻辑结构.从物理结构上看是放在数据文件中.一个表空间可由多个数据文件组成. 如下图所示, ...
- RMAN-03002, RMAN-06059, ORA-19625 and ORA-27037 When Running RMAN Backup of Archivelogs
RMAN备份数据库时,出现下面错误错误信息: Starting backup at 25-MAY-15 current log archived allocated channel: ORA_DISK ...
- Linux 使用fdisk添加新分区
Linux系统由于数据累计增长.前期存储规划不合理等诸多因素,出现存储不够用的情况时,此时就需要扩展逻辑分区或添加新的逻辑分区.下面介绍一下通过使用fdsik添加新的逻辑分区. 首先使用df命令检查文 ...
- MongoDB学习笔记~自己封装的Curd操作(查询集合对象属性,更新集合对象)
回到目录 我不得不说,mongodb官方驱动在与.net结合上做的不是很好,不是很理想,所以,我决定对它进行了二次封装,这是显得很必然了,每个人都希望使用简单的对象,而对使用复杂,麻烦,容易出错的对象 ...
- [Java入门笔记] Java语言基础(一):注释、标识符与关键字
注释 什么是注释? 注释是我们在编写代码时某段代码.某个方法.某个类的说明文字,方便大家对于代码的阅读.被注释的内容不会被编译.执行. Java的注释分为三种类型:单行注释.多行注释.文档注释. 单行 ...
- 在CentOS安装PHP5.6
简单介绍一下,如何在CentOS上安装PHP5.6. 配置yum源 追加CentOS 6.5的epel及remi源. # rpm -Uvh http://ftp.iij.ad.jp/pub/linux ...
- 联发科发布全球首款搭载Android TV的智能电视系统芯片MT5595
联发科发布全球首款搭载Android TV的智能电视系统芯片MT5595 admin 资讯 01-07 1 1月7日消息,联发科宣布与Google共同开发出全世界第一个搭载Android TV操作系统 ...
- win7+ubuntu双系统 重装win7后grub修复
问题:之前安装的是win7+ubuntu双系统,重装win7后启动选项没有了,直接进入的是win7系统,无法进入ubuntu系统了. 解决办法:我们需要修复grub,将ubuntu系统重新挂载一下,具 ...
- [WPF系列]-基础系列 TabControl应用
引言 Tabcontrol控件也是我们在项目中经常用到的一个控件,用它将相关的信息组织在一起分类显示. 简介 ========================================= ...
- ACM失败之路
校赛打完,已过四月,该是准备背起行囊,踏上考研之路了,自然,得先阔别一下ACM了,想起这几年ACM路,感慨颇多,不得不一诉心肠,与大家分享一下我的ACM历程,如果有人能从此文获取一些益处,那我就很欣慰 ...