前言

之前写过一篇关于贪吃蛇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时蛇的形态可能很特殊),所以可以多设置几种无聊必胜 策略,防止某一策略不可行

参考

AI贪吃蛇(二)的更多相关文章

  1. Python制作AI贪吃蛇

    前提:本文实现AI贪吃蛇自行对战,加上人机对战,文章末尾附上源代码以及各位大佬的链接,还有一些实现步骤,读者可再次基础上自行添加电脑VS电脑和玩家VS玩家(其实把人机对战写完,这2个都没什么了,思路都 ...

  2. AI贪吃蛇前瞻——基于Dijkstra算法的最短路径问题

    在贪吃蛇流程结构优化之后,我又不满足于亲自操刀控制这条蠢蠢的蛇,干脆就让它升级成AI,我来看程序自己玩,哈哈. 一.Dijkstra算法原理 作为一种广为人知的单源最短路径算法,Dijkstra用于求 ...

  3. Python制作AI贪吃蛇,很多很多细节、思路都写下来了!

    前提:本文实现AI贪吃蛇自行对战,加上人机对战,读者可再次基础上自行添加电脑VS电脑和玩家VS玩家(其实把人机对战写完,这2个都没什么了,思路都一样) 实现效果: 很多人学习python,不知道从何学 ...

  4. Python-pygame案例AI贪吃蛇

    # coding: utf-8 import pygame,sys,time,random from pygame.locals import * # 定义颜色变量 redColour = pygam ...

  5. C++ 贪吃蛇二维

    #include <iostream> #include <conio.h> #include <windows.h> #include <time.h> ...

  6. 数据结构算法C语言实现(九)--- 拓展:由迷宫问题引申的AI贪吃蛇

    一.简述 [开发中]由于期末时间有限,而且要用到后面的最短路径(可能),所以打算小学期在实现这一部分

  7. 浅析初等贪吃蛇AI算法

    作为小学期程序设计训练大作业的一部分,也是自己之前思考过的一个问题,终于利用小学期完成了贪吃蛇AI的一次尝试,下作一总结. 背景介绍: 首先,我针对贪吃蛇AI这一关键词在百度和google上尽心了检索 ...

  8. 如何用python制作贪吃蛇以及AI版贪吃蛇

    用python制作普通贪吃蛇 哈喽,大家不知道是上午好还是中午好还是下午好还是晚上好! 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很 ...

  9. 贪吃蛇AI

    贪吃蛇AI 作者:CodeNoob 转载请标明作者和出处 序言 前几天在网上看到一张让人涨姿势的图片,这张图片我很早以前看过,当时就觉得肯定是程序实现的,只是当时还比较渣,不会算法.这次学了java也 ...

随机推荐

  1. Android 高级面试题及答案

    一 性能优化 1.如何对 Android 应用进行性能分析 android 性能主要之响应速度 和UI刷新速度. 可以参考博客:Android系统性能调优工具介绍 首先从函数的耗时来说,有一个工具Tr ...

  2. ORACLE会话连接进程三者总结

    概念介绍 通俗来讲,会话(Session) 是通信双方从开始通信到通信结束期间的一个上下文(Context).这个上下文是一段位于服务器端的内存:记录了本次连接的客户端机器.通过哪个应用程序.哪个用户 ...

  3. SQL SERVER出现大量一致性错误的解决方法

    如果DBCC CHECKDB发现了比较少的一致性错误,可以使用   DBCC UPDATEUSAGE(DatabaseName,"dbo.ObjectName"); 语句逐个针对表 ...

  4. MySQL frm+ibd文件还原data的办法【数据恢复】

    MySQL frm+ibd文件还原data的办法[数据恢复] 此方法只适合innodb_file_per_table          = 1 当误删除ibdata 该怎么办? 如下步骤即可恢复: 1 ...

  5. Fedora 23安装配置mysql数据库,修改初始密码及登陆

    下载MySQL5.7.9 yum仓库 wget http://dev.mysql.com/get/mysql57-community-release-fc23-7-noarch.rpm rpm -iv ...

  6. 【转】Java并发编程:深入剖析ThreadLocal

    来自: http://www.importnew.com/17849.html 想必很多朋友对ThreadLocal并不陌生,今天我们就来一起探讨下ThreadLocal的使用方法和实现原理.首先,本 ...

  7. 深入java集合系列文章

    搞懂java的相关集合实现原理,对技术上有很大的提高,网上有一系列文章对java中的集合做了深入的分析, 先转载记录下 深入Java集合学习系列 Java 集合系列目录(Category) HashM ...

  8. ANSI Common Lisp Practice - My Answers - Chatper - 2

    I work out the questions by myself Chapter 2 question 4. (defun greater (x y) (if (> x y) x y ) ) ...

  9. svm训练显示信息说明

    现简单对屏幕回显信息进行说明: #iter 为迭代次数, nu  与前面的操作参数 -n nu  相同, obj 为 SVM 文件转换为的二次规划求解得到的最小值, rho  为判决函数的常数项 b  ...

  10. C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 服务器之间的接口通讯功、信息交换

    1:当远程调用方法时,会有很多种可能性发生.接口调用之后,发生错误是什么原因发生的?反馈给开发人员需要精确.精准.高效率,这时候若能返回出错状态信息的详细信息,接口之间的调用就会非常顺利,各种复杂问题 ...