Unity 波函数坍缩算法随机地图生成

news2025/3/11 3:28:28

Unity 波函数坍缩算法随机地图生成

  • 波函数
    • 波函数基本概念
      • 位置空间波函数
      • 动量空间波函数
      • 两种波函数之间的关系
      • 波函数的本征值和本征态
      • 波函数坍缩
    • 熵是什么
      • 熵作为状态函数
      • 时间之箭
    • 实现原理
      • 举个例子:2D迷宫地图生成
    • Unity 如何实现
      • 前期准备
      • 单元格代码
      • 瓦片地图代码
      • 波函数代码
        • 熵检查方法
        • 坍缩方法
        • 有效性方法
        • 完整代码
    • 脚本搭载
    • 实现 效果
    • 可扩展效果

波函数

波函数基本概念

在量子力学里,量子系统的量子态可以用波函数(英语:Wave function)来描述。薛定谔方程设定波函数如何随着时间流逝而演化。
波函数 ψ(r,t) 是一种复值函数,表示粒子在位置 r 、时间 t 的概率幅,它的绝对值平方 |ψ(r,t)|² 是在位置 r 、时间 t 找到粒子的概率密度。以另一种角度诠释,波函数 ψ(r,t) 是“在某时间、某位置发生相互作用的概率幅”。

设想经典力学里的谐振子系统(A-B),一条弹簧的一端固定不动,另一端有一个带质量圆球;
在量子力学里,(C-H)展示出同样系统的薛定谔方程的六个波函数解。
横轴坐标表示位置,竖轴坐标表示波函数概率幅的实部(蓝色)或虚部(红色)。
(C-F)是定态,(GH)不是定态。定态的能量为驻波振动频率与约化普朗克常数的乘积。
这里简单了解一下就行。

在这里插入图片描述

位置空间波函数

我们主要用到的就是这个位置空间波函数,不过也不用管,了解基本概念就行

假设一个自旋为零的粒子移动于一维空间。这粒子的量子态以波函数表示为 ψ(r,t) ;其中,x 是位置,是时间。波函数是复值函数。测量粒子位置所得到的结果不是决定性的,而是概率性的。粒子的位置 x 在区间 [a,b](即 a ≤ x ≤b )的概率为 Pa ≤ Px ≤ Pb

在这里插入图片描述

其中,** t** 是对于粒子位置做测量的时间。
换句话说 |ψ(r,t)|² 是粒子在位置 x 、时间 t 的概率密度。
这导致归一化条件:在位置空间的任意位置找到粒子的概率为 100%

在这里插入图片描述

好了终于打完了,真不好写。简单来说就是你想在什么时候吃饭就会在什么时候吃饭。
由于世界的不确定性,当你决定做什么的时候,就证明你已经做了什么事情。
完了,还解释不清楚了。
也可以这么理解,当你喝咖啡的时候你喝奶茶的概率就变成 0,你喝咖啡的概率就变成 1。
就先这样理解吧,这个还真不好解释。

动量空间波函数

这个算是扩展,看不看都行

在动量空间,粒子的波函数便是为 ψ(p,t) ;其中 p 是一维动量,值域从 ** -∞ ** 到 +∞。测量粒子动量所得到的结果不是决定性的,而是概率性的。粒子的动量 p 在区间 [a,b](a ≤ p ≤ b) 的概率为
在这里插入图片描述

动量空间波函数的归一条件是:

在这里插入图片描述

两种波函数之间的关系

位置空间波函数与动量空间波函数彼此是对方的傅里叶变换。他们各自拥有的信息相同,任何一种波函数都可以用来计算粒子的相关性质。两种波函数之间的关系为
在这里插入图片描述

波函数的本征值和本征态

在量子力学中,,态就意味着函数,因为量子力学的状态是用波函数来描述的,因此只要是态,,就是波函数。
本征函数定义:如果一个算符A作用在一个函数上,等于一个常数a乘以这个函数, 就说该函数是这个算符本征值为a的本征函数。
如果是非简并的本征态,,本征值和本征态存在着一 一对应的关系。 量子力学中属于不同本征值的本征态一定相互正交(厄米算符性质)
如果是简并的本征态,属于同一本征值的本征态的线性组合依然是该算符的本征态, 不再存在着一一对应的关系,但依然可以组合成相互正交的本征函数。

本征值和本征态

在这里插入图片描述

波函数坍缩

