【问题标题】:To find objects of the same value using Queue.contains() in C#, Unity要在 C# 中使用 Queue.contains() 查找具有相同值的对象,Unity
【发布时间】:2019-03-11 04:19:47
【问题描述】:

我尝试找到具有相同值的坐标值。 我将链接三个坐标值。

我这样做是为了在 Unity 中制作网格。

我首先通过bfs方法找到了相同的坐标。

并且尝试连接三个相邻坐标时出现问题。

为了找出八个方向上是否有相邻点,我做了以下操作。

private int[,] fx = new int[8, 2] { { -1, 0 }, { -1, 0 }, { 1, 0 }, { 1, 1 }, 
                                    { -1, 0 }, { -1, 0 }, { 0, 1 }, { 0, 1 } };

private int[,] fy = new int[8, 2] { { -1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, 
                                    { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, 1 } };

void CreateTriangle()
{
    int index = 0;
    while (SegNode.Count > 0)
    {
        Node curNode = SegNode.Peek();
        for (int i = 0; i < 8; i++)
        {


            Node nextNode = new Node(curNode.x + fx[i, 0], curNode.y + fy[i, 0], curNode.color);
            Node nextNode2 = new Node(curNode.x + fx[i, 1], curNode.y + fy[i, 1], curNode.color);

            Debug.Log("CurNode " + curNode.x + " , " + curNode.y + 
                " NextNode " + nextNode.x + " , " + nextNode.y + 
                " NextNode2 " + nextNode2.x + " , " + nextNode2.y);


            if (SegNode.Contains(nextNode) && SegNode.Contains(nextNode2))
            {
                newTriangles.Add(SegNode.ToArray().ToList().IndexOf(curNode) + index);
                newTriangles.Add(SegNode.ToArray().ToList().IndexOf(nextNode) + index);
                newTriangles.Add(SegNode.ToArray().ToList().IndexOf(nextNode2) + index);
            }
        }
        index++;
        SegNode.Dequeue();
    }
}

关于 (0,1) (1,0) 显然有一点,但我使用 Queue.Contains() 找不到它

也许 Contains() 无法识别它,因为我使用 [new] 创建了一个新对象。 如何找到对象?

这是我的完整代码

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

public class MeshCreator : MonoBehaviour
{

// This first list contains every vertex of the mesh that we are going to render
public List<Vector3> newVertices = new List<Vector3>();

// The triangles tell Unity how to build each section of the mesh joining
// the vertices
public List<int> newTriangles = new List<int>();

// The UV list is unimportant right now but it tells Unity how the texture is
// aligned on each polygon
public List<Vector2> newUV = new List<Vector2>();


// A mesh is made up of the vertices, triangles and UVs we are going to define,
// after we make them up we'll save them as this mesh


private Mesh mesh;
// Start is called before the first frame update

private int[,] pixel = new int[15, 15] {
                                        { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                                        { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                                        { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                                        { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                                        { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                                        { 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                                        { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                                        { 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
                                        { 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
                                        { 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 2, 0, 0, 0 },
                                        { 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 2, 2, 0, 0, 0 },
                                        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0 },
                                        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0 },
                                        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 },
                                        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
                                       };


private bool[,] visit = new bool[15, 15];

private int[] dx = new int[4] { 0, 1, -1, 0 };
private int[] dy = new int[4] { 1, 0, 0, -1 };

public int idx = 0;

public class Node
{
    public int x, y, color;

    public Node(int x, int y, int color)
    {
        this.x = x;
        this.y = y;
        this.color = color;
    }
}


public Queue<Node> SegNode = new Queue<Node>();

void bfs(int r, int c, int color)
{
    Queue<Node> q = new Queue<Node>();
    q.Enqueue(new Node(r, c, color));

    while (q.Count > 0)
    {
        Node curNode = q.Dequeue();
        SegNode.Enqueue(curNode);
        for (int i = 0; i < 4; i++)
        {
            int tr = curNode.x + dx[i];
            int tc = curNode.y + dy[i];

            if (tr >= 0 && tr < 15 && tc >= 0 && tc < 15)
            {
                if (!visit[tr, tc] && pixel[tr, tc] == color)
                {
                    visit[tr, tc] = true;
                    q.Enqueue(new Node(tr, tc, color));

                    newVertices.Add(new Vector3(tr, tc, 0));
                }
            }
        }
    }
}

private int[,] fx = new int[8, 2] { { -1, 0 }, { -1, 0 }, { 1, 0 }, { 1, 1 }, 
                                    { -1, 0 }, { -1, 0 }, { 0, 1 }, { 0, 1 } };
private int[,] fy = new int[8, 2] { { -1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, 
                                    { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, 1 } };


void CreateTriangle()
{
    int index = 0;
    while (SegNode.Count > 0)
    {
        Node curNode = SegNode.Peek();
        for (int i = 0; i < 8; i++)
        {


            Node nextNode = new Node(curNode.x + fx[i, 0], curNode.y + fy[i, 0], curNode.color);
            Node nextNode2 = new Node(curNode.x + fx[i, 1], curNode.y + fy[i, 1], curNode.color);

            Debug.Log("CurNode " + curNode.x + " , " + curNode.y + 
                " NextNode " + nextNode.x + " , " + nextNode.y + 
                " NextNode2 " + nextNode2.x + " , " + nextNode2.y);


            if (SegNode.Contains(nextNode) && SegNode.Contains(nextNode2))
            {
                newTriangles.Add(SegNode.ToArray().ToList().IndexOf(curNode) + index);
                newTriangles.Add(SegNode.ToArray().ToList().IndexOf(nextNode) + index);
                newTriangles.Add(SegNode.ToArray().ToList().IndexOf(nextNode2) + index);
            }
        }
        index++;
        SegNode.Dequeue();
    }
}



void Start()
{

    //int result = 0;
    for (int r = 0; r < 15; r++)
    {
        for (int c = 0; c < 15; c++)
        {
            if (!visit[r, c] && pixel[r, c] != 0)
            {
                newVertices.Add(new Vector3(r, c, 0));
                bfs(r, c, pixel[r, c]);
                //result++;
            }
        }
    }

    CreateTriangle();

    mesh = GetComponent<MeshFilter>().mesh;
}
}

【问题讨论】:

    标签: c# unity3d queue


    【解决方案1】:

    类是引用类型。这意味着您的 SegNode 队列实际上并不包含值,而是对 Node 实例的引用

    正如您已经说过的,您的 Contains 检查不起作用,因为您正在检查队列中是否存在对完全相同的 Node 实例的相同引用。


    您可以简单地将Node 设为值类型,而不是将其从class 更改为struct

    public struct Node
    {
        public int x, y, color;
    
        public Node(int x, int y, int color)
        {
            this.x = x;
            this.y = y;
            this.color = color;
        }
    }
    

    比你的支票

    Node nextNode = new Node(curNode.x + fx[i, 0], curNode.y + fy[i, 0], curNode.color);
    Node nextNode2 = new Node(curNode.x + fx[i, 1], curNode.y + fy[i, 1], curNode.color);
    
    Debug.Log("CurNode " + curNode.x + " , " + curNode.y + 
              " NextNode " + nextNode.x + " , " + nextNode.y + 
              " NextNode2 " + nextNode2.x + " , " + nextNode2.y);
    
    if (SegNode.Contains(nextNode) && SegNode.Contains(nextNode2))
    {
        //...
    }
    

    应该可以。


    或者,您可以使用例如Linq FirstOrDefault点赞

    var nextNode = SegNode.FirstOrDefault(n => n.x == curNode.x + fx[i, 0] 
                                            && n.y == curNode.y + fy[i, 0]);
    
    var nextNode2 = SegNode.FirstOrDefault(n => n.x == curNode.x + fx[i, 1] 
                                            && n.y == curNode.y + fy[i, 1]);
    
    if(nextNode != null && nextNode2 != null)
    {
        // ...
    }
    
    • FirstOrDefault 返回谓词定义的第一个匹配项,例如

      n.x == curNode.x + fx[i, 0] && n.y == curNode.y + fy[i, 0]
      

      如果没有找到匹配项或列表/队列为空,则为null


    作为更广泛的替代方案,您也可以让您的 Node 实现 IEquatable 但这对于您的用例来说可能有点矫枉过正;)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-25
      • 1970-01-01
      • 2014-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多