Taş Oyunu

     Üniversite 1. sınıfta, Bilgisayar Programlamaya Giriş dersi güz dönemi proje ödevini sizlerle paylaşmak istiyorum.

    Ödevin adı Taş Oyunu2 oyuncu arasında bir taş oyunu oynanmaktadır. 

Oyun ve kurallar ise şu şekilde;

  1. Oyunun başlangıcında her 2 oyuncunun elinde 20 mavi 20 kırmızı olmak üzere toplam 40 taş bulunmaktadır.
  2. Her bir hamle bir oyuncunun diğerine bir taş vermesi ile gerçekleşir.
  3. Oyunun başlangıcında oyunculardan biri diğerine numarası 10’dan küçük olan bir taş verir.
    • Başlangıçta verilecek taşın mavi veya kırmızı olmasına rastgele karar verilir.
    • 1-10 arası toplardan hangisinin verileceği rastgele seçilir.
  4. Her oyuncu aldığı karşılık bir taş verir. Vereceği taşı aşağıdaki kurallara göre seçer.
    • Aldığı taşla aynı renk ve numarası aldığı taşın numarasının 2 katı.
    • Aldığı taşla farklı renk ve numarası aldığı taşın numarasından 4 eksik.
    • Oyuncunun elinde her 2 kurala da uygun taş varsa hangisini vereceğini rastgele seçer. Aksi halde şartları sağlayan taşı diğer oyuncuya verir.
  5. Oyuncunun elinde kurallara uygun verebileceği taş kalmadığında oyun sonlanır ve taş veremeyen oyuncu oyunu kaybeder.

Ek olarak hocamızın istedikleri:

  1. Her 2 oyuncu için de birer tahta olması gerekir.
  2. Her hamle sonrasında oyun tahtalarının güncel halini ekrana bastırmalısınız ve hangi taşın verildiğini ekran yazdırmalısınız.
  3. Oyun sonlandığında hangi oyuncunun kazandığını ve kaç hamle yapıldığını ekrana yazdırmalısınız.

Ödev için bizden istenen bunlardır. Çözümü ise şu şekildedir:

    İlk olarak talimatların tamamını dikkatlice okuyalım. Daha sonra ne yapacağımıza karar verip adım adım ilerleyelim. 
  1. Oyuncuların elindeki taşları kontrol edebilmek için iki boyutlu, iki adet diziye ihtiyacımız var. Bu dizilere ilk atama olarak 1 değerini atamalıyız.
  2. Dizilerin başlangıç durumunu kullanıcıya göstermeliyiz, yani kısaca diziyi ekrana yazdırmalıyız. Bunu yaparken özelleştirmeden yapmalıyız ki, dizileri her ekrana yazdırmak istediğimiz zaman bu kod dizisini (fonksiyonunu) çağıralım.
  3. İlk adım için rastgele oyuncu, renk ve 1-10 arasında bir sayı belirlememiz gerekiyor.
    • Belirlenen değerleri, oyunun oynanacağı yani hamlenin gerçekleşeceği fonksiyona göndermemiz gerekiyor.
  4. Hamleleri gerçekleştirmemiz için bir fonksiyona ihtiyacımız var. Bu fonksiyon gödereceğimiz değerleri kullanıcıya göstermeli ve gelen değerlere göre, hamleyi yapan oyuncunun oynadığı taşını azaltan diğer oyuncunun o taşını arttıran işlemleri yapmalı.
  5. Hamle yapıldıktan sonra oyuncuların tablosunu tekrar göstermemiz gerekiyor, bu kodu daha önce yazmıştık ve özelleştirmeden yazdığımız için her yerde kullanabiliriz, bu yüzden tekrar tekrar yazmak yerine bu kod dizisini (fonksiyonunu) çağırmamız yeterli olacaktır.
  6. Sırada diğer oyuncunun -kurallara göre- yapabileceği hamleyi bulacak koşul kodlarını yazmamız gerekiyor (Not: En karmaşık yeri burası 😅)
    • Bulunan değerleri, tekrar hamleyi gerçekleştireceğimiz fonksiyona göndermeliyiz. Yani kısaca fonksiyonlarla döngü oluşturacağız. Döngüyü kırma işini kodları anlatırken göstereceğim.
    • Eğer kullanıcı hamle yapamıyorsa yani oynayabileceği taşlar elinde yoksa, oyuncuyu ve oynayabileceği taşların bilgilerini oyunu bitirdiğimiz fonksiyona yollamalıyız.
  7. Oyunu bitiren fonksiyona ihtiyacımız var. Bu fonksiyona gelen veriler ile kullanıcıya kaybeden oyuncuyu ve kaybetme nedenini gösteren kodları yazmalıyız.
    her adımı bir fonksiyon olacak şekilde düşünüp tek tek ele alalım. Herhangi bir adımı, birbiriyle bağlantılı birden fazla fonksiyon şeklinde de yazabiliriz.
    Teorik kısmını fazla uzattım kusura bakmayın 😅. Konuyu daha fazla dağıtmadan kodlar üzerinden anlatayım;

    İlk olarak bize lazım olan kütüphaneleri ve main fonksiyonunu yazalım ve main'de oyunumuzun ismini yazalım;