波函数坍缩(wave function collapse)指的是某些量子力学体系与外界发生某些作用后波函数发生突变,变为其中一个本征态或有限个具有相同本征值的本征态的线性组合的现象。波函数坍缩可以用来解释为何在单次测量中被测定的物理量的值是确定的,尽管多次测量中每次测量值可能都不同。

双缝干涉实验

在这里插入图片描述

熵是什么

熵是一种测量在动力学方面不能做功的能量总数,也就是当总体的熵增加,其做功能力也下降熵的量度正是能量退化的指标。熵亦被用于计算一个系统中的失序现象,也就是计算该系统混乱的程度。
熵是一个描述系统状态的函数,但是经常用熵的参考值和变化量进行分析比较它在控制论、概率论、数论、天体物理、生命科学等领域都有重要应用在不同的学科中也有引申出的更为具体的定义,是各领域十分重要的参量。

在这里插入图片描述

熵作为状态函数

首先,想象一个可逆过程,如果将系统从一个平衡状态A转移到另一个平衡状态B。假如再经过一个任何可逆过程将系统带回状态A,结果是熵的绝对变化等于零。这意味着在第一个过程中,熵的变化仅仅取决于初始与终结状态.由此可以定义一个系统的任何平衡状态的熵。选择一个参照状态R,定义它的熵为,任何平衡状态X的熵为:

因为这个积分式与热转移过程无关,所以当作为熵的定义。

时间之箭

熵是在物理学领域中似乎暗示只朝向一个特定行进方向的量,有时被称为时间之箭。随着时间的推移,热力学第二定律:孤立系统的熵状态永远只会增加,不会减少。因此,从这个角度看,熵的测量被看作是一种时钟。

实现原理

我们假定你有图案的一些“局部信息 A ”,也就是说,图案中的一小块应该长成什么样子,以及这些小块之间的一些重叠关系能否出现。图案中的一小块我们用一个固定大小的小图片来表示。如果你还知道这些小块之间出现几率的比例就更好了。当然不知道也没有关系,我们可以假定它们的出现几率差不多。那么我们的目标就是生成一个图片,使得其所有的局部(也就是固定大小的小区域)都是在之前的“局部信息”中出现过的,并且出现的几率和之前给出的“局部信息”的几率尽量相近。

最小不确定性原则:
在每次迭代中,选择具有最小可能图案数的格子进行确定性坍缩,这有助于减少错误和回溯的可能性。

兼容性检查:
当一个格子的波函数坍缩时,必须检查它与相邻格子的兼容性,以确保生成的地图符合局部规则。

概率分布:
波函数的坍缩基于概率分布,这意味着算法可以生成具有随机性的地图,同时保持整体的连贯性和规则性。
示例1:切片A 是已经确定的地图,那么连接处 瓦片地图出现的概率就是下面这张图

在这里插入图片描述

示例2:切片A 是已经确定的地图,那么连接处 瓦片地图出现的概率就是下面这张图
这里考虑的是四方,可以自己进行扩展。

在这里插入图片描述

举个例子:2D迷宫地图生成

假设我们要用波函数坍缩算法在Unity中生成一个2D迷宫地图,这个地图由墙壁和路径组成。

1. 定义基本单元:
墙壁瓦片:表示迷宫中的墙壁,不可通过。
路径瓦片:表示迷宫中的开放路径,可以通行。

2. 初始化波函数:
我们有一个10x10的网格,每个格子的波函数包含墙壁和路径两种可能的状态。

3. 建立局部规则:
规则定义了路径瓦片周围不能有4个连续的墙壁瓦片,以避免形成死胡同或封闭区域。
墙壁瓦片则可以与任何类型的瓦片相邻。

4. 确定性坍缩:
假设我们从左上角开始,选择一个格子进行坍缩,由于没有其他信息,这个格子有相等的机会成为墙壁或路径。
假设我们随机选择路径瓦片,那么这个格子的波函数就坍缩为路径瓦片。

5. 传播更新:
坍缩后,我们需要更新相邻格子的波函数。例如,如果选择了路径瓦片
那么它的直接邻居不能全部是墙壁瓦片,以避免形成死胡同。

6. 迭代过程:
接下来,我们选择下一个熵最小的格子进行坍缩,重复这个过程,直到整个网格都被填充。

7. 生成地图:
最终,我们根据每个格子坍缩后的状态,实例化对应的Unity预制体。
例如,路径瓦片可能是一个可通行的平面,而墙壁瓦片可能是一个不可通行的障碍物。
假设我们的迷宫网格如下:

