OKEY 101 OYUNUN KOD DOKUMANI

encode Fonksiyonu

Parametre (b) – byte dizisi
encode fonksiyonu, girilen byte dizisini base64 formatında bir string'e çevirir.
Base64 Kullanımı – Amaç
Base64, ikili veriyi metin olarak güvenli taşımak veya saklamak için yaygın olarak kullanılır.
  func encode(b []byte) string {
      return base64.StdEncoding.EncodeToString(b)
  }
        

decode Fonksiyonu

Parametre (s) – base64 formatında metin
decode fonksiyonu, base64 ile kodlanmış metni çözerek orijinal byte dizisine dönüştürür.
Base64 Çözme – Amaç
Şifreleme veya veri iletiminde base64 kullanılan veriler, bu fonksiyon ile tekrar ham veriye dönüştürülür.
  func decode(s string) ([]byte, error) {
      data, err := base64.StdEncoding.DecodeString(s)
      if err != nil {
          return nil, err
      }
      return data, nil
  }
        

Encrypt Fonksiyonu

Parametre (text) – Şifrelenecek düz metin
AES algoritması ile şifrelenmek üzere kullanıcıdan alınan ham veri.
Parametre (MySecret) – Anahtar (key)
AES algoritmasında kullanılacak olan şifreleme anahtarı (string olarak verilmelidir).
Amaç – AES Şifreleme
Bu fonksiyon, verilen metni AES algoritması (CFB modu) ile şifreler ve base64 string olarak geri döner.
  func Encrypt(text, MySecret string) (string, error) {
      block, err := aes.NewCipher([]byte(MySecret))
      if err != nil {
          return "", err
      }
      plainText := []byte(text)
      cfb := cipher.NewCFBEncrypter(block, bytes)
      cipherText := make([]byte, len(plainText))
      cfb.XORKeyStream(cipherText, plainText)
      return encode(cipherText), nil
  }
        

Decrypt Fonksiyonu

Parametre (text) – Şifrelenmiş veri (base64)
decode fonksiyonuyla çözülecek base64 formatındaki şifrelenmiş metindir.
Parametre (MySecret) – Anahtar (key)
AES algoritmasında çözümleme işlemi için kullanılan şifreleme anahtarıdır.
Amaç – Şifre Çözme
Bu fonksiyon, AES algoritması (CFB modu) ile şifrelenmiş metni çözerek orijinal düz metni elde eder.
  func Decrypt(text, MySecret string) (string, error) {
      block, err := aes.NewCipher([]byte(MySecret))
      if err != nil {
          return "", err
      }
      cipherText, err := decode(text)
      if err != nil {
          return "", err
      }
      cfb := cipher.NewCFBDecrypter(block, bytes)
      plainText := make([]byte, len(cipherText))
      cfb.XORKeyStream(plainText, cipherText)
      return string(plainText), nil
  }
        

HashAndSalt Fonksiyonu

Parametre (pwd) – Parola (byte dizisi)
Şifrelenmek üzere alınan ham parola verisi. `[]byte` formatında olmalıdır.
Amaç – Parola Hashleme
Bu fonksiyon, kullanıcı parolasını bcrypt algoritması ile hash'ler ve güvenli biçimde string olarak döndürür.
bcrypt.MinCost – Güvenlik seviyesi
Şifreleme işlemi için minimum işlem maliyeti ayarlanır (düşük CPU kullanımı sağlar).
  func HashAndSalt(pwd []byte) string {
      hash, err := bcrypt.GenerateFromPassword(pwd, bcrypt.MinCost)
      if err != nil {
          log.Println(err)
      }
      return string(hash)
  }
        

ComparePasswords Fonksiyonu

Parametre (hashedPwd) – Hash'lenmiş şifre
Daha önce `HashAndSalt` fonksiyonu ile hash'lenmiş olan parola string formatında verilir.
Parametre (plainPwd) – Ham şifre
Kullanıcının giriş sırasında girdiği gerçek (ham) parola byte dizisi olarak alınır.
Amaç – Doğrulama
Hash'lenmiş parola ile kullanıcının girdiği ham parola eşleşiyor mu kontrol edilir. Eşleşiyorsa true, değilse false döner.
  func ComparePasswords(hashedPwd string, plainPwd []byte) bool {
      byteHash := []byte(hashedPwd)
      err := bcrypt.CompareHashAndPassword(byteHash, plainPwd)
      if err != nil {
          log.Println(err)
          return false
      }
      return true
  }
        

DetermineOkeyTile Fonksiyonu

Parametre (indicator) – Gösterge taşı
Oyun başladığında rastgele belirlenen taş. Gerçek okey taşını bulmak için kullanılır.
Kullanımı – Amaç
  • Gösterge taşının numarasını 1 artırarak gerçek okey taşını belirler.
  • Renk olarak gösterge taşıyla aynı kalır.
  • Numara 13’ten büyükse 1’e sarar (dönel yapı).
  • `IsOkey = true`, `IsJoker = false` olacak şekilde okey nesnesi döndürür.
  // OkeyTaşınıBelirle, gösterge taşına göre gerçek okey taşını döner
  func DetermineOkeyTile(indicator Model.Tile) Model.Tile {
      nextNumber := indicator.Number + 1 // Gösterge numarasının bir fazlası alınır

      if nextNumber > 13 {               // Okey taş numarası 13'ü aşarsa 1'e sarar
          nextNumber = 1
      }

      return Model.Tile{                 // Gerçek okey taşı nesnesi döndürülür
          Number:  nextNumber,           // Hesaplanan numara
          Color:   indicator.Color,      // Gösterge taşıyla aynı renk
          IsOkey:  true,                 // Bu taş gerçek okeydir
          IsJoker: false,                // Joker değildir
      }
  }
        

MarkOkeyTiles Fonksiyonu

Parametre (indicator) – Gösterge taşı
Oyun başlangıcında seçilen taş olup, gerçek okey taşının hesaplanmasında temel alınır.
Kullanımı – Amaç
  • Gösterge taşına göre gerçek okey taşını hesaplar.
  • Gösterge taşını sahte okey (joker) olarak işaretler.
  • Renksiz ve numarasız joker taşlara, gerçek okey taşının bilgilerini atar.
  • Diğer tüm taşları joker/okey olmayan taş olarak sıfırlar.
  func (tiles *TileBag) MarkOkeyTiles(indicator Model.Tile) {
      okey := DetermineOkeyTile(indicator) // Gösterge taşına göre gerçek okey belirlenir

      for i := range *tiles {              // Tüm taş torbası gezilir
          tile := &(*tiles)[i]             // İlgili taşın referansı alınır

          if tile.Number == indicator.Number && tile.Color == indicator.Color {
              // Bu taş gösterge taşıysa sahte okey olur
              tile.IsJoker = true          // Sahte okey olarak işaretlenir
              tile.IsOkey = false          // Gerçek okey olmadığı belirtilir
          } else if tile.Number == okey.Number && tile.Color == okey.Color && !tile.IsJoker {
              // Bu taş gerçek okey taşına eşitse ve joker değilse
              tile.IsOkey = true           // Gerçek okey olarak işaretlenir
          } else if tile.Number == 0 && tile.Color == ColorEnum.None && tile.IsJoker {
              // Ön tanımlı renksiz-numarasız joker taşlar
              tile.Number = okey.Number    // Gerçek okeyin numarası atanır
              tile.Color = okey.Color      // Gerçek okeyin rengi atanır
          } else {
              // Diğer tüm taşlar için sıfırlama yapılır
              tile.IsOkey = false
              tile.IsJoker = false
          }
      }
  }
        

CreateFullTileSet Fonksiyonu

Parametre – Yok
Bu fonksiyon herhangi bir dış parametre almaz. Tüm taş yapısını kendi içinde oluşturur.
Kullanımı – Amaç
  • Okey oyunu için gerekli olan 106 taşlık tam seti oluşturur.
  • Her bir taş, dört renkten biriyle (Kırmızı, Sarı, Mavi, Siyah) ve 1–13 arası numarayla üretilir.
  • Her taşın oyunda tanımlanabilir olması için benzersiz bir ID atanır.
  • Her taş türünden 2 adet üretildiği için toplamda 104 taş oluşur.
  • Ek olarak, oyun kurallarına uygun olarak 2 adet sahte okey taşı (renksiz, numbersız, joker) eklenir.
  • Oluşturulan taşlar, karıştırma algoritması (`ShuffleTilesSecure`) ile güvenli biçimde rastgele dizilir.
  • Bu fonksiyon genellikle oyun başlangıcında bir kez çağrılır ve başlangıç torbasını (TileBag) oluşturur.
  func CreateFullTileSet() TileBag {
      var tiles []Model.Tile // Taşları tutacak ana liste
      id := 0                // Her taşa atanacak benzersiz ID
      colors := []int{
          ColorEnum.Red,
          ColorEnum.Yellow,
          ColorEnum.Blue,
          ColorEnum.Black,
      }
      for _, color := range colors {          // Tüm renkler için
          for number := 1; number <= 13; number++ { // 1–13 arası sayılar
              for i := 0; i < 2; i++ {         // Her renkten 2 taş
                  tiles = append(tiles, Model.Tile{
                      ID:      id,
                      Number:  number,
                      Color:   color,
                      IsJoker: false,
                      IsOkey:  false,
                      IsOpend: false,
                  })
                  id++
              }
          }
      }
      // 2 adet sahte okey taşı (renksiz, numbersız)
      for i := 0; i < 2; i++ {
          tiles = append(tiles, Model.Tile{
              ID:      id,
              Number:  0,
              Color:   ColorEnum.None,
              IsJoker: true,
              IsOkey:  false,
          })
          id++
      }
      return ShuffleTilesSecure(tiles) // Taşları karıştırarak döndür
  }
        

ShuffleTilesSecure Fonksiyonu

