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

2048 Klonu: Birleşme ve Skor Mantığı Detaylı Rehber

Paylaşan: Unity Eğitim 08 December 2025 10 dakika okuma 153 görüntülenme

Giriş: 2048 Oyununun Temelleri

Unity ve C# kullanarak kendi 2048 klonunuzu geliştirmek mi istiyorsunuz? Bu rehber, popüler bulmaca oyununun kalbi olan karo birleştirme ve skorlama mekaniklerini detaylı bir şekilde ele alacak. Temel oyun döngüsünü anlamak, bu tür oyunları geliştirmenin ilk adımıdır. Bu makalede, oyun tahtasını nasıl temsil edeceğinizden, karoları nasıl kaydırıp birleştireceğinize ve skoru nasıl güncelleyeceğinize kadar her şeyi adım adım öğreneceksiniz. Özellikle 2048 birleşme mantığı üzerine odaklanarak, bu kritik algoritmayı en verimli şekilde uygulamanın yollarını keşfedeceğiz.

2048 oyununun temel prensibi oldukça basittir: 4x4'lük bir ızgarada aynı değere sahip karoları birleştirerek daha büyük sayılar elde etmek. Her hamlede yeni bir 2 veya 4 karosu belirir. Amaç, 2048 değerine ulaşmak ve mümkün olan en yüksek skoru elde etmektir. Bu basit kurallar, altında yatan karmaşık bir algoritma gerektirir. Biz de bu algoritmanın derinliklerine ineceğiz.

Oyun Tahtası ve Karo Yapısı

Oyun tahtasını C# içinde temsil etmek için genellikle iki boyutlu bir dizi (array) kullanılır. Bu dizi, her bir hücredeki karonun değerini veya karo nesnesinin referansını tutabilir. Basitlik açısından, genellikle bir `int[,]` dizisi yeterlidir. Ancak, karoların pozisyonu, animasyon durumu gibi ek bilgilere ihtiyacınız varsa, bir `Tile` sınıfı veya `struct` tanımlamak daha uygun olacaktır.

public class Tile
{
    public int Value { get; private set; }
    public bool MergedThisTurn { get; set; } // Bu turda birleşip birleşmediğini takip eder

    public Tile(int value)
    {
        Value = value;
        MergedThisTurn = false;
    }

    public void Merge(Tile other)
    {
        Value += other.Value;
        MergedThisTurn = true;
    }

    public void ResetMergeStatus()
    {
        MergedThisTurn = false;
    }
}

// Oyun tahtası
private Tile[,] board = new Tile[4, 4];

Bu yapı, her bir karo için bir değer ve o karonun o turda birleşip birleşmediğini takip eden bir bayrak tutmamızı sağlar. Bu `MergedThisTurn` bayrağı, 2048 birleşme mantığı için hayati öneme sahiptir, çünkü bir karonun aynı hareket içinde birden fazla kez birleşmesini engeller.

Oyuncu Girişi ve Hareket Yönleri

Oyuncu girişlerini işlemek, oyunun ilk adımıdır. Klavyeden veya dokunmatik ekranlardan gelen kaydırma hareketlerini algılamanız gerekir. Dört temel hareket yönü vardır: Yukarı, Aşağı, Sol ve Sağ. Bu yönleri temsil etmek için bir `enum` kullanmak kodunuzu daha okunabilir hale getirecektir.

public enum Direction
{
    Up,
    Down,
    Left,
    Right
}

// Örnek giriş işleme (Unity'de Update metodu içinde)
void Update()
{
    if (Input.GetKeyDown(KeyCode.UpArrow))
        MakeMove(Direction.Up);
    else if (Input.GetKeyDown(KeyCode.DownArrow))
        MakeMove(Direction.Down);
    // Diğer yönler için de benzer kontroller...
}

void MakeMove(Direction direction)
{
    // Burada kaydırma ve birleşme mantığı çalışacak
}

Ana Oyun Mantığı: Karoları Kaydırma

Bir oyuncu bir yön seçtiğinde, tüm karolar o yöne doğru mümkün olduğunca kaydırılmalıdır. Bu, boşlukları doldurmayı ve karoları birleşmeye hazırlamayı içerir. Kaydırma işlemi, birleşme işleminden önce gerçekleşmelidir. Her yön için döngülerin farklı sıralarda çalışması gerekir. Örneğin, sola kaydırırken her satırda soldan sağa doğru ilerlemek, sağa kaydırırken sağdan sola doğru ilerlemek mantıklıdır.

private bool ShiftTiles(Direction direction)
{
    bool moved = false;
    // Yöne göre döngüleri ayarla (örneğin sola kaydırma için)
    if (direction == Direction.Left)
    {
        for (int row = 0; row < 4; row++)
        {
            for (int col = 0; col < 4; col++)
            {
                if (board[row, col] == null) continue;
                int targetCol = col;
                while (targetCol > 0 && board[row, targetCol - 1] == null)
                {
                    targetCol--;
                }
                if (targetCol != col)
                {
                    board[row, targetCol] = board[row, col];
                    board[row, col] = null;
                    moved = true;
                }
            }
        }
    }
    // Diğer yönler için benzer döngüler...
    return moved;
}