[墙壁, 路径, 墙壁, ..., 路径]
[路径, 路径, 路径, ..., 墙壁]
[墙壁, 墙壁, 路径, ..., 路径]
...
[路径, 墙壁, 路径, ..., 墙壁]

现在,我们从左上角开始,第一个格子坍缩为路径瓦片,然后根据规则更新相邻格子的波函数。
比如,第一个格子的右边和下边的格子不能同时是墙壁瓦片。
其实还挺好理解的。

Unity 如何实现

前期准备

1. 新建一个工程,根据自己使用的创建就行,我这里使用的是 2022.30
2. 准备 自己喜欢并且可以连续的网片地图
3. 最好写一个实现流程或者思维导图(不写也行,写的话会更有条理一些)

在这里插入图片描述

单元格代码

根据你想要实现的效果,设置单元地图预制体。
这个代码的作用就是地图生成缓存
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 单元格
/// </summary>
public class Cell_ZH : MonoBehaviour
{
    /// <summary>
    /// 坍缩布尔
    /// </summary>
    public bool _Collapsed;

    /// <summary>
    /// 瓦片地图
    /// </summary>
    public Tile_ZH[] _Tileoptions;

    /// <summary>
    /// 创建单元格
    /// </summary>
    /// <param name="_CollapseState"></param>
    /// <param name="_Tiles"></param>
    public void CreateCell(bool _CollapseState, Tile_ZH[] _Tiles)
    {
        _Collapsed = _CollapseState;

        _Tileoptions = _Tiles;
    }

    /// <summary>
    /// 重建 单元
    /// </summary>
    /// <param name="_Tiles"></param>
    public void RecreateCell(Tile_ZH[] _Tiles)
    {
        _Tileoptions = _Tiles;
    }
}

脚本搭载以及预制体

在这里插入图片描述

在这里插入图片描述

瓦片地图代码

就是生成瓦片地图相关的概率分布,没坍缩之前都是均等的。
当然也可以扩展成八方和 3D 的。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 瓦片地图
/// </summary>
public class Tile_ZH : MonoBehaviour
{
    //可增加 瓦片类型  比如左上角 右上角 左下角 右下角等
    [Header("上方 相邻数组")]
    public Tile_ZH[] _UpNeighbours;
    [Header("右边 相邻数组")]
    public Tile_ZH[] _RigihtNeighbours;
    [Header("下方 相邻数组")]
    public Tile_ZH[] _DownNeighbours;
    [Header("左边 相邻数组")]
    public Tile_ZH[] _LeftNeighbours;
}
脚本搭载以及预制体

在这里插入图片描述

在这里插入图片描述

波函数代码

熵检查方法
主要作用就是:
	创建一个临时网格列表,移除已坍缩的单元格,按照瓦片选项数组长度对单元格排序
	优先处理选项最少的单元格。
    /// <summary>
    /// 检查熵
    /// 临时网格获取
    /// </summary>
    /// <returns></returns>
    private IEnumerator CheckEntropy()
    {
        // 临时网格数组,用于存储当前未坍缩的单元格
        List<Cell_ZH> _TempGrid = new List<Cell_ZH>(_GridCompoents);

        // 从临时网格中移除所有已经坍缩的单元格
        _TempGrid.RemoveAll(c => c._Collapsed);

        // 按照 _Tileoptions 数组的长度进行排序,长度最小的单元格优先处理
        _TempGrid.Sort((a, b) => { return a._Tileoptions.Length - b._Tileoptions.Length; });

        // 获取最小的 _Tileoptions 数组的长度
        int _ArrLenght = _TempGrid[0]._Tileoptions.Length;

        int _StopIndex = default;

        // 查找最小长度的单元格群组,并获取停止索引
        for (int i = 0; i < _TempGrid.Count; i++)
        {
            if (_TempGrid[i]._Tileoptions.Length > _ArrLenght)
            {
                _StopIndex = i;
                break;
            }
        }

        // 如果找到了停止索引,就移除后续的单元格,只保留熵最低的一组
        if (_StopIndex > 0)
        {
            _TempGrid.RemoveRange(_StopIndex, _TempGrid.Count - _StopIndex);
        }

        // 等待一段时间后开始坍缩单元格
        yield return new WaitForSeconds(0.01f);

        // 调用 CollapseCell 方法,对选中的单元格群组进行坍缩处理
        CollapseCell(_TempGrid);
    }
