Suppression d'îles
J'ai déjà fait ce genre de chose dans l'un de mes jeux. Pour se débarrasser des îles extérieures, le processus était essentiellement:
- Tout d'abord, il doit y avoir une garantie que le centre de la carte appartiendra toujours à la terre principale, et chaque pixel commence soit par "Terre" ou "Eau" (c'est-à-dire différentes couleurs).
- Faites ensuite un remplissage à quatre directions en commençant par le centre de la carte et en vous étalant sur toutes les tuiles "Terre". Marquez chaque pixel visité par ce remplissage comme un type différent tel que "MainLand".
- Enfin, parcourez toute la carte et convertissez tout pixel "Terre" restant en "Eau" pour vous débarrasser des autres îles.
Suppression des lacs
Quant à se débarrasser des trous (ou lacs) à l'intérieur de l'île, vous effectuez un processus similaire, mais en partant des coins de la carte et en vous propageant à travers les tuiles "Eau" à la place. Cela vous permettra de distinguer la "mer" des autres tuiles d'eau, et vous pourrez ensuite vous en débarrasser comme vous vous êtes débarrassé des îles auparavant.
Exemple
Permettez-moi de creuser ma mise en œuvre du remblai d'inondation que j'ai ici quelque part (avertissement, je ne me souciais pas de l'efficacité, donc je suis sûr qu'il existe de nombreuses façons plus efficaces de le mettre en œuvre):
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);
}
J'ai utilisé cela comme une première étape pour se débarrasser des lacs dans mon jeu. Après avoir appelé cela, tout ce que j'avais à faire était quelque chose comme:
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;
}
modifier
Ajout d'informations supplémentaires sur la base des commentaires. Dans le cas où votre espace de recherche est trop grand, vous pourriez rencontrer un débordement de pile lors de l'utilisation de la version récursive de l'algorithme. Voici un lien sur stackoverflow (jeu de mots prévu :-)) vers une version non récursive de l'algorithme, en utilisant à la Stack<T>
place (également en C # pour correspondre à ma réponse, mais devrait être facile à adapter à d'autres langages, et il existe d'autres implémentations à ce sujet lien aussi).