iskelet

    time.h, kütüphanesine rastgele seçimler yapabilmek için ihtiyacımız var. 
    Şimdi iki adet dizimizi tanımlamamız gerekiyor ama bu iki diziyi birçok yerde kullanabileceğimiz için global olarak tanımlamamız daha işlevsel olacaktır.

Dizi tanımlama

    Şimdi dizilerimize ilk atamayı yapmamız gerekiyor. İlk atama olarak 1 değerini atayacağız.

İlk değer atama

    Burada fonksiyonumuz geri dönüş işlemi yapmadığı için tipini "void" yapmamız daha uygun olacaktır. Bu işlemden sonra fonksiyonu main'de çağıralım.
    Şimdi oyun başlamadan kullanıcıya oyuncuların tablosunu göstermeliyiz yani dizileri ekrana yazacağız, bu işlemi daha önce söylediğim gibi genel olarak yazarsak istediğimiz her yerde kullanabiliriz.

Dizileri ekrana yazdırma

    Tasarım ile uğraştığım için bu kod gereğinden fazla uzun oldu, ama söz veriyorum buna değecek.
    Şimdi bu yazdığımız fonksiyonları main'de çağıralım.

fonksiyonları main'de çağırma

    Bu işlemden sonra şimdi sıra ilk hamleyi yapmaya geldi. Bunun için üç adet rasgele seçilen değerlere ihtiyacımız var. Bu işlemi bir fonksiyonda yapalım ve bu fonksiyonu main'de çağırıp, kullanıcıya oyunun başladığını belirtelim.

rasgele değerler belirleyen fonksiyon

    Bu fonksiyonunda tipini "void" yaptık çünkü bir değer döndürmeyeceğiz.
    Kullandığımız rand() fonksiyonu bize rastgele sayılar belirliyor, %x dediğimizde sıfır ile x sayısına kadar rastgele sayılar belirliyor (x sayısı dahil değil).
    srand(time(0)); fonksiyonu bize, her seferinde rastgele sayılar belirlememizi sağlıyor.
    Şimdi 'random_selection()' fonksiyonu içinde çağırdığım game(); fonksiyonuna gelelim. game() fonksiyonunda biz hamleleri gerçekleştireceğiz ve yapılan işlemleri ekrana yazdıracağız.

game fonksiyonu

    Burada game ile game_control arasında bir döngü yapacağız. Bu döngüyü kırmak için is_game_over değişkenine ihtiyacımız var, bu değişkeni global olarak tanımladık ki iki yerde de rahatça kullanalım.
    move değişkeni ile yapılan hamle sayısını tutabileceğiz, bu değişkeni fonksiyon dışında tanımlamamızın amacı; fonksiyonları sürekli olarak birbiri içinde çağıracağız bu yüzden değişkenin değeri her seferinde sıfır atanmaması için fonksiyon dışında tanımlıyoruz.
    Fonksiyonda ilk başta oyun bitirme değişkenini kontrol edeceğiz (is_game_over), eğer 1 değeri atanmışsa fonksiyondan direkt çıkacak ve oyunu bitirecek.
    Her fonksiyon çağırıldığında hamle (move) değişkenini bir arttırarak ekrana yazdıracağız.
    Ekrana yazdırma kodlarında; birinci hamlede rastgele seçim yapılacağı ve diğer hamlelerde sıradaki oyuncu ve onun oynayabileceği belli taşlar olduğu için ona göre metinler yazacağız.
    game fonksiyonuna gelen parametrelerdeki değerlere göre dizilerden birinde azaltma diğerinde arttırma işlemi yapacağız.
    Bu işlemlerden sonra tekrar oyuncu tablosunu ekrana yazdırmalıyız. Bunun için table() fonksiyonunu çağırmamız yeterli olacaktır.
    "other_possibility" değişkenini ve işlevini game_control fonksiyonunu anlatırken söyleyeceğim.
    Şimdi hamle işlemini gerçekleştirdikten sonra sıradaki oyuncuyu ve oynayabileceği taşları bulmak ve belirlemek için game_control() fonksiyonunu yazacağız.
 
