2012-11-14 2 views
-2

어제 이상한 행동이 C# 코드에서 감지되었습니다. 내 설치는 다음 (정확히하지만 compareable로)입니다 :C# 서클 길 찾기

사용자는 내가 중간에 좌표 0,0 확인란을 할당 확인란의 그리드를 본다. 당신으로

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

: 나는의 standart 윈폼 체크 박스에서 상속하는 클래스라는 위치를 사용하는 체크 박스를 들어

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

:

나는 두 좌표 사이에 쉽게 비교를 위해 구조체를 썼다 사용자가 각 체크 박스를 한 번만 클릭 할 수 있음을 알 수 있습니다.
목록 nearPositions에는이 근처의 클릭 한 확인란 만 포함됩니다.
checkConnections() 메소드에서 나는 모든 (또는 일부만) 클릭 된 체크 박스가 서클에 연결될 수 있는지 알아 내려고합니다. 따라서 각 클래스 경로에 대한 클래스 경로의 새 개체를 만듭니다.

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

내가 모든 possibity 국도의 객체를 만드는 것을 기억하십시오. 따라서 원에 많은 체크 박스가 포함되어있는 경우 많은 수의 Route 객체가 동시에 존재합니다. 어쩌면 내 문제를 재현하는 것이 중요합니다.
경로의 시작 위치는 항상 동일합니다. 사용자가 클릭 한 위치.
목록 노드에서 나는 cricle을 만드는 단계를 저장합니다.

이제 getConnection() 메서드 내부에 List nextPosition에 this.nodes [this.nodes.Count - 1] .nearPositions 목록 내부에 exsists가없는 위치가 포함될 수 있습니다. 그래서 foreach 루프 안에 추가 조건을 추가했습니다.

내 생각은 어쩌면 .FindAll() 메서드의 버그 일 수도 있고, 동시에 mutiple eoutes의 끝내기 문제 일 수도 있습니다.

내 질문 :
1. 내 문제를 재현 할 수 있습니까?
2. 그것은 어디에서 왔습니까?
3. 어떻게 해결할 수 있습니까?

답장을 보내 주셔서 감사합니다.

+0

http://www.dotnetperls.com/debugging –

+0

findConnection 및 checkConnections 메소드에서 작성한 Route로는 아무 작업도 수행하지 않습니다. 목록이나 다른 데이터 구조에 추가해야합니까? 나는이 방법들의 부작용을 볼 수 없다. –

+0

@ NikolaD-Nick 점 // 경로가 원일 경우 경로를 처리하는 다른 함수를 호출하지만 전혀 문제가되지 않는다고 생각합니다. –

답변

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

로 변경 나는 이전 것을 알해야합니다. 죄송 해요!
어쨌든 도와 주셔서 감사합니다!

1

문제를 찾아내어 더 이상 작동하지 않는 코드를 게시해야합니다. 모든 세부 사항을 읽고 알고리즘을 파악하는 데 어느 정도 시간이 걸리고 대부분의 세부 사항은 관련이 없습니다.

그런데 내가 보았던 한 가지 의심스러운 점은 Coord 구조체를 정의하는 방식에 있다고 말했습니다. 멤버를 올바르게 비교하는 동등 연산자 대체를 지정했으나 Equals 무시에서는 멤버를 비교하지 않습니다.

FindAll이 제대로 작동하지 않고 디버거를 사용하여 목록의 내용이 올바른지 확인한 경우이 Equal 무시가 문제의 원인 일 수 있습니다.

또한 회원의 값 조합을 위해 GetHashCode 재정의를 변경해야합니다.

+0

빠른 답장을 보내 주셔서 감사합니다! 이미 코드를 많이 단축했지만 오류의 정확한 위치를 지적 할 수 없기 때문에 어떤 코드가 중요한지 잘 모릅니다. 중요한 부분을 잘라내는 것보다 훨씬 낫습니다.) 재정의 된 .Equals() 및 .GetHashCode() 메서드의 구현을 완전히 제거하지만 아무것도 변경되지 않았습니다. 따라서이 솔루션이 아닙니다. –

+0

오버라이드를 제거하는 대신 올바르게 구현하십시오 ...'operator ==','Equal' 오버라이드와'GetHashCode'는 모두 일관된 로직을 가져야합니다. – Ran

+0

좋아, 내가 위의 코드를 편집 한 것처럼 두 가지 방법을 업데이트했다. 그 행동은 변하지 않았다. 디버거는 이러한 메서드가 호출되지 않는다는 것을 보여줍니다. 제 생각에는 문제는 구조체에 없습니다. –