unity应用实例(二)——用unity模拟深度优先遍历(DFS)

DFS是被广泛运用的搜索算法,它属于一种盲目搜索,定义如下:

1、起始访问的顶点是指定的;

2、若当前访问的顶点的邻接顶点有未被访问的,则任选一个访问;反之,退回到最近访问过的顶点;直到与起始顶点相通的全部顶点都访问完毕;

3、若此时图中尚有顶点未被访问,则再选其中一个顶点作为起始顶点并访问之,转 2; 反之,遍历结束。

    大多数时候我们用dfs时会采用递归的方式,但是非递归的方式更加直观,思路更清晰,更便于我们去理解”深度“的思想。这篇文章主要介绍如何用unity引擎来可视化模拟非递归的dfs算法。为了方便理解,给出一个经典的红黑格题目,要求如下:

    有一个长方形的房间,房间里的地面上布满了正方形的瓷砖,瓷砖要么是红色的,要么是黑色的。一个人站在其中一块黑色的瓷砖上,他可以向四周的瓷砖上移动,但是不能移动到红色的瓷砖上,只能在黑色的瓷砖上移动,用深度优先搜索的思想模拟该过程。

    输入数据有三个,分别是房间的长和宽,以及一个字符串。字符串含有房间中砖块的颜色信息,例如“#”表示黑色瓷砖,“*”表示红色瓷砖,“@”表示该位置的黑色瓷砖,那么字符串可以是

"***#**######@#***##**#***##***#***#****##*###*#**"

(注意,长和宽的乘积应该和字符串字符数相同。)

脚本代码如下(c#):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
using System;
using UnityEditor;

public class NewBehaviourScript : MonoBehaviour
{
    public GameObject redcube, blackcube, yellowcube, origncube, Ethan;
    public string Str1;
    public int weight, height;
    private int k = 0;
    public char[,] map;
    public int[] path;//记录走过的坐标
    private int[] dx = { 1, -1, 0, 0 }, dy = { 0, 0, 1, -1 };
    public int[,] visited;//记录每一块砖走过的次数
    private int cnt = 0, row = 0, cnt2 = 0;
    private int sx = 0, sy = 0;
    public float time = 0;
    private bool moved = false, isbacking = false, once = false;
    private float deltaposxy = 4.2f, deltaposz = 0.27f;
    void Start()
    {
        //初始化map 生成地图
        Transform temp = transform;
        temp.position = new Vector3(orign.transform.position.x, 0, orign.transform.position.z);
        visited = new int[weight, height];
        map = new char[weight, height];
        path = new int[weight * height * 100];
        for (int j = 0; j < height; j++)
        {
            for (int i = 0; i < weight; i++)
            {
                if (Str1[k] == '*')
                {
                    map[i, j] = Str1[k];
                    temp.position = new Vector3(orign.transform.position.x + i * deltaposxy, 0, orign.transform.position.z + j * deltaposxy);
                    GameObject ared = Instantiate(red, temp.position, temp.rotation);
                    k++;
                    continue;
                }
                if (Str1[k] == '#')
                {

                    map[i, j] = Str1[k];
                    temp.position = new Vector3(orign.transform.position.x + i * deltaposxy, 0, orign.transform.position.z + j * deltaposxy);
                    GameObject ablack = Instantiate(black, temp.position, temp.rotation);
                    k++;
                    continue;
                }
                if (Str1[k] == '@')
                {
                    map[i, j] = Str1[k];
                    sx = i; sy = j;
                    temp.position = new Vector3(orign.transform.position.x + i * deltaposxy, 0, orign.transform.position.z + j * deltaposxy);
                    GameObject ayellow = Instantiate(yellow, temp.position, temp.rotation);
                    k++;
                    continue;
                }
            }
        }
        k = 0;
        gameObject.transform.position = new Vector3(orign.transform.position.x + sx * deltaposxy, deltaposz, orign.transform.position.z + sy * deltaposxy);
        dfs();
    }
    private int j = 0;
    void Update()
    {
        time++;
        if (time % 30 == 0)
        {
            if (cnt2 > 0)
            {
                Transform temp = transform;
                temp.position = new Vector3(orign.transform.position.x + path[j] * deltaposxy, deltaposz, orign.transform.position.z + path[j + 1] * deltaposxy);
                GameObject aethan = Instantiate(Ethan, temp.position, temp.rotation);
                j += 2;
                Destroy(aethan, 0.35f);
                cnt2--;
            }
        }
    }
    void dfs()
    {
        visited[sx, sy] = 1;//标记1表示Ethan走过此砖一次
        cnt++;
        while (true)
        {
            for (int i = 0; i < 4; i++)
            {
                int nx = sx + dx[i], ny = sy + dy[i];//前后左右选择一个方向判断

                if (nx >= 0 && nx < weight && ny >= 0 && ny < height)
                {
                    if (visited[nx, ny] == 0 && map[nx, ny] != '*')//找到了某一方向有从未走过的砖,前进
                    {
                        path[row] = nx; row++;
                        path[row] = ny; row++;
                        moved = true;
                        //在返回的途中发现没走过的砖,将现在脚下拐弯的砖标记为1(原本应该标记为2),因为后面一定还会至少再经过一次
                        if (isbacking == true) visited[sx, sy] = 1; //
                        isbacking = false;
                        sx = nx; sy = ny;
                        visited[sx, sy] = 1;//将走过一次的砖标记为1
                        cnt++;
                        cnt2++;
                        time = 0;
                        break;
                    }
                }

            }
            if (moved == true)
            {
                moved = false;
                continue;
            }
            //前后左右都不存在没走过的砖,此时找走过一次的砖
            for (int i = 0; i < 4; i++)
            {
                int nx = sx + dx[i], ny = sy + dy[i];//前后左右选择一个方向判断
                if (nx >= 0 && nx < weight && ny >= 0 && ny < height)
                {
                    if (visited[nx, ny] == 1 && map[nx, ny] != '*')//找到了某一方向有走过一次的砖,前进
                    {
                        path[row] = nx; row++;
                        path[row] = ny; row++;
                        moved = true;
                        sx = nx; sy = ny;
                        visited[sx, sy] = 2;//将走过两次的砖标记为2
                        isbacking = true;
                        time = 0;
                        cnt2++;
                        break;
                    }
                }
            }
            if (moved == true)
            {
                moved = false;
                continue;
            }
            Debug.Log(cnt);
            break;
        }
    }
}

将此脚本挂在一个空物体上,并在unity中给脚本的每一个数据成员赋上初始值,点击开始就可以开到模拟出的dfs算法思路。效果如下:

扫描二维码关注公众号,回复: 1796298 查看本文章



谢谢观看:)




猜你喜欢

转载自blog.csdn.net/qq_37553152/article/details/79857871
今日推荐