C++ ile basit XOX oyunu (Konsol Uygulaması)


Bu yazıda, konsol uygulaması olarak çalışan, C++ dilinde yazılmış ve 160 satırlık koddan oluşan 2 kişilik basit bir XOX oyunu ele alınacaktır.



Koda belirli aralıklar ile yorum satırları eklenerek hangi kısımların ne amaçla yazıldığı açıklanmıştır. Aşağıda bu açıklamaların üstünden biraz daha detaylı bir şekilde geçilecektir.


Sayfanın sonunda .cpp dosyasını indirmek için ilgili link yer almaktadır.



Uygulama main fonksiyonu haricinde 6 adet fonksiyon içermektedir. Bunlar:


  • Programın temel değişkenlerine başlangıç değeri ataması yapan "hazirla" fonksiyonu. (Bir nevi Classlar'daki "Constructor" fonksiyonu.)

  • Her çağrıldığında mevcut ekranı temizleyen ve oyunun durumuna göre ekranı baştan çizen "ekranciz" fonksiyonu.

  • Oyunculardan girdi almayı sağlayan, alınan girdinin gerekli kriterlere uygunluğunu kontrol eden, uygun olmaması durumunda hata mesajı gösterip tekrar girilmesini isteyen, uygun olması durumunda ise ilgili değişkenlerin değerlerini girilen girdiye göre güncelleyen "girdial" fonksiyonu.

  • Her çağrıldığında oyunun bitip bitmediğini, başka bir deyişle bir oyuncunun oyunu kazanıp kazanmadığını kontrol eden (oyunun bitmesini sağlayan 8 adet durumu kontrol ederek), bir kazananın olması durumunda, "sonucekrani" isminde başka bir fonksiyonu çağıran ve ekrana oyun sonu mesajını gösteren "kazanan" fonksiyonu.

  • Her çağrıldığında oynama sırasının mevcut oyuncudan diğer oyuncuya geçmesini sağlayan, buna bağlı olarak da ilgili değişkenlerin değerlerini güncelleyen "oyuncudegistir" fonksiyonu.

  • "kazanan" fonksiyonu içerisinden oyunun bitmesi durumunda çağrıldığında, her döngüde "ekranciz" fonksiyonu sayesinde ekrana gösterilen programın temel değişkenlerini;
    1. Oyunu kimin kazandığı,
    2. Oyunun 8 adet durumdan hangisi ile bittiği
           bilgilerine göre güncelleyen "sonucekrani" fonksiyonu.



main fonksiyonunun içerisinde ise, sırasıyla:


  • "oyun" isminde bir etiket tanımlanır.

  • Ekran temizlenir.

  • "hazirla" fonksiyonu çağrılır.

  • Oyunculardan sırasıyla 1. ve 2. oyuncunun isimlerini girmeleri istenir. 1. oyuncunun ismi ilgili değişkene atanarak oyuna 1. oyuncunun başlaması sağlanır.

  • Ana döngü başlatılır. Bu döngü içerisinde, sırasıyla:
    1. "ekranciz" fonksiyonu ile ekran çizilir.
    2. "girdial" fonksiyonu ile kullanıcıdan girdi alınır.
    3. "kazanan" fonksiyonunun geri döndürdüğü değere bakılarak oyunun bitip bitmediği kontrol edilir. Oyunun bitmesi durumunda "kazanan" fonksiyonu çağrılarak oyun sonu mesajı gösterilir ve bu noktada döngünün dışına çıkılır.
    4. Oyunun devam etmesi durumunda "oyuncudegistir" fonksiyonu ile sıra diğer oyuncuya geçirilir.

  • Oyun bitip ana döngüden çıkıldıktan sonra oyuncuya tekrar oynamak isteyip istemediği sorulur. Evet cevabı alınması durumunda main fonksiyonunun en başındaki "oyun" etiketine gidilerek main fonksiyonunun tekrar işlenmesi sağlanır.


Kodu aşağıda görebilirsiniz. İlgilenenler .cpp dosyasını buraya tıklayarak indirebilir.


#include <iostream>
#include <Windows.h>
using namespace std;
char ekran[3][3], oyuncu;
string birinci, ikinci, sira;

void hazirla() {
    char a = 1;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {       //Bu fonksiyon, temel değişkenlere başlangıç değerlerinin atamasını gerçekleştirir.
            ekran[i][j] = '0' + a;
            a++;
        }
    }
    oyuncu = 'X';
}
void ekranciz() {
    system("cls");
    cout << endl << endl;
    for (int i = 0; i < 3; i++) {           //Bu fonksiyon, her döngüde ekranın temizlenmesini ve güncellenen değerler ile tekrar çizilmesini sağlar.
        cout << "       ";
        for (int j = 0; j < 3; j++) {
            cout << ekran[i][j] << "    ";
        }
        cout << endl << endl << endl;
    }
}
void girdial() {
    int a;
    cout << "Oyuncu sirasi: " << sira << "." << endl;
    cout << oyuncu << " koymak istediginiz sayiyi tuslayarak enter'a basiniz." << endl;     // Bu fonksiyon, kullanıcıdan girdi alma ve alınan girdinin
basla:                                                                                      // kriterlere uygunluğunun kontrolünü gerçekleştirir.
    cin >> a;
    while (a < 1 || a > 9) {
        cout << "1 ile 9 arasinda bir sayi tuslayiniz." << endl;
        cin >> a;
    }
    if (a < 4 && ekran[0][a - 1] == 'X' || ekran[0][a - 1] == 'O') {                        // Girdinin kriterlere uygun olmaması durumunda hata mesajı gösterir ve
        cout << "Dolu hucrenin uzerine yazamazsiniz." << endl;                              // kullanıcıdan tekrar denemesini ister.
        goto basla;
    }
    else if (a >= 4 && a < 7 && ekran[1][a - 4] == 'X' || ekran[1][a - 4] == 'O') {
        cout << "Dolu hucrenin uzerine yazamazsiniz." << endl;
        goto basla;
    }
    else if (a >= 7 && ekran[2][a - 7] == 'X' || ekran[2][a - 7] == 'O') {
        cout << "Dolu hucrenin uzerine yazamazsiniz." << endl;
        goto basla;
    }

    if (a < 4) {
        ekran[0][a - 1] = oyuncu;                                // Girdi kriterlere uygun ise gerekli değişkenlere atama
    }                                                            // yaparak değişkenlerin değerlerini günceller.
    else if (a >= 4 && a < 7) {
        ekran[1][a - 4] = oyuncu;
    }
    else if (a >= 7) {
        ekran[2][a - 7] = oyuncu;
    }
}