Parametre (tiles) – Karıştırılacak taş dizisi
Oyun başında oluşturulmuş olan tam taş setidir. Rastgele ve güvenli biçimde karıştırılması için bu fonksiyona verilir.
Kullanımı – Amaç
  • Fisher–Yates algoritmasını kullanarak taşları karıştırır.
  • Standart `math/rand` yerine kriptografik olarak güvenli `crypto/rand` fonksiyonu ile çalışır.
  • Güvenli oyun deneyimi ve öngörülemezlik sağlamak için rastgelelik önemlidir.
  • Her taşın yeri diğerlerinden bağımsız olarak güvenli biçimde değiştirilir.
  • Hata durumunda orijinal sıralı taş dizisi geri döner.
  // Fisher-Yates Shuffle :)
  // ShuffleTilesSecure, taşları kriptografik olarak güvenli şekilde karıştırır
  func ShuffleTilesSecure(tiles []Model.Tile) TileBag {
      shuffled := make([]Model.Tile, len(tiles)) // Yeni boş bir dizi oluştur
      copy(shuffled, tiles)                      // Orijinal taşları kopyala

      for i := len(shuffled) - 1; i > 0; i-- {    // Diziyi sondan başa gez
          j, err := cryptoRandInt(i + 1)         // 0–i arasında güvenli bir sayı üret
          if err != nil {
              // Hata durumunda karıştırılmadan orijinal dizi döner
              return tiles
          }
          shuffled[i], shuffled[j] = shuffled[j], shuffled[i] // i ve j indekslerini yer değiştir
      }

      return shuffled // Karıştırılmış diziyi döndür
  }
        

cryptoRandInt Fonksiyonu

Parametre (max) – Üst sınır
Üretilecek rastgele sayının dahil olmayacağı en büyük değerdir. 0 ile max-1 arasında sayı üretir.
Kullanımı – Amaç
  • Bu fonksiyon, güvenli bir şekilde 0 ile max-1 arasında bir tamsayı üretmek için kullanılır.
  • math/rand yerine crypto/rand kullanılarak tahmin edilemez sonuçlar elde edilir.
  • Genellikle oyun taşlarını güvenli karıştırma işlemleri gibi hassas alanlarda kullanılır.
  • Hatalı durumlarda varsayılan olarak 0 ve error döner.
  // cryptoRandInt returns a random int between 0 and max-1 using crypto/rand
  func cryptoRandInt(max int) (int, error) {
      nBig, err := rand.Int(rand.Reader, big.NewInt(int64(max))) // Büyük sayı üretimi
      if err != nil {
          return 0, err // Hata varsa varsayılan 0 döndürülür
      }
      return int(nBig.Int64()), nil // Güvenli sayı int'e çevrilerek döndürülür
  }
        

GetTiles Fonksiyonu

Parametre (count) – Çekilecek taş adedi
Taş torbasından kaç adet taş çekileceğini belirtir. Eğer torbada yeterli taş yoksa elde kalan taş kadar döner.
Kullanımı – Amaç
  • TileBag içerisinden istenilen sayıda taşı çekmek için kullanılır.
  • Seçilen taşlar `selected` listesine eklenir ve TileBag'den çıkarılır.
  • Bu fonksiyonla oyunculara oyun başında veya oyun esnasında taş dağıtımı yapılabilir.
  • Güvenlik amacıyla, eğer istenenden az taş varsa sadece kalanları verir ve hata vermez.
  • Çekilen taşlar yeni bir TileBag olarak döndürülür.
  func (tiles *TileBag) GetTiles(count int) *TileBag {
      if len(*tiles) < count {
          count = len(*tiles) // Taş sayısı yetersizse, kalan kadarını al
      }

      selected := (*tiles)[:count]      // Seçilen taşlar
      *tiles = (*tiles)[count:]         // Geriye kalan taşları TileBag'e geri yaz

      return &selected                  // Seçilen taşları geri döndür
  }
        

ShowPlayerTiles Fonksiyonu

Parametre (tiles) – TileBag (Taş torbası)
Tüm taşları içeren TileBag referansı. Bu torbadan oyuncuya taş dağıtımı yapılır.
Parametre (name) – Oyuncu adı
Ekrana yazdırılacak olan oyuncunun adıdır. Konsol çıktısı için kullanılır.
Parametre (topCount) – Çekilecek taş sayısı
Oyuncuya kaç taş verileceğini belirtir. Bu sayı kadar taş torbadan çekilir ve gösterilir.
Kullanımı – Amaç
  • Bir oyuncuya dağıtılan taşları almak ve konsola görsel olarak yazdırmak için kullanılır.
  • Taşların ID, renk, numara, joker ve okey olup olmadığı bilgileri yazdırılır.
  • Dağıtılan taşlar, TileBag'den çıkartılır ve oyuncuya atanır.
  • Fonksiyon sonunda, oyuncuya ait taşlar geri döndürülür.
  func ShowPlayerTiles(tiles *TileBag, name string, topCount int) *TileBag {
      player := tiles.GetTiles(topCount) // Belirtilen sayıda taşı al

      fmt.Println(name) // Oyuncu adı yazdırılır
      fmt.Println(strings.Repeat("-", 30)) // Görsel ayraç

      for i, tile := range *player {
          colorName := GetEnumName(ColorEnum, tile.Color) // Renk ismini al
          fmt.Printf("%d-) ID: %d, %s %d, Joker: %v Okey: %v\n",
              i+1, tile.ID, colorName, tile.Number, tile.IsJoker, tile.IsOkey)
      }

      fmt.Println() // Satır atla
      fmt.Printf("Kalan taş sayısı: %d\n", len(*tiles)) // TileBag'deki taş sayısını yazdır

      return player // Oyuncuya verilen taşlar döndürülür
  }
        

GetRandomIndicatorFromTiles Fonksiyonu

Parametre (tiles) – TileBag referansı
Oyun başında rastgele gösterge taşı seçimi yapılacak taş torbası. Fonksiyon bu taş torbası üzerinden rastgele geçerli bir taş (joker olmayan) seçecektir.
Kullanımı – Amaç
  • Okey oyununda başlangıç gösterge taşını güvenli şekilde belirlemek için kullanılır.
  • Joker olmayan taşlar arasından kriptografik olarak güvenli rastgele seçim yapar.
  • Seçilen taş, gösterge taşı olarak işaretlenir ve TileBag’den çıkarılır.
  • Kodun sonunda seçilen taş `indicator` olarak döndürülür.
  func (tiles *TileBag) GetRandomIndicatorFromTiles() Model.Tile {
      validTiles := make([]Model.Tile, 0) // Joker olmayan taşlar için boş bir liste oluştur

      for _, tile := range *tiles {
          if !tile.IsJoker {
              validTiles = append(validTiles, tile) // Joker olmayanları ekle
          }
      }

      if len(validTiles) == 0 {
          log.Fatal("TileBag contains no valid (non-Joker) tiles for indicator selection")
      }

      max := big.NewInt(int64(len(validTiles))) // Liste boyutunu BigInt olarak al
      n, err := rand.Int(rand.Reader, max)      // Rastgele index üret (crypto güvenli)
      if err != nil {
          log.Fatalf("crypto/rand failed: %v", err) // Hata varsa programı durdur
      }

      randomIndex := int(n.Int64()) // Rastgele index'e karşılık gelen taş alınır
      indicator := validTiles[randomIndex]

      DropTileFromTiles((*[]Model.Tile)(tiles), indicator) // Seçilen taş torbadan çıkarılır

      return indicator // Gösterge taşı döndürülür
  }
        

TakeOneFromBag Fonksiyonu

Parametre (tiles) – Taş torbası (TileBag)
Taş çekiminin yapılacağı mevcut taş torbasıdır. İçinden bir taş alınır ve kalanlar güncellenir.
Parametre (player) – Oyuncunun taş listesi
Çekilen taş, bu diziye (oyuncunun taşları) eklenir.
Kullanımı – Amaç
  • TileBag’den bir adet taş çeker.
  • Çekilen taşı oyuncunun eline ekler.
  • TileBag’in ilk elemanını çıkararak torbayı günceller.
  • Boş torba durumunda programı durdurur (log.Fatal).
  • Genellikle oyun sırasında bir oyuncunun ortadan taş çekmesi gibi işlemlerde kullanılır.
  func (tiles *TileBag) TakeOneFromBag(player *[]Model.Tile) Model.Tile {
      if len(*tiles) == 0 {
          log.Fatal("TileBag contains no valid (non-Joker) tiles for indicator selection") // Boşsa hata ver
      }

      var tile = (*tiles)[0]       // İlk taşı seç
      *tiles = (*tiles)[1:]        // TileBag'den çıkar
      *player = append(*player, tile) // Oyuncunun taş listesine ekle

      return tile                  // Seçilen taşı döndür
  }
        

TakeOneFromTable Fonksiyonu

Parametre (player) – Oyuncunun taş listesi
Oyuncuya ait mevcut taş dizisini temsil eder. Yeni taş bu diziye eklenecektir.
Parametre (tile) – Alınacak taş
Ortadan alınan ya da başka bir kaynaktan gelen taş. Bu taş oyuncunun eline eklenecektir.
Kullanımı – Amaç
  • Bir oyuncuya dış kaynaktan (örneğin masa ortası) taş verme işlemini yapar.
  • Gönderilen taşı oyuncunun taş listesine ekler.
  • Yardımcı bir fonksiyondur ve basit veri ekleme işlemi içerir.
  func TakeOneFromTable(player *[]Model.Tile, tile Model.Tile) {
      *player = append(*player, tile) // Taşı oyuncuya ekle
  }
        

DropTileFromTiles Fonksiyonu

Parametre (playerTiles) – Oyuncunun taş listesi
Oyuncunun elinde bulunan taşların dizisidir. İçinden bir taş çıkarılacaktır.
Parametre (dropTile) – Atılacak taş
Oyuncunun elinden çıkarmak istediği taşı temsil eder. Bu taşın `ID` değeri eşleşmelidir.
Kullanımı – Amaç
  • Bir oyuncunun elinden belirli bir taşı (`dropTile`) çıkarmak için kullanılır.
  • Taş `ID` değeriyle eşleştiğinde listeden silinir.
  • Taş başarılı şekilde silinirse true, bulunamazsa false döner.
  • Listeyi manuel olarak güncellemek yerine bu fonksiyon güvenli ve kontrol edilebilir silme sunar.
  func DropTileFromTiles(playerTiles *[]Model.Tile, dropTile Model.Tile) bool {
      var isFound bool = false                      // Taşın bulunup bulunmadığını tutar

      for i, tile := range *playerTiles {           // Oyuncunun elindeki taşları döngüyle tara
          if tile.ID == dropTile.ID {               // ID eşleşiyorsa
              *playerTiles = append(                // Bu index'teki taşı çıkar
                  (*playerTiles)[:i],
                  (*playerTiles)[i+1:]...,
              )
              isFound = true                        // Bulundu ve silindi
              break
          }
      }

      return isFound                                // Sonuç olarak true veya false döndür
  }
        

FloatPtr Fonksiyonu