坍缩方法
主要作用就是:
	随机选择一个单元格进行坍缩,设置坍缩状态并选择一个瓦片进行实例化
	调用 UpdateGeneration() 方法更新网格。
    /// <summary>
    /// 单元格 坍缩
    /// 获取当前单元格 确定变量
    /// </summary>
    /// <param 临时网格="_TempGrid"></param>
    private void CollapseCell(List<Cell_ZH> _TempGrid)
    {
        //随机瓦片数组
        int _RandIndex = UnityEngine.Random.Range(0, _TempGrid.Count);


        //获取当前随机的地图
        Cell_ZH _CellToCollapse = _TempGrid[_RandIndex];

        //坍缩布尔设置
        _CellToCollapse._Collapsed = true;

        //获取当前单元格坍缩值
        //print(UnityEngine.Random.Range(0, _CellToCollapse._Tileoptions.Length));


        if (_CellToCollapse._Tileoptions != null && _CellToCollapse._Tileoptions.Length > 0)
        {
            Tile_ZH _SelectedTile = _CellToCollapse._Tileoptions[UnityEngine.Random.Range(0, _CellToCollapse._Tileoptions.Length)];
            _CellToCollapse._Tileoptions = new Tile_ZH[] { _SelectedTile };


            _CellToCollapse._Tileoptions = new Tile_ZH[] { _SelectedTile };

            Tile_ZH _FoundTile = _CellToCollapse._Tileoptions[0];

            //实例化当前地图
            Instantiate(_FoundTile, _CellToCollapse.transform.position * 4.73f, Quaternion.identity, GameObject.Find("Model").transform);

            //网格更新
            UpdateGeneration();
        }
    }
有效性方法
主要作用就是:这个方法比较重要
	确保当前单元格的瓦片选项在有效选项列表中
	如果没有有效选项,添加一个默认选项。
    /// <summary>
    /// 有效性 检查
    /// </summary>
    /// <param 功能单元格列表="_OptionList"></param>
    /// <param 有效性单元格列表="_ValidOptions"></param>
    private void CheckValidity(List<Tile_ZH> _OptionList, List<Tile_ZH> _ValidOptions)
    {
        // 有效性检查 布尔
        bool _HasValidOptions = false;

        // 单元格列表比对
        for (int x = _OptionList.Count - 1; x >= 0; x--)
        {
            var _Element = _OptionList[x];

            // 检查有效性单元格列表是否包含当前单元格数据
            if (!_ValidOptions.Contains(_Element))
            {
                // 如果不包含就进行移除处理
                _OptionList.RemoveAt(x);
            }
            else
            {
                _HasValidOptions = true;
            }
        }

        // 如果没有找到任何有效选项,采取措施
        if (!_HasValidOptions)
        {
            // 保留一个默认的选项(这里可以根据具体情况设定)
            if (_OptionList.Count == 0 && _ValidOptions.Count > 0)
            {
                // 添加一个有效性选项中的第一个作为默认选项
                _OptionList.Add(_ValidOptions[0]); 
            }
            else if (_OptionList.Count == 0)
            {
                // 如果确实没有任何有效选项,则添加一个兜底选项(可以是一个最常用或最不影响整体的瓦片)
                // 假设第一个瓦片是兜底选项
                _OptionList.Add(_TileObjects[0]); 
            }
            Debug.Log("没有有效选项,回退操作");
        }
    }
完整代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

/// <summary>
/// 波函数
/// </summary>
public class WaveFunctiopn_ZH : MonoBehaviour
{
    [Header("地图尺寸")]
    public int _Dimensions;

    [Header("平铺对象数组")]
    public Tile_ZH[] _TileObjects;

    [Header("网格数组")]
    public List<Cell_ZH> _GridCompoents;

    [Header("单元格")]
    public Cell_ZH _CellObj;

    //迭代    
    int _Iterations = 0;

    private void Awake()
    {
       _GridCompoents = new List<Cell_ZH>();

        InitializeGrid();
    }


    /// <summary>
    /// 网格初始化
    /// </summary>
    void InitializeGrid()
    {
        for (int y = 0; y < _Dimensions; y++)
        {
            for (int x = 0; x < _Dimensions; x++)
            {
                //根据地图大小 生成单元格
                Cell_ZH _NewCell = Instantiate(_CellObj, new Vector2(x, y), Quaternion.identity, GameObject.Find("Model").transform);

                //单元格创建
                _NewCell.CreateCell(false, _TileObjects);

                //网格数组添加
                _GridCompoents.Add(_NewCell);


            }
        }
        StartCoroutine(CheckEntropy());
    }