int kazanan() {
    if (ekran[0][0] == oyuncu && ekran[0][1] == oyuncu && ekran[0][2] == oyuncu) {          // Bu fonksiyon, her döngüde oyunun bitip bitmediğini kontrol eder.
        int sayilar[2][3] = { { 000 }, { 012 } };                                   // Oyunun bitmesini sağlayan tüm durumları (8) kontrol ederek, oyunun
        sonucekrani(sayilar);                                                               // bitmesi durumunda sonuç ekranı düzenlemesini yapan fonksiyonu çağırır
        cout << "Tebrikler! " << sira << " kazandi." << endl;                               // ve ekrana kazanan oyuncu ile beraber oyun sonu mesajını yazdırır.
        return 1;                                                                           // Oyun bittiyse 1, devam ediyorsa 0 değerini geri döndürür.
    }
    else if (ekran[0][0] == oyuncu && ekran[1][0] == oyuncu && ekran[2][0] == oyuncu) {
        int sayilar[2][3] = { { 012 }, { 000 } };
        sonucekrani(sayilar);
        cout << "Tebrikler! " << sira << " kazandi." << endl;
        return 1;
    }
    else if (ekran[0][0] == oyuncu && ekran[1][1] == oyuncu && ekran[2][2] == oyuncu) {
        int sayilar[2][3] = { { 012 }, { 012 } };
        sonucekrani(sayilar);
        cout << "Tebrikler! " << sira << " kazandi." << endl;
        return 1;
    }
    else if (ekran[0][2] == oyuncu && ekran[1][1] == oyuncu && ekran[2][0] == oyuncu) {
        int sayilar[2][3] = { { 012 }, { 210 } };
        sonucekrani(sayilar);
        cout << "Tebrikler! " << sira << " kazandi." << endl;
        return 1;
    }
    else if (ekran[1][0] == oyuncu && ekran[1][1] == oyuncu && ekran[1][2] == oyuncu) {
        int sayilar[2][3] = { { 111 }, { 012 } };
        sonucekrani(sayilar);
        cout << "Tebrikler! " << sira << " kazandi." << endl;
        return 1;
    }
    else if (ekran[0][1] == oyuncu && ekran[1][1] == oyuncu && ekran[2][1] == oyuncu) {
        int sayilar[2][3] = { { 012 }, { 111 } };
        sonucekrani(sayilar);
        cout << "Tebrikler! " << sira << " kazandi." << endl;
        return 1;
    }
    else if (ekran[2][0] == oyuncu && ekran[2][1] == oyuncu && ekran[2][2] == oyuncu) {
        int sayilar[2][3] = { { 222 }, { 012 } };
        sonucekrani(sayilar);
        cout << "Tebrikler! " << sira << " kazandi." << endl;
        return 1;
    }
    else if (ekran[0][2] == oyuncu && ekran[1][2] == oyuncu && ekran[2][2] == oyuncu) {
        int sayilar[2][3] = { { 012 }, { 222 } };
        sonucekrani(sayilar);
        cout << "Tebrikler! " << sira << " kazandi." << endl;
        return 1;
    }
    else {
        return 0;
    }
}