2048 Birleşme Mantığı: Kalp Algoritması

İşte 2048 oyununun en kritik kısmı: karoları birleştirme. Karolar kaydırıldıktan sonra, aynı değere sahip bitişik karolar birleşmelidir. Her birleşme, karonun değerini iki katına çıkarır ve oyuncuya skor kazandırır. Bu noktada `MergedThisTurn` bayrağı devreye girer. Bir karo bir kez birleştikten sonra, aynı hareket içinde tekrar birleşmemelidir.

2048 birleşme mantığı, kaydırma mantığına benzer şekilde, seçilen yöne göre doğru sırayla hücreleri kontrol etmeyi gerektirir. Örneğin, sola kaydırırken birleşmeyi kontrol etmek için soldan sağa doğru ilerlemelisiniz. Ancak, birleşmeyi gerçekleştirdiğinizde, birleşen karonun hedef hücreye taşınması ve orijinal hücrenin boşaltılması gerekir.

private bool MergeTiles(Direction direction, out int scoreChange)
{
    bool merged = false;
    scoreChange = 0;

    // Her hareketten önce tüm karoların birleşme durumunu sıfırla
    ResetAllTileMergeStatus();

    // Yöne göre döngüleri ayarla (örneğin sola kaydırma için)
    if (direction == Direction.Left)
    {
        for (int row = 0; row < 4; row++)
        {
            for (int col = 0; col < 3; col++) // Son sütuna kadar kontrol et
            {
                if (board[row, col] == null || board[row, col].MergedThisTurn) continue;

                // Boşlukları atla, birleşecek karoyu bul
                int nextCol = col + 1;
                while (nextCol < 4 && board[row, nextCol] == null)
                {
                    nextCol++;
                }

                if (nextCol < 4 && board[row, nextCol] != null && 
                    board[row, col].Value == board[row, nextCol].Value && 
                    !board[row, nextCol].MergedThisTurn)
                {
                    // Birleşme işlemi
                    board[row, col].Merge(board[row, nextCol]);
                    scoreChange += board[row, col].Value; // Yeni değeri skora ekle
                    board[row, nextCol] = null; // Birleşen karoyu sil
                    merged = true;
                }
            }
        }
    }
    // Diğer yönler için benzer döngüler...
    // Örneğin, yukarı kaydırırken en üstten başlayarak aşağı doğru kontrol et.
    // Sola: col = 0 -> 3
    // Sağa: col = 3 -> 0
    // Yukarı: row = 0 -> 3
    // Aşağı: row = 3 -> 0
    return merged;
}

private void ResetAllTileMergeStatus()
{
    for (int r = 0; r < 4; r++)
    {
        for (int c = 0; c < 4; c++)
        {
            if (board[r, c] != null)
            {
                board[r, c].ResetMergeStatus();
            }
        }
    }
}

Yukarıdaki kod bloğu, sola doğru birleşme işlemini gösterir. `MergedThisTurn` bayrağı, bir karonun birden fazla kez birleşmesini önler. Bu, 2048 birleşme mantığı için olmazsa olmaz bir detaydır.

Yeni Karo Oluşturma ve Skorlama

Her geçerli hareketten sonra (yani karolar kaydırıldıysa veya birleştiyse), tahtadaki boş bir hücreye yeni bir karo eklenmelidir. Bu karo genellikle %90 ihtimalle 2, %10 ihtimalle 4 değerine sahip olur. Skorlama ise, her birleşen karonun yeni değerinin toplamıdır.

private void SpawnNewTile()
{
    List<(int row, int col)> emptyCells = new List<(int, int)>();
    for (int r = 0; r < 4; r++)
    {
        for (int c = 0; c < 4; c++)
        {
            if (board[r, c] == null)
            {
                emptyCells.Add((r, c));
            }
        }
    }

    if (emptyCells.Count > 0)
    {
        int randomIndex = Random.Range(0, emptyCells.Count);
        (int row, int col) spawnPos = emptyCells[randomIndex];
        int tileValue = Random.Range(0, 100) < 90 ? 2 : 4;
        board[spawnPos.row, spawnPos.col] = new Tile(tileValue);
    }
}

Oyunun genel akışı şöyle olmalıdır: Oyuncu hareket eder -> Karoları kaydır -> Karoları birleştir -> Karoları tekrar kaydır (birleşme sonrası oluşan boşlukları doldurmak için) -> Yeni karo oluştur -> Skoru güncelle.

Pratik İpuçları

İpucu 1: UI ve Mantık Ayrımı