Parametre (f) – float64 türünde bir sayı
Bellekte işaretçisini almak istediğimiz ondalıklı sayıdır.
Kullanımı – Amaç
  • Bir `float64` sayının işaretçisini döndürür.
  • Struct gibi yapılarda opsiyonel alanlar pointer olarak tutulmak istenirse bu fonksiyon kullanılır.
  • Kodda sabit ya da literal float değerlerin kolayca pointer'a çevrilmesini sağlar (örn: `FloatPtr(3.14)`).
  • Yardımcı (utility) fonksiyondur ve genellikle veri modellerinde null/boş olasılıklı alanlar için kullanılır.
  func FloatPtr(f float64) *float64 {
      return &f // f'nin adresini döndür (pointer)
  }
        

IntPtr Fonksiyonu

Parametre (i) – int türünde bir değer
Pointer’a çevrilmek istenen tamsayı değeridir.
Kullanımı – Amaç
  • Bir `int` sayının bellek adresini (işaretçisini) döndürür.
  • Struct yapılarında opsiyonel `int` alanlarını tanımlamak için kullanılır.
  • Fonksiyonlara doğrudan integer pointer göndermek gerektiğinde pratiklik sağlar.
  • Örnek: IntPtr(5)*int türünde dönüş sağlar.
  func IntPtr(i int) *int {
      return &i // i'nin adresini döndür
  }
        

BoolPtr Fonksiyonu

Parametre (b) – bool türünde bir değer
Pointer’a çevrilmek istenen boolean (true/false) değeri.
Kullanımı – Amaç
  • Bir `bool` (mantıksal) değerin adresini döndürür.
  • Genellikle opsiyonel ayarlar, tercihler veya JSON/DB veri modellerinde null olabilen boolean alanlar için kullanılır.
  • True veya false değerleri işaretçi olarak başka yapılara aktarılabilir.
  • Örnek: BoolPtr(true)*bool tipinde sonuç verir.
  func BoolPtr(b bool) *bool {
      return &b // b değerinin adresini döndür
  }
        

ResetGame Fonksiyonu

Global Değişken: Game
`GameGroupState` türünden global bir değişkendir. Oyun grubu ile ilgili genel durumu temsil eder.
Fonksiyon: ResetGame()
  • Global Game değişkenini sıfırlamak için kullanılır.
  • GroupIDCounter alanını 0 yaparak, yeni bir oyun oturumu için başlangıç durumu sağlar.
  • Yeni bir oyun başlatıldığında, önceki oyunla ilgili veriler temizlenmiş olur.
  • Uygulama içinde global oyun durumu takibi için ideal bir başlangıç fonksiyonudur.
  var Game GameGroupState

  func ResetGame() {
      Game = GameGroupState{
          GroupIDCounter: 0, // Sayacı sıfırla
      }
  }
        

Game & GameGroupState Yapısı

Global Değişken: Game
`Game`, uygulama içinde merkezi olarak tanımlanan bir global değişkendir. Tipi GameGroupState olup oyun grubu durumunu takip eder.
Yapı: GameGroupState
Oyun grupları ile ilgili yönetimi sağlayan bir veri yapısıdır. Aşağıdaki alanı içerir:
  • GroupIDCounter (int) – Oyun gruplarına benzersiz ID atamak için kullanılan sayaçtır. Her yeni grup oluşturulduğunda artırılır.
Kullanımı – Amaç
  • Sunucudaki tüm oyun gruplarının kontrolü merkezi olarak `Game` değişkeniyle yapılır.
  • GroupIDCounter, benzersiz grup kimlikleri üretmek için kullanılır.
  • ResetGame() veya GenerateGroupID() gibi fonksiyonlarla birlikte çalışır.
  • Çok oyunculu sistemlerde oturum ve grup yönetimini kolaylaştırır.
  // Global oyun durumu
  var Game GameGroupState

  // Oyun grup bilgilerini tutar
  type GameGroupState struct {
      GroupIDCounter int // Grup ID üretimi için sayaç
  }
        

GenerateGroupID Fonksiyonu

Parametre (g *GameGroupState)
`GameGroupState` yapısına ait bir referanstır. Bu fonksiyon struct üzerinden çağrılır.
Kullanımı – Amaç
  • Her yeni oyun grubu için benzersiz bir grup ID'si üretir.
  • GroupIDCounter sayacını bir artırır ve yeni değeri döner.
  • Çok oyunculu sistemlerde her oyuncu grubunu ayırt etmek için kullanılır.
  • Global Game nesnesi üzerinden çağrılır: Game.GenerateGroupID()
  func (g *GameGroupState) GenerateGroupID() int {
      g.GroupIDCounter++             // Sayaç 1 artırılır
      return g.GroupIDCounter        // Yeni grup ID değeri döndürülür
  }
        

IsValidGroupOrRun Fonksiyonu

Parametre (tiles) – Taş dizisi
Kontrol edilecek taş dizisi. Her taş Model.Tile türündedir.
Kullanımı – Amaç
  • Okey oyununda 3 veya daha fazla taştan oluşan bir dizinin geçerli olup olmadığını kontrol eder.
  • Geçerli dizi koşulları: Grup (aynı sayı, farklı renk) veya Sıralı Seri (aynı renk, ardışık sayılar).
  • Okey (joker) taşları varsa, bu taşlar eksik taşların yerine sayılır.

func IsValidGroupOrRun(tiles []*Model.Tile) bool {
    if len(tiles) < 3 {
        return false
    }

    okeyCount := countOkeys(tiles)               // Joker (okey) taşlarını sayar
    nonOkeyTiles := filterNonOkeys(tiles)        // Gerçek taşları ayıklar

    // Grup veya sıralı dizi kontrolü yapılır
    return isGroup(nonOkeyTiles, okeyCount) || isSequence(nonOkeyTiles, okeyCount)
}
      

isGroup Fonksiyonu

Parametre (tiles) – Gerçek taşlar
Joker olmayan taşların dizisidir. Aynı sayı ve farklı renk şartı burada kontrol edilir.
Parametre (okeyCount) – Joker sayısı
Eksik taşları tamamlamak için kullanılabilecek joker (okey) taşı sayısı.
Kullanımı – Amaç
  • Aynı sayıya sahip ama farklı renklere ait taşlardan oluşan geçerli bir “grup” dizisinin doğruluğunu kontrol eder.
  • Joker taşları, eksik olan renkleri tamamlamak için gruba sayılabilir.
  • Geçerli olması için grup toplamı en az 3 taş olmalıdır.

// Örnek: Kırmızı 5, Mavi 5, Sarı 5
func isGroup(tiles []*Model.Tile, okeyCount int) bool {
    if len(tiles) == 0 {
        return false
    }

    number := tiles[0].Number               // Tüm taşların bu sayıya sahip olması gerekir
    colors := make(map[int]bool)           // Kullanılan renkleri takip etmek için map

    for _, tile := range tiles {
        if tile.Number != number || colors[tile.Color] {
            return false                   // Farklı sayı veya tekrar eden renk varsa geçersiz
        }
        colors[tile.Color] = true
    }

    return len(tiles) + okeyCount >= 3     // Toplam (taş + joker) en az 3 olmalı
}
      

isSequence Fonksiyonu

Parametre (tiles) – Gerçek taşlar
Joker olmayan taşların dizisidir. Sıralı ve aynı renk kontrolü burada yapılır.
Parametre (okeyCount) – Joker sayısı
Sıralamada eksik taşları tamamlamak için kullanılabilecek okey (joker) sayısı.
Kullanımı – Amaç
  • Taşların sıralı ve aynı renkten olup olmadığını kontrol eder (örnek: Siyah 3-4-5).
  • Taşlar sıralı olmasa bile, fonksiyon sıralayıp kontrol yapar.
  • Eksik taşlar varsa, belirtilen okey (joker) sayısı kadar tamamlamaya izin verir.
  • Toplam taş sayısı (joker dahil) 3’ten az ise geçersiz kabul edilir.

// Örnek: Siyah 3, Siyah 4, Siyah 5
func isSequence(tiles []*Model.Tile, okeyCount int) bool {
    if len(tiles) == 0 {
        return false
    }

    // Aynı renkte değillerse seri olamaz
    if !allSameColor(tiles) {
        return false
    }

    // Sayı sıralamasına göre sırala
    sort.Slice(tiles, func(i, j int) bool {
        return tiles[i].Number < tiles[j].Number
    })

    // Eksik taşlar için gereken joker sayısını hesapla
    neededOkeys := calculateNeededOkeysForRun(tiles, okeyCount)

    // Joker yetmiyorsa veya toplam sayı yetersizse geçersiz
    return neededOkeys <= okeyCount && len(tiles) + okeyCount >= 3
}
      

calculateNeededOkeysForRun Fonksiyonu

Parametre (tiles) – Sıralı taşlar
Joker olmayan ve sıralanmış taşların listesi. Fonksiyon aradaki boşlukları tespit etmek için kullanır.
Parametre (maxOkeys) – Maksimum izin verilen joker sayısı
Gerek duyulacak joker (okey) sayısının bu değeri aşması durumunda geçersiz kombinasyon kabul edilir.
Kullanımı – Amaç
  • Sıralı taşlar arasında eksik olan (boşluklu) sayıları tespit eder.
  • Her bir boşluk için 1 veya daha fazla joker gerekiyorsa bu sayı `neededOkeys` olarak hesaplanır.
  • Fark 1 ise sorun yok; fark 2 ise 1 joker, fark 3 ise 2 joker gerekir.
  • Fark 3’ten büyükse yapı geçersiz kabul edilir ve `maxOkeys + 1` döndürülür.

func calculateNeededOkeysForRun(tiles []*Model.Tile, maxOkeys int) int {
    neededOkeys := 0
    for i := 1; i < len(tiles); i++ {
        diff := tiles[i].Number - tiles[i-1].Number
        switch diff {
        case 1:
            continue // Arada boşluk yoksa
        case 2:
            neededOkeys++ // 1 boşluk → 1 joker gerekir
        case 3:
            neededOkeys += 2 // 2 boşluk → 2 joker gerekir
        default:
            return maxOkeys + 1 // Çok büyük boşluk varsa geçersiz
        }
    }
    return neededOkeys
}
      

countOkeys Fonksiyonu

Parametre (tiles) – Taş dizisi
Oyun sırasında kontrol edilen taşların bulunduğu slice’dır. Her bir taşın okey olup olmadığı incelenir.
Kullanımı – Amaç
  • Verilen taşlar içinde kaç adet IsOkey = true olan taş olduğunu sayar.
  • Seri ve grup kontrollerinde, eksik taşların yerine joker kullanımı için gereklidir.
  • Fonksiyon, toplam joker (gerçek okey) sayısını geri döner.