void oyuncudegistir() {
    oyuncu = (oyuncu == 'X') ? 'O' : 'X';               // Bu fonksiyon, her döngü sonunda sıranın diğer oyuncuya geçirilmesi ve buna bağlı olarak
    sira = (oyuncu == 'X') ? birinci : ikinci;          // gerekli değişkenlerin değerlerinin değiştirilmesi işlemini gerçekleştirir.
}

void sonucekrani(int a[2][3]) {                         // Bu fonksiyon, oyunun bitmesi durumunda, ilgili kontrolü yapan fonksiyonun içerisinden çağırılması
    for (int i = 0; i < 3; i++) {                       // ile birlikte, oyun sonu ekranında ekrana çizilecek değerlere göre ilgili değişkenleri düzenler.
        for (int j = 0; j < 3; j++) {
            if (i == a[0][0] && j == a[1][0] || i == a[0][1] && j == a[1][1] || i == a[0][2] && j == a[1][2]) {
                continue;
            }
            ekran[i][j] = ' ';
        }
    }
}


int main()
{
oyun:
    system("cls");
    char secim;
    hazirla();
    cout << "1. oyuncunun ismini giriniz: ";            // Oyunculardan isimlerini girmeleri istenir, oyuna başlayacak olan 1. oyuncunun ismi, sıranın hangi
    cin >> birinci;                                     // oyuncuda olduğu ile ilgili olan değişkene atanır. 
    cout << "2. oyuncunun ismini giriniz: ";
    cin >> ikinci;
    sira = birinci;
    while (1) {
        ekranciz();                                     // Bu döngü, oyunun gerekli düzende çalışmasını sağlayan ana döngüdür.
        girdial();                                      // Sırasıyla; ekranı çizdirir, kullanıcıdan girdiyi aldırır, oyunun bitip bitmediğini kontrol ettirir,
        if (kazanan() == 1) {                           // eğer oyun bittiyse ilgili fonksiyon çağırılıp sonuç ekranı çizildikten sonra döngüden çıkılır, bitmediyse
            ekranciz();                                 // oyuncu sırasını değiştirir ve başa sarıp aynı adımları tekrar uygular.
            kazanan();
            break;
        }
        oyuncudegistir();
    }
    cout << "Tekrar oynamak ister misiniz?  < E  /  H >" << endl;
    cin >> secim;
    while (secim != 'E' && secim != 'e' && secim != 'H' && secim != 'h') {             // Oyuncuya tekrar oynamak isteyip istemediğini sorar, oyuncunun tekrar oynamak
        cout << "Hatali giris. Tekrar oynamak ister misiniz?  < E  /  H >" << endl;    // istemesi durumunda, main fonksiyonunun en başında tanımlanmış olan "oyun"
        cin >> secim;                                                                  // etiketine zıplar ve böylelikle oyun baştan başlar.
    }
    if (secim == 'E' || secim == 'e') {
        goto oyun;
    }
    return 0;
}

Comments

My photo
Ercan Tomac
instagram.com/ercantomac