简体   繁体   English

深度优先搜索 - 2D游戏地图

[英]Depth first search - 2D Game map

I have created a 2D maze, and I want to find the quickest path between the red->blue colored nodes. 我创建了一个2D迷宫,我想找到红色 - 蓝色节点之间最快的路径。 I'm an unsure how I would go about implementing a depth-first search. 我不确定如何实施深度优先搜索。 I know that an adjacency matrix or list could be used to represent the connections between nodes. 我知道可以使用邻接矩阵或列表来表示节点之间的连接。 Though, I am unsure of how to construct it. 虽然,我不确定如何构建它。

for brevity : I need to return a list with the tiles coordinates searched (when looking for goal node), so i can depict the search on the maze. 为简洁起见 :我需要返回一个列表,其中搜索了瓷砖坐标(当寻找目标节点时),因此我可以在迷宫上描绘搜索。 Or how would i construct an adjacency matrix for this? 或者我将如何为此构建一个邻接矩阵? and the corresponding vertex list? 和相应的顶点列表?

Depth first search general structure 深度首先搜索一般结构

  1. Visit node(cell) (change visited flag to true) 访问节点(单元格)(将访问标志更改为true)
  2. Push to Stack 推送到堆栈
  3. get unvisited vertex (peek stack) if none (pop stack) - update maze model view 获取未访问的顶点(peek stack)如果没有(pop stack) - 更新迷宫模型视图

Repeat 1 - 3 until stack empty 重复1 - 3直到堆栈为空

Here is the current code for the maze class. 这是迷宫类的当前代码。

public class Maze {

    //Tile ids
    public static short OBSTICLE = 0;
    public static short START_LOC_VALUE = -2;
    public static short GOAL_LOC_VALUE = -3;

    private int rows, cols;
    private int numTiles;
    private int[][] map;
    private int[][] adjMatrix;
    private Queue theQueue; 

    public Maze(int rows, int cols){
        this.rows = rows;
        this.cols = cols;

        theQueue = new Queue();

        numTiles = rows*cols;

        map = new int[rows][cols];
        adjMatrix = new int[rows][cols];

        for (int i=0; i<rows; i++) {
            for (int j=0; j<cols; j++) {
                map[i][j] = 1;
            }
        }
    }

    /*
     * Generate Maze
     * @param numObstacles - number of obstacles
     */
    public void generateMaze(int numObstacles){
        for (int i = 0; i < numObstacles; i++)
            setTile((int)(Math.random()*rows),(int)(Math.random()*cols), Maze.OBSTICLE);

       //setTile((int)(Math.random()*rows),(int)(Math.random()*cols),Maze.START_LOC_VALUE);
       //setTile((int)(Math.random()*rows),(int)(Math.random()*cols),Maze.GOAL_LOC_VALUE);
        createAdjMatrix();
    }

    public void createAdjMatrix(){
        for (int i=0; i<rows; i++) {
            for (int j=0; j<cols; j++) {
                if (map[i][j] == 1) {
                    addEdge(i,j);
                }
            }
        }
    }

     /*
     * Set Tile
     * @param x - x cord
     * @param y - y cord
     * @param entity - OBSTICLE,START_LOC_VALUE or GOAL_LOC_VALUE ID
     */
    public void setTile(int x, int y, short entity){
        this.map[x][y] = entity;
    }

    public void addEdge(int start, int end) {//Start and end arguments index multidimensional array
            adjMatrix[start][end] = 1;
            adjMatrix[end][start] = 1;
    }

    public void bfs(int startDest, int goalDest) // breadth-first search
        { 
            // begin at vertex 0
            vertexList[startDest].wasVisited = true; // mark it
            displayVertex(startDest); // display it
            theQueue.enQueue(startDest); // insert at tail
            int v2;

            while (!theQueue.isEmpty()) // until queue empty,
            {
                int v1 = theQueue.deQueue(); // remove vertex at head

                // until it has no unvisited neighbors
                while ((v2 = getAdjUnvisitedVertex(v1)) != -1)
                { // get one,

                    vertexList[v2].wasVisited = true; // mark it
                    displayVertex(v2); // display it
                    theQueue.enQueue(v2); // insert it

                } // end while(unvisited neighbors)
            } // end while(queue not empty)

            // queue is empty, so we’re done
            for (int j = 0; j < nVerts; j++) // reset flags
                vertexList[j].wasVisited = false;
        }// end bfs()