func countOkeys(tiles []*Model.Tile) int {
    count := 0
    for _, tile := range tiles {
        if tile.IsOkey {
            count++
        }
    }
    return count
}
      

filterNonOkeys Fonksiyonu

Parametre (tiles) – Taş dizisi
Bu parametre, oyuncunun elindeki tüm taşları (joker dahil) içeren slice'tır.
Kullanımı – Amaç
  • Elinizdeki taşlar arasından IsOkey = true olanları hariç tutarak, yalnızca normal taşları döner.
  • Seri (run) ve grup kontrollerinde sadece gerçek taşlarla kontrol yapılmasını sağlar.
  • Fonksiyonun çıktısı, joker (okey) olmayan taşlardan oluşan bir slice’tır.

func filterNonOkeys(tiles []*Model.Tile) []*Model.Tile {
    result := make([]*Model.Tile, 0, len(tiles))
    for _, tile := range tiles {
        if !tile.IsOkey {
            result = append(result, tile)
        }
    }
    return result
}
      

allSameColor Fonksiyonu

Parametre (tiles) – Taş dizisi
Bu parametre, kontrol edilecek olan taş grubunu temsil eder. Her taşın rengi incelenir.
Kullanımı – Amaç
  • Tüm taşların aynı renge sahip olup olmadığını kontrol eder.
  • Seri (run) setlerinin doğrulanmasında kullanılır, çünkü seri aynı renkte olmalıdır.
  • Hiç taş yoksa (boş slice) true döner, çünkü renk çelişkisi oluşmaz.
  • İlk taşın rengi referans alınır ve diğer tüm taşlarla karşılaştırılır.

func allSameColor(tiles []*Model.Tile) bool {
    if len(tiles) == 0 {
        return true
    }
    color := tiles[0].Color
    for _, tile := range tiles {
        if tile.Color != color {
            return false
        }
    }
    return true
}
      

CalculateTileScore Fonksiyonu

Parametreler
  • tile: Değeri hesaplanacak taş
  • index: Bu taşın bulunduğu pozisyon
  • tiles: Grubu oluşturan taş dizisi
  • isSequence: Taşlar bir sequence (seri) mi yoksa group (grup) mu belirtir
Amaç ve Kullanımı
  • Bu fonksiyon, joker/okey taşlarının hangi değeri temsil ettiğini hesaplar.
  • Grup ise: Tüm taşların sayıları aynı olmalı. İlk gerçek taşın number değeri alınır.
  • Sıralı set ise: Eksik sıra aralığı bulunarak okey’in değeri tahmin edilir.
  • Hiç okey yoksa, normal taşın kendi değeri döndürülür.
  • 1 ile 13 aralığı sınır olarak kabul edilir. Sona eklenemeyen taş başa koyulabilir.

func CalculateTileScore(tile *Model.Tile, index int, tiles []*Model.Tile, isSequence bool) int {
    if !tile.IsOkey {
        return tile.Number
    }

    if !isSequence {
        for _, t := range tiles {
            if !t.IsOkey {
                return t.Number
            }
        }
        return tile.Number
    }

    nonOkeys := filterNonOkeys(tiles)
    if len(nonOkeys) == 0 {
        return 1
    }

    sort.Slice(nonOkeys, func(i, j int) bool {
        return nonOkeys[i].Number < nonOkeys[j].Number
    })

    numbers := []int{}
    for _, t := range nonOkeys {
        numbers = append(numbers, t.Number)
    }

    for i := 0; i < len(numbers)-1; i++ {
        if numbers[i+1]-numbers[i] > 1 {
            return numbers[i] + 1
        }
    }

    if numbers[len(numbers)-1] < 13 {
        if index == 0 {
            return numbers[0] - 1
        } else {
            return numbers[len(numbers)-1] + 1
        }
    }

    if numbers[0] > 1 {
        return numbers[0] - 1
    }

    return 1
}
      

CanOpenTiles Fonksiyonu

Parametreler
  • opened: Açılmak istenen taş gruplarını içeren 2D dizi ([][]*Model.Tile)
Amaç ve Kullanımı
  • Okey 101 oyununda bir oyuncunun taşları açabilmesi için, toplam puanının 101 veya üzeri olması gerekir.
  • Bu fonksiyon, açılmak istenen taşların her birini kontrol eder.
  • Açık taş (IsOpend) içeren gruplar geçersiz sayılır.
  • Her grup geçerli group ya da sequence olmalıdır. Aksi halde işlem iptal edilir.
  • Geçerli grupların her biri CalculateTileScore ile puanlanır ve toplam puan hesaplanır.
  • Eğer toplam puan 101 veya üzeri ise, taşlar SetOpentiles ile açılmış olarak işaretlenir.
  • Fonksiyon sonucunda işlem geçerli ise true, aksi durumda false döner.

func CanOpenTiles(opened [][]*Model.Tile) bool {
    totalScore := 0
    for _, group := range opened {

        // İçlerinde zaten açılmış taş varsa hata döner
        if HasOpenTail(group...) {
            return false
        }

        // Grup geçerli mi kontrol edilir
        if !IsValidGroupOrRun(group) {
            return false
        }

        isSeq := isSequence(filterNonOkeys(group), countOkeys(group))
        for index, tile := range group {
            totalScore += CalculateTileScore(tile, index, group, isSeq)
        }
    }

    var result = totalScore >= 101

    // Eğer toplam skor uygunsa, taşları açık olarak işaretle
    if result {
        SetOpentiles(opened)
    }

    return result
}
      

CanOpenTilesWithRemaining Fonksiyonu

Parametreler
  • tiles: Oyuncunun elindeki tüm taşlar ([]*Model.Tile)
  • opened: Açılmak istenen taş grupları ([][]*Model.Tile)
Amaç ve Kullanımı
  • Oyuncunun açmak istediği taş gruplarının geçerli olup olmadığını kontrol eder.
  • Her grup için:
    • İçinde önceden açılmış taş varsa false döner.
    • Geçerli bir grup (group/run) değilse işlem iptal edilir.
  • Her taş için CalculateTileScore fonksiyonu ile skor hesaplanır.
  • Toplam skor 0’dan büyükse, elde kalan taşlar getRemainingInOpenedTiles ile bulunur.
  • SetOpentiles çağrısı bilinçli olarak iptal edilmiştir. (Bayram’ın isteğiyle)
Dönüş Değerleri
  • remaining: Açılmayan, elde kalan taşlar
  • score: Açılan taşlardan elde edilen toplam skor
  • error: Taşlar başarılı şekilde açılabildiyse true, aksi halde false

func CanOpenTilesWithRemaining(tiles []*Model.Tile, opened [][]*Model.Tile) (remaining []*Model.Tile, score int, error bool) {
    totalScore := 0
    var remainList []*Model.Tile

    for _, group := range opened {
        if HasOpenTail(group...) {
            return remainList, 0, false
        }

        if !IsValidGroupOrRun(group) {
            return remainList, 0, false
        }

        isSeq := isSequence(filterNonOkeys(group), countOkeys(group))
        for index, tile := range group {
            totalScore += CalculateTileScore(tile, index, group, isSeq)
        }
    }

    var result = totalScore > 0

    if result {
        remainList = getRemainingInOpenedTiles(tiles, opened)
    }

    return remainList, totalScore, result
}
      

CanOpenTilesWithRemainingWithAllGroups Fonksiyonu

Parametreler
  • groups: Oyuncunun elindeki taşlar, gruplanmış olarak ([][]*Model.Tile)
Amaç ve Kullanımı
  • Elimizdeki tüm grupları değerlendirerek hangilerinin açılabilir (geçerli) olduğunu belirler.
  • Her grup için:
    • İçinde daha önce açılmış taş varsa işlem iptal edilir.
    • Geçerli değilse remainList listesine alınır.
    • Geçerliyse, CalculateTileScore ile skor hesaplanır ve openedList listesine eklenir.
  • totalScore > 0 ise başarılı kabul edilir.
  • Not: Önceden SetOpentiles çağrılırken, Bayram’ın isteğiyle bu işlem kaldırılmıştır.
Dönüş Değerleri
  • opened: Geçerli olarak açılan taş grupları
  • remaining: Geçersiz kalan taş grupları (elde kalanlar)
  • score: Açılan taşlardan elde edilen toplam puan
  • error: Başarı durumu – geçerli set varsa true, yoksa false

func CanOpenTilesWithRemainingWithAllGroups(groups [][]*Model.Tile) 
    (opened [][]*Model.Tile, remaining [][]*Model.Tile, score int, error bool) {

    totalScore := 0
    var remainList [][]*Model.Tile
    var openedList [][]*Model.Tile

    for _, group := range groups {
        if HasOpenTail(group...) {
            return openedList, remainList, 0, false
        }

        if !IsValidGroupOrRun(group) {
            remainList = append(remainList, group)
        } else {
            openedList = append(openedList, group)
            isSeq := isSequence(filterNonOkeys(group), countOkeys(group))
            for index, tile := range group {
                totalScore += CalculateTileScore(tile, index, group, isSeq)
            }
        }
    }

    var result = totalScore > 0
    return openedList, remainList, totalScore, result
}
      

getRemainingInOpenedTiles Fonksiyonu

Parametreler
  • tiles: Oyuncunun elindeki tüm taşlar
  • opened: Açılmış taş grupları ([][]*Model.Tile)
Amaç ve Kullanımı
  • Bu fonksiyon, oyuncunun elindeki taşlardan hangilerinin henüz açılmadığını bulmak için kullanılır.
  • Önce opened listesindeki taşları renk ve numaraya göre used map’inde tutar.
  • Sonra, tiles listesindeki her taşı kontrol ederek:
    • Eğer o taş daha önce açılmışsa, kullanılmış listeden düşer.
    • Eğer hiç kullanılmamışsa, remainList'e eklenir.
  • Sonuçta geriye kalan (kullanılmamış) taşlar döndürülür.
Dönüş Değeri
  • remaining: Açılmamış, elde kalan taşlar listesi

func getRemainingInOpenedTiles(tiles []*Model.Tile, opened [][]*Model.Tile) (remaining []*Model.Tile) {
    type pairKey struct {
        Color  int
        Number int
    }

    used := make(map[pairKey][]*Model.Tile)
    var remainList []*Model.Tile

    for _, group := range opened {
        for _, tile := range group {
            key := pairKey{Color: tile.Color, Number: tile.Number}
            used[key] = append(used[key], tile)
        }
    }

    for _, tile := range tiles {
        key := pairKey{Color: tile.Color, Number: tile.Number}
        if usedList, ok := used[key]; ok && len(usedList) > 0 {
            used[key] = usedList[1:]
        } else {
            remainList = append(remainList, tile)
        }
    }

    return remainList
}
      

