Чтобы найти объекты с одинаковым значением, используя Queue.contains () в C #, Unity - PullRequest
0 голосов
/ 11 марта 2019

Я пытаюсь найти значения координат с одинаковыми значениями. И я собираюсь связать три значения координат.

Я делаю это для создания сетки в Unity.

Сначала я нашел те же координаты методом bfs.

И при попытке соединения трех смежных координат возникла проблема.

enter image description here

Я сделал следующее, чтобы выяснить, есть ли смежные точки в восьми направлениях.

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

enter image description here enter image description here

Ясно, что есть точка около (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;
}
}

1 Ответ

1 голос
/ 11 марта 2019

классы ссылочные типы . Это означает, что ваша очередь 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 , но это может быть немного излишним для вашего сценария использования;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...