用unity做个n皇后可视化

2022/3/9 23:45:59

本文主要是介绍用unity做个n皇后可视化,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

今天算法课学了个采用递归思想的n皇后算法,闲来无事,用unity简单做个可视化,顺便巩固一下自己先前学习的程序纹理。记录一下自己踩过的坑

(纯粹是为了把学过的知识进行一个综合练习,实用价值不大。。生成这么多程序纹理巨耗性能)

 

首先是核心的算法部分,在书本的基础上简单做了些修改

Queen.cs

using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Queen
{
    static int[] q = new int[10];//当前在运算的数组列表
    static List<int[]> QueenList = new List<int[]>();//存储结果的列表

    //其他unity脚本获取该结果列表的唯一接口
    public static List<int[]> GetQueenList(int n)
    {
        QueenSolution(1, n);
        return QueenList;
    }

    //给结果列表赋值 每次一趟递归运算完得到新的皇后排位会调用一次
    static void Disposulation(int n)
    {
        int[] array = new int[n+1];
        for (int i = 1; i <= n; i++)
        {
            array[i] = q[i];
        }
        QueenList.Add(array);
    }


    private static bool Place(int i, int j)
    {
        if (i == 1) return true;
        int k = 1;
        while (k < i)
        {
            //n皇后的一个核心判断条件 可以自己脑补一下
            if ((q[k] == j) || (System.Math.Abs(q[k] - j) == System.Math.Abs(i - k)))
                return false;
            k++;
        }

        return true;
    }

    //递归部分 递归挺烧脑的
    private static void QueenSolution(int i, int n)
    {
        if (i > n)
        {
            Disposulation(n);
        }
        else
        {
            for (int j = 1; j <= n; j++)
            {
                if (Place(i, j))
                {
                    q[i] = j;
                    QueenSolution(i + 1, n);
                }
            }
        }
    }
}

这里自己有踩到一个坑,在定义List的时候忘记了,List是用来存放引用类型的数据了,直接就把q数组拿来存进去了,导致后面结果输出都一样,调试调了好久。。

 

程序纹理也是通过脚本代码来实现的

ProceduralTextureGeneration.cs

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ProceduralTextureGeneration : MonoBehaviour
{

	//public Material material = null;

	#region Material properties

	[SerializeField]
	private int m_Matrix = 5;//n皇后 n=几

	[SerializeField]
	private int m_textureWidth = 512;


	[SerializeField]
	private Color m_backgroundColor = Color.white;


	[SerializeField]
	private Color m_circleColor = Color.black;

	[SerializeField]
	private Color m_queenColor = Color.yellow;


	[SerializeField]
	private float m_blurFactor = 2.0f;

	//使用list存对象后出现了不销毁的问题 ?
	//List<GameObject> objList = new List<GameObject>();
	//预制体
	public GameObject preObj;
	//预制shader
	public Shader shader;
	//Queen算法得到的结果
	List<int[]> queenList = new List<int[]>();
	//记录obj移动的大小 取值是Queen数量能存放的最小矩阵的一个大小
	int width;
	#endregion

	private Texture2D m_generatedTexture = null;

	// Use this for initialization
	void Start()
	{
		queenList = Queen.GetQueenList(m_Matrix);

		int count = queenList.Count;
		width = (int)Mathf.Ceil(Mathf.Sqrt(count));//计算这个存放矩阵的大小
		int w = 0, h = 0;

		for (int i = 0; i < count; i++)
        {
			h = i / width; //计算纵向平移大小
			w = i % width;//计算水平平移大小

            GameObject obj = Instantiate(preObj, transform);

			//移动物体
			obj.transform.Translate(new Vector3(w, -h, 0));

			//生成赋给meshRenderer组件中的material的新材质
			Renderer renderer = obj.GetComponent<Renderer>();
            Material mat = new Material(shader);
            mat.hideFlags = HideFlags.DontSave;

            m_generatedTexture = _GenerateProceduralTexture(queenList[i]);

			//生成程序纹理
            _UpdateMaterial(mat);
            renderer.material = mat;
        }
	}



	private void _UpdateMaterial(Material material)
	{
		//设置纹理至 _MainTex
		if (material != null)
		{
			material.SetTexture("_MainTex", m_generatedTexture);
		}
	}

	private Color _MixColor(Color color0, Color color1, float mixFactor)
	{
		Color mixColor = Color.white;
		mixColor.r = Mathf.Lerp(color0.r, color1.r, mixFactor);
		mixColor.g = Mathf.Lerp(color0.g, color1.g, mixFactor);
		mixColor.b = Mathf.Lerp(color0.b, color1.b, mixFactor);
		mixColor.a = Mathf.Lerp(color0.a, color1.a, mixFactor);
		return mixColor;
	}

	//生成程序纹理
	private Texture2D _GenerateProceduralTexture(int[] q)
	{
		Texture2D proceduralTexture = new Texture2D(m_textureWidth, m_textureWidth);

		// The interval between circles
		float circleInterval = m_textureWidth / (m_Matrix+1);
		// The radius of circles
		float radius = circleInterval / 3f;
		// The blur factor
		float edgeBlur = 1.0f / m_blurFactor;

		for (int w = 0; w < m_textureWidth; w++)
		{
			for (int h = 0; h < m_textureWidth; h++)
			{
				// Initalize the pixel with background color
				Color pixel = m_backgroundColor;

				// Draw circles one by one
				for (int i = 0; i < m_Matrix; i++)
				{
					for (int j = 0; j < m_Matrix; j++)
					{
						// Compute the center of current circle
						Vector2 circleCenter = new Vector2(circleInterval * (i + 1), circleInterval * (j + 1));

						// Compute the distance between the pixel and the center
						float dist = Vector2.Distance(new Vector2(w, h), circleCenter) - radius;

						Color color = m_circleColor;
						if (q[i + 1] == j + 1) color = m_queenColor;
						// Blur the edge of the circle
						color = _MixColor(color, new Color(pixel.r, pixel.g, pixel.b, 0.0f), Mathf.SmoothStep(0f, 1.0f, dist * edgeBlur));

						// Mix the current color with the previous color
						pixel = _MixColor(pixel, color, color.a);
					}
				}

				proceduralTexture.SetPixel(w, h, pixel);
			}
		}

		proceduralTexture.Apply();

		return proceduralTexture;
	}
}

 

在start中直接调取了Queen中的算法结果,直接依次生成预制体,然后对其材质进行新建和赋值纹理

最后效果如下:

 



这篇关于用unity做个n皇后可视化的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程