2013-02-11 4 views
4

저는 체스 엔진에서 일하고 있습니다. 그리고 나는 현재 전치 테이블 (과거 이동으로부터 이미 평가 된 보드 위치 집합)을 구현 중입니다. 일반적인 생각은 이동이 이루어질 때 전치 테이블에서 일치하는 위치를 확인한다는 것입니다. 존재하는 경우, 나는 값 비싼 평가 프로세스를 건너 뛰고 이전에 계산 된 결과를 전이 테이블에서 가져옵니다. 존재하지 않는 경우 필요한 계산을 수행 한 다음 나중에 참조 할 수 있도록 전치 테이블에 추가합니다.참조 유형 사전 키의 속성을 참조하려면 어떻게합니까?

나에게 이것은 해시 세트 또는 사전에 대한 작업처럼 들립니다. 나는 사전을 결정했다. 키가 내 보드를 나타내는 클래스이고 값이 위치에 얼마나 많은 횟수가 발생했는지에 대한 int 카운트가되기를 원했습니다. 카운트 이유는 3 배의 반복 추첨을 감지 할 수 있기 때문입니다. 동일한 위치에 세 번 이상 접하게되면 플레이어는 추첨을 선택할 수 있습니다. 해시 셋 대신 사전을 사용하면 3 단계 반복 그리기를 내 전치 테이블과 결합하여 검색을 크게 단순화 할 수 있습니다.

이렇게하기 위해 보드의 상태 재정의를 Equals() 및 GetHashCode()로 나타내는 클래스를 만들었습니다. 그것은 정상적으로 작동하며, 이제 게임이 이전에 마주 쳤던 모든 역사적 상태를 추적 할 수 있습니다.

제 문제는 사전에 키 객체의 속성에 액세스 할 수 있어야한다는 것입니다. .ContainsKey (...) 메서드와 My Equals()/GetHashCode() 논리를 사용하여) 일치 여부를 확인할 수 있지만 이전에 언급 한 계산 된 값을 가져와야합니다 (내 보드의 공용 속성으로 저장 됨) 상태 개체)를 키에서 삭제합니다.

내가 가지고 올 수 있었다 :

BoardState board = TranspositionTable.Keys.FirstOrDefault(tt => tt.GetHashCode() == this.GetHashCode()); 

이 작동하지만, 나에게 어설픈 느낌. 전치 테이블의 전체적인 포인트는 수백만 개의 연속적인 보드 상태를 재귀 적으로 검색하는 것입니다. 각 일치에 대해 사전을 쿼리하면 반 직관적으로 들립니다. 이 작업을 수행하는 더 좋은 방법이 있습니까?

편집 : 그것은 지적 된 것으로

, 내 해시 인해 유효 보드 상태의 거대한 수를 완벽하게 할 수 없습니다. My Equals() 오버라이드는 충돌의 가능성을 줄이기 위해 대안으로 생성 된 두 번째 해시를 검사합니다. 위의 '솔루션'에는 결함이 있습니다. 불완전한 해시에 의존하기 때문입니다. 나는 사용해야했다 :

BoardState board = TranspositionTable.Keys.FirstOrDefault(tt => tt.Equals(this)); 

내 부분에 어리석은 감시. 아직도, 나는 팬을 질의하는 사전이 아니다.

Dictionary<BoardState, Tuple<BoardState, int>> 

을 다음 객체를 추가 할 때마다 :

+0

사전에 정확히 어떤 키가 있습니까? 'GetHashCode()'의 결과를 열쇠로 만들 수 있습니까? 만약 그렇다면, 이것은 더 자연스럽고 자연스럽게 처리됩니다. – Yahia

+0

@Yahia 해시 코드는 매우 자연스럽지 않으므로 고유 한 것이 아니므로 객체 목록을 값으로 지원하고 '같음'을 사용해야합니다 해당 해시 코드로 * 참 * 같은 객체를 찾으십시오. – Servy

+0

@Servy 사실입니다 ...하지만 OP는 (표시된 코드에 따라) 해시 코드와 일치하는 모든 결과가 만족스러워 보입니다. – Yahia

답변

2

하나의 옵션은, 사전의 값의 키에 대한 참조뿐만 아니라 사전의 실제 값을 유지과 같이하는 것입니다 키에 같은 값에 동일한 개체를 추가 :

Dictionary<BoardState, Tuple<BoardState, int>> boards = 
    new Dictionary<BoardState,Tuple<BoardState,int>>(); 
BoardState board = new BoardState(); 
boards.Add(board, Tuple.Create(board, 1)); 

다른 옵션을 (아마도 더 나은 디자인 인)의 두 가지 종류로 보드 상태 개체를 파괴하는 것입니다. 실제로 보드의 상태를 나타내는 것 (이것은 변경 불가능해야 함)과, 발생한 시간을 포함하여 해당 주에 대한 다른 정보를 보유하는 다른 하나와 변경 가능한 속성을 특정 응용 프로그램에 적용 할 수 있습니다. 이렇게하면 사전 키에 액세스하지 않아도됩니다.

+0

나는 상태를 분리하는 아이디어를 좋아합니다 ... 쉬운 해결책은 아니지만 그것은 올바른 방향으로 생각합니다. – Chronicide

+0

첫 번째 솔루션은 내 질문에 답할뿐만 아니라 키 속성에 직접 액세스 할 수있는 쉬운 방법이 없다는 것을 의미하기 때문에 대답을 선택했음을 유의해야합니다. 라운드 방식). 그냥 제쳐두고, 내 특정 상황에 대한 또 다른 해결책은 중첩 테이블에 대한 해시 집합을 실행하고 세 배 반복 규칙에 대해 별도의 사전을 실행하는 것입니다. 이것은 각자가 한 가지만을 책임지는 명확성의 부가적인 이점을 가지고 있습니다. – Chronicide

관련 문제