SetOpentiles Fonksiyonu

Parametreler
  • opened [][]*Model.Tile: Açılmış tüm grup veya sıra taşlarının 2D dizisi.
Amaç ve Kullanımı
  • Bu fonksiyon, geçerli bir hamlede (örneğin ilk açma sırasında) 101 puanı geçen tüm taşları açık hale getirir.
  • Her bir grup (set) için ayrı GroupID tanımlanır.
  • Her taşın IsOpend özelliği true yapılır ve GroupID referansı atanır.
Ne Zaman Çağrılır?
  • CanOpenTiles fonksiyonunda, eğer oyuncunun toplam puanı 101 ve üzeri ise çağrılır.
  • Oyuncunun masaya açtığı tüm setlerin oyun alanına yerleştirildiğini göstermek için kullanılır.

func SetOpentiles(opened [][]*Model.Tile) {
    for _, group := range opened {
        //101'i geçen elde açılan tüm array gruplara ayrı ayrı unique groupID tanımlanır.
        var groupID = Game.GenerateGroupID()
        for _, tile := range group {
            tile.IsOpend = true
            tile.GroupID = &groupID
        }
    }
}
      

SetOpenPairtiles Fonksiyonu

Parametreler
  • setTiles []*Model.Tile: Açılacak çift taşları içeren dilim.
  • grpID ...int: (Opsiyonel) Eğer verildiyse, taşlara atanacak olan mevcut bir GroupID.
Amaç ve Kullanımı
  • Çift olarak açılmış taşları (pair) masa üzerine açık set olarak işaretler.
  • Eğer bir GroupID parametre olarak verilirse, o ID kullanılır.
  • Eğer parametre verilmezse, yeni bir GroupID otomatik olarak üretilir.
  • Tüm taşların IsOpend alanı true yapılır.
  • GroupID referansı taşlara atanır.
Ne Zaman Çağrılır?
  • Oyuncunun çift taşları (pair) masa üzerine açması durumunda çağrılır.
  • Özellikle CanAddPairToPairSets veya CanAddTilesToSet gibi fonksiyonlarda kullanılır.
  • Yeni açılan çiftlerin açık olarak kabul edilmesini sağlar.

func SetOpenPairtiles(setTiles []*Model.Tile, grpID ...int) {
    var groupID int
    if len(grpID) > 0 {
        groupID = grpID[0]
    } else {
        groupID = Game.GenerateGroupID()
    }
    for _, tile := range setTiles {
        tile.IsOpend = true
        tile.GroupID = &groupID
    }
}
      

HasOpenTail Fonksiyonu

Parametreler
  • tiles ...*Model.Tile: Kontrol edilecek taşların listesi (variadic parametre olarak gönderilir).
Amaç ve Kullanımı
  • Bu fonksiyon, verilen taşlar arasında daha önce açılmış (oyuna dahil edilmiş) bir taş olup olmadığını kontrol eder.
  • Eğer taşlardan herhangi birinin IsOpend alanı true ise true döner.
  • Hiçbir taş daha önce açılmamışsa, sonuç false olur.
Ne Zaman Kullanılır?
  • Oyuncunun açılmış taşları tekrar kullanmasını engellemek için.
  • Örneğin: CanOpenTiles, CanAddTilesToSet, IsValidPair gibi fonksiyonlarda kontrol mekanizması olarak çağrılır.

func HasOpenTail(tiles ...*Model.Tile) bool {
    for _, tile := range tiles {
        if tile.IsOpend {
            return true
        }
    }
    return false
}
      

HasAtLeastFivePairs Fonksiyonu

Parametreler
  • opened [][]*Model.Tile: Oyuncunun açmak istediği çiftlerden oluşan liste.
Amaç ve Kullanımı
  • Oyuncunun açmak istediği çiftleri değerlendirerek, geçerli olup olmadıklarını kontrol eder.
  • Toplamda en az 5 geçerli çift varsa true döner, aksi halde false.
  • Geçerli çift, sayıların eşleştiği ve en az birinin rengi aynı veya okey olması durumudur.
  • İçinde sahte okeyten (joker) oluşan bir çift varsa veya taş zaten açılmışsa fonksiyon false döner.
Ek Davranış
  • Geçerli çift sayısı 5 veya daha fazlaysa, bu çiftler SetOpentiles fonksiyonu ile açılmış olarak işaretlenir.

func HasAtLeastFivePairs(opened [][]*Model.Tile) bool {
    pairCount := 0

    for _, group := range opened {
        if len(group) == 2 {
            tile1, tile2 := group[0], group[1]

            if HasOpenTail(tile1, tile2) {
                return false
            }

            if tile1.IsJoker && tile2.IsJoker {
                return false
            }

            score1 := CalculateTileScore(tile1, 0, group, false)
            score2 := CalculateTileScore(tile2, 1, group, false)

            if score1 == score2 {
                if tile1.IsOkey || tile2.IsOkey || tile1.Color == tile2.Color {
                    pairCount++
                } else {
                    return false
                }
            } else {
                return false
            }
        }
    }

    var result = pairCount >= 5
    if result {
        SetOpentiles(opened)
    }
    return result
}
      

HasAtLeastFivePairsForSetNewPair Fonksiyonu

Parametreler
  • opened [][]*Model.Tile: Oyuncunun açmak üzere hazırladığı çift (pair) setleri
Amaç ve Kullanımı
  • Oyuncunun elindeki çift sayısının 5 veya daha fazla olup olmadığını kontrol eder.
  • Geçerli bir çift, aynı sayıya sahip taşlar olup, aynı renkte olmaları veya en az birinin okey olması gerekir.
  • Eğer her iki taş da joker (sahte okey) ise çift geçersiz sayılır.
  • Bu fonksiyon taşlar açılmaz, yalnızca kontrol yapılır. (Yani SetOpentiles çağrısı yoktur.)
Notlar
  • HasAtLeastFivePairs fonksiyonuna benzer, fakat burada taşlar açılmaz (işaretlenmez).
  • Yeni eşleşme eklenmeden önce kural kontrolü için kullanılır.

func HasAtLeastFivePairsForSetNewPair(opened [][]*Model.Tile) bool {
    pairCount := 0

    for _, group := range opened {
        if len(group) == 2 {
            tile1, tile2 := group[0], group[1]

            if tile1.IsJoker && tile2.IsJoker {
                return false
            }

            score1 := CalculateTileScore(tile1, 0, group, false)
            score2 := CalculateTileScore(tile2, 1, group, false)

            if score1 == score2 {
                if tile1.IsOkey || tile2.IsOkey || tile1.Color == tile2.Color {
                    pairCount++
                } else {
                    return false
                }
            } else {
                return false
            }
        }
    }

    var result = pairCount >= 5
    return result
}
      

CanAddTilesToSet Fonksiyonu

Parametreler
  • set []*Model.Tile: Var olan açık taş grubu
  • tiles ...*Model.Tile: Bu gruba eklenmek istenen 1 veya 2 yeni taş
Amaç ve Kullanımı
  • Var olan açık bir taş grubuna, yeni taşların eklenip eklenemeyeceğini kontrol eder.
  • Eklenmek istenen taşlar en fazla 2 adet olmalıdır ve zaten açık olmamalıdır.
  • Yeni taşlarla oluşturulacak birleşik grup geçerli bir Group (aynı sayı, farklı renk) veya Sequence (aynı renk, artan sıra) olmalıdır.
  • Eğer geçerli ise, grup ID ile birlikte tüm taşlar açık olarak işaretlenir.
Notlar
  • SetOpenPairtiles çağrısı ile orijinal grubun GroupID değeri yeni taşlara da atanır.
  • Oyun kurallarına göre grup büyütme işlemleri buradan kontrol edilir.

func CanAddTilesToSet(set []*Model.Tile, tiles ...*Model.Tile) bool {
    if len(tiles) == 0 || len(set) == 0 || len(tiles) > 2 || len(set) < 3 {
        return false
    }

    if HasOpenTail(tiles...) {
        return false
    }

    newSet := append([]*Model.Tile{}, set...)
    newSet = append(newSet, tiles...)

    var result = IsValidGroupOrRun(newSet)
    if result {
        SetOpenPairtiles(newSet, *set[0].GroupID)
    }
    return result
}
      

TryAddTilesToSet Fonksiyonu

Parametreler
  • set *[]*Model.Tile: Ek yapılacak mevcut açık taş grubu (referans ile)
  • tiles ...*Model.Tile: Bu gruba eklenmek istenen 1 veya 2 yeni taş
Amaç ve Kullanımı
  • Bu fonksiyon, taş grubuna yeni taş eklenme denemesini gerçekleştirir.
  • Yeni taşlarla birlikte grup geçerli (valid group/run) olursa:
    • Gerçek gruba ekleme yapılır.
    • Yeni taşlar SetOpenPairtiles ile açılmış olarak işaretlenir.
    • Taşlar etkili numaraya göre sıralanır.
  • Eğer grup geçerli değilse değişiklik yapılmaz.
Kritik Kontroller
  • HasOpenTail: Eklenecek taşların daha önce açılıp açılmadığını kontrol eder.
  • IsValidGroupOrRun: Güncel grup kurallara uygun mu?
  • sortGroupByEffectiveNumber: Jokerler ve okeylerin mantıksal sıralamasını düzenler.

func TryAddTilesToSet(set *[]*Model.Tile, tiles ...*Model.Tile) bool {
    if len(tiles) == 0 || len(*set) == 0 || len(tiles) > 2 || len(*set) < 3 {
        return false
    }

    if HasOpenTail(tiles...) {
        return false
    }

    newSet := append([]*Model.Tile{}, *set...)
    newSet = append(newSet, tiles...)

    if IsValidGroupOrRun(newSet) {
        *set = append(*set, tiles...)
        SetOpenPairtiles(*set, *(*set)[0].GroupID)
        *set = sortGroupByEffectiveNumber(*set)
        return true
    }
    return false
}
      

IsValidPair Fonksiyonu

Parametreler
  • tiles []*Model.Tile: Kontrol edilmek istenen potansiyel çift taşlar
Amaç ve Kullanımı
  • Gönderilen iki taşın geçerli bir çift (pair) olup olmadığını belirler.
  • Oyun kuralları çerçevesinde “çift açmak” isteyen oyuncular için kullanılır.
  • Taşlar doğru koşulları sağlıyorsa true döner.