Oyun mantığınızı (yani `board` dizisi ve `Tile` nesneleri) görsel temsilinden (Unity `GameObject`'leri) ayırın. Bu, kodunuzu daha temiz, test edilebilir ve yönetilebilir hale getirir. Oyun mantığı sadece değerleri ve pozisyonları güncellerken, UI katmanı bu değişiklikleri görsel olarak yansıtır.

İpucu 2: Tek Yönlü Birleşme Kuralı

Daha önce de bahsettiğimiz gibi, bir karonun bir hareket içinde yalnızca bir kez birleşmesini sağlamak 2048 birleşme mantığı için esastır. `MergedThisTurn` gibi bir bayrak kullanmak, bu kuralı uygulamanın en etkili yoludur. Her yeni hareket başlamadan önce bu bayrakları sıfırlamayı unutmayın.

İpucu 3: Animasyonları Düşünmek

Kullanıcı deneyimini artırmak için karo hareketleri ve birleşmelerine animasyonlar eklemeyi düşünün. Karoların anında zıplaması yerine yumuşak geçişlerle hareket etmesi, oyunu daha akıcı ve tatmin edici hale getirir. Bu animasyonlar genellikle oyun mantığı tamamlandıktan sonra UI katmanında uygulanır.

Yaygın Hatalar ve Çözümleri

Hata 1: Yanlış Birleşme Sırası

Bir yöne kaydırırken veya birleştirirken döngülerin yanlış yönde çalıştırılması, karoların yanlış birleşmesine veya hiç birleşmemesine neden olabilir. Örneğin, sola kaydırırken döngüyü soldan sağa başlatırsanız, bir karo birleştikten sonra hemen yanındaki karo ile tekrar birleşebilir (ki bu istenmez). Doğru yaklaşım, her zaman hareketin tersi yönde döngüleri başlatmaktır. Sola kaydırırken sağdan sola, sağa kaydırırken soldan sağa kontrol etmek gibi.

Hata 2: Çift Birleşme

Bir karonun aynı hareket içinde birden fazla kez birleşmesi, 2048'in temel kurallarını bozar (örn: 2-2-4 dizisi sola kaydırıldığında 8 yerine 4-4 sonra 8 olması). Bunun çözümü, her bir karonun o turda birleşip birleşmediğini takip eden bir `MergedThisTurn` (veya benzeri) bayrağı kullanmaktır. Bu, 2048 birleşme mantığı'nın en kritik detaylarından biridir.

Hata 3: Performans Sorunları

Özellikle mobil platformlarda, her hareket için yeni `GameObject`'ler oluşturup yok etmek performansı olumsuz etkileyebilir. Çözüm olarak, bir 'Object Pooling' sistemi kullanın. Bu sayede, karoları yok etmek yerine sadece devre dışı bırakıp ihtiyaç duyulduğunda tekrar etkinleştirebilirsiniz.

Performans ve Optimizasyon Notları

2048 gibi bir oyunun performansı genellikle C# kodunun döngüleri ve dizi erişimlerinin etkinliğine bağlıdır. 4x4'lük küçük bir ızgara için performans genellikle bir sorun teşkil etmez, ancak daha büyük ızgaralar veya daha karmaşık oyunlar için bazı optimizasyonlar düşünebilirsiniz:

  • Dizi Erişimi: `List` yerine `int[,]` veya `Tile[,]` gibi doğrudan diziler kullanmak, bellek ve erişim hızı açısından daha verimli olabilir.
  • Çöp Toplama (Garbage Collection): Her karede veya her hareket sonrası gereksiz nesneler oluşturmaktan kaçının. Bu, çöp toplayıcının sık sık çalışmasına ve oyununuzda takılmalara (hiccups) neden olabilir. Özellikle `new List()` gibi sık sık liste oluşturma işlemlerinden kaçınmaya çalışın, bunun yerine listeyi bir kez oluşturup temizleyerek tekrar kullanın (`Clear()` metodu).
  • Kodun Okunabilirliği: Performans için kodunuzu aşırı optimize etmeden önce, okunabilirliğe ve doğruluğa öncelik verin. Çoğu durumda, 2048'in algoritmaları zaten oldukça hızlıdır.

Sonuç

Bu rehberde, Unity ve C# kullanarak 2048 klonunuz için 2048 birleşme mantığı ve skorlama sistemini nasıl uygulayacağınızı detaylı bir şekilde inceledik. Oyun tahtası temsilinden, karoları kaydırma ve birleştirme algoritmalarına kadar birçok önemli konuya değindik. Uyguladığımız `MergedThisTurn` bayrağı ve doğru döngü sıralamaları, çift birleşme gibi yaygın hataları önlemenin anahtarıdır. Bu temel bilgileri ve ipuçlarını kullanarak, kendi 2048 oyununuzu başarıyla geliştirebilir ve üzerine farklı özellikler ekleyerek benzersiz bir deneyim sunabilirsiniz. İyi kodlamalar!

🧠 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!