     /*
     * Drawn Maze
     * @param g - Graphics object
     */
    public void draw(Graphics g){
        for (int y = 0; y < cols; y++) 
            for (int x = 0; x < rows; x++) {
                int val = map[x][y];

                if (val==Maze.OBSTICLE) {
                    g.setColor(Color.BLACK);
                    g.fillRect(x*20, y*20, 20, 20);
                }else if(val == Maze.START_LOC_VALUE){
                    g.setColor(Color.RED);
                    g.fillRect(x*20, y*20, 20, 20);
                }else if(val==Maze.GOAL_LOC_VALUE){
                    g.setColor(Color.BLUE);
                    g.fillRect(x*20, y*20, 20, 20);
                }else{
                    g.setColor(Color.BLACK);
                    g.drawRect(x*20, y*20, 20, 20); 
                }
            } 
    }
}

current DFS code.. 目前的DFS代码..

public void dfs(int vertexStart) // depth-first search
        { 
            // begin at vertexStart
            vertexList[vertexStart].wasVisited = true; // mark it
            displayVertex(vertexStart); // display it
            theStack.push(vertexStart); // push it

            while (!theStack.isEmpty()) // until stack empty,
            {
                // get an unvisited vertex adjacent to stack top
                int v = getAdjUnvisitedVertex(theStack.peek());

                if (v == -1) // if no such vertex,
                    theStack.pop(); // pop a new one
                else // if it exists,
                {
                    vertexList[v].wasVisited = true; // mark it
                    displayVertex(v); // display it
                    theStack.push(v); // push it
                }
            } // end while
    }

The following pictures depicts the maze structure, it has been generated pseudo randomly; 以下图片描绘了迷宫结构,它是伪随机生成的; the final maze implementation will be refined. 最终的迷宫实施将得到完善。

迷宫

Thanks, I will be great full if you could guide me in the right direction... 谢谢,如果你能引导我朝着正确的方向前进,我将会非常满意......

For 2D Maze you can simply use Breadth First Search instead of Depth First Search, It will find it in O(n 2 ) if you have n*n maze. 对于2D迷宫,您可以简单地使用广度优先搜索而不是深度优先搜索,如果您有n * n迷宫,它将在O(n 2 )中找到它。

But there is another option, which is kind of labeling and BFS and works on your maze (no need to graph). 但还有另一种选择,即标签和BFS,可以在您的迷宫上运行(无需图表)。

Numbering algorithm 编号算法

One of an interesting ways to understand the breadth first search is do it in this way (for maze): 了解广度优先搜索的一种有趣方法是以这种方式(对于迷宫):

  1. Set all cells to 0, and set blocks to -1 将所有单元格设置为0,并将块设置为-1

  2. Start from your source position set it to 1, mark all of it's 0 neighbors to 2, and save all 2's in a list. 从源位置开始将其设置为1,将所有0个邻居标记为2,并将所有2个保存在列表中。 after that mark all 0 neighbors of 2's to 3, clear list of 2's and save list of 3's and go on to reach the destination. 在那之后标记所有0个2到3的邻居,清除2的列表并保存3的列表并继续到达目的地。 in each level just do not change the source value. 在每个级别只是不要更改源值。

  3. Now assume you are in destination and you want to find path, your destination has score m, find neighbor with score m-1, .... and output the path. 现在假设您在目的地,并且您想要找到路径,您的目的地有得分m,找到分数为m-1的邻居,....并输出路径。

In fact normal and simple way of BFS is using Q, but I offered this for it's simplicity and because it simulates Q manner. 事实上,BFS的正常和简单方式是使用Q,但我提供了它的简单性,因为它模拟Q方式。

Using adjacency matrix 使用邻接矩阵

For creating adjacency matrix, you should have named node and edges, so you can have a classes like below for edges and nodes (I wrote it in pseudo C#): 为了创建邻接矩阵,你应该有命名节点和边,所以你可以为边和节点创建如下所示的类(我用伪C#编写):

public class Edge
{

   public Edge(Node start, Node end, decimal weight)
   {
      StartNode = ...,...,...
   }
   public Node StartNode;
   public Node EndNode;
   public decimal weight;
   public bool IsDirected;
}

public class Node
{
   public Node(int index)
   {
        this.Index = index;
   }
   public int Index;
   public List<Edge> Edges = new List<Edge>();
   public bool Visited = false;
}

Now your graph is list of your Node objects: 现在您的图表是Node对象的列表:

public class Graph
{
   public List<Node> Nodes = new List<Node>();
}

And for modeling your Maze you should select cells as node, and draw edge between neighbor cells. 对于Maze的建模,您应该选择单元格作为节点,并在相邻单元格之间绘制边缘。 I'll left it to you how to add node to your graph. 我会告诉你如何在你的图表中添加节点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM