Adaları Kaldırma
Bu tür şeyleri daha önce oyunlarımdan birinde yaptım. Dış adalardan kurtulmak için, süreç temel olarak:
- Öncelikle haritanın merkezinin her zaman ana araziye ait olacağının bir garantisi olmalı ve her piksel "Arazi" veya "Su" (yani farklı renkler) olarak başlar.
- Ardından haritanın ortasından başlayıp herhangi bir "Arazi" döşemesine yayılan dört yönlü bir taşma dolgusu yapın . Bu sel dolgusunun ziyaret ettiği her pikseli "MainLand" gibi farklı bir tür olarak işaretleyin.
- Sonunda tüm haritayı gözden geçirin ve kalan diğer “Land” piksellerini diğer adalardan kurtulmak için “Su” ya dönüştürün.
Gölleri Çıkarma
Adanın içindeki deliklerden (veya göllerden) kurtulmak için, benzer bir işlem yapıyorsunuz, ancak haritanın köşelerinden başlayıp yerine "Su" çinileri arasında yayılıyor. Bu, "Deniz" i diğer su kiremitlerinden ayırmanıza izin verecek ve daha önce adalardan kurtulmuş olduğunuz gibi onlardan kurtulabileceksiniz.
Örnek
Beni Buralarda olduğunu taşkın dolgu benim uygulanmasını kazıp edelim (Emin vardır değilim bu yüzden reddi, ben, verimlilik umursamadı birçok uygulamak daha etkili yollar):
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);
}
Bunu oyunumdaki göllerden kurtulmak için ilk adım olarak kullandım. Bunu çağırdıktan sonra tek yapmam gereken şey gibiydi:
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;
}
Düzenle
Yorumlara dayanarak bazı ek bilgiler eklemek. Arama alanınızın çok büyük olması durumunda, algoritmanın özyinelemeli sürümünü kullanırken bir yığın taşması yaşayabilirsiniz. İşte algoritma özyinelemeli olmayan bir versiyonuna istif akışına (pun amaçlı :-)) bir link ( Stack<T>
bunun yerine cevabımla eşleşmek için C # dilinde), ancak diğer dillere adapte olmak kolay olmalı ve bu konuda başka uygulamalar da var. bağlantı da).