Geçerlilik Kuralları
  • Mutlaka 2 taş olmalıdır.
  • Taşlar önceden açılmış olmamalıdır (HasOpenTail kontrolü).
  • İkisi de sahte okey (joker) olamaz.
  • Her taş için CalculateTileScore ile hesaplanan değer eşit olmalıdır.
  • Değerler eşitse, taşlar aynı renk olmalı ya da en az biri okey olmalıdır.

func IsValidPair(tiles []*Model.Tile) bool {
    if len(tiles) != 2 {
        return false
    }

    if HasOpenTail(tiles...) {
        return false
    }

    tile1, tile2 := tiles[0], tiles[1]

    if tile1.IsJoker && tile2.IsJoker {
        return false
    }

    score1 := CalculateTileScore(tile1, 0, tiles, false)
    score2 := CalculateTileScore(tile2, 1, tiles, false)

    if score1 != score2 {
        return false
    }

    return tile1.IsOkey || tile2.IsOkey || tile1.Color == tile2.Color
}
      

CanAddPairToPairSets Fonksiyonu

Parametreler
  • remaining []*Model.Tile: Eklenmek istenen 2'li taş çifti
  • pairSets [][]*Model.Tile: Oyuncunun önceden açmış olduğu çift setleri
Amaç ve Kullanımı
  • Yeni bir taş çiftinin mevcut çift setlerine eklenip eklenemeyeceğini kontrol eder.
  • Eklenen çift, oyun kurallarına uygun olmalı ve tüm çiftlerin sayısı en az 5 olmalıdır.
  • Kurallar sağlanıyorsa taşlara IsOpend = true atanır ve GroupID belirlenir.
Kontrol ve Koşullar
  • IsValidPair fonksiyonu ile çift geçerliliği kontrol edilir.
  • HasAtLeastFivePairsForSetNewPair ile tüm çiftlerin sayısı en az 5 mi bakılır.
  • Bu kurallar sağlanıyorsa SetOpenPairtiles ile taşlar işaretlenir.

func CanAddPairToPairSets(remaining []*Model.Tile, pairSets [][]*Model.Tile) bool {
    if IsValidPair(remaining) {
        var result = HasAtLeastFivePairsForSetNewPair(pairSets)
        if result {
            SetOpenPairtiles(remaining)
        }
        return result
    }
    return false
}
      

CanThrowingTileBeAddedToOpponentSets Fonksiyonu

Parametreler
  • newPair *Model.Tile: Atılmak istenen taş
  • opponentSets [][]*Model.Tile: Rakibin mevcut açık setleri
Amaç ve Kullanımı
  • Oyuncunun attığı bir taşın, rakibin açık setlerine uygun olup olmadığını kontrol eder.
  • Taş, daha önce açılmışsa tekrar kullanılamaz.
  • Her bir rakip seti için CanAddTilesToSet fonksiyonu çağrılarak uygunluk kontrol edilir.
Koşullar ve Sonuç
  • Taş IsOpend durumundaysa false döner (yani tekrar oynanamaz).
  • Rakip setlerinden en az birine eklenebiliyorsa true döner.
  • Hiçbir sete eklenemiyorsa false döner.

func CanThrowingTileBeAddedToOpponentSets(newPair *Model.Tile, opponentSets [][]*Model.Tile) bool {
    if newPair.IsOpend {
        //Acilan tas bir daha atilamaz.
        return false
    }
    for _, set := range opponentSets {
        if CanAddTilesToSet(set, newPair) {
            return true
        }
    }
    return false
}
      

SplitTilesByValidGroupsOrRuns Fonksiyonu

Parametreler
  • tiles []*Model.Tile: Oyuncunun elindeki tüm taşlar.
  • maxGroupSizeOptional ...int: (Opsiyonel) Maksimum grup büyüklüğü. Belirtilmezse 5 alınır.
Fonksiyonun Amacı
  • Geçerli group veya sequence oluşturabilecek taş kombinasyonlarını bulur.
  • Oluşabilecek en iyi (en fazla taş ve en yüksek skor içeren) grupları seçer.
  • Kalan taşları ve toplam skoru da döner.
Kullanımı – Amaç
  • Oyuncunun elindeki taşları geçerli grup (aynı sayı farklı renk) veya sıralı set (aynı renk artan sayı) kombinasyonlarına ayırmak için kullanılır.
  • Okey taşlarını da değerlendirerek tüm geçerli olasılıkları dener.
  • Backtracking algoritması ile en fazla taş içeren ve en yüksek skoru getiren kombinasyonlar seçilir.
  • Kullanılamayan (açılamayan) taşlar ayrıca belirtilir.
Dönüş Değerleri
  • [][]*Model.Tile: En iyi seçilen geçerli taş grupları
  • []*Model.Tile: Kullanılamayan taşlar (geriye kalanlar)
  • int: Gruplardan elde edilen toplam puan

func SplitTilesByValidGroupsOrRuns(tiles []*Model.Tile, maxGroupSizeOptional ...int) ([][]*Model.Tile, []*Model.Tile, int) {
    n := len(tiles)
    maxGroupSize := 5
    if len(maxGroupSizeOptional) > 0 && maxGroupSizeOptional[0] > 0 {
        maxGroupSize = maxGroupSizeOptional[0]
    }
    if n < maxGroupSize {
        maxGroupSize = n
    }

    sort.Slice(tiles, func(i, j int) bool {
        if tiles[i].Color == tiles[j].Color {
            return tiles[i].Number < tiles[j].Number
        }
        return tiles[i].Color < tiles[j].Color
    })

    type candidate struct {
        Indices []int
        Group   []*Model.Tile
    }

    var allGroups []candidate

    for size := maxGroupSize; size >= 3; size-- {
        indices := make([]int, size)
        var generate func(start, depth int)
        generate = func(start, depth int) {
            if depth == size {
                group := make([]*Model.Tile, size)
                okeyCount := 0
                for i, idx := range indices {
                    tile := tiles[idx]
                    group[i] = tile
                    if tile.IsOkey {
                        okeyCount++
                    }
                }
                if okeyCount > 2 {
                    return
                }
                nonOkeys := filterNonOkeys(group)
                if isGroup(nonOkeys, okeyCount) || isSequence(nonOkeys, okeyCount) {
                    tmp := make([]*Model.Tile, len(group))
                    copy(tmp, group)
                    tmpIdx := make([]int, len(indices))
                    copy(tmpIdx, indices)
                    allGroups = append(allGroups, candidate{Indices: tmpIdx, Group: tmp})
                }
                return
            }
            for i := start; i <= n-(size-depth); i++ {
                indices[depth] = i
                generate(i+1, depth+1)
            }
        }
        generate(0, 0)
    }

    var (
        maxTilesUsed    int
        maxScore        int
        bestCombination [][]*Model.Tile
    )

    var backtrack func(start int, used map[int]bool, current [][]*Model.Tile)
    backtrack = func(start int, used map[int]bool, current [][]*Model.Tile) {
        usedCount := len(used)
        score := 0
        for _, group := range current {
            score += sumGroupScore(group)
        }
        if usedCount > maxTilesUsed || (usedCount == maxTilesUsed && score > maxScore) {
            maxTilesUsed = usedCount
            maxScore = score
            bestCombination = deepCopyGroups(current)
        }

        for i := start; i < len(allGroups); i++ {
            canUse := true
            for _, idx := range allGroups[i].Indices {
                if used[idx] {
                    canUse = false
                    break
                }
            }
            if !canUse {
                continue
            }
            for _, idx := range allGroups[i].Indices {
                used[idx] = true
            }
            backtrack(i+1, used, append(current, allGroups[i].Group))
            for _, idx := range allGroups[i].Indices {
                delete(used, idx)
            }
        }
    }

    backtrack(0, make(map[int]bool), [][]*Model.Tile{})

    usedIndices := make(map[*Model.Tile]bool)
    for _, group := range bestCombination {
        for _, tile := range group {
            usedIndices[tile] = true
        }
    }

    var remaining []*Model.Tile
    for _, tile := range tiles {
        if !usedIndices[tile] {
            remaining = append(remaining, tile)
        }
    }

    for i, g := range bestCombination {
        bestCombination[i] = sortGroupByEffectiveNumber(g)
    }

    return bestCombination, remaining, maxScore
}

deepCopyGroups Fonksiyonu

Parametreler
  • groups [][]*Model.Tile: Taş gruplarından oluşan iki boyutlu slice. Her bir grup sıralı veya grup olabilir.
Kullanımı – Amaç
  • Taş gruplarının bağımsız bir kopyasını üretir. Yani orijinal veri yapısını değiştirmeden, üzerinde işlem yapılabilecek yeni bir yapı oluşturur.
  • Özellikle backtracking algoritmalarında alternatif kombinasyonları denerken kullanılır.
  • Orijinal taşları etkilemeden alternatif çözümleri kıyaslamaya olanak tanır.
Dönüş Değeri
  • [][]*Model.Tile: Girdi olarak verilen taş gruplarının birebir kopyalanmış yeni hali.

func deepCopyGroups(groups [][]*Model.Tile) [][]*Model.Tile {
    copied := make([][]*Model.Tile, len(groups))
    for i := range groups {
        copied[i] = make([]*Model.Tile, len(groups[i]))
        copy(copied[i], groups[i])
    }
    return copied
}

sumGroupScore Fonksiyonu

Parametreler
  • group []*Model.Tile: Puanı hesaplanacak taş grubudur. Bu grup geçerli bir "run" (sıralı) ya da "group" (aynı sayı, farklı renk) olmalıdır.
Kullanımı – Amaç
  • Bir taş grubunun toplam skorunu hesaplar.
  • Grubun sıralı (sequence) mi yoksa grup (group) mu olduğunu analiz eder.
  • Okey veya joker taşların gerçek sayı değerlerini CalculateTileScore fonksiyonuyla tespit eder.
  • Toplam skoru geri döndürmek için her taşın değerini toplar.
  • Bu fonksiyon özellikle SplitTilesByValidGroupsOrRuns gibi fonksiyonların içinde en yüksek skorlu kombinasyonları belirlemek için kullanılır.
Dönüş Değeri
  • int: Verilen grubun toplam puanını döndürür. Her taşın hesaplanmış puanlarının toplamıdır.

func sumGroupScore(group []*Model.Tile) int {
    isSeq := isSequence(filterNonOkeys(group), countOkeys(group))
    total := 0
    for i, tile := range group {
        total += CalculateTileScore(tile, i, group, isSeq)
    }
    return total
}

sumAllGroupsNumbers Fonksiyonu

Parametreler
  • groups [][]*Model.Tile: Skoru toplanacak tüm geçerli taş gruplarının listesi. Her iç liste, tek bir grup ya da sıralı seti temsil eder.