    /// <summary>
    /// 检查熵
    /// 临时网格获取
    /// </summary>
    /// <returns></returns>
    private IEnumerator CheckEntropy()
    {
        // 临时网格数组,用于存储当前未坍缩的单元格
        List<Cell_ZH> _TempGrid = new List<Cell_ZH>(_GridCompoents);

        // 从临时网格中移除所有已经坍缩的单元格
        _TempGrid.RemoveAll(c => c._Collapsed);

        // 按照 _Tileoptions 数组的长度进行排序,长度最小的单元格优先处理
        _TempGrid.Sort((a, b) => { return a._Tileoptions.Length - b._Tileoptions.Length; });

        // 获取最小的 _Tileoptions 数组的长度
        int _ArrLenght = _TempGrid[0]._Tileoptions.Length;

        int _StopIndex = default;

        // 查找最小长度的单元格群组,并获取停止索引
        for (int i = 0; i < _TempGrid.Count; i++)
        {
            if (_TempGrid[i]._Tileoptions.Length > _ArrLenght)
            {
                _StopIndex = i;
                break;
            }
        }

        // 如果找到了停止索引,就移除后续的单元格,只保留熵最低的一组
        if (_StopIndex > 0)
        {
            _TempGrid.RemoveRange(_StopIndex, _TempGrid.Count - _StopIndex);
        }

        // 等待一段时间后开始坍缩单元格
        yield return new WaitForSeconds(0.01f);

        // 调用 CollapseCell 方法,对选中的单元格群组进行坍缩处理
        CollapseCell(_TempGrid);
    }



    /// <summary>
    /// 单元格 坍缩
    /// 获取当前单元格 确定变量
    /// </summary>
    /// <param 临时网格="_TempGrid"></param>
    private void CollapseCell(List<Cell_ZH> _TempGrid)
    {
        //随机瓦片数组
        int _RandIndex = UnityEngine.Random.Range(0, _TempGrid.Count);


        //获取当前随机的地图
        Cell_ZH _CellToCollapse = _TempGrid[_RandIndex];

        //坍缩布尔设置
        _CellToCollapse._Collapsed = true;

        //获取当前单元格坍缩值
        //print(UnityEngine.Random.Range(0, _CellToCollapse._Tileoptions.Length));


        if (_CellToCollapse._Tileoptions != null && _CellToCollapse._Tileoptions.Length > 0)
        {
            Tile_ZH _SelectedTile = _CellToCollapse._Tileoptions[UnityEngine.Random.Range(0, _CellToCollapse._Tileoptions.Length)];
            _CellToCollapse._Tileoptions = new Tile_ZH[] { _SelectedTile };


            _CellToCollapse._Tileoptions = new Tile_ZH[] { _SelectedTile };

            Tile_ZH _FoundTile = _CellToCollapse._Tileoptions[0];

            //实例化当前地图
            Instantiate(_FoundTile, _CellToCollapse.transform.position * 4.73f, Quaternion.identity, GameObject.Find("Model").transform);

            //网格更新
            UpdateGeneration();
        }
    }



