Unity Eğitim
Dersler
Forum Sınav Merkezi Premium 💎
C# Dersleri

Unity'de Mayın Tarlası: Grid Oluşturma ve Mayınları Açığa Çıkarma

Paylaşan: Unity Eğitim 06 October 2025 10 dakika okuma 58 görüntülenme

Unity'de Mayın Tarlası: Grid Oluşturma ve Mayınları Açığa Çıkarma

Mayın Tarlası (Minesweeper), basit kuralları ve derin stratejileriyle yıllardır popülerliğini koruyan klasik bir oyundur. Unity ile kendi Mayın Tarlası oyununuzu geliştirmek, hem oyun mantığına hakim olmanızı sağlayacak hem de temel Unity/C# becerilerinizi pekiştirecektir. Bu makalede, oyunun temelini oluşturan grid (ızgara) yapısını nasıl oluşturacağınızı, mayınları alana nasıl dağıtacağınızı ve en önemlisi, tıklanan hücreleri ve çevresindeki boş alanları nasıl açığa çıkaracağınızı adım adım inceleyeceğiz. Odak noktamız, Unity Mayın Tarlası oyununun çekirdek mekaniklerini kodlamak olacak.

Mayın Tarlası Temelleri: Grid ve Hücreler

Bir Mayın Tarlası oyununun kalbi, hücrelerden oluşan iki boyutlu bir grid'dir. Her hücre, bir mayın içerip içermediği, çevresindeki mayın sayısı ve açılıp açılmadığı gibi bilgilere sahiptir. Bu bilgileri yönetmek için bir C# sınıfı veya yapı (struct) kullanmak en uygun yaklaşımdır.

Hücre Yapısını Tanımlama

Her bir hücre için gerekli bilgileri tutacak bir yapı oluşturalım. Bu yapı, hücrenin görsel temsilinden (GameObject) ayrı olarak oyun mantığını içerecektir.

public class Cell
{
    public int x; // Hücrenin X koordinatı
    public int y; // Hücrenin Y koordinatı
    public bool isMine; // Bu hücrede mayın var mı?
    public bool isRevealed; // Bu hücre açıldı mı?
    public bool isFlagged; // Bu hücreye bayrak dikildi mi?
    public int adjacentMines; // Çevresindeki mayın sayısı
    public GameObject visualGameObject; // Unity sahnesindeki görsel temsil

    public Cell(int x, int y)
    {
        this.x = x;
        this.y = y;
        isMine = false;
        isRevealed = false;
        isFlagged = false;
        adjacentMines = 0;
    }
}

Bu `Cell` sınıfı, her bir hücrenin durumunu kolayca takip etmemizi sağlar. `visualGameObject` alanı, Unity sahnesindeki ilgili hücre objesine referans tutarak oyun mantığı ile görsel temsil arasında bağlantı kurar.

Grid'i Oluşturma

Oyun alanı, bir Cell dizisinden oluşacaktır. Genellikle iki boyutlu bir dizi (`Cell[,]`) kullanılır. Bir MonoBehaviour sınıfı içinde, örneğin `MinesweeperGridManager` adında bir script'te, bu grid'i başlatabilir ve hücrelerin görsel temsillerini oluşturabiliriz.

public class MinesweeperGridManager : MonoBehaviour
{
    public int width = 10; // Grid genişliği
    public int height = 10; // Grid yüksekliği
    public int totalMines = 15; // Toplam mayın sayısı
    public GameObject cellPrefab; // Hücrelerin görsel prefab'ı
    private Cell[,] grid; // Oyun alanı grid'i

    void Start()
    {
        GenerateGrid();
    }

