首页 > 其他分享 >AI贪吃蛇

AI贪吃蛇

时间:2024-03-24 23:34:43浏览次数:23  
标签:neibors console log AI current length 贪吃蛇 data

背景

一个朋友请我帮忙在他的手动版贪吃蛇的基础上,改进一个AI贪吃蛇
我查找了一些资料,AI贪吃蛇主要用到的是A星算法
目前的算法比较简单,即计算从蛇头到食物的路径,按路径去移动即可
所以还比较笨,演示如下

代码及博客路径:

算法原理:
Astar算法项目 https://github.com/wangqqiyue/Astar
Astar算法博客 https://www.cnblogs.com/studentWangqy/p/18059817

AI贪吃蛇项目 https://github.com/wangqqiyue/snake_easy

代码解释

//TODO
//解释一下代码为什么这么写

关键点

代码中比较关键的几个点是
优先队列类(PriorityQueue)
节点类和地图类(Node, neibors)
获取路径的函数getPath

PriorityQueue

优先队列的代码是我从网上找的现成的代码
我认为如无必要,勿增实体,既然已经有了现成的经过测试的代码,我没有必要重新写

class PriorityQueue {
        constructor(compare) {
          if (typeof compare !== "function") {
            throw new Error("compare function required!");
          }

          this.data = [];
          this.compare = compare;
          this.length = 0;
        }
        //二分查找 寻找插入位置
        search(target) {
          let low = 0,
            high = this.data.length;
          while (low < high) {
            let mid = low + ((high - low) >> 1);
            if (this.compare(this.data[mid], target) > 0) {
              high = mid;
            } else {
              low = mid + 1;
            }
          }
          return low;
        }
        //添加
        push(elem) {
          // console.log("elem=", elem);
          // console.log("data.length=", this.data.length);
          let index = this.search(elem);
          this.data.splice(index, 0, elem);
          // console.log("data.length=", this.data.length);

          this.length = this.data.length;
          return this.data.length;
        }
        //取出最优元素
        pop() {
          // console.log("this.data=", this.data);
          // console.log("data.length=", this.data.length);

          // for (var i = 0; i < this.data.length; i++) {
          //   console.log("data[", i, "]=", this.data[i]);
          // }
          this.length--;
          return this.data.pop();
        }

        //判断是否为空
        empty() {
          return 0 === this.data.length;
        }
      }

Map

地图存放了所有地图节点,并且提供了计算指定节点的邻居节点的方法

class Node {
        constructor(x, y) {
          this.x = x;
          this.y = y;
          this.g = 0;
          this.h = 0;
          this.f = 0;
          this.open = false;
          this.close = false;
          this.parent = null;
          this.walkable = true;
        }
        moveToClose() {
          this.open = false;
          this.close = true;
        }
        moveToOpen() {
          this.open = true;
          this.close = false;
        }
      }
      class Map {
        constructor() {
          //创建二维地图,用于规划贪吃蛇路径
          this.mapForAI = new Array(ROWS);
          for (var i = 0; i < ROWS; i++) {
            this.mapForAI[i] = new Array(COLS);
            for (var j = 0; j < COLS; j++) {
              this.mapForAI[i][j] = new Node(j, i); //x是COL,y是ROW,别弄错了
            }
          }

          //初始化不可通行节点
          snakes.forEach((curr) => {
            this.mapForAI[curr.y][curr.x].walkable = false;
          });

          //console.log(this.mapForAI);
        }

        getNeibors(center) {
          var r, c, i;
          var neibors = new Array(NEIBOR_NUM_MAX);

          for (i = 0; i < NEIBOR_NUM_MAX; i++) {
            neibors[i] = null;
          }

          r = center.y;
          c = center.x;

          if (r > 0) neibors[UP] = this.mapForAI[r - 1][c];

          if (r < ROWS - 1) neibors[DOWN] = this.mapForAI[r + 1][c];

          if (c > 0) neibors[LEFT] = this.mapForAI[r][c - 1];

          if (c < COLS - 1) neibors[RIGHT] = this.mapForAI[r][c + 1];

          //console.log(neibors);
          return neibors;
        }
      }

getPath