    /// <summary>
    /// 网格迭代更新
    /// </summary>
    private void UpdateGeneration()
    {
        //缓存单元格数组
        List<Cell_ZH> _NewGeneraTionCell = new List<Cell_ZH>(_GridCompoents);

        for (int y = 0; y < _Dimensions; y++)
        {
            for (int x = 0; x < _Dimensions; x++)
            {
                //快查算法
                var _Index = x + y * _Dimensions;

                //如果当前单元格已经坍缩 就直接 break
                if (_GridCompoents[_Index]._Collapsed)
                {
                    _NewGeneraTionCell[_Index] = _GridCompoents[_Index];                   
                }
                //如果没有坍缩
                else
                {
                    //创建瓦片地图索引
                    List<Tile_ZH> _Options = new List<Tile_ZH>();

                    foreach (var item in _TileObjects)
                    {
                        _Options.Add(item);
                    }

                    //四方检测
                    //上方单元格检测
                    if (y>0)
                    {
                        //索引查找
                        Cell_ZH _Up = _GridCompoents[x + (y - 1) * _Dimensions];

                        List<Tile_ZH> _ValidOptions= new List<Tile_ZH>();

                        foreach (Tile_ZH _PossibleOptions in _Up._Tileoptions)
                        {
                            var _ValOptions = Array.FindIndex(_TileObjects, _Obj => _Obj == _PossibleOptions);

                            var _Valid = _TileObjects[_ValOptions]._UpNeighbours;


                            _ValidOptions = _ValidOptions.Concat(_Valid).ToList();
                        }
                        //单元格有效性检查
                        CheckValidity(_Options,_ValidOptions);
                    }
                    //右侧单元格检测
                    if (x<_Dimensions-1)
                    {
                        Cell_ZH _Right = _GridCompoents[x +1+y  * _Dimensions].GetComponent<Cell_ZH>();

                        List<Tile_ZH> _ValidOptions = new List<Tile_ZH>();

                        foreach (Tile_ZH _PossibleOptions in _Right._Tileoptions)
                        {
                            var _ValOptions = Array.FindIndex(_TileObjects, _Obj => _Obj == _PossibleOptions);

                            var _Valid = _TileObjects[_ValOptions]._LeftNeighbours;


                            _ValidOptions = _ValidOptions.Concat(_Valid).ToList();
                        }

                        //单元格有效性检查
                        CheckValidity(_Options, _ValidOptions);

                    }
                    //下方 单元格检测
                    if (y<_Dimensions-1)
                    {
                        Cell_ZH _Down = _GridCompoents[x + (y+1) * _Dimensions].GetComponent<Cell_ZH>();

                        List<Tile_ZH> _ValidOptions = new List<Tile_ZH>();

                        foreach (Tile_ZH _PossibleOptions in _Down._Tileoptions)
                        {
                            var _ValOptions = Array.FindIndex(_TileObjects, _Obj => _Obj == _PossibleOptions);

                            var _Valid = _TileObjects[_ValOptions]._DownNeighbours;


                            _ValidOptions = _ValidOptions.Concat(_Valid).ToList();
                        }

                        //单元格有效性检查
                        CheckValidity(_Options, _ValidOptions);
                    }

                    //左侧 单元格检测
                    if (x>0)
                    {
                        Cell_ZH _Left = _GridCompoents[x -1+y  * _Dimensions].GetComponent<Cell_ZH>();

                        List<Tile_ZH> _ValidOptions = new List<Tile_ZH>();

                        foreach (Tile_ZH _PossibleOptions in _Left._Tileoptions)
                        {
                            var _ValOptions = Array.FindIndex(_TileObjects, _Obj => _Obj == _PossibleOptions);

                            var _Valid = _TileObjects[_ValOptions]._RigihtNeighbours;


                            _ValidOptions = _ValidOptions.Concat(_Valid).ToList();
                        }

                        //单元格有效性检查
                        CheckValidity(_Options,_ValidOptions);
                    }

                    //瓦片地图编号
                    //数组位置等于该瓦片位置
                    Tile_ZH[] _NewTileList = new Tile_ZH[_Options.Count];

                    for (int i = 0; i < _Options.Count; i++)
                    {
                        _NewTileList[i] = _Options[i];
                    }

                    //瓦片地图创建
                    _NewGeneraTionCell[_Index].RecreateCell(_NewTileList);
                }
            }
        }

        //瓦片地图 通用组件判定
        _GridCompoents = _NewGeneraTionCell;
        //迭代次数 增加
        _Iterations++;

        //如果迭代次数 小于设置的瓦片地图大小
        if (_Iterations<_Dimensions*_Dimensions)
        {
            //就再次进行熵 检查
            StartCoroutine(CheckEntropy());
        }
    }

    /// <summary>
    /// 有效性 检查
    /// </summary>
    /// <param 功能单元格列表="_OptionList"></param>
    /// <param 有效性单元格列表="_ValidOptions"></param>
    private void CheckValidity(List<Tile_ZH> _OptionList, List<Tile_ZH> _ValidOptions)
    {
        // 有效性检查 布尔
        bool _HasValidOptions = false;

        // 单元格列表比对
        for (int x = _OptionList.Count - 1; x >= 0; x--)
        {
            var _Element = _OptionList[x];

            // 检查有效性单元格列表是否包含当前单元格数据
            if (!_ValidOptions.Contains(_Element))
            {
                // 如果不包含就进行移除处理
                _OptionList.RemoveAt(x);
            }
            else
            {
                _HasValidOptions = true;
            }
        }

        // 如果没有找到任何有效选项,采取措施
        if (!_HasValidOptions)
        {
            // 保留一个默认的选项(这里可以根据具体情况设定)
            if (_OptionList.Count == 0 && _ValidOptions.Count > 0)
            {
                // 添加一个有效性选项中的第一个作为默认选项
                _OptionList.Add(_ValidOptions[0]); 
            }
            else if (_OptionList.Count == 0)
            {
                // 如果确实没有任何有效选项,则添加一个兜底选项(可以是一个最常用或最不影响整体的瓦片)
                // 假设第一个瓦片是兜底选项
                _OptionList.Add(_TileObjects[0]); 
            }
            Debug.Log("没有有效选项,回退操作");
        }
    }

}

