猴子与香蕉 AI 游戏

  • 一款解决从源头到目的地寻找正确路径问题的 AI 游戏。

  • 使用广度优先算法。


游戏 APK 下载安装链接


YouTube 上的游戏视频


解释游戏玩法

  • 猴子找到四条通往香蕉的路。
  • 它会走每一条路,检查香蕉是否在那里,或者什么。
  • 如果在那里,它就赢了,否则它就走下一条路……
  • 香蕉的目标或位置是随机的。

Image of Yaktocat


项目实现 (一些重要代码) :-

我们使用 Flutter 进行开发。

  • 首先:我们使用图来设计 UI,并将游戏视为一组节点和边,然后使用广度优先算法,使用 Dart 中的迭代器来搜索随机目标 (香蕉)。

  • _BreadthFirstTree 创建 BreadthFirstIterator。此外,这两个集合都存储 Graph 对象以保存树数据结构本身。

ITreeIterator 为所有特定的树集合迭代器定义了一个通用接口

  • hasNext() – 如果迭代器尚未到达集合末尾,则返回 true,否则返回 false;
  • getNext() – 返回集合的下一个值;
  • reset() – 重置迭代器并将当前位置设置为开头。

广度优先算法使用 **队列** 数据结构

来存储需要接下来访问的节点(顶点)。


Dart 中的图代码

一个存储图的邻接列表的类。它存储为映射数据结构,其中键代表节点的(顶点的)ID,值是与该 ID (键) 的顶点相邻的顶点的列表(其他节点 ID)。此外,该类定义了 addEdge() 方法来向邻接列表添加边。

class Graph {
  final Map<int, Set<int>> adjacencyList = Map<int, Set<int>>();

  void addEdge(int source, int target) {
    if (adjacencyList.containsKey(source)) {
      adjacencyList[source].add(target);
    } else {
      adjacencyList[source] = {target};
    }
  }
}

树集合

  • BreadthFirstTreeCollection – 一个树集合类,它存储图对象并实现 createIterator() 方法来创建一个使用广度优先算法遍历图的迭代器。

class BreadthFirstTreeCollection implements ITreeCollection {
  final Graph graph;

  const BreadthFirstTreeCollection(this.graph);

  @override
  ITreeIterator createIterator() {
    return BreadthFirstIterator(this);
  }

  @override
  String getTitle() {
    return 'Breadth-first';
  }
}

广度优先算法代码 :-

  • BreadthFirstIterator – 树迭代器的特定实现,它使用广度优先算法遍历树集合。该算法使用 **队列** 数据结构来存储需要通过 getNext() 方法访问的顶点(节点)。

class BreadthFirstIterator implements ITreeIterator {
  final BreadthFirstTreeCollection treeCollection;
  final Set<int> visitedNodes = <int>{};
  final ListQueue<int> nodeQueue = ListQueue<int>();

  final int _initialNode = 1;
  int _currentNode;

  BreadthFirstIterator(this.treeCollection) {
    _currentNode = _initialNode;
    nodeQueue.add(_initialNode);
  }

  Map<int, Set<int>> get adjacencyList => treeCollection.graph.adjacencyList;

  @override
  bool hasNext() {
    return nodeQueue.isNotEmpty;
  }

  @override
  int getNext() {
    if (!hasNext()) {
      return null;
    }

    _currentNode = nodeQueue.removeFirst();
    visitedNodes.add(_currentNode);

    if (adjacencyList.containsKey(_currentNode)) {
      for (var node in adjacencyList[_currentNode]
          .where((n) => !visitedNodes.contains(n))) {
        nodeQueue.addLast(node);
      }
    }

    return _currentNode;
  }

  @override
  void reset() {
    _currentNode = _initialNode;
    visitedNodes.clear();
    nodeQueue.clear();
    nodeQueue.add(_initialNode);
  }
}

图 (节点 & 边) 定义

  Graph _buildGraph() {
    var graph = Graph();

    graph.addEdge(1, 21);
    graph.addEdge(1, 22);
    graph.addEdge(1, 23);
    graph.addEdge(1, 24);

    graph.addEdge(21, 31);
    graph.addEdge(21, 25);
    graph.addEdge(21, 20);
    graph.addEdge(21, 14);
    graph.addEdge(21, 13);
    graph.addEdge(21, 7);
    graph.addEdge(21, 11);
    graph.addEdge(21, 28);
    ....
    ....
    ....
    ....
    return graph;
  }

您将在 (lib) 文件夹中找到实现代码

GitHub

查看 Github