2013-06-28 2 views
2

벽이 정사각형 블록으로되어있는 게임을 만들고 있습니다. 벽은 다음과 같이 2 차원 격자에 배치됩니다 :최소 벽량 찾기

[X][X][X][X] 
[ ][X][ ][ ] 
[ ][X][ ][ ] 
[ ][X][ ][ ] 

지금, 나는 내 충돌 감지를 최적화하고있어, 그것은이 최소한으로 벽 수를 줄이는데 도움이된다. 위의 경우에는 블록이 결합 된 경우 7 개의 벽 블록이 있지만 두 개의 벽만 존재합니다. 이러한 결합 된 벽을 찾는 최적의 솔루션을 찾는 데 어려움을 겪고 있으며 검색이 시작되는 블록 (블록은 순서가 지정되지 않은 목록에 저장 됨)에 따라 다양한 결과를 얻습니다. 순서는 순서대로 이루어집니다. 편집자). 이 문제를 해결하는 방법에 대한 의견이 있으십니까? 꽤 기초적인 것이어야하지만, 금식이야, 제대로 작동하지 않아. :)

여기에 내 최적의 코드가 있습니다. 기본적으로 수평 및 수직 "연속성"에 대한 두 가지 검사를 수행 한 다음 어느 것이 더 나은지 확인합니다. 또한 "이미 처리 된"벽 블록을 저장하므로 두 번 인식되지 않지만 교차점에서 펑키하게됩니다.

public void CreateCollidersForExport() 
{ 
    List<Wall> handledWalls = new List<Wall>(); 

    foreach (Wall w in walls) 
    { 
     if (handledWalls.Contains(w)) continue; 
     handledWalls.Add(w); 

     // Search how many walls there is horizontally 
     Vector3 horizontalCenter = new Vector3(w.X, w.Y, w.Z); 
     List<Wall> tmpWallsHorizontal = new List<Wall>(); 
     tmpWallsHorizontal.Add(w); 
     foreach (Wall other in walls) 
     { 
      if (handledWalls.Contains(other) || tmpWallsHorizontal.Contains(other)) continue; 
      bool canAdd = false; 
      foreach (Wall _w in tmpWallsHorizontal) 
      { 
       if (other.X == _w.X + Wall.size && other.Y == _w.Y && other.Z == _w.Z) 
       { 
        canAdd = true; 
        horizontalCenter.X += Wall.size/2; 
        break; 
       } 
       else if (other.X == _w.X - Wall.size && other.Y == _w.Y && other.Z == _w.Z) 
       { 
        canAdd = true; 
        horizontalCenter.X -= Wall.size/2; 
        break; 
       } 
      } 

      if (canAdd) 
      { 
       tmpWallsHorizontal.Add(other); 
      } 
     } 

     // Search how many walls there is vertically 
     Vector3 verticalCenter = new Vector3(w.X, w.Y, w.Z); 
     List<Wall> tmpWallsVertical = new List<Wall>(); 
     tmpWallsVertical.Add(w); 
     foreach (Wall other in walls) 
     { 
      if (handledWalls.Contains(other) || tmpWallsVertical.Contains(other)) continue; 
      bool canAdd = false; 
      foreach (Wall _w in tmpWallsVertical) 
      { 
       if (other.X == _w.X && other.Y == _w.Y && other.Z == _w.Z + Wall.size) 
       { 
        canAdd = true; 
        verticalCenter.Z += Wall.size/2; 
        break; 
       } 
       else if (other.X == _w.X && other.Y == _w.Y && other.Z == _w.Z - Wall.size) 
       { 
        canAdd = true; 
        verticalCenter.Z -= Wall.size/2; 
        break; 
       } 
      } 

      if (canAdd) 
      { 
       tmpWallsVertical.Add(other); 
      } 
     } 

     if (tmpWallsHorizontal.Count > tmpWallsVertical.Count) 
     { 
      // tmpWallsHorizontal has the longest "wall" now 
     } 
     else if (tmpWallsVertical.Count > tmpWallsHorizontal.Count) 
     { 
      // tmpWallsVertical has the longest "wall" now 
     } 
     else 
     { 
      // Both ways are the same length 
     } 
    } 
} 
+1

최적의 코드가 아닌 것을 알려주세요. – Bazzz

+0

원하는 출력입니까? '(0,0) - (0,3)과 (0,1) - (3,1)'? –

+0

최적의 조합을 찾기 위해 가능한 모든 조합을 계산해야하는 것처럼 들립니다. 2 개가 아닌 3 개의 벽으로 끝나면 그렇게 나쁠까요? 또는 2 개의 겹치는 것들? – dtb

답변

1

나는 이것을 flood fill의 형태로 처리하려고합니다. 아이디어는 그리드의 셀을 계속 걷는 것입니다. '벽'을 칠 때마다 홍수 채우기가 시작됩니다 (홍수 채우기가 단일 축에서만 작동한다는 것을 제외하고는) 위/아래 또는 왼쪽/오른쪽으로 만 이동).

당신이 당신의 초기 그리드를 가정하고, 왼쪽에서 오른쪽, 위쪽에서 아래쪽 세포를 반복 시작 :

당신은 왼쪽 위 셀 시작
[X][X][X][X] 
[ ][X][ ][ ] 
[ ][X][ ][ ] 
[ ][X][ ][ ] 

, 홍수를 시작, 그것은 벽의 알 수 있습니다. 너는 오른쪽으로 만 홍수를 칠 수 있기 때문에 너는 수평적인 홍수를 피운다. 당신은 '1'로 표시된 지역을 커버 결국 및 목록의 영역을 암기 :

당신은 이동
[1][1][1][1]     0/0 -> 3/0 
[ ][X][ ][ ] 
[ ][X][ ][ ] 
[ ][X][ ][ ] 

는 결국 두 번째 행에 벽을 쳤다. 당신은 (어떤 벽) 남아 있지 홍수가 없습니다, 당신은 최대 홍수 수 없습니다 (이미 포함), 당신은 (어떤 벽)을 마우스 오른쪽 범람 할 수 있지만 아래로 갈 수 있습니다 - 그래서 당신은 수직 홍수 수행

[1][1][1][1]     1: 0/0 -> 3/0 
[ ][2][ ][ ]     2: 1/1 -> 1/3 
[ ][2][ ][ ] 
[ ][2][ ][ ] 

그리고 지금 다시 끝났어. 이 버전에서는 항상 'X'가 항상 한 벽에만 포함됩니다.

[ ][1][ ][ ]     1: 1/0 -> 1/3 
[2][*][2][2]     2: 0/1 -> 3/1 
[ ][1][ ][ ] 
[ ][1][ ][ ] 

: 당신은 홍수 'X'세포가 다른 벽으로 덮여 허용하는 경우

[ ][1][ ][ ]     1: 1/0 -> 1/3 
[2][1][3][3]     2: 0/1 -> 0/1 
[ ][1][ ][ ]     3: 2/1 -> 3/1 
[ ][1][ ][ ] 

, 당신은 두를 가질 수있다 : 당신이

[ ][X][ ][ ] 
[X][X][X][X] 
[ ][X][ ][ ] 
[ ][X][ ][ ] 

가 있다면 그래서 당신은 세 개의 벽을 것 '*'는 두 개의 벽으로 덮힌 셀을 나타냅니다.

+0

감사합니다. 이것은 이미 수행 한 작업이었습니다. 검색을 실행하기 전에 벽을 주문해야했습니다. – manabreak