脚本搭载

在这里插入图片描述

实现 效果

在这里插入图片描述

波函数坍缩算法示例工程: 示例工程

可扩展效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

希望这些信息能够进一步满足您对Untiy 波函数坍缩算法 随机地图生成的需求。
如果您有任何特定的问题或需要更深入的讨论,请随时提出。

路漫漫其修远兮,与君共勉。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2056746.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用亮数据爬虫工具解锁复杂爬虫场景

在当今数据驱动型时代&#xff0c;数据采集和分析能力算是个人和企业的核心竞争力。然而&#xff0c;手动采集数据耗时费力且效率低下&#xff0c;而且容易被网站封禁。 我之前使用过一个爬虫工具&#xff0c;亮数据&#xff08;Bright Data&#xff09; &#xff0c;是一款低…

PCIe学习笔记(25)

数据完整性 PCI Express的基本数据可靠性机制包含在数据链路层(data Link Layer)中&#xff0c;它使用32位的LCRC (CRC)码逐链路检测TLP中的错误&#xff0c;并采用逐链路重传机制进行错误恢复。TLP是一个数据和事务控制单元&#xff0c;由位于PCI Express域“边缘”的数据源(…

重大发现!看Apache与nginx工作模型,享web服务幸福人生

文章目录 文章相关连接如下&#xff1a; Web 服务基础介绍ApacheApache prefork 模型 Apache worker 模型Apache event模型 Nginx-高性能的 Web 服务端nginx源码安装平滑升级和回滚平滑升级步骤&#xff1a;回滚步骤 nginx启动文件 文章相关连接如下&#xff1a; 如果想更多了…

【GH】【EXCEL】P4: Chart