    void GenerateGrid()
    {
        grid = new Cell[width, height];

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                Cell newCell = new Cell(x, y);
                grid[x, y] = newCell;

                // Görsel objeyi oluştur ve konumlandır
                GameObject cellGO = Instantiate(cellPrefab, new Vector3(x, y, 0), Quaternion.identity);
                cellGO.transform.parent = this.transform; // Grid Manager altına yerleştir
                newCell.visualGameObject = cellGO;
                // Cell objesine bir script ekleyip referansı verebiliriz.
                // Örneğin: cellGO.GetComponent<CellVisualController>().SetCell(newCell);
            }
        }
        PlaceMines();
        CalculateAdjacentMines();
    }
    // ... diğer metodlar
}

Bu kod bloğu, belirli bir genişlik ve yükseklikte bir grid oluşturur ve her bir hücre için Unity sahnesinde bir `GameObject` örneği (prefab'dan) yaratır. Bu, Unity Mayın Tarlası projenizin temel görsel ve mantıksal yapısını kurar.

Mayınları Yerleştirme ve Komşu Sayılarını Hesaplama

Mayınları rastgele yerleştirmek için, toplam mayın sayısı kadar rastgele koordinat seçip o hücreyi mayın olarak işaretleyebiliriz. Ancak, aynı yere birden fazla mayın gelmemesi için dikkatli olmak gerekir.

void PlaceMines()
{
    int minesPlaced = 0;
    while (minesPlaced < totalMines)
    {
        int randomX = Random.Range(0, width);
        int randomY = Random.Range(0, height);

        if (!grid[randomX, randomY].isMine)
        {
            grid[randomX, randomY].isMine = true;
            minesPlaced++;
        }
    }
}

void CalculateAdjacentMines()
{
    for (int x = 0; x < width; x++)
    {
        for (int y = 0; y < height; y++)
        {
            if (!grid[x, y].isMine)
            {
                grid[x, y].adjacentMines = CountMinesAround(x, y);
            }
        }
    }
}

int CountMinesAround(int x, int y)
{
    int count = 0;
    for (int dx = -1; dx <= 1; dx++)
    {
        for (int dy = -1; dy <= 1; dy++)
        {
            if (dx == 0 && dy == 0) continue; // Kendi hücresini atla

            int nx = x + dx;
            int ny = y + dy;

            // Grid sınırları içinde mi kontrol et
            if (nx >= 0 && nx < width && ny >= 0 && ny < height)
            {
                if (grid[nx, ny].isMine)
                {
                    count++;
                }
            }
        }
    }
    return count;
}

PlaceMines metodu, mayınları rastgele ve benzersiz bir şekilde yerleştirir. Ardından, CalculateAdjacentMines metodu, her bir mayın olmayan hücre için çevresindeki 8 komşu hücreyi kontrol ederek mayın sayısını bulur. Bu sayı, hücre açıldığında kullanıcıya gösterilir.

Hücreleri Açığa Çıkarma Mekaniği

Bir hücreye tıklandığında ne olacağı, Mayın Tarlası'nın en kritik kısmıdır. Bu mekanik, oyunun akışını ve zorluğunu belirler.

Tıklama ve İlk Açığa Çıkarma

Kullanıcı bir hücreye tıkladığında (genellikle sol tıklama), o hücrenin durumu kontrol edilir:

  • Eğer hücrede mayın varsa: Oyun biter (Game Over).
  • Eğer hücrede mayın yoksa ve çevresinde mayın varsa (adjacentMines > 0): Hücre açılır ve üzerindeki sayı gösterilir.
  • Eğer hücrede mayın yoksa ve çevresinde de mayın yoksa (adjacentMines == 0): Bu, en ilginç senaryodur. Bu hücre açılır ve ardından çevresindeki tüm komşu hücreler de otomatik olarak açığa çıkarılır. Bu işlem, komşu hücreler de boş olduğunda zincirleme devam eder.
public void RevealCell(int x, int y)
{
    // Grid sınırları dışında veya zaten açılmış/bayraklı ise işlem yapma
    if (x < 0 || x >= width || y < 0 || y >= height || grid[x, y].isRevealed || grid[x, y].isFlagged)
    {
        return;
    }

    Cell cell = grid[x, y];
    cell.isRevealed = true;
    // Görsel güncellemeyi burada veya ayrı bir scriptte yapın
    // cell.visualGameObject.GetComponent<CellVisualController>().UpdateVisual(cell);

    if (cell.isMine)
    {
        Debug.Log("Oyun Bitti! Mayına Bastınız!");
        // Oyun bitiş ekranı, tüm mayınları gösterme vb.
        return;
    }

    if (cell.adjacentMines == 0)
    {
        // Çevresindeki komşuları da açığa çıkar
        for (int dx = -1; dx <= 1; dx++)
        {
            for (int dy = -1; dy <= 1; dy++)
            {
                if (dx == 0 && dy == 0) continue; // Kendi hücresini atla
                RevealCell(x + dx, y + dy); // Özyinelemeli çağrı
            }
        }
    }
    // Kazanma kontrolü (tüm mayınsız hücreler açıldı mı?)
}

Boş Hücrelerin Zincirleme Açılması

Yukarıdaki RevealCell metodundaki özyinelemeli (recursive) çağrı, boş bir hücreye tıklandığında çevresindeki tüm boş hücreleri otomatik olarak açığa çıkarma mekaniğini sağlar. Bu, Unity Mayın Tarlası oyununun en tatmin edici özelliklerinden biridir. Sistem, bir hücre açıldığında ve çevresinde mayın yoksa, komşularını da aynı `RevealCell` metoduyla açmaya çalışır. Bu, mayınsız geniş alanların tek bir tıklamayla temizlenmesini sağlar.

Pratik İpuçları

Enum Kullanımı ile Hücre Durumlarını Yönetme

Hücrelerin durumunu (kapalı, açık, bayraklı, soru işaretli) daha okunabilir ve yönetilebilir hale getirmek için `enum` kullanabilirsiniz. Bu, `bool` bayrakları yerine tek bir durum değişkeniyle çalışmanızı sağlar.

public enum CellState
{
    Covered,
    Revealed,
    Flagged,
    QuestionMark
}

public class Cell
{
    // ... diğer alanlar
    public CellState state;
    // ...
}

Bu yaklaşım, kodunuzu daha anlaşılır hale getirir ve olası mantık hatalarını azaltır.

Komşu Kontrolleri İçin Verimli Yaklaşımlar

CountMinesAround ve RevealCell metodlarındaki iç içe döngüler (`dx`, `dy`), komşu hücreleri kontrol etmek için standart ve etkili bir yoldur. Ancak, büyük grid'lerde performans kritik hale gelirse, komşu koordinatları önceden tanımlanmış bir liste (örneğin, (dx, dy) çiftleri) şeklinde tutmak ve bu liste üzerinde döngü yapmak kodu biraz daha düzenli hale getirebilir.

// Örneğin, Cell sınıfı içinde veya Grid Manager'da tanımlanabilir
private static readonly (int dx, int dy)[] Neighbors = {
    (-1, -1), (0, -1), (1, -1),
    (-1,  0),          (1,  0),
    (-1,  1), (0,  1), (1,  1)
};

Daha sonra döngünüzü bu `Neighbors` dizisi üzerinde yapabilirsiniz.

Oyun Mantığını UI'dan Ayırma

Yukarıdaki örneklerde `Cell` sınıfı hem mantıksal veriyi hem de `visualGameObject` referansını tutuyor. Daha büyük projelerde, oyun mantığını (Cell sınıfı, MinesweeperGridManager) tamamen görsel temsilinden (CellVisualController gibi bir script) ayırmak iyi bir uygulamadır. `MinesweeperGridManager`, `Cell` objelerini yönetirken, `CellVisualController` ise kendi GameObject'inin nasıl görüneceğini (mayın resmi, sayı, kapalı/açık doku vb.) `Cell` objesindeki verilere göre günceller. Bu ayrım, kodunuzu daha modüler ve bakımı kolay hale getirir.

Yaygın Hatalar ve Çözümleri

Dizi Sınırları Dışına Çıkma Hataları (`IndexOutOfRangeException`)

Komşu hücreleri kontrol ederken (özellikle grid'in kenarlarında veya köşelerinde), `x` ve `y` koordinatlarının grid sınırları içinde kalmasını sağlamak kritik öneme sahiptir. Yukarıdaki kod örneklerinde `nx >= 0 && nx < width && ny >= 0 && ny < height` kontrolleri bu hatayı önlemek içindir. Bu kontrolleri her zaman yaptığınızdan emin olun.

Sonsuz Özyineleme (Stack Overflow)

RevealCell metodundaki özyinelemeli çağrılar, eğer bir hücrenin `isRevealed` durumu doğru şekilde güncellenmezse veya zaten açılmış bir hücre tekrar açılmaya çalışılırsa sonsuz bir döngüye yol açabilir. `if (grid[x, y].isRevealed)` kontrolü bu hatayı önlemek için çok önemlidir. Her zaman bir hücreyi açmadan önce zaten açılıp açılmadığını kontrol edin.

Mayınların Üst Üste Yerleşmesi

PlaceMines metodunda, rastgele seçilen koordinata zaten mayın yerleştirilmiş olup olmadığını kontrol etmek önemlidir (`if (!grid[randomX, randomY].isMine)`). Bu kontrol olmadan, aynı hücreye birden fazla mayın atanabilir ve toplam mayın sayısı beklediğinizden az olur.

Performans ve Optimizasyon Notları

Küçük grid boyutları için yukarıdaki yaklaşımlar genellikle yeterince performanslıdır. Ancak, çok büyük grid'ler veya mobil cihazlar için bazı optimizasyonlar düşünebilirsiniz:

  • Objelerin Havuzlanması (Object Pooling): Her hücre için `Instantiate` çağırmak yerine, başlangıçta tüm hücre objelerini oluşturup bunları bir havuzda tutabilir ve ihtiyaç duyulduğunda yeniden kullanabilirsiniz. Bu, çalışma zamanı bellek ayırmalarını ve çöp toplama (garbage collection) yükünü azaltır.
  • Görsel Güncellemeleri Azaltma: Her `Cell` objesinin kendi `visualGameObject`'i olması yerine, tek bir grid görseli üzerinde dokuları veya Sprite'ları değiştirerek hücre durumlarını yansıtabilirsiniz. Bu, özellikle çok sayıda hücre olduğunda `GameObject` sayısını ve çizim çağrılarını azaltır.
  • Komşu Kontrolleri: Yukarıda belirtildiği gibi, komşu koordinatlarını önceden tanımlanmış bir dizi veya liste olarak tutmak, döngülerin daha okunaklı ve bazen daha optimize olmasına yardımcı olabilir.

Sonuç

Bu makalede, Unity Mayın Tarlası oyununun temelini oluşturan grid yapısını, mayın yerleştirmeyi ve hücreleri açığa çıkarma mekaniklerini detaylı bir şekilde inceledik. Bu temel bilgileri kullanarak kendi Mayın Tarlası oyununuzu geliştirmeye başlayabilir, üzerine kullanıcı arayüzü (UI), zamanlayıcı, puanlama sistemi ve daha fazlasını ekleyebilirsiniz. Unutmayın, oyun geliştirme bir öğrenme sürecidir ve bu tür klasik oyunları yeniden yaratmak, temel programlama ve oyun tasarımı prensiplerini pekiştirmek için harika bir yoldur. Bol şanslar!

🧠 Ders Sonu Değerlendirme Testi

Dersi tamamladıktan sonra bilgilerinizi test edin ve ekstra puanlar kazanın.

🔥 +50 XP Ödül
🔒

Sınava Katılmak İçin Giriş Yapın

Bu ders sonu testini çözebilmek, bilginizi test edip **+50 XP** kazanmak ve **Sınav Şampiyonu** rozetinin kilidini açmak için üye girişi yapmalısınız.

Yorumlar (0)

Yorum yazabilmek ve derslere katkıda bulunabilmek için giriş yapmalısınız.

İlk yorumu siz yapın!