getPath是计算蛇头到食物的路径
这里的代码的结构全部来自我的Astar项目(https://github.com/wangqqiyue/Astar)

//获取从起点到终点的路径,如果存在则返回路径数组,不存在则返回空数组
      function getPath(src, dst) {
        let havePath = false;
        var path = [];
        var neibors;
        //初始化mapForAI
        map = new Map();

        //构建优先队列
        var openList = new PriorityQueue((n1, n2) => n1.f - n2.f);

        //调用A星算法
        // console.log("src=", src);
        // console.log("dst=", dst);
        var current = map.mapForAI[src.y][src.x];
        // console.log("current=", current);
        openList.push(current);
        current.moveToOpen();
        while (false === openList.empty()) {
          // console.log("openList=", openList);
          current = openList.pop();
          // console.log("current=", current);
          current.moveToClose();

          if (current.x === dst.x && current.y === dst.y) {
            havePath = true;
            break;
          }
          neibors = map.getNeibors(current);
          for (i = 0; i < NEIBOR_NUM_MAX; i++) {
            if (
              null === neibors[i] ||
              false === neibors[i].walkable ||
              true === neibors[i].close
            ) {
              continue;
            }

            if (false === neibors[i].open) {
              neibors[i].g = getManhattan(neibors[i], src);
              neibors[i].h = getManhattan(neibors[i], dst);
              neibors[i].f = neibors[i].g + neibors[i].h;
              neibors[i].moveToOpen();
              neibors[i].parent = current;
              // console.log("neibors[i]=", neibors[i]);
              openList.push(neibors[i]);
              // console.log("openList=", openList);
            } else if (true === neibors[i].open) {
              g = getManhattan(neibors[i], current) + neibors[i].g;
              if (g < neibors[i].g) {
                neibors[i].g = g;
                neibors[i].f = neibors[i].g + neibors[i].h;
                neibors[i].parent = current;
              }
            }
          }
        }

        // console.log("havePath=", havePath);
        //返回路径数组
        if (havePath) {
          current = map.mapForAI[dst.y][dst.x];
          while (null != current.parent) {
            path.unshift(current);
            current = current.parent;
          }
        }
        drawPath(path);
        return path;
      }

调试过程记录

javascript

这个项目原型代码是html的,算法实现是使用javascript
我对javascript其实并不熟悉
还学习了一下
学习javascript记录:
javascript中的函数式编程 https://www.cnblogs.com/studentWangqy/p/18086252
在VSCode调试js代码 https://blog.csdn.net/qq_42235030/article/details/112801656
有调试功能是真的很方便,帮我发现了好几处错误,比如x和y分别对应的应该是col和row

标签:neibors,console,log,AI,current,length,贪吃蛇,data
From: https://www.cnblogs.com/studentWangqy/p/18093364

相关文章

  • [AIGC] 使用Spring Boot进行单元测试:一份指南
    在现代软件开发过程中,确认你的应用正确运行是至关重要的一步。SpringBoot提供了一组实用工具和注解来辅助你在测试你的应用时,使得这个过程变得简单。下面就来分享一下如何在SpringBoot中进行单元测试。文章目录为什么需要单元测试SpringBoot单元测试的基本步骤示......
  • [AIGC] SQL中的数据添加和操作:数据类型介绍
    SQL(结构化查询语言)作为一种强大的数据库查询和操作工具,它能够完成从简单查询到复杂数据操作的各种任务。在这篇文章中,我们主要讨论如何在SQL中添加(插入)数据,以及在数据操作过程中,会产生哪些类型的数据。文章目录如何在SQL中添加数据更新和删除数据更新数据删除数据......
  • RAID
    RAID0RAID0将数据分割成块,并通过条带化(striping)的方式将这些块分散存储在多个磁盘上。没有冗余数据,所有数据块都会被平均地分配到各个磁盘中。优点:提高了读写性能,因为数据可以并行地从多个磁盘中读取或写入。实际存储容量等于所有磁盘的总和,没有用于冗余数据的额外空间开......
  • aida64
    目录aida64记录aida64.exe程序信息IDRTForm_EnterProductKey_UpdateScreencheck_F85B98pyaida64记录最近换了电脑,微星主板带了aida64程序,结果只能试用60天0.0aida64.exe程序信息32位程序,编译器:BorlandDelphi(7)[-]IDRDelphi程序直接祭出大杀器IDR定位注册窗口和注......
  • AI每日一问:世界的本源是什么?是原子的吗?无限可分的吗?是物质的还是想象的? 我们应当怎样
    1.世界的本源是什么?是原子的吗?无限可分的吗?是物质的还是想象的?我们应当怎样看待物质世界?以及怎么快速促进强人工智能的到来?Claude-3-Opus这些都是非常深奥而有趣的哲学问题,需要我们深入探讨和思考。关于世界本源的问题,不同的哲学流派有不同的看法。原子论认为物质世界......
  • 详解rtklib中main函数如何配置文件(下)
    目录一、main函数流程总结二、分析识别-k后如何配置三、最后传参的数据文件处理方式 一、main函数流程总结详解rtklib中main函数如何配置文件(上)-CSDN博客在这片文章中讲解了rtklib中main函数的整个流程。(1)通过两种方法给main函数传递参数,并放在argv这个指针数组......
  • 使用AI技术(单张图片或文字)生产3D模型 —— Ai生成3D模型的时代来了
    地址:https://www.bilibili.com/video/BV1A2421P7pH/视频用到的工具voxcraft体验地址:https://voxcraft.ai/......
  • 【通以灵码】————您的ai代码助手已上线!!!
    大家好,我是又菜又爱代码的CodeNerd影,这周我看了阿里的《AI大模型技术周:AIGC趋势下的软件工程重塑智能编码探索与实践》体会到了ai的强大,本文就以阿里的通义灵码为例,来介绍ai大模型。一.通以灵码是什么通义灵码是阿里云出品的一款基于通义大模型的智能编码辅助工具,提供行级/函......
  • 用AI给人生开挂的正确方式 - 在AI迅速进化的时代,我们应该如何不落伍
    作者:明明如月学长,CSDN博客专家,大厂高级Java工程师,《性能优化方法论》作者、《解锁大厂思维:剖析《阿里巴巴Java开发手册》》、《再学经典:《EffectiveJava》独家解析》专栏作者。热门文章推荐:(1)《为什么很多人工作3年却只有1年经验?》(2)《一文掌握大模型提示词技巧:......
  • Python编程异步爬虫——aiohttp的使用
    异步爬虫—aiohttp的使用基本介绍asyncio模块其内部实现了对TCP、UDP、SSL协议的异步操作,但是对于HTTP请求来说,就需要用aiohttp实现了。aiohttp是一个基于asyncio的异步HTTP网络模块,它既提供了服务端,又提供了客户端。requests发起的是同步网络请求,aiohttp则是异步。ai......