要在C#,Unity中使用Queue.contains()查找具有相同值的对象 [英] To find objects of the same value using Queue.contains() in C#, Unity

查看:198
本文介绍了要在C#,Unity中使用Queue.contains()查找具有相同值的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I try to find coordinate values with the same values. And I'm going to link three coordinate values.

我这样做是为了在Unity上制作网格物体.

I am doing this to make mesh at Unity.

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

I first found the same coordinates by bfs method.

尝试连接三个相邻坐标时出现问题.

And there is a problem trying to connect the three adjacent coordinates.

我做了以下工作,以找出在八个方向上是否有相邻的点.

I did the following to find out if there are any adjacent points in eight directions.

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()找到它

there is clearly a point about (0,1) (1,0), but I can't find it using Queue.Contains()

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

Maybe Contains() don't recognize it because I used [new] to create a new object. How can I find an object?

这是我的完整代码

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;
}
}

推荐答案

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

classes are reference types. That means your SegNode queue doesn't actually contain values but references to instances of Node.

正如您已经说过的那样,您的Contains检查不能那样工作,因为您要检查队列中是否存在对Node相同实例的相同引用.

As you said already your Contains check doesn't work like that since you are checking if the same reference to the excatly same instance of Node exists in the queue.

您只需将Node设置为值类型,而不是将其从class更改为struct

You could simply make your Node a value type instead by changing it from a class to a 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 之类的

Alternatively you can use e.g. Linq FirstOrDefault like

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返回由谓词定义的第一个匹配,例如

    • FirstOrDefault returns the first match defined by the predicate e.g.

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

      null如果未找到匹配项或列表/队列为空

      or null if no matches are found or the list/queue is empty

      作为更广泛的替代方案,您还可以让Node实现 IEquatable ,但这可能对您的用例有些过分了;)

      as a broader alternative you could also let your Node implement IEquatable but that's maybe a bit overkill for your usecase ;)

      这篇关于要在C#,Unity中使用Queue.contains()查找具有相同值的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