Kullanımı – Amaç
  • Tüm taş gruplarındaki taşların değerlerinin toplamını döner.
  • Her grup için sırayla CalculateTileScore fonksiyonu çağrılarak, taşların efektif değerleri hesaplanır (özellikle okey taşları için).
  • Grubun sıralı mı (run) yoksa grup mu (group) olduğunu otomatik belirler ve buna göre hesap yapar.
  • Özellikle oyun açılışlarında veya toplu değerlendirme gereken anlarda kullanılır.
Dönüş Değeri
  • int: Tüm gruplardaki taşların efektif skorlarının toplamı döndürülür.

func sumAllGroupsNumbers(groups [][]*Model.Tile) int {
    total := 0
    for _, group := range groups {
        isSeq := isSequence(filterNonOkeys(group), countOkeys(group))
        for index, tile := range group {
            total += CalculateTileScore(tile, index, group, isSeq)
        }
    }
    return total
}

getEffectiveNumber Fonksiyonu

Parametreler
  • tile *Model.Tile: Değeri çözümlemek istenen taş (joker ya da okey olabilir).
  • group []*Model.Tile: Bu taşın bulunduğu grup ya da set. Taşın hangi değeri temsil ettiğini anlamak için grup analizi yapılır.
Kullanımı – Amaç
  • Joker ya da okey taşının hangi sayıyı temsil ettiğini belirlemek için kullanılır.
  • Eğer taş normal bir taşsa (okey değilse), kendi sayısı döndürülür.
  • Grup ise (aynı sayı, farklı renk): grubun ortak sayısı döndürülür.
  • Sıralı set ise (aynı renk, artan sayı): eksik olan sayı tespit edilir ve döndürülür.
  • Seri tamamlanmışsa ve sıranın sonunda taş varsa (örneğin 11-12-13 yerine 10-11-13 varsa): eksik olan 12 döndürülür.
Dönüş Değeri
  • int: Taşın temsil ettiği efektif sayı değeri (özellikle joker/okey taşları için çözülmüş hali).

func getEffectiveNumber(tile *Model.Tile, group []*Model.Tile) int {
    if tile.IsOkey {
        nonOkeys := filterNonOkeys(group)

        if isGroup(nonOkeys, countOkeys(group)) {
            for _, t := range nonOkeys {
                return t.Number
            }
        } else if isSequence(nonOKeys, countOkeys(group)) {
            nums := []int{}
            for _, t := range nonOkeys {
                nums = append(nums, t.Number)
            }
            sort.Ints(nums)
            expected := nums[0]
            for _, n := range nums {
                if n != expected {
                    return expected
                }
                expected++
            }
            if expected > 13 {
                return nums[0] - 1
            }
            return expected
        }
    }
    return tile.Number
}

sortGroupByEffectiveNumber Fonksiyonu

Parametreler
  • group []*Model.Tile: Etkili sayılarına göre sıralanacak taşlardan oluşan grup.
Kullanımı – Amaç
  • Bu fonksiyon, verilen taş grubundaki tüm taşları, temsil ettikleri gerçek (etkili) sayıya göre sıralar.
  • Joker veya okey taşları için getEffectiveNumber fonksiyonu kullanılarak hangi değeri temsil ettikleri belirlenir.
  • Gerçek taşlar ise doğrudan kendi sayıları ile karşılaştırılır.
  • Sıralama işlemi kararlı (stable sort) olarak yapılır, yani eşit değerli taşlar orijinal sırasını korur.
Dönüş Değeri
  • []*Model.Tile: Etkili değerlere göre sıralanmış taş listesi.

func sortGroupByEffectiveNumber(group []*Model.Tile) []*Model.Tile {
    type tileWithValue struct {
        tile  *Model.Tile
        value int
    }

    var withValues []tileWithValue
    for _, t := range group {
        withValues = append(withValues, tileWithValue{
            tile:  t,
            value: getEffectiveNumber(t, group),
        })
    }

    sort.SliceStable(withValues, func(i, j int) bool {
        return withValues[i].value < withValues[j].value
    })

    var sorted []*Model.Tile
    for _, tw := range withValues {
        sorted = append(sorted, tw.tile)
    }
    return sorted
}
      

SplitTilesByValidPairs Fonksiyonu

Parametreler
  • tiles []*Model.Tile: Değerlendirilecek tüm taşlar.
Kullanımı – Amaç
  • Verilen taş listesinden, kurallara uygun olacak şekilde çift (pair) oluşturmaya çalışır.
  • Aynı sayı ve aynı renkten en az 2 taş varsa bunları eşleştirir.
  • Tek kalan taşlar varsa, okey taşlarıyla eşleştirmeye çalışır.
  • Kullanılmış taşlar işaretlenir, tekrar çift oluşturulmaz.
Dönüş Değeri
  • ([][]*Model.Tile, []*Model.Tile): İlk değer çiftlere ayrılmış taş grupları listesidir, ikinci değer ise eşleşemeyen (artakalan) taşlardır.

func SplitTilesByValidPairs(tiles []*Model.Tile) ([][]*Model.Tile, []*Model.Tile) {
    type pairKey struct {
        Color  int
        Number int
    }

    grouped := make(map[pairKey][]*Model.Tile)
    var okeys []*Model.Tile

    for _, tile := range tiles {
        if tile.IsOkey {
            okeys = append(okeys, tile)
        } else {
            key := pairKey{Color: tile.Color, Number: tile.Number}
            grouped[key] = append(grouped[key], tile)
        }
    }

    var pairs [][]*Model.Tile
    used := make(map[*Model.Tile]bool)

    for _, group := range grouped {
        available := []*Model.Tile{}
        for _, t := range group {
            if !used[t] {
                available = append(available, t)
            }
        }
        for len(available) >= 2 {
            pair := available[:2]
            pairs = append(pairs, pair)
            used[pair[0]] = true
            used[pair[1]] = true
            available = available[2:]
        }
    }

    for _, group := range grouped {
        if len(okeys) == 0 {
            break
        }
        available := []*Model.Tile{}
        for _, t := range group {
            if !used[t] {
                available = append(available, t)
            }
        }
        for len(available) >= 1 && len(okeys) > 0 {
            t := available[0]
            okey := okeys[0]
            pairs = append(pairs, []*Model.Tile{t, okey})
            used[t] = true
            used[okey] = true
            available = available[1:]
            okeys = okeys[1:]
        }
    }

    var remaining []*Model.Tile
    for _, t := range tiles {
        if !used[t] {
            remaining = append(remaining, t)
        }
    }

    return pairs, remaining
}
      

1. Tüm Okey Taşlarını Oluşturma

tiles := Core.CreateFullTileSet()
Bu satır, tüm oyun taşlarını üretir: 4 renk x 13 sayı x 2 = 104 taş + 2 sahte okey = 106 taş. Her taşın ID, Color, Number gibi özellikleri tanımlıdır. Dönüş olarak karıştırılmış bir taş dizisi (tile bag) elde edilir.

2. Player 1’e 22 Taş Dağıtılır

player1 = Core.ShowPlayerTiles(&tiles, "Player 1:", 22)
Player 1'e havuzdan 22 taş çekilir. Fonksiyon, oyuncunun elini terminale yazdırır ve kalan taşları havuzdan eksiltir.

3. Player 2’ye 21 Taş Dağıtılır

player2 = Core.ShowPlayerTiles(&tiles, "Player 2:", 21)
Player 2'ye 21 taş verilir. Aynı şekilde taşlar yazdırılır, havuz güncellenir.

5. Kalan Taş Havuzu Görüntülenir

for i, tile := range tiles {...}
Gösterge sonrası, elde kalan tüm taşlar (taş havuzu) yazdırılır. Her taşın ID, Color, Number, IsJoker, IsOkey bilgisi gösterilir.

6. Okey Taşları Belirlenip Etiketlenir

tiles.MarkOkeyTiles(indicatorTile)
player1.MarkOkeyTiles(indicatorTile)
player2.MarkOkeyTiles(indicatorTile)
Göstergeye göre okey olan taşlar belirlenir. `IsOkey = true` olarak güncellenir. Hem havuzda hem oyuncularda işlem yapılır.

7. Okey Etiketlemesinden Sonra Oyuncu Elleri Yazdırılır

for i, tile := range *player1 {...}
for i, tile := range *player2 {...}
Oyuncuların elleri tekrar yazdırılır. Bu sefer hangi taşların okey olduğu da belirtilir.

8. Player 1 Taş Çeker (Turn Başlangıcı)

takenTile = tiles.TakeOneFromBag((*[]Model.Tile)(player1))
Player 1, taş havuzundan bir taş çeker. Bu işlem, oyuncunun taş sayısını 23’e çıkarır. Terminale bu taşın bilgileri yazdırılır.

ResetGame – Oyun Grubu Sayacını Sıfırlama

Kullanımı
Core.ResetGame()
Amaç
Bu fonksiyon, oyun içerisindeki Game isimli global GameGroupState nesnesini sıfırlar. Özellikle açılan grup ID sayaçlarının yeniden başlatılması gereken durumlarda (yeni oyun başlangıcı gibi) çağrılır.
Ne Yapar?
  • Global Game nesnesine yeni bir GameGroupState atanır.
  • İçerisindeki GroupIDCounter sıfırlanır.
  • Yani, taşlara verilecek yeni grup ID'leri sıfırdan başlatılır.
Tipik Kullanım Zamanı
Yeni bir oyun başladığında veya tüm oyun durumu sıfırlanmak istendiğinde kullanılır.
var Game GameGroupState

type GameGroupState struct {
    GroupIDCounter int
}

func ResetGame() {
    Game = GameGroupState{
        GroupIDCounter: 0,
    }
}

// Örnek çağrı:
Core.ResetGame()

      

4. Gösterge Taşının Belirlenmesi

indicatorTile := tiles.GetRandomIndicatorFromTiles()
Oyun kurallarına göre bir gösterge taşı rastgele seçilir. Bu taşın bir üst değeri Okey taşı olur. Gösterge taş bilgisi terminalde gösterilir.

CreateFullTileSet Fonksiyonu