game_control fonksiyonu

        İlk olarak game_control() fonksiyonunda game() fonksiyonunu çağıracağımız için yukarıda game fonksiyonunun prototip tanımlamasını (ön tanımlama) yapmalıyız.
    Yeni oyuncuyu ve oynayacağı taşın rengini ve numarasını tutacağımız üç adet değişkene ihtiyacımız var bu değerleri başka yerlerde de kullanacağımız için fonksiyon dışında tanımlamamız daha uygun olucaktır.
    Bize iki adet değer lazım bunlar;
  • gelen sayının iki katı
  • gelen sayının dört eksiği
    Not: Biz devamlı olarak index (indeks) değerleri ile uğraşacağımız için değerleri hesaplarken index değeri olucak şekilde işlemler yapacağız.
    Şimdi sıradaki oyunucuyu belirlememiz gerekiyor, bunu yapmak kolay çünkü gelen değeri zıttına çevireceğiz.
    Bu işlemlerden sonra oyuncunun oynayabileciği taşları bulacağız ve iki tane ise rastgele seçim, tek ise o sayıyı alıp rengin değişip değişmediğinide kontrol ederek tekrar game fonksiyona yollayacağız.
    En dıştaki if-elseif- else kısmından anlatmaya başlayayım;
Burada if içerisine girebilmemiz için iki değişkenimizinde (two_times_number ve four_missing_number) değerleri 1 ile 20 arasında olması gerekiyor (1 ve 20 dahil). Koşul sağlanmıyorsa sıra  elseif'e geliyor. elseif içerisine girebilmek için "two_times_number" değişkenimizin değeri 1 ile 20 arasında olması gerekiyor. Bu koşulda sağlanmazsa else kısmı çalışacak.
    Not: Burda else yerine, elseif deyip koşulunada, "four_missing_number" değikeninin değeri 1 ile 20 arasında olmalı diyebilirdik ama gereksiz ve fazladan kod olacaktı çünkü 1 ile 20 arasında herhangi bir sayı düşünün bu sayının hem iki katı hemde dört eksiği olabilir (10), yada iki katı olup dört eksiği olmayabilir (4) yada dört eksiği olup iki katı olmayabilir (11) ama hem iki katının hem de dört eksiğinin olmama olasılığı yoktur. Bu yüzden en dışta üç adet koşul kodlarımız var. Ama yine de yapımız if - elseif - else yerine if - elseif- elseif de olabilirdi. Yani tamamen kişisel tercih, istediğinizi yapabilirsiniz.
    Şimdi ilk olarak if içerisini anlatayım,
öncelikle bir if - else yapımız var. Bu yapı sıradaki oyuncuya göre işlem yapmamızı sağlayacak. Bu if  içerisinde de bir if - elseif - elseif - else yapımız var. Bu yapı sıradaki oyuncunun dizisinde istenilen taşın olup olmadığını kontrol ediyor.
  • if: Gelen sayının hem iki katı hem de dört eksiği oyuncunun elinde varsa çalışacak. koşul sağlanmazsa,
  • elseif: Gelen sayının iki katı oyuncunun elinde varsa çalışacak. Koşul sağlanmazsa,
  • elseif: Gelen sayının dört eksiği oyuncunun elinde varsa çalışacak. Koşul sağlanmazsa,
  • else: Çalışacak
    else dışında diğer üçü de aynı fonksiyonu çağırıyor  (set_moves_to_play) . Tek farkları, fonksiyona yollanan değerlerden sonuncu değerdir.
  • 2: İki olasılık da olduğunda
  • 1: Sadece iki katının olduğunda
  • 0: sadece dört eksiğinin olduğunda