文章目录 data and chartdonut chart (radial chart)Radial Chart bar chartBar Chart line chartLine Chart Scatter ChartScatter Chart Surface ChartSurface Chart Chart DecoratorsChart Decorators Chart GraphicsChart Graphics data and chart donut chart (radial cha…

《面板变系数模型及 Stata 具体操作步骤》

目录 一、文献综述 二、理论原理 三、实证模型 四、稳健性检验 五、程序代码及解释 六、代码运行结果 一、文献综述 在经济和社会科学研究领域&#xff0c;面板数据模型因其能够同时考虑个体和时间维度的信息而被广泛应用。传统的面板数据模型通常假设系数是固定的&#…

1.初识redis

文章目录 1.认识redis1.1 mysql和redis 对比1.2分布式系统1.2.1单机架构与分布式架构1.2.2数据库分离(应用服务器和存储服务器分离)与负载均衡1.2.3负载均衡器1.2.4 数据库读写分离1.2.5 数据库服务器引入缓存1.2.6数据库分库分表1.2.7 引入微服务 2.常见概念解释2.1 应用(Appl…

GoModule

GOPATH 最早的就是GOPATH构建模式&#xff0c; go get下载的包都在path中的src目录下 src目录是源代码存放目录。 package mainimport ("net/http""github.com/gorilla/mux" )func main() {r : mux.NewRouter()r.HandleFunc("/hello", func(w h…

iptables流量走向图

关联教学 https://www.bilibili.com/video/BV1dw411J7Qk/?spm_id_from333.337.search-card.all.click

7.2 算法设计与分析

分治法&#xff08;考的概率较低&#xff09; 回溯法&#xff08;考的概率较低&#xff09; 动态规划法&#xff08;考的概率较高&#xff09; 1

第四届机电一体化、自动化与智能控制国际学术会议(MAIC 2024)

目录 大会官网 会议简介 组织机构 大会主席 程序委员会主席 主讲嘉宾 征稿主题 参会说明 大会官网 http://www.icmaic.org 会议简介 第四届机电一体化、自动化与智能控制国际学术会议&#xff08;MAIC 2024&#xff09;将于2024年9月27-29日在中国成都召开。MAIC 20…

高性能MySQL04_操作系统和硬件优化

1. 从软件本身和它运行的典型工作负载来看&#xff0c;MySQL通常也更适合运行在廉价硬件上 2. 基本资源 2.1. CPU 2.2. 内存 2.3. 磁盘 2.4. 瓶颈 2.5. 网络资源 3. CPU 3.1. 最常见的瓶颈是CPU耗尽 3.2. 检查CPU使用率来确定工作负载是否受CPU限制 3.3. 低延迟&…

机器人学——正向运动学(机械臂)

Manipulator Forward Kinematics 机械臂基础概念 Joint and Link 连杆长度、连杆夹角 连杆偏距与关节角 移动关节看距离、旋转关节看角度 如何在杆上建立坐标系 地杆&#xff08;link0&#xff09;坐标系的建立 末端杆件坐标系的建立 DH表达法 如何计算出两杆之间的变换矩阵…

Qt鼠标键盘事件监听

普通的程序中. 鼠标事件监听 要监听鼠标事件&#xff0c;你可以使用QMouseEvent类&#xff0c;它提供了多种类型的鼠标事件&#xff0c;如QMouseEvent::MouseButtonPress、QMouseEvent::MouseButtonRelease、QMouseEvent::MouseMove等。 但是离开程序后就很难监听到&#xff0c…

机器学习第十一章--特征选择与稀疏学习

一、子集搜索与评价 我们将属性称为 “特征”(feature&#xff09;&#xff0c;对当前学习任务有用的属性称为 “相关特征”(relevant feature&#xff09;、没什么用的属性称为 “无关特征”(irrelevant feature)&#xff0e;从给定的特征集合中选择出相关特征子集的过程&…

单位订餐小程序开发:便捷高效,重塑职场餐饮新体验

随着移动互联网技术的飞速发展&#xff0c;各行各业都在积极探索数字化转型之路&#xff0c;以提升工作效率与用户体验。在单位日常运营中&#xff0c;餐饮管理作为保障员工基本生活需求的重要环节&#xff0c;其便捷性、高效性直接关系到员工的工作满意度与整体氛围。因此&…

鸿蒙内核源码分析(Fork篇) | 一次调用,两次返回

笔者第一次看到fork时&#xff0c;说是一次调用&#xff0c;两次返回&#xff0c;当时就懵圈了&#xff0c;多新鲜&#xff0c;真的很难理解.因为这足以颠覆了以往对函数的认知&#xff0c; 函数调用还能这么玩&#xff0c;父进程调用一次&#xff0c;父子进程各返回一次.而且只…

linux memory cgroup的memory.move_charge_at_immigrate含义

1.内核文档 上面的例子说明&#xff1a; 最开始某个进程是在cgroup A中&#xff0c;后面要迁移到cgroup B中&#xff0c;那么进程的内存计数是否要完全迁入B中&#xff0c;就是通过memory.move_charge_at_immigrate控制&#xff0c;如果目标cgroup也就是B设置了1到该字段中&am…

猫头虎 分享:什么是Thrift?Thrift的简介、安装、用法详解入门教程

猫头虎 分享&#xff1a;什么是Thrift&#xff1f;Thrift的简介、安装、用法详解入门教程 今天猫头虎带大家一起探讨 一个在人工智能和分布式系统开发中十分重要的工具——Thrift。无论你是AI开发者还是大数据工程师&#xff0c;了解和掌握Thrift都将极大地提高你的跨语言服务…

高性能web服务器

目录 一、简介 &#xff08;一&#xff09;nginx-高性能的web服务端 &#xff08;二&#xff09;用户访问体验 二、I/O模型 &#xff08;一&#xff09;概念 &#xff08;二&#xff09;网络I/O模型 &#xff08;三&#xff09;阻塞型 I/O 模型 &#xff08;四&#xf…

AI系列-黑神话:悟空

今天的朋友圈被黑神话悟空刷圈了&#xff0c;喝的咖啡都是黑神话联名版本。四年磨一剑的本地游戏&#xff0c;身边也不少小伙伴用金钱支持了&#xff0c;属于现象级的游戏产品。游戏引擎后续是否可以结合AI文生图&#xff0c;小说编写、文生视频。加快大作的快速生成 &#xff…