-2

昨天我在我的 C# 代码中检测到一个奇怪的行为。我的设置是(不完全是,但可以比较)以下:

用户看到一个复选框网格,我将中间的复选框分配为坐标 0,0。

我写了一个结构来更容易地比较两个坐标:

public struct Coord
{
  public int x, y;

  public static bool operator == (Coord coord1, Coord coord2)
  {
    return coord1.x == coord2.x && coord1.y == coord2.y;
  }

  public static bool operator != (Coord coord1, Coord coord2)
  {
    return coord1.x != coord2.x || coord1.y != coord2.y;
  }

  public override int GetHashCode()
  {
    return this.x.GetHashCode() ^ this.y.GetHashCode();
  }

  public override bool  Equals(object obj)
  {
    if (!(obj is Coord))
      return false;

    Coord coord = (Coord)obj;

    if (coord.x == this.x && coord.y == this.y)
      return true;
    return false;
  }
}

对于一个复选框,我使用一个名为 Position 的类,它继承自标准 WinForms 复选框:

public class Position : CheckBox
{
  public Coord coord;
  public List<Position> nearPositions = new List<Position>();

  public Position(int x, int y)
  {
    this.coord.x = x;
    this.coord.y = y;
  }

  protected override void OnClick(EventArgs e)
  {
    if (this.Checked)
      return;

    base.OnClick(e);

    this.checkConnections();
  }

  private void checkConnections()
  {
    foreach (Position position in this.nearPositions)
    {
      Route route = new Route(this, position);
    }
  }
}

如您所见,用户只能单击每个复选框一次。
List nearPositions 仅包含此选项附近的单击复选框
现在在 checkConnections() 方法中,我尝试找出所有(或仅部分)单击的复选框是否可以连接到一个圆圈。因此,我为每个可能的路径创建了我的类 Route 的新对象。

public class Route
{
  private Position startPosition;
  private List<Position> nodes = new List<Position>();

  public Route(Position startPosition, Position nextPosition)
  {
    this.startPosition = startPosition;
    this.nodes.Add(nextPosition);
    this.findConnection();
  }

  public Route(Route route, Position nextPosition)
  {
    this.startPosition = route.startPosition;
    this.nodes = route.nodes;
    this.Add(nextPosition);
    this.findConnection();
  }

  private void findConnection()
  {
    if (this.nodes.Count > 2 && this.nodes[this.nodes.Count - 1].nearPositions.Contains(this.startPosition))
    {
      //HERE THE ROUTE IS A CIRCLE
      return;
    }
    List<Position> nextPositions = this.nodes[this.nodes.Count - 1].nearPositions.FindAll(p => !p.Equals(this.startPosition) && !this.nodes.Contains(p));
    foreach (Position position in nextPositions)
    {
      if (this.nodes[this.nodes.Count - 1].nearPositions.FindAll(p => !p.Equals(this.startPosition) && !this.nodes.Contains(p)).Contains(position)) //TODO strange problem here...bad workaround need to fix
      {
        Route route = new Route(this, position);
      }
    }
  }
}

请记住,我为每种可能性创建了一个 Route 对象。因此,如果圆圈包含许多复选框,则同时存在许多 Route 对象。也许重现我的问题很重要。
Route 始终具有相同的 startPosition。它是用户单击的位置。
在列表节点中,我保存了构建 cricle 的步骤。

现在我得到的是在 findConnection() 方法内部 List nextPosition 有时包含的 Positions 甚至不存在于 this.nodes[this.nodes.Count - 1].nearPositions 列表中。这就是我在 foreach 循环中添加额外条件的原因。

我的想法是它可能是 .FindAll() 方法的错误或同时存在多个 eoutes 的问题。

所以我的问题:
1.你能重现我的问题吗?
2. 它来自哪里?
3. 我该如何解决?

感谢您的回复!

4

2 回答 2

1

您应该尝试查明问题并发布更短的代码,以显示对您不起作用的东西。通读所有细节并弄清楚算法有点费时,而且大多数细节都不相关。

也就是说,我看到的一件可疑的事情是你定义Coord结构的方式。你给了它一个相等的运算符覆盖,它正确地比较了成员,但是在你的Equals覆盖中你不比较成员。

如果您的问题是FindAll工作不正常,并且您使用调试器验证了列表的内容是正确的,那么这个Equal覆盖可能是问题的原因。

您还应该更改GetHashCode覆盖以组合成员的值。

于 2012-11-14T21:46:25.583 回答
0

我找到了解决方案。
问题出在

public Route(Route route, Position nextPosition)
{
  this.startPosition = route.startPosition;
  this.nodes = route.nodes;
  this.Add(nextPosition);
  this.findConnection();
}

新路由只获得对前一个路由节点的引用,但它应该有自己的节点列表。
所以我把它改成了

public Route(Route route, Position nextPosition)
{
  this.startPosition = route.startPosition;
  this.nodes.AddRange(route.nodes);
  this.Add(nextPosition);
  this.findConnection();
}

我应该早点看到的。对不起!
但无论如何感谢您的帮助!

于 2012-11-15T09:44:28.247 回答