제도 제거
나는 내 게임 중 하나에서 이런 종류의 일을 해본 적이있다. 외부 섬을 제거하기 위해 프로세스는 기본적으로 다음과 같습니다.
- 먼저지도의 중심이 항상 본토에 속하고 각 픽셀이 "랜드"또는 "물"(즉, 다른 색상)로 시작한다는 보장이 있어야합니다.
- 그런 다음 지도 중심에서 시작하여 "랜드"타일 전체에 4 방향 홍수 채우기를 수행합니다 . 이 플러드 필에 방문한 모든 픽셀을 "MainLand"와 같은 다른 유형으로 표시하십시오.
- 마지막으로 전체지도를 살펴보고 남은 "랜드"픽셀을 "물"로 변환하여 다른 섬을 제거하십시오.
호수 제거
섬 내부의 구멍 (또는 호수)을 제거하는 것과 비슷한 과정을하지만지도 모서리에서 시작하여 대신 "물"타일을 통해 퍼집니다. 이렇게하면 "바다"를 다른 물 타일과 구별 할 수 있으며 이전에 섬을 제거한 것처럼 제거 할 수 있습니다.
예
여기 어딘가에있는 홍수 채우기 구현을 파헤 보겠습니다 (면책 조항, 효율성에 대해서는 신경 쓰지 않았으므로 그것을 구현하는 더 효율적인 방법 이 많이 있다고 확신 합니다).
private void GenerateSea()
{
// Initialize visited tiles list
visited.Clear();
// Start generating sea from the four corners
GenerateSeaRecursive(new Point(0, 0));
GenerateSeaRecursive(new Point(size.Width - 1, 0));
GenerateSeaRecursive(new Point(0, size.Height - 1));
GenerateSeaRecursive(new Point(size.Width - 1, size.Height - 1));
}
private void GenerateSeaRecursive(Point point)
{
// End recursion if point is outside bounds
if (!WithinBounds(point)) return;
// End recursion if the current spot is a land
if (tiles[point.X, point.Y].Land) return;
// End recursion if this spot has already been visited
if (visited.Contains(point)) return;
// Add point to visited points list
visited.Add(point);
// Calculate neighboring tiles coordinates
Point right = new Point(point.X + 1, point.Y);
Point left = new Point(point.X - 1, point.Y);
Point up = new Point(point.X, point.Y - 1);
Point down = new Point(point.X, point.Y + 1);
// Mark neighbouring tiles as Sea if they're not Land
if (WithinBounds(right) && tiles[right.X, right.Y].Empty)
tiles[right.X, right.Y].Sea = true;
if (WithinBounds(left) && tiles[left.X, left.Y].Empty)
tiles[left.X, left.Y].Sea = true;
if (WithinBounds(up) && tiles[up.X, up.Y].Empty)
tiles[up.X, up.Y].Sea = true;
if (WithinBounds(down) && tiles[down.X, down.Y].Empty)
tiles[down.X, down.Y].Sea = true;
// Call the function recursively for the neighboring tiles
GenerateSeaRecursive(right);
GenerateSeaRecursive(left);
GenerateSeaRecursive(up);
GenerateSeaRecursive(down);
}
나는 이것을 게임에서 호수를 없애기위한 첫 단계로 사용했다. 그것을 부른 후, 내가해야 할 일은 다음과 같습니다.
private void RemoveLakes()
{
// Now that sea is generated, any empty tile should be removed
for (int j = 0; j != size.Height; j++)
for (int i = 0; i != size.Width; i++)
if (tiles[i, j].Empty) tiles[i, j].Land = true;
}
편집하다
주석을 기반으로 추가 정보를 추가합니다. 검색 공간이 너무 큰 경우 재귀 버전의 알고리즘을 사용할 때 스택 오버플로가 발생할 수 있습니다. 여기의 링크 알고리즘의 비 재귀 버전으로 유래에은 (말장난 의도 :-))는을 사용하여, Stack<T>
내 대답에 맞게 (또한 C #으로 대신하지만, 다른 언어에 적응하기 용이해야하고, 그 다른 구현이있다 링크도).