Yollanacak değerlerdir.
    else kısmı ise oyunu bitirmek için "is_game_over" değişkenine 1 değerini atıyor ve game_over fonksiyonunu çağırıyor.
    Not: set_moves_to_play ve game_over fonksiyonlarını birazdan anlatacağım.
    Şimdi, sıradaki oyuncuya göre işlem yapacağımız if - else yapısındaki else kısmındayız. Bu kısımda if  içerisindekilerle aynı olacak. Tek farkı kontrol edilen dizinin ikinci oyuncuya ait olması olacak.
    Bundan sonra en dıştaki if - elseif - else yapısından elseif kısmındayız. Mantık aynı olacak. elseif içerisine,
  • İlk başta sıradaki oyunucuya göre işlem yapmamızı sağlayacak if - else yapısını yazacağız. Daha sonra hem if hemde else içerisine,
    • Oyuncunun elinde gelen sayının iki katının olup olmadığını kontrol eden bir if -else yapısı yazacağız. if içerisinde set_moves_to_play fonksiyonunu çağıracağız. else içerisinde "is_game_over" değişkenine 1 değerini atayıp game_over fonksiyonunu çağıracağız.
Şimdi ise en dıştaki else kısmındayız. Burada da elseif içerisine yaptığımızın aynısını yapacağız. Tek fark gelen sayının iki katını kontrol etmek yerine dört eksiğini kontrol etme olacak.
    En sonunda game fonksiyonunu tekrar çağıracağız.

    Şimdi ise size set_moves_to_play() fonksiyonunu anlatayım. 

set_moves_to_play fonksiyonu

    Burada önemli olan son gelen değerdir. 2, 1 yada 0, bu değerler kontrol edilir ve ve buna göre değişkenlere değer atanır.
    Oynanacak sayı gelen sayının dört eksiği ise renginde değişmesi gerekiyor. Bu yüzden de bir change_color() fonksiyonu yazacağız.
    "other_possibility" değişkenine diğer ihtimali de atayacağız ki kullanıcıya bu ihtimali neden yapamadığının bilgisini vereceğiz.
    Şimdi change_color() fonksiyonunu anlatayım,
 
change_color fonksiyonu

    Çok basit bir şekilde gelen renk değeri 0 ise 1, değilse (ki o zaman değeri 1 olur, çünkü color değişkenine 0 ve 1'den başka hiçbir değer atanmadı ve atanmamalı) 0 değerini atıyoruz ve bu fonksiyonu çağırdığımız yerde (int tipinde) bir değişkene atıyoruz. (Burada sıfır Maviyi, bir kırmızıyı ifade ediyor.)
    En son aşamaya geldik. Oyunu bitiren fonksiyonumuzu yazalım,

game_over fonksiyonu

    Burada oyunun bittiğini ve toplam hamleyi yazdırıyoruz, sonra gelen değerlerden kaybeden oyunucuyu da yazdırıyoruz.
    Diğer gelen iki adet değişkenimizi (two_times_number ve four_missing_number) kontrol ederek kullanıcıya,
  • Değerler 1 - 20 arasında ise elinde o taşlar olmadığı için,
  • 1 - 20 arasında olmayan değer için, oyundaki taşlar arasında bulunmadığı,
mesajını veriyoruz.

    Sonunda uygulamayı yaptık, Biraz uzun ve karmaşık anlatmış olabilirim kusura bakmayın 😅. Şimdi size kendi yazdığım kodların tamamını vereceğim, kendi yazdığınız kodlar ile karşılaştırabilirsiniz. 
    Yaptığım hataları, daha iyisinin yapılabileceği noktaları, yorumlarınızı yazmayı unutmayın, görüşleriniz benim için çok önemli. İyi günler dilerim.
    Kodları görmek için tıklayınız: Taş Oyunu Kodları
    Diğer uygulamalarımı görmek istiyorsanız, Projelerim sayfasına göz atabilirsiniz.

Popüler Yayınlar

Makine Öğrenmesi Temel Bilgiler

Veri Görselleştirme Temel Bilgi

Cpp'da Nesne Yönelimli Programlama (OOP) Mantığı İle Sınav Uygulaması

C Dili İle İlgili Örnek Sorular Ve Çözümleri

Machine Learning Tahmin (Prediction) Metotları

Python İle Nesne Yönelimli Programlama (OOP) Uygulamaları