#include #include #include #include // Kod içinde kullanılacak global değerler #define MAKSIMUM_DEGER 30 // Haritanın maksimum genişlik ve yüksekliği #define GORUS_ALANI 3 // Kullanıcının maksimum görebileceği görüş alanı // Oyunun haritasının kaydedilip okunması için // yaratılmış (x,y) koordinat sistemini kullanan // karakter haritası, maksimum değerleri global // verilerde tanımlanan MAKSIMUM_DEGER. char map[MAKSIMUM_DEGER][MAKSIMUM_DEGER]; // Kullanıcı karakterinin oluşturulacağı x,y int oyuncuSatir, oyuncuSutun; // Çıkışın oluştulacağı x,y int cikisSatir, cikisSutun; // Kullanıcının mevcut x,y int satir, sutun; // Mevcut satır ve sütun sayısını tutmak için // Terminal ekranını temizlemek için yazılmış fonksiyon void clearScreen() { printf("\033[2J\033[H"); // Terminal ekranını temizle } // Haritayı rastgele oluşturup char map'e atanan fonksiyon void haritayiTanimla() { // Global verilerdeki maksimum x,y değerleri satir = MAKSIMUM_DEGER; sutun = MAKSIMUM_DEGER; /* Her satir ve her sutun boyunca calisacak for dongusu, bu döngü haritanın dış çevresini duvar olarak işaretler Eger satir = 0 ve ya sutun = 0 ve ya sutun = maksimum sutun - 1 ve ya satir = maksimum satir -1 ise duvar olarak seç. Yani kısaca (0,herhangi bir deger) ve (herhangi bir deger, 0) (maksimumdeger - 1,herhangi bir deger) ve (herhangi bir deger, maksimumdeger - 1)'ı duvar olarak işaretler Örneğin maksimum değeri 5 olan bir haritanın dış çevresi: X X X X X X X X X X X X X X X X Çünkü 0lı tüm satırlar, sütunlar ve maksimum değerden 1 eksik tüm satırlar ve sütunlar o haritanın çevresini verir Dış çerçeve dışı tüm koordinatları boşluk olarak belirler. */ for (int i = 0; i < satir; ++i) { for (int j = 0; j < sutun; ++j) { if (i == 0 || i == satir - 1 || j == 0 || j == sutun - 1) { map[i][j] = '#'; // Haritanın kenarları duvarla çevrili } else { map[i][j] = ' '; // Diğer her yer koridor olarak başlar } } } // Labirentin oluşturulması /* Her 2 satır ve 2 sütun başına çalıştırılan for döngüsü 0 ila 4 arası rastgele bir sayı belirler, Eğer sayı 0 ise şuan for döngüsünde dönen sütunun üstünü duvar olarak işaretler Eğer sayı 1 ise şuan for döngüsünde dönen sütunun altını duvar olarak işaretler Eğer sayı 2 ise şuan for döngüsünde dönen satırın solunu duvar olarak işaretler Eğer sayı 3 ise şuan for döngüsünde dönen satırın sağını duvar olarak işaretler Bu kısım bizim koridor oluşturmamıza yarayan kısmımız. Rastgele çıkan değerlere döre duvarlar koyup düzgün bir koridor sistemi oluşturuyor. Kullanıcıya hareket edecek yer vermek için her 2 sütun ve 2 satırda bir oluşturuyor. Eğer her 1 satır ve 1 sütunda oluşturulsaydı kullanıcının yolunu kapayacak duvarlar oluşabilirdi bunu önleme amaçlı koridorların etrafı duvar ile kapatılıyor. Bir sütunun altı duvar olarak işaretlenirse o forda dönen o sütun boş olarak işaretleniyor bu da bize yana dönebileceğimiz duvarlar sağlıyor. Aynı mantık satırlar için de geçerli. */ for (int i = 2; i < satir - 2; i += 2) { for (int j = 2; j < sutun - 2; j += 2) { map[i][j] = '#'; // Her ikinci satır ve sütun duvarla çevrili int yon = rand() % 4; // Rastgele bir yöne gidilir switch (yon) { case 0: // Yukarı if (i - 1 >= 1) { map[i - 1][j] = '#'; } break; case 1: // Aşağı if (i + 1 < satir - 1) { map[i + 1][j] = '#'; } break; case 2: // Sol if (j - 1 >= 1) { map[i][j - 1] = '#'; } break; case 3: // Sağ if (j + 1 < sutun - 1) { map[i][j + 1] = '#'; } break; } } } // Oyuncu pozisyonunu belirlerken duvarın içinde olmamasını sağlayan kontrol do { oyuncuSatir = rand() % (satir - 2) + 1; oyuncuSutun = rand() % (sutun - 2) + 1; } while (map[oyuncuSatir][oyuncuSutun] == '#'); map[oyuncuSatir][oyuncuSutun] = 'P'; // Oyuncu pozisyonu belirlenir // Çıkış pozisyonunu belirlerken duvarın içinde olmamasını sağlayan kontrol do { cikisSatir = rand() % (satir - 2) + 1; cikisSutun = rand() % (sutun - 2) + 1; } while (map[cikisSatir][cikisSutun] == '#' && map[cikisSatir][cikisSutun] == 'P'); map[cikisSatir][cikisSutun] = 'E'; // Çıkış pozisyonu belirlenir // Çıkış pozisyonu belirlenir } /* Bu bizim ana haritayı resme dökme fonksiyonumuz. haritayiTanimla fonksiyonunda haritayı rastgele koridorlarla oluşturup Kullanıcıyı ve Çıkışı bir koordinat char map'e tanımladık. Bu fonksiyonda bu char mapi terminale yazdıracağız. */ void haritayiRenderla() { printf("\n"); /* Her satır ve sütun sayısı kadar çalışan for döngüsü Kullanıcının şuanki bulunan (x,y)sine göre etrafında GORUS_ALANI kadar haritayı renderlayan kod 1 2 3 4 5 6 1 # # # # # # 2 # E # 3 # # # # 4 # P # # 5 # # # # 6 # # # # # # haritayiTanimla'da oluşturulan harita yukarıdaki olduğunu düşünelim. Kullanıcının (x,y)si şuan (3,4) ve GORUS_ALANI'mızın 1 olduğunu düşünelim Her (kullanıcının sütunu - görüş alanı) kadar, (kullanıcının satırı - görüş alanı) çalıştıracağız Bu durumda kullanıcının her yönden 1 karelik alanı renderlayacak. Kullanıcının göreceği: # # P # # */ for (int i = oyuncuSatir - GORUS_ALANI; i <= oyuncuSatir + GORUS_ALANI; ++i) { for (int j = oyuncuSutun - GORUS_ALANI; j <= oyuncuSutun + GORUS_ALANI; ++j) { if (i >= 0 && i < satir && j >= 0 && j < sutun) { // Eğer şuan kontrol edilen (x,y) haritayiTanimla'da tanımlanan oyuncu (x,y)sine eşitse if (i == oyuncuSatir && j == oyuncuSutun) { // Renderlanan (x,y)yi P olarak renderla printf("P "); // Eğer şuan kontrol edilen (x,y) haritayiTanimla'da tanımlanan çıkış (x,y)sine eşitse } else if (i == cikisSatir && j == cikisSutun) { // Renderlanan (x,y)yi E olarak renderla printf("E "); // Eğer (x,y) oyuncu ya da çıkış değilse char map'teki değeri yazdır (duvar ya da boşluk) } else { printf("%c ", map[i][j]); } // Eğer kullanıcının görüş alanı haritayı aşıyorsa yani renderlayacak bir duvar, boşluk yoksa // tilde işareti renderla } else { printf("~ "); // Görüş alanı dışını '~' olarak göster } } printf("\n"); } } int main() { // Her seferinde farklı bir sayı oluşturulması için gerekli srand srand(time(NULL)); // Kullanıcının bitirdiği seviyeleri kaydetmek için kullanılan seviye değeri int level = 1; // Oyun bitse bile çalışması için kullanılan while while (1) { // Her yeni seviye başladığında yeni bir harita tanımlar ve komutları yazdırır haritayiTanimla(); printf("Seviye %d: Çıkışı 'E'yi bul. W/A/S/D kullanarak hareket et.\n", level); printf("Şuanki pozisyonun 'P' olarak işaretli!.\n"); // oyunBittimi diye bir değer ayarlar ve 0 olduğu sürece ana oyunu renderlar int oyunBittimi = 0; while (!oyunBittimi) { // Kullanıcının her yeni hareketinde kullanıcının yeni (x,y) sine göre haritayı renderlar haritayiRenderla(); printf("Hareketini Gir (W/A/S/D): "); // Kullanıcının hareketini move değerine tanımlar char move; scanf(" %c", &move); // Kullanıcının yeni satır ve sütununu belirlemek için 2 yeni değişken belirler int yeniSatir = oyuncuSatir, yeniSutun = oyuncuSutun; // Kullanıcıdan aldığımız move değerine göre satır ve sütunlar ayarlanır ve // kullanıcının pozisyonunun değiştikten sonra yeni harita renderlanması için // önceki renderlanan haritayı terminalden siler switch (move) { case 'W': case 'w': clearScreen(); yeniSatir--; break; case 'A': case 'a': clearScreen(); yeniSutun--; break; case 'S': case 's': clearScreen(); yeniSatir++; break; case 'D': case 'd': clearScreen(); yeniSutun++; break; default: // Eğer kullanıcı WASD dışı bir giriş yaptıysa yanlış giriş hatası verir clearScreen(); printf("Yanlış giriş, W/A/S/D kullan.\n"); continue; } /* Eğer kullanıcının gitmeye çalıştığı yer duvar değilse Kullanıcının eski (x,y)sini boşluk olarak ayarlayıp Kullanıcının yeni (x,y)sini 'P' olarak ayarlar */ if (map[yeniSatir][yeniSutun] != '#') { map[oyuncuSatir][oyuncuSutun] = ' '; oyuncuSatir = yeniSatir; oyuncuSutun = yeniSutun; map[oyuncuSatir][oyuncuSutun] = 'P'; } /* Eğer kullanıcının (x,y)si çıkış (x,y)sine eşitse Tüm ekranı temizler, Tebrikler çıkışı buldunuz yazdırır ve while döngüsünden çıkmak için oyunBittimi değerini 1 yapar Seviyeyi 1 arttırır ve break ile döngüden çıkar */ if (oyuncuSatir == cikisSatir && oyuncuSutun == cikisSutun) { clearScreen(); printf("Tebrikler Çıkışı Buldunuz.\n"); oyunBittimi = 1; level++; break; } } } return 0; }