main.go İçinde Kullanımı
tiles := Core.CreateFullTileSet()
Amaç
Bu fonksiyon, oyunun başında gerekli olan tüm okey taşlarını (106 adet) üretmek için çağrılır.
Kapsam
- Her renkten (Kırmızı, Sarı, Mavi, Siyah) 1’den 13’e kadar olan taşlardan ikişer adet üretir.
- Toplamda 4 renk x 13 sayı x 2 = 104 taş oluşturulur.
- Ayrıca 2 adet sahte okey (renksiz, sayı 0, IsJoker = true) eklenir.
- Böylece toplam taş sayısı 106 olur.
main.go'da Ne Zaman ve Neden Çağrılır?
Oyun başlatıldığında, tüm taşların sıfırdan ve karışık bir şekilde oluşturulması gerekir. Bu yüzden CreateFullTileSet fonksiyonu main fonksiyonu içinde ilk adımda çağrılır.
Fonksiyonun İçsel İşleyişi
1. Taşları ID vererek oluşturur.
2. Renk ve sayı değerlerini atar.
3. Sahte okey taşlarını ayrı olarak tanımlar.
4. En sonunda tüm taşları kriptografik olarak güvenli şekilde karıştırmak için ShuffleTilesSecure() fonksiyonuna gönderir.

DropTileFromTiles – Player 1

main.go İçinde Kullanımı
var result = Core.DropTileFromTiles((*[]Model.Tile)(player1), dropTile)
if result { fmt.Printf("...") }
Amaç
Bu satır, Player 1’in elinden belirli bir taşı çıkarmak (oyun alanına atmak) için kullanılır. Oyunda her tur sonunda bir taş atılır; bu davranışı simüle eder.
Detaylı Açıklama
- dropTile, atılmak istenen taşı temsil eder (örneğin elin 3. taşı).
- DropTileFromTiles() fonksiyonu:
  • Player 1’in elindeki taşları döngüyle kontrol eder.
  • Taşın ID eşleşmesi varsa onu listeden çıkarır.
  • Başarıyla çıkardıysa true döner, değilse false.
Kullanım Nedeni
Okey oyununda her oyuncu sırası geldiğinde bir taş çeker ve bir taş atar. Bu satır, "taş atma" adımını uygulamak için kullanılır. Ayrıca `fmt.Printf(...)` satırı sayesinde, atılan taşın ID’si, rengi, numarası ve joker durumu terminale yazdırılır.

TakeOneFromTable Fonksiyonu

Parametre (player) – Taşı alacak oyuncunun elindeki taş listesi
Bu parametre, taşın ekleneceği oyuncuya ait taş listesidir. Pointer olarak geçirilir, böylece orijinal veri doğrudan güncellenir.
Parametre (tile) – Eline alınacak taş
Masadan veya rakipten alınan belirli taş. Bu taş doğrudan oyuncunun eline eklenir.
Kullanımı – Amaç
  • Oyuncunun masadan ya da başka bir kaynaktan (örneğin başka oyuncudan) bir taşı eline almasını sağlar.
  • Ana fonksiyon (örnek: main.go) içerisinde taş çekme veya alma işlemleri için çağrılır.
  • Örneğin, Player 2 oyuncusunun, Player 1 oyuncusunun attığı bir taşı eline almasını simüle eder:
  • Core.TakeOneFromTable((*[]Model.Tile)(player2), dropTile)
  • Bu satır, dropTile taşını player2’nin eline ekler.
func TakeOneFromTable(player *[]Model.Tile, tile Model.Tile) {
    *player = append(*player, tile)
}

// Örnek çağrım:
// Player 2, dropTile adındaki taşı masadan alır
Core.TakeOneFromTable((*[]Model.Tile)(player2), dropTile)

      

DropTileFromTiles Fonksiyonu

Parametre (playerTiles) – Oyuncunun elindeki taş listesi
Taşı elinden bırakacak oyuncunun taş dizisi. Pointer olarak gönderilir ki taş elden kalıcı olarak silinebilsin.
Parametre (dropTile) – Atılacak taş
Elinden çıkarılmak istenen belirli taş. ID eşleşmesi ile oyuncunun elinden silinir.
Kullanımı – Amaç
  • Bir oyuncunun elindeki taşlardan birini masaya atmasını sağlar.
  • Taş, ID eşleşmesi ile bulunarak oyuncunun taş listesinden kaldırılır.
  • Eğer taş başarıyla bulunup çıkarılırsa true döner, aksi takdirde false.
  • Örnek kullanım: Core.DropTileFromTiles((*[]Model.Tile)(player2), (*player2)[4])
  • Bu örnekte player2 oyuncusu, elindeki 5. taşı (indeks 4) atmaktadır.
func DropTileFromTiles(playerTiles *[]Model.Tile, dropTile Model.Tile) bool {
    var isFound bool = false
    for i, tile := range *playerTiles {
        if tile.ID == dropTile.ID {
            *playerTiles = append((*playerTiles)[:i], (*playerTiles)[i+1:]...)
            isFound = true
            break
        }
    }
    return isFound
}

// Örnek çağrım:
// Player 2, elindeki 5. taşı atar
Core.DropTileFromTiles((*[]Model.Tile)(player2), (*player2)[4])

      

ShowPlayerTiles Fonksiyonu

Parametre (tiles) – TileBag (taş havuzu)
Oyunculara verilecek taşların bulunduğu havuz. Taşlar buradan seçilir ve oyuncuya atanır.
Parametre (name) – Oyuncu ismi (ekrana yazdırmak için)
Hangi oyuncuya ait taşların gösterildiğini belirtmek için yazı olarak kullanılır.
Parametre (topCount) – Çekilecek taş sayısı
Oyuncuya başlangıçta verilecek taş adedini belirtir. Belirtilen sayı kadar taş seçilir ve gösterilir.
Kullanımı – Amaç
  • Taş havuzundan belirtilen sayıda taşı çekip, oyuncuya dağıtır.
  • Konsola detaylı bilgi yazdırır: taş ID’si, rengi, numarası, okey ya da joker olup olmadığı.
  • Hem görsel çıktı sağlar hem de oyuncuya ait taşları döndürür.
  • Örnek kullanım: Core.ShowPlayerTiles(player1, "Player 1:", 22)
  • Bu örnekte player1 oyuncusuna 22 taş verilir ve bilgileri konsola yazdırılır.
func ShowPlayerTiles(tiles *TileBag, name string, topCount int) *TileBag {
    player := tiles.GetTiles(topCount)

    fmt.Println(name)
    fmt.Println(strings.Repeat("-", 30))

    for i, tile := range *player {
        colorName := GetEnumName(ColorEnum, tile.Color)
        fmt.Printf("%d-) ID: %d, %s %d, Joker: %v Okey: %v\n", 
            i+1, tile.ID, colorName, tile.Number, tile.IsJoker, tile.IsOkey)
    }

    fmt.Println()
    fmt.Printf("Kalan taş sayısı: %d\n", len(*tiles))
    return player
}

// Örnek çağrım:
// Player 1’e 22 taş verilip, bilgileri yazdırılır.
Core.ShowPlayerTiles(player1, "Player 1:", 22)

      

ShowPlayerTiles – Player 2

Parametre (tiles) – Taş havuzu (TileBag)
Oyuna başlarken veya yeni taş çekilirken kullanılan tüm taşların bulunduğu dizidir.
Parametre (name) – Oyuncu adı (örnek: "Player 2:")
Konsola yazdırılan başlık. Oyuncunun taşlarının kimde olduğunu belirtmek için görsel çıktıda kullanılır.
Parametre (topCount) – Çekilecek taş sayısı
Taş havuzundan kaç taş çekileceğini belirtir. Bu örnekte 21 taş "Player 2" için alınır.
Kullanımı – Amaç
  • Oyuncuya başlangıçta veya oyun sırasında taş vermek için kullanılır.
  • Konsol üzerinde görsel bilgi sağlar: her taşın ID’si, rengi, numarası, okey veya joker durumu.
  • Fonksiyon, hem taşları yazdırır hem de dağıtılan taşları döndürür.
  • Örnek çağrı: Core.ShowPlayerTiles(player2, "Player 2:", 21)
  • Bu kullanımda, player2'ye 21 taş verilir ve oyuncunun taşları listelenir.
func ShowPlayerTiles(tiles *TileBag, name string, topCount int) *TileBag {
    player := tiles.GetTiles(topCount)

    fmt.Println(name)
    fmt.Println(strings.Repeat("-", 30))

    for i, tile := range *player {
        colorName := GetEnumName(ColorEnum, tile.Color)
        fmt.Printf("%d-) ID: %d, %s %d, Joker: %v Okey: %v\n", 
            i+1, tile.ID, colorName, tile.Number, tile.IsJoker, tile.IsOkey)
    }

    fmt.Println()
    fmt.Printf("Kalan taş sayısı: %d\n", len(*tiles))
    return player
}

// Kullanım örneği:
// Player 2 için 21 taş dağıtılır ve konsola yazdırılır.
Core.ShowPlayerTiles(player2, "Player 2:", 21)

      

ShowPlayerTiles – Tüm Taş Havuzunun Gösterimi

Parametre (tiles) – TileBag (Taş Havuzu)
Oyunun başında oluşturulan ve tüm taşları (jokerler dahil) içeren listeyi temsil eder.
Parametre (name) – "Bag :"
Konsol çıktısında başlık olarak gösterilir. Bu durumda taş havuzunun görüntülendiği belirtiliyor.
Parametre (topCount) – len(tiles)
Taş havuzundaki tüm taşların gösterileceği anlamına gelir. len(tiles) kadar taş çekilir ve yazdırılır.
Kullanımı – Amaç
  • Oyun başında taş havuzunun içeriğini kontrol etmek için kullanılır.
  • Renk, sayı, okey ve joker durumlarıyla birlikte her taşın detayını gösterir.
  • Genellikle CreateFullTileSet() ile oluşturulan taş setinin doğru olup olmadığını gözlemlemek için kullanılır.
  • Taşlar çekildiği için havuzdan çıkar; bu yüzden sadece kontrol amaçlı kullanılmalıdır.
  • Örnek çağrı: Core.ShowPlayerTiles(&tiles, "Bag :", len(tiles))
func ShowPlayerTiles(tiles *TileBag, name string, topCount int) *TileBag {
    player := tiles.GetTiles(topCount)

    fmt.Println(name)
    fmt.Println(strings.Repeat("-", 30))

    for i, tile := range *player {
        colorName := GetEnumName(ColorEnum, tile.Color)
        fmt.Printf("%d-) ID: %d, %s %d, Joker: %v Okey: %v\n", 
            i+1, tile.ID, colorName, tile.Number, tile.IsJoker, tile.IsOkey)
    }

    fmt.Println()
    fmt.Printf("Kalan taş sayısı: %d\n", len(*tiles))
    return player
}

// Örnek kullanım:
Core.ShowPlayerTiles(&tiles, "Bag :", len(tiles))