Bölüm 4 — Amaç ve Kapsam
Genel Amaç
Bu bölümün temel amacı, tuval sınırı ve şekil çarpışması temellerini durum makinesi deseniyle birleştirerek menü–oyun–bitiş akışlı, iki oyunculu bir XOX oyununu bağımsız sketch olarak tamamlamak ve Temel Kavramlar kitabındaki becerileri bütünleşik bir ürünle pekiştirmektir. Bölüm boyunca her ana başlık kendi içinde amaç, öğrenme çıktıları, örnek kod ve değerlendirme sorularıyla tamamlanır; böylece bir sonraki bölüme geçmeden önce ölçülebilir kazanımlar elde edilir.
Kapsam
Bu bölüm şu ana başlıklar altında ele alınmaktadır:
Ana Başlık 1: Çarpışma Temelleri ve Sekme
Ana Başlık 2: Durum Makinesi Kavramı ve Geçişler
Ana Başlık 3: Menü–Oyun–Bitiş Akışı ve Kaç-Kaç
Ana Başlık 4: Adım Adım: XOX (Tic-Tac-Toe)
Ana Başlık 1. Çarpışma Temelleri ve Sekme
Amaç: Tuval sınırı, AABB, daire çarpışması ve sekme tepkisini öğreterek mini oyunlarda temel çarpışma testleri kurmak.
Öğrenme Çıktıları:
- Tuval sınırında konum ve hız tepkisini uygular.
- AABB ve dist tabanlı çarpışma testlerini ayırt eder.
- Sekme için hız bileşenini tersine çevirir.
- Basit fizik tepkisini hareketli nesneye bağlar.
Anahtar Sözcükler: çarpışma, AABB, dist, sekme, tuval sınırı
Giriş
Hareketli bir sketch’te nesne ekranda gezer; oyuna dönüşmesi için “değdi mi?” sorusu gerekir. Çarpışma algılama, iki şeklin kesişip kesişmediğini sınayan testlerdir. En basit hali tuval kenarıdır; ardından dikdörtgen (AABB) ve daire (dist) testleri gelir. Sekme, ilgili hız bileşenini tersine çevirerek fizik hissi verir.
Bu ana başlık temel testleri ve sekme tepkisini kurar. Hitbox ayrımı ile çoklu nesnede maliyet, İleri Teknikler kitabında ayrı bir ana başlıkta ele alınır; burada kurulan dil, durum makinesi ve XOX için yeterlidir. Bundan sonra gelen alt başlıklarda önce veri modeli, sonra hamle kuralı, en sonda çizim ve etkileşim kurulur. Her yeni fonksiyon mümkün olduğunca küçük bir örnekte çalıştırılır; böylece hatanın kaynağı daha kolay bulunur. Anlatımda önce ilgili yapının ne işe yaradığı açıklanır, ardından kod satır satır okunur. Terimler ilk geçtikleri yerde kısa bir tanımla verilir; gerekirse tablo veya görsel ile desteklenir. Örnek sketch’ler tek bir mekaniğe odaklanır; böylece yan konular okumayı dağıtmaz. Parametreleri değiştirip yeniden çalıştırmak, kuralın sınırını görmenin en hızlı yoludur. Bu ana başlığın çıktısı, sonraki oyunda yeniden kullanılabilecek bir iskelet oluşturur.
1.1. Çarpışma Algılama Nedir?
Tanım: Çarpışma algılama — İki veya daha fazla oyun nesnesinin (veya nesne ile sınırın) geometrik olarak kesişip kesişmediğini her frame (her draw() çağrısında) kontrol etme işlemidir.
Oyun döngüsünde tipik sıra:
Tablo 1.
| Adım | İş | Örnek |
|---|---|---|
| 1 | Girdi oku | keyIsDown, mouseIsPressed |
| 2 | Konumu güncelle | topX = topX + hizX * dt |
| 3 | Çarpışma kontrol et | Tuval kenarı, başka blok |
| 4 | Tepki uygula | Sekme, skor, oyun bitişi |
| 5 | Çiz | rect, ellipse, text |
Çarpışma görsel değil, mantıksal bir testtir: koşul true döndüğünde kod tepki verir; tuvalde otomatik bir efekt oluşmaz. Basit oyunlarda test genelde if ile yazılır. Aynı kontrolün (ör. AABB veya dist) birkaç yerde tekrarlanması gerekiyorsa, daha önce tanıtılan yardımcı fonksiyon yaklaşımıyla bu kontrol tek bir yere toplanabilir — fonksiyon true/false döndürür, draw içinde yalnızca if (dikdortgenlerCarpisiyor(...)) sorusu sorulur.
Dikkat: Çarpışma algılama, çarpışmanın fizik simülasyonu değildir. Gerçekçi sekme, sürtünme veya dönme ileri konulardır; burada yön tersine çevirmek (hizX = -hizX) yeterli bir basit tepkidir.
Oyunlarda neden bu kadar önemli?
Çarpışma olmadan çoğu oyun “boşlukta süzülen şekiller”e iner: raket topa değmez, mermi hedefi delip geçer, karakter duvardan yürür. Skor artışı, can kaybı, sekme, kapı açma veya ölme gibi kurallar çoğu zaman tam da bu test true olduğunda uygulanır. İlk bilgisayar oyunlarından (Pong, 1972) bugünün mobil hit’lerine kadar aynı iskelet tekrar eder: hareket et → değdi mi? → tepki ver.
Tablo 2.
| Bilinen oyun / tür | Çarpışma olunca ne olur? | Bu başlıktaki karşılık |
|---|---|---|
| Pong | Raket topa değer → yön değişir; kenar → sekme veya sayı | Sınır + daire/kutu sekmesi (§1.2, §1.5) |
| Breakout / Arkanoid | Top tuğlaya değer → tuğla kaybolur, skor artar | Daire ↔ dikdörtgen (veya AABB yaklaşımı) |
| Pac-Man | Hayalete değince can kaybı; duvara değince yol kesilir | Kutu / ızgara AABB |
| Super Mario Bros. benzeri | Zemine inme, düşmana üstten/yandan değme, coin alma | AABB; bazen ek olarak daire şeklinde çarpışma bölgesi |
| Flappy Bird | Boruya bir kez değmek → oyun biter | Sıkı AABB |
| Space Invaders / Galaga | Mermi uzaylıya değer → düşman yok olur | Küçük kutu veya daire ↔ daire |
| Angry Birds | Kuş / blok / domuz kesişince yıkım ve skor | Daire ↔ daire / kutu (fizik motoru arkada) |
| Pinball / bilardo tarzı | Top bumper veya kenara değer → sekme | Sınır + daire (§1.5’e yakın his) |
Bu tablodaki oyunların çoğunda ekranda süslü bir çizim (sprite) görülür; çarpışma ise çoğu zaman görünmez sade bir kutu veya daire ile yapılır. Bu görünmez bölgeye oyun dilinde hitbox (çarpışma kutusu / çarpışma bölgesi) denir — çizim ne kadar detaylı olursa olsun, “değdi mi?” sorusu genelde bu sade şekle sorulur.
Ticari oyunlarda bu soru çoğu zaman iki adımda sorulur. Kaba test ucuzdur: örneğin her nesnenin etrafındaki büyük AABB’ye bakılır; kutular birbirinden uzaksa “değmedi” denir ve iş biter. İnce test daha pahalıdır: yalnızca kutular örtüşünce devreye girer; çoklu hitbox, üçgen–üçgen veya piksel gibi daha sıkı bir kontrol yapılır. Amaç, uzak çiftlerde boşuna ağır hesap yapmamaktır. Bu ana başlıkta sınır, AABB ve dist gibi temel (çoğu zaman kaba) yöntemleri kuruyoruz; bunlar Pong’tan Flappy Bird’e kadar oyun hissinin omurgasıdır.
1.2. Tuval Sınırları
Tanım: Sınır (boundary) çarpışması — Hareketli nesnenin tuval kenarına (x = 0, x = width, y = 0, y = height) veya tanımlı bir oyun alanı sınırına değip değmediğinin kontrolüdür.
p5.js'te rect(x, y, w, h) sol üst köşe (x, y) ve genişlik/yükseklik kullanır. Daire için ellipse(x, y, d, d) merkez (x, y) ve çap kullanır; yarıçap r = d / 2 alınır.
Tablo 3.
| Şekil | Sol kenar | Sağ kenar | Üst kenar | Alt kenar |
|---|---|---|---|---|
Dikdörtgen (x, y, w, h) |
x |
x + w |
y |
y + h |
Daire merkez (cx, cy), yarıçap r |
cx - r |
cx + r |
cy - r |
cy + r |
Kod bloğu: Dikdörtgen kare — tuval dışına çıkmadan durdurma (Bölüm 3 Ana Başlık 4'teki constrain() alternatifi).
Kod 1.
let kareX = 100;let kareY = 80;const BOYUT = 40;const HIZ = 150; function setup() { createCanvas(400, 300); noStroke();} function draw() { background(35, 40, 55); let dt = deltaTime / 1000; if (keyIsDown(RIGHT_ARROW)) { kareX = kareX + HIZ * dt; } // Sağ kenar: sol üst x + genişlik tuvali aşmasın if (kareX + BOYUT > width) { kareX = width - BOYUT; } if (kareX < 0) { kareX = 0; } fill(100, 200, 255); rect(kareX, kareY, BOYUT, BOYUT);}Bilgi: Önceki ana başlıkta constrain(oyuncuX, 0, width - BOYUT) ile aynı sınır tek satırda uygulanmıştı. constrain() pratik bir kısayoldur; yukarıdaki if blokları sınırın neden ve ne zaman devreye girdiğini gösterir. Sekme gerektiğinde (top duvara çarpınca yön değişsin) constrain() tek başına yetmez; konumu düzelten açık if blokları ile hız tersine çevirme birlikte kullanılır.
Daire için kenar testi merkez ve yarıçap üzerinden yapılır: topX - r < 0 sol duvara değme; topX + r > width sağ duvara değme.
1.3. Dikdörtgen Çarpışması
Tanım: AABB (Axis-Aligned Bounding Box — eksen hizalı sınır kutusu) — Kenarları tuvalin X ve Y eksenlerine paralel dikdörtgen. p5.js rect() ile çizilen kutular AABB sayılır. Kutu rotate ile döndürüldüğünde kenarlar eksene paralel kalmaz; o zaman bu dört eşitsizlik tek başına yetmez (bu durum aşağıdaki Bilgi kutusunda ve ilgili YZ etkinliğinde ele alınır).
Bilgi — analitik geometri burada işe yarar: Çarpışma testi çoğu zaman lisedeki analitik geometri dilinin oyun koduna çevrilmiş hâlidir: nokta koordinatları (x, y), doğru/kenar eşitsizlikleri, iki nokta arası Öklid mesafesi (dist), dikdörtgenlerin eksenler üzerindeki izdüşümlerinin örtüşmesi. Formülleri ezberlemek değil; “ekranda gördüğüm şekil → hangi geometrik soru?” diye sormak yeterlidir.
İki dikdörtgen yalnızca hem X hem Y ekseninde aynı anda örtüşüyorsa çarpışır. Bir eksende aralarında boşluk varsa çarpışma yoktur.

Görsel 1 dört durumu gösterir: (1) hem X hem Y örtüşür → çarpışma; (2) yalnızca Y örtüşür → çarpışma yok; (3) hiçbir eksende örtüşme yok → çarpışma yok; (4) B, A’nın içinde (yine her iki eksende örtüşme) → çarpışma. A ve B’nin sekiz köşesi ayrı renklerle işaretlenir; hangi rengin hangi köşeye ait olduğu, panellerin altındaki renk anahtarında (gösterge) yazılır. Siyah düz çizgi örtüşme aralığını gösterir. Alttaki not, A ile B etiketlerinin yer değiştirmesinin sonucu değiştirmediğini (simetri) hatırlatır.
Dikdörtgen A: (ax, ay, aw, ah) — sol üst (ax, ay), genişlik aw, yükseklik ah.
Dikdörtgen B: (bx, by, bw, bh).
Tablo 4.
| Koşul | Anlam |
|---|---|
ax < bx + bw |
A'nın sol kenarı, B'nin sağ kenarından solda |
ax + aw > bx |
A'nın sağ kenarı, B'nin sol kenarından sağda |
ay < by + bh |
A'nın üst kenarı, B'nin alt kenarından yukarıda |
ay + ah > by |
A'nın alt kenarı, B'nin üst kenarından aşağıda |
Dört koşul da true ise çarpışma vardır.
Bilgi: A ile B’nin etiketlerini değiştirmek (hangisine “A”, hangisine “B” dendiği) sonucu değiştirmez: çarpışma varsa dikdortgenlerCarpisiyor(A, B) ile dikdortgenlerCarpisiyor(B, A) aynı değeri döndürür. Dört eşitsizlik bir bütün olarak simetriktir; örneğin ax < bx + bw, yer değişiminde bx < ax + aw olur ve bu, eski ax + aw > bx ile aynı örtüşme fikridir.
Kod bloğu: İki dikdörtgen çarpışma testi — yardımcı fonksiyon (önceki bölümler, fonksiyonlar).
Kod 2.
function dikdortgenlerCarpisiyor(ax, ay, aw, ah, bx, by, bw, bh) { return ax < bx + bw && ax + aw > bx && ay < by + bh && ay + ah > by;} let oyuncuX = 50;let oyuncuY = 120;const OYUNCU_BOYUT = 36;let engelX = 200;let engelY = 100;const ENGEL_W = 80;const ENGEL_H = 60; function setup() { createCanvas(480, 280); noStroke();} function draw() { background(28, 32, 48); let dt = deltaTime / 1000; if (keyIsDown(RIGHT_ARROW)) { oyuncuX = oyuncuX + 160 * dt; } if (keyIsDown(LEFT_ARROW)) { oyuncuX = oyuncuX - 160 * dt; } let carpisti = dikdortgenlerCarpisiyor( oyuncuX, oyuncuY, OYUNCU_BOYUT, OYUNCU_BOYUT, engelX, engelY, ENGEL_W, ENGEL_H ); fill(100, 200, 255); rect(oyuncuX, oyuncuY, OYUNCU_BOYUT, OYUNCU_BOYUT); // carpisti true/false → engel rengi (önceki bölümler: if / else) if (carpisti) { fill(255, 90, 90); // çarpışma var: kırmızımsı } else { fill(120, 120, 130); // çarpışma yok: gri } rect(engelX, engelY, ENGEL_W, ENGEL_H); fill(255); textSize(14); textAlign(LEFT, TOP); text("Ok: hareket | Çarpışma: " + carpisti, 12, 12);}carpisti ve if — ne oluyor?
dikdortgenlerCarpisiyor(...)dört örtüşme koşulunu hesaplar ve sonuç boolean döner:true(örtüşme var) veyafalse(yok). Bu değercarpistideğişkeninde saklanır.- Her
draw()turundaif (carpisti)sorusu sorulur — önceki bölümlerdeki koşullu ifadeyle aynı mantık: koşul doğruysaifgövdesi, değilseelsegövdesi çalışır. Burada tepki yalnızca görseldir: engel kırmızıya veya griye boyanır; skor veya sekme yoktur. - Ekrandaki
Carpisma: true/falsemetni de aynı boolean’ı yazdırır; böylece hem renk hem yazı testi doğrular.
Kısa yazım (isteğe bağlı): if/else ile fill seçmek yerine tek satırda koşullu (üçlü) operatör kullanılabilir — anlam aynıdır:
Kod 3.
fill(carpisti ? color(255, 90, 90) : color(120, 120, 130));koşul ? doğruysaDeğer : değilseDeğer okunuşu: “carpisti true ise kırmızı color, false ise gri color.” Yeni başlarken üstteki açık if/else daha okunaklıdır.
Algılama ≠ çözümleme: Bu örnekte oyuncu engelin içine girebilir; kod yalnızca “değdi mi?” diye sorar (algılama). Oyuncuyu dışarı itmek, hızı ters çevirmek veya hareketi iptal etmek (çözümleme / resolution) ayrı adımdır — §1.5’teki sekmede konum + hız düzeltilir. Önce algılamayı doğru yazmak, sonra tepki eklemek daha güvenlidir.
Bilgi — Processing ↔ p5.js (Jeff Thompson okurken): Kaynakta boolean hit = rectRect(...);, float s1x = 0;, void draw() { ... } gibi satırlar görülür. p5.js’te çoğu zaman let hit = ..., let s1x = 0, function draw() { ... } yazılır; boolean / float / void tür bildirimleri yoktur (let ve function yeterlidir). size(600, 400) yerine createCanvas(600, 400) kullanılır; fare için mouseX / mouseY aynıdır. AABB matematiği değişmez — yalnızca dil yazımı farklıdır. Çeviri pratiği bu ana başlığın YZ etkinliklerinde ele alınır.
Bilgi: Jeff Thompson'un dikdörtgen–dikdörtgen bölümü (https://www.jeffreythompson.org/collision-detection/rect-rect.php) aynı AABB mantığını görsel örneklerle anlatır (Processing sözdizimi).
1.4. Daire Çarpışması
Tanım: Daire–daire çarpışması — İki dairenin merkezleri arasındaki mesafe, yarıçapların toplamından küçükse daireler kesişir (iç içe geçer veya dışarıdan birbirine değer).

Görsel 2 merkezler arası mesafe d, yarıçaplar r1 ve r2 ile çarpışma koşulunu gösterir.
İki nokta (x1, y1) ve (x2, y2) arası Öklid mesafesi (kodda yazıldığı gibi; kare alma, ifadenin kendisiyle çarpılmasıdır):
Kod 4.
d = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))Bu formül Pisagor teoremine dayanır: yatay fark dx = x2 - x1, dikey fark dy = y2 - y1; dik üçgende hipotenüs d = sqrt(dx * dx + dy * dy).
Tablo 5.
| Daire | Merkez | Yarıçap |
|---|---|---|
| 1 | (x1, y1) |
r1 |
| 2 | (x2, y2) |
r2 |
Çarpışma koşulu: d < r1 + r2 (tam dışarı değme için <= de kullanılabilir; oyunlarda < veya <= tercihi tutarlı olmalıdır).
Önceki bölümlerde tanıtılan dist(x1, y1, x2, y2) p5.js fonksiyonu bu mesafeyi hesaplar; karekök ve kare işlemini elle yazmaya gerek kalmaz.
Kod bloğu: İki daire — çarpışma testi. Yeşil daire sabittir; sarı/kırmızı daire ok tuşlarıyla (sol/sağ/yukarı/aşağı) yaklaştırılır — değince renk değişir.
Kod 5.
let daire1X = 120;let daire1Y = 150;const R1 = 35;let daire2X = 280;let daire2Y = 140;const R2 = 28; function setup() { createCanvas(440, 260); noStroke();} function draw() { background(25, 30, 45); let adim = 120 * deltaTime / 1000; if (keyIsDown(LEFT_ARROW)) { daire2X = daire2X - adim; } if (keyIsDown(RIGHT_ARROW)) { daire2X = daire2X + adim; } if (keyIsDown(UP_ARROW)) { daire2Y = daire2Y - adim; } if (keyIsDown(DOWN_ARROW)) { daire2Y = daire2Y + adim; } let mesafe = dist(daire1X, daire1Y, daire2X, daire2Y); let carpisti = mesafe < R1 + R2; // boolean: dikdörtgen testindeki if ile aynı fill(100, 200, 120); ellipse(daire1X, daire1Y, R1 * 2, R1 * 2); if (carpisti) { fill(255, 100, 100); } else { fill(255, 220, 80); } ellipse(daire2X, daire2Y, R2 * 2, R2 * 2); fill(255); textSize(14); textAlign(LEFT, TOP); text("mesafe: " + nf(mesafe, 0, 1) + " eşik: " + (R1 + R2), 12, 12); text("Çarpışma: " + carpisti, 12, 32); text("Ok tuşlarıyla sarı daireyi hareket ettirin", 12, 52);}Daire Tıklama oyununda dist(mouseX, mouseY, hedefX, hedefY) < hedefYaricap kullanılmıştı; fare konumu sabit yarıçaplı bir “nokta gibi” daire, hedef ise oyun dairesiydi. İki eşit statüdeki daire için koşul mesafe < r1 + r2 biçiminde genellenir — bu da analitik geometrideki “iki nokta arası uzaklık ≤ yarıçaplar toplamı” sorusunun ta kendisidir.
Bilgi: Jeff Thompson'un daire–daire bölümü (https://www.jeffreythompson.org/collision-detection/circle-circle.php) aynı dist mantığını görsel örneklerle anlatır; formülü doğrulamak için başvurulabilir. Daire–dikdörtgen (ileri): https://www.jeffreythompson.org/collision-detection/circle-rect.php
1.5. Sekme ve Basit Fizik Tepkisi
Tuval sınırına çarpan dairesel top için tipik tepki: konumu sınırın içine düzeltmek ve hız bileşeninin işaretini ters çevirmek (sekme).
Tanım: Hız vektörü — Nesnenin yatay (hizX) ve dikey (hizY) yönlerdeki saniye başına piksel cinsinden hızı. Konum güncellemesi: x = x + hizX * dt, y = y + hizY * dt.
Tablo 6.
| Olay | Konum düzeltmesi | Hız tepkisi |
|---|---|---|
Sol duvar (x - r < 0) |
x = r |
hizX = -hizX |
Sağ duvar (x + r > width) |
x = width - r |
hizX = -hizX |
Üst duvar (y - r < 0) |
y = r |
hizY = -hizY |
Alt duvar (y + r > height) |
y = height - r |
hizY = -hizY |
Önce konum sınırın dışına taşmış olabilir; sekmeden önce içeri itmek (clamp), topun duvarın içine gömülmesini azaltır.
Oyun kuralları (duvarlara çarpan top):
- Top sürekli hareket eder; hız
deltaTimeile uygulanır. - Dört tuval kenarına çarpınca ilgili hız bileşeni tersine döner.
- Ekranda anlık
hizXvehizYgösterilir.
Kod 6.
let topX;let topY;let hizX;let hizY;const YARICAP = 22;const HIZ = 220; function setup() { createCanvas(560, 360); noStroke(); topX = width / 2; topY = height / 2; hizX = HIZ * 0.7; hizY = HIZ * 0.5;} function draw() { background(22, 28, 42); let dt = deltaTime / 1000; topX = topX + hizX * dt; topY = topY + hizY * dt; if (topX - YARICAP < 0) { topX = YARICAP; hizX = -hizX; } if (topX + YARICAP > width) { topX = width - YARICAP; hizX = -hizX; } if (topY - YARICAP < 0) { topY = YARICAP; hizY = -hizY; } if (topY + YARICAP > height) { topY = height - YARICAP; hizY = -hizY; } fill(255, 190, 70); ellipse(topX, topY, YARICAP * 2, YARICAP * 2); fill(220); textSize(14); textAlign(LEFT, TOP); text("Duvarlara çarpan top", 12, 12); text("hizX: " + nf(hizX, 0, 1) + " hizY: " + nf(hizY, 0, 1), 12, 32);}Bu örnek klavye girdisi içermez; top kendi hızıyla hareket eder. Klavye kontrolü ve engel dikdörtgenleri sonraki projelerde birleştirilebilir.
Dikkat: Köşede iki duvara birden değildiğinde ilgili iki if bloğu birlikte çalışır ve hizX ile hizY aynı frame'de ters döner; bu beklenen davranıştır. Asıl dikkat edilmesi gereken nokta konum düzeltmesidir: topX = YARICAP gibi satırlar yazılmazsa top duvarın içinde kalır, aynı test ardışık frame'lerde yeniden true olur ve hız sürekli tersine çevrildiği için top kenara yapışıp titrer.
Bu başlıkta görülen çiftler → hangi test?
Çarpışma temelde bir çift üzerinden düşünülür: “A ile B değdi mi?” Bu ana başlıkta işlenen çiftler ve uygun testler:
Tablo 7.
| Çift (örnek) | Şekiller | Test | Bu başlıkta nerede? |
|---|---|---|---|
| Kare / top ↔ tuval kenarı | dikdörtgen veya daire ↔ sınır | Kenar if (sınır) |
§1.2, §1.5 |
| Blok ↔ blok | iki rect (AABB) |
Dört koşul örtüşme | §1.3 |
| Top ↔ top | iki ellipse |
dist + r1 + r2 |
§1.4 |
| Fare ↔ hedef daire | nokta ↔ daire | dist + yarıçap |
önceki bölümler Daire Tıklama (hatırlatma) |
Bu ana başlıkta “uzay gemisi / mermi” gibi yeni varlıklar tanımlanmamıştır; test seçimi önce bu tablodaki çiftler üzerinde pekiştirilir. İleride yeni bir nesne eklendiğinde aynı soru sorulur: şekil ne → sınır / AABB / dist?
Yapay Zekâ Etkileşimi: Sekme Yönü Tahmini süre: 15–20 dakika.
Amaç: Hız bileşeni ile sekme ilişkisini pekiştirmek.
Adım 1: Yatay duvara çarpan top için vx / vy değişimini yazın.
Adım 2: Yapay zekâdan aynı senaryoyu doğrulamasını isteyin.
Adım 3: Köşe çarpışmasında iki bileşenin birden tersine dönmesi riskini bir cümleyle not edin.
Özet
Tuval sınırı, AABB ve daire–daire (dist < r1 + r2) testleri mini oyunların omurgasıdır. Sekme çoğu zaman vx = -vx veya vy = -vy ile yapılır. Bu araçlar tek veya az sayıda nesne için yeterlidir.
Durum makinesi ve XOX, bu temel çarpışma dilinin üzerine kontrol akışı ekler. Görsel ile çarpışma kutusunu ayırma ve nesne sayısı artınca maliyet, sonraki kitapta hitbox ve çoklu nesne başlığında derinleşir.
Üç nokta bu ana başlığın sınırlarını çizer. Birincisi, algılama ile çözümlemenin ayrı adımlar olmasıdır: test yalnızca «değdi mi?» sorusunu yanıtlar, konumu düzeltmek veya hızı çevirmek ayrıca yazılır. İkincisi, testin şekle göre seçilmesidir; dikdörtgen için aralık örtüşmesi, daire için merkezler arası uzaklık kullanılır ve iki modeli karıştırmak yanlış sonuç üretir. Üçüncüsü, hızlı nesnelerde tek frame'lik sıçramanın engelin içinden geçmeye yol açabilmesidir; küçük adımlar veya daha büyük hitbox bu durumu azaltır.
Testin kendisi birkaç satırlık bir koşuldan ibarettir; asıl tasarım kararı, çarpışma gerçekleştiğinde oyunun ne yapacağıdır. Sekme, durma, can azaltma veya seviye geçişi aynı testin üzerine kurulur ve oyunun türünü belirleyen de bu tepkidir.
Neler Öğrendik?
Soru 1 AABB neyi test eder?
A) X ve Y aralıklarının örtüşmesini
B) Yalnızca rengi
C) DNS’i
D) Fontu
E) Git branch’i
Soru 2 İki daire çarpışmasında uygun koşul hangisidir?
A) dist < r1 + r2
B) width === height
C) key === 'a'
D) frameCount < 0
E) mouseX === mouseY
Soru 3 Duvardan sekmede tipik tepki nedir?
A) İlgili hız bileşeninin işaretini tersine çevirmek
B) Diziyi sıralamak
C) CSS yazmak
D) Tarayıcıyı kapatmak
E) createCanvas’ı draw içine almak
Soru 4 Tuval sınırı testinin pedagojik yararı nedir?
A) En basit “değdi mi?” senaryosunu somutlaştırmak
B) setup’ı silmek
C) HTML’i kapatmak
D) Ses kartını kalibre etmek
E) EPUB üretmek
Neler Öğrendik Yanıt Anahtarı
Soru 1: Doğru Cevap: A
- Çözüm: AABB eksen hizalı kutu örtüşmesidir.
- İlgili Konu: 1.3. Dikdörtgen Çarpışması
Soru 2: Doğru Cevap: A
- Çözüm: Merkez mesafesi yarıçaplar toplamıyla kıyaslanır.
- İlgili Konu: 1.4. Daire Çarpışması
Soru 3: Doğru Cevap: A
- Çözüm: vx veya vy negatife döner.
- İlgili Konu: 1.5. Sekme
Soru 4: Doğru Cevap: A
- Çözüm: Kenar teması çarpışmaya giriş kapısıdır.
- İlgili Konu: 1.2. Tuval Sınırları
Yararlanılan Kaynaklar
Bu içerik aşağıdaki kaynaklardan derlenerek hazırlanmıştır:
- McCarthy, L., Reas, C., & Fry, B. (2015). Make: Getting Started with p5.js. Maker Media.
- Moren, B. (n.d.). p5.collide2D. https://github.com/bmoren/p5.collide2D
- Nystrom, R. (2014). Game Programming Patterns. Genever Benning. https://gameprogrammingpatterns.com/
- p5.js Foundation. (n.d.). createGraphics(). https://p5js.org/reference/p5/createGraphics/
- p5.js Foundation. (n.d.). dist(). p5.js Reference. https://p5js.org/reference/p5/dist/
- p5play. (n.d.). p5.play. https://p5play.org/
- Shiffman, D. (n.d.). Code! Programming with p5.js. The Coding Train. https://thecodingtrain.com/tracks/code-programming-with-p5-js
- Thompson, J. (n.d.). Collision Detection. https://www.jeffreythompson.org/collision-detection/ (bölümler
.phpuzantılıdır; ör. rect-rect, circle-circle, circle-rect, line-line, içindekiler) - Wikipedia contributors. (n.d.). Collision detection. Wikipedia. https://en.wikipedia.org/wiki/Collision_detection (hitbox tanımı ve çoklu/parça hitbox fikri)
Ana Başlık 2. Durum Makinesi Kavramı ve Geçişler
Amaç: Oyun durumunu saklama, duruma göre çizim/girdi ve geçiş kurallarıyla durum makinesi modelini kurmak.
Öğrenme Çıktıları:
- Durum makinesi kavramını oyun akışına bağlar.
- Durumu değişkende saklar.
- Duruma göre çizim ve girdi yollarını ayırır.
- Geçiş kurallarını açıkça tanımlar.
Anahtar Sözcükler: durum makinesi, state, geçiş, menü, oyunDurumu
Giriş
Çarpışma ve hareket “oyun içi” davranışı kurar; ama bir ürün menü, oynanış ve bitiş ekranı arasında geçiş de ister. Bunları if yığınıyla dağınık yazmak yerine durum makinesi (state machine) modeli kullanılır: sistem her anda tek bir durumda bulunur; olaylar belirli geçişleri tetikler.
Durum bir değişkende saklanır ("menu", "oyun", "bitti"). draw ve girdi işleyicileri duruma göre dallanır. Geçiş kuralları “hangi olay hangi yeni duruma götürür?” sorusunu tablolaştırır. Bu ana başlık modeli ve kuralları kurar; menü–oyun–bitiş’in tam akışlı mini oyunu bir sonraki ana başlıkta tamamlanır. Bundan sonra gelen alt başlıklarda önce veri modeli, sonra hamle kuralı, en sonda çizim ve etkileşim kurulur. Her yeni fonksiyon mümkün olduğunca küçük bir örnekte çalıştırılır; böylece hatanın kaynağı daha kolay bulunur. Anlatımda önce ilgili yapının ne işe yaradığı açıklanır, ardından kod satır satır okunur. Terimler ilk geçtikleri yerde kısa bir tanımla verilir; gerekirse tablo veya görsel ile desteklenir. Örnek sketch’ler tek bir mekaniğe odaklanır; böylece yan konular okumayı dağıtmaz. Parametreleri değiştirip yeniden çalıştırmak, kuralın sınırını görmenin en hızlı yoludur.
2.1. Durum Makinesi Kavramı
Tanım: Durum makinesi (state machine) — Sistemin (oyunun) her an yalnızca bir durumda olduğu; belirli olaylar (tuş, tıklama, süre, çarpışma) ile başka durumlara geçiş yapabildiği yapıdır.
Bu ana başlığın omurgası üç durumludur — menü, oyun, bitiş:
Tablo 1.
| Durum | Ekranda ne görünür? | Girdi ne işe yarar? |
|---|---|---|
| Menü | Başlık, “Başla” talimatı | SPACE → oyunu başlat |
| Oyun | Oyuncu, hedef/top, skor | WASD hareket; çarpışma → bitiş |
| Bitiş | Skor, “Tekrar dene” | R → menüye dön |
Durum = oyunun aşaması. Geçiş (transition) = bir olay gerçekleşince durum değişkeninin güncellenmesi (oyunDurumu = DURUM_BITIS gibi).

Görsel 1, üç durumun birbirine nasıl bağlandığını özetler: menüden SPACE ile oyuna, çarpışma ile bitişe, R ile tekrar menüye. Menüde WASD veya bitişte SPACE yok sayılır — olay yalnızca o durum için tanımlıysa geçiş olur.
Ayrı boolean'ların riski küçük bir örnekle netleşir: menuAcik = true ve oyunAcik = true aynı anda olursa draw() aynı frame'de hem menüyü hem sahneyi çizebilir; girdi hangi bloğa gideceği belirsizleşir. Tek oyunDurumu değişkeninde ise her an yalnızca bir değer vardır; geçiş tek atama satırıdır.
Önceki bölümlerdeki oyunBitti boolean'ı aslında iki durumlu mini bir makinedir: oynuyor / bitti. Üç veya daha fazla aşama için string veya sabit kullanmak okunabilirliği artırır:
Tablo 2.
| Yaklaşım | Örnek | Ne zaman yeterli? |
|---|---|---|
| Tek boolean | oyunBitti |
Yalnızca devam / bitti |
| String durum | "menu", "oyun", "bitis" |
Birkaç aşamalı akış |
| Ayrı boolean'lar | menuAcik, oyunAcik |
Önerilmez — çakışma riski |
Bilgi — bilgisayar biliminde yeri: Durum makinesi yalnızca oyun deseni değildir. Bilgisayar biliminde sonlu durum makinesi (finite state machine, FSM) biçimsel bir modeldir: sınırlı sayıda durum, olaylarla tanımlı geçişler. Derleyiciler, ağ protokolleri, arayüz ekranları ve gömülü sistemler aynı fikri kullanır. Bu kitapta otomat teorisinin matematiğine girilmez; menü–oyun–bitiş diyagramı ile aynı aileye ait pratik sürüm yeterlidir.
Bilgi: Robert Nystrom'un Game Programming Patterns kitabındaki State bölümü, durum makinesini oyun mimarisinde ayrıntılı ele alır: https://gameprogrammingpatterns.com/state.html — bu kitapta yalnızca string tabanlı basit sürüm kullanılacaktır.
Bilgi — nesne yönelimli tasarımla ilişkisi: Durum makinesi, nesne yönelimli tasarıma (OOP) çok uygundur. Durum sayısı arttıkça draw() içindeki if / else if zinciri uzar; OOP yaklaşımında her durum ayrı bir sınıf olur, kendi guncelle() ve ciz() metotlarını taşır, geçiş ise aktif durum nesnesini değiştirmeye indirgenir. Nystrom'un anlattığı State deseni budur. Sınıflar ve kalıtım İleri Teknikler kitabında işlendiğinde durum diyagramı konusuna bu açıdan yeniden dönülecektir; şimdilik string sabitli sürüm hem yeterli hem de okunması kolaydır.
Günlük hayattan basit örnekler
Durum makinesi kavramı oyun programlamasına özgü değildir; aşağıdaki üç örnek de üç durumlu iskelet gösterir — tıpkı menü/oyun/bitiş gibi. Trafik ışığında kırmızıdan yeşile doğrudan geçilmez; önce sarı, sonra yeşil, ardından yine sarı, yeniden kırmızı gelir. Turnikede kart okutulunca önce doğrulama beklenir; kart geçersizse veya kimse geçmeden 5 sn dolarsa sistem Kilitli'ye döner. Medya oynatıcıda play ile Çalıyor, pause ile Duraklatıldı'ya geçilir; stop veya şarkı bitince Durduruldu'ya dönülür. Ortak nokta: sistem bir anda tek durumdadır ve yalnızca somut bir olay olunca başka duruma geçer.
Bu üç örneğin diyagramları biraz aşağıda, Mermaid anlatıldıktan hemen sonra gelir.
Durum diyagramını kendiniz çizmek
Diyagramda kutular = durumlar, oklar = geçişler, ok yazısı = olay (SPACE, çarpışma, R…). Kâğıt yeterlidir; dijital için de ücretsiz araçlar vardır.
Mermaid, diyagramı düz metin satırlarıyla tanımlamanızı sağlayan bir notasyondur. Metni Mermaid Live Editor adresine yapıştırdığınızda şekil otomatik oluşur; kaynak metin dosyada saklanabildiği için Git gibi sürüm kontrolüne de uygundur. Yapay zekâya geçiş tablonuzu verip “bunu stateDiagram-v2 olarak yaz” demek yaygındır; çıkan metni mutlaka Live Editor’da açıp okları kontrol edin (YZ bazen hatalı sözdizimi üretir). Ok veya kutu renkleri gibi görünüm isteklerini de YZ’ye sorabilirsiniz — bunun için aşağıdaki Mermaid YZ etkinliğindeki makyaj adımına bakın.
Kod bloğu: Basit durum diyagramı (Mermaid) — menü / oyun / bitiş.
Kod 1.
stateDiagram-v2 [*] --> menu menu --> oyun : SPACE oyun --> bitis : carpisma bitis --> menu : RSatır satır mantık:
Tablo 3.
| Satır | Anlam |
|---|---|
stateDiagram-v2 |
Bu bir durum diyagramıdır (Mermaid sözdizimi sürümü) |
[*] --> menu |
Siyah nokta ([*]) = başlangıç; sketch açılınca ilk durum menu |
menu --> oyun : SPACE |
menu iken SPACE olayı → oyun durumuna geç |
oyun --> bitis : carpisma |
oyun iken çarpışma → bitis |
bitis --> menu : R |
bitis iken R → yeniden menu |
A --> B : olay kalıbında sol durum, sağ durum, iki nokta sonrası ok etiketidir. Bu metin, p5.js’teki oyunDurumu = DURUM_OYUN atamalarının görsel özetidir; diyagram kod yazmaz, yalnızca geçiş kurallarını resmeder.

Görsel 2 solda aynı Mermaid kodunu, sağda canlı editörde oluşacak çıktıya benzer bir diyagramı gösterir. Resmi sözdizimi: State diagrams — Mermaid.
Diğer çevrimiçi araçlar (sürükle-bırak):
Tablo 4.
| Araç | Adres | Not |
|---|---|---|
| diagrams.net (draw.io) | https://app.diagrams.net | Genel diyagram; durum kutusu + ok |
| Excalidraw | https://excalidraw.com | El çizimi hissi; hızlı taslak |
| Mermaid Live | https://mermaid.live | Metinden otomatik şekil |
Bilgi: Ödev veya defter için önce Mermaid veya kâğıtta üç kutu + üç ok yeterlidir. Amaç sanat değil; “hangi olay hangi duruma götürür?” sorusunu tek bakışta yanıtlamaktır. Kod yazarken bu diyagram, keyPressed() ve draw() dallarının kontrol listesi olur.
Yukarıdaki günlük hayat örneklerinin Mermaid karşılıkları (her birinde önce kod, sonra diyagram):
Kod bloğu: Trafik ışığı (Mermaid).
Kod 2.
stateDiagram-v2 direction LR [*] --> kirmizi kirmizi: Kırmızı sari: Sarı yesil: Yeşil kirmizi --> sari : 20 sn bekle sari --> yesil : 3 sn bekle yesil --> sari : 25 sn bekle sari --> kirmizi : 3 sn bekle
Görsel 3, üç renkli döngüdür: Kırmızı → Sarı → Yeşil → Sarı → Kırmızı. Kırmızıdan yeşile doğrudan ok yok; sarı hem yeşile hazırlık hem kırmızıya uyarı rolündedir. Geçişler süre dolmasıyla olur (ör. 20 / 3 / 25 / 3 sn).
Kod bloğu: Turnike / geçiş kapısı (Mermaid).
Kod 3.
stateDiagram-v2 direction LR [*] --> kilitli kilitli: Kilitli dogrulaniyor: Doğrulanıyor acik: Açık kilitli --> dogrulaniyor : kart okutuldu dogrulaniyor --> acik : kart geçerli dogrulaniyor --> kilitli : kart geçersiz acik --> kilitli : geçildi acik --> kilitli : 5 sn içinde geçilmedi
Görsel 4, turnike örneğidir: kart okutuldu → doğrulanıyor → geçerliyse Açık; geçersizse veya süre dolarsa doğrudan Kilitli'ye döner. Turnikeye itmek başlı başına bir olay değildir — Kilitli iken hiçbir geçiş tanımlı olmadığı için sistem olduğu yerde kalır; menüde WASD'ın hiçbir şey yapmamasıyla aynı mantık.
Kod bloğu: Medya oynatıcı (Mermaid).
Kod 4.
stateDiagram-v2 direction LR [*] --> durduruldu durduruldu: Durduruldu calisiyor: Çalıyor duraklatildi: Duraklatıldı durduruldu --> calisiyor : play tıklandı calisiyor --> duraklatildi : pause tıklandı duraklatildi --> calisiyor : play tıklandı calisiyor --> durduruldu : stop / şarkı bitti duraklatildi --> durduruldu : stop tıklandı
Görsel 5, üç durumludur: Durduruldu ↔ Çalıyor ↔ Duraklatıldı. Menü / oyun / bitiş iskeletine doğrudan oturur; DURUM_DURAKLAT eklemek istediğinizde de aynı kalıp kullanılır — yeni sabit, yeni geçiş satırları.
Başka oyunlardan örnekler
Aynı omurga başka türlerde de görülür. Geçiş sütununda durum adları aynen kullanılır: “Şu durum iken şu olursa → bu durum”.
Tablo 5.
| Örnek | Durumlar (o anda ne olur?) | Geçişler |
|---|---|---|
| Satranç (sıra tabanlı) | Beyazın sırası: yalnızca beyaz taş oynanır. Siyahın sırası: yalnızca siyah. Oyun bitti: mat/pat; hamle kabul edilmez. | • Beyazın sırası iken hamle oyunu bitirmiyorsa → Siyahın sırası • Beyazın sırası iken hamle mat veya pat üretirse → Oyun bitti • Siyahın sırası iken hamle oyunu bitirmiyorsa → Beyazın sırası • Siyahın sırası iken hamle mat veya pat üretirse → Oyun bitti |
| Hafıza kartları | İlk kart: bir kapalı kart açılır; ikinci seçim beklenir. İkinci kart: başka bir kapalı kart açılır; iki yüz görünür. Eşleşme kontrolü: kısa bekleme; eşleşirse açık kalır, değilse kapanır. Bitti: tüm çiftler bulundu. | • İlk kart iken kart açılırsa → İkinci kart • İkinci kart iken kart açılırsa → Eşleşme kontrolü • Eşleşme kontrolü iken kartlar eşleşmezse → İlk kart • Eşleşme kontrolü iken eşleşme olur ama kapalı çift kalmışsa → İlk kart • Eşleşme kontrolü iken son çift de eşleşirse → Bitti |
| Bilgi yarışması | Soru: bir sorunun metni + şıklar + süre (10 veya 50 soruda da aynı durum). Cevap kontrolü: o sorunun doğru/yanlış geri bildirimi; şıklar kilitli. Sonuç: tüm sorular bitince toplam puan. | • Soru iken şık seçilirse veya süre dolarsa → Cevap kontrolü • Cevap kontrolü iken sonraki soru varsa → Soru • Cevap kontrolü iken soru kalmadıysa → Sonuç |
| Tetris | Parça düşüyor: oklarla hareket/döndürme. Satır temizleme: dolu satırlar silinirken kontrol kapalı. Oyun bitti: yeni parça doğduğu yere sığmaz (tepe dolmuştur). | • Parça düşüyor iken parça yere oturur ve satır doluysa → Satır temizleme • Satır temizleme iken animasyon biterse → Parça düşüyor • Parça düşüyor iken parça yere oturur ve dolu satır yoksa → Parça düşüyor (yeni parça) • Parça düşüyor iken yeni parça yerleştirilemezse → Oyun bitti |
| XOX (bir sonraki ana başlık) | Menü: kurallar. X'in sırası: yalnızca X boş hücreye konur. O'nun sırası: yalnızca O konur. Bitiş: üçlü veya berabere. | • Menü iken SPACE basılırsa → X'in sırası • X'in sırası iken hamle oyunu bitirmiyorsa → O'nun sırası • X'in sırası iken hamle üçlü yapar veya tahtayı doldurursa → Bitiş • O'nun sırası iken hamle oyunu bitirmiyorsa → X'in sırası • O'nun sırası iken hamle üçlü yapar veya tahtayı doldurursa → Bitiş • Bitiş iken R basılırsa → Menü |
XOX’ta X/O sırası kavramsal olarak ayrı durumdur; bir sonraki ana başlıkta bunlar tek DURUM_OYUN içinde sira = "X" / "O" değişkeniyle tutulur — menü/oyun/bitiş omurgası aynı kalır, sıra ise oyun içi alt bilgidir. Aşağıda ilk dört örneğin Mermaid diyagramları vardır.
Kod bloğu: Satranç (Mermaid).
Kod 5.
stateDiagram-v2 direction LR [*] --> beyaz beyaz: Beyazın sırası siyah: Siyahın sırası bitti: Oyun bitti beyaz --> siyah : hamle (oyun sürüyor) siyah --> beyaz : hamle (oyun sürüyor) beyaz --> bitti : hamle mat veya pat siyah --> bitti : hamle mat veya pat
Kod bloğu: Hafıza kartları (Mermaid).
Kod 6.
stateDiagram-v2 direction LR [*] --> ilk ilk: İlk kart ikinci: İkinci kart kontrol: Eşleşme kontrolü bitti: Bitti ilk --> ikinci : kart açıldı ikinci --> kontrol : kart açıldı kontrol --> ilk : eşleşmedi kontrol --> ilk : eşleşti (çift kaldı) kontrol --> bitti : tüm çiftler bulundu
Kod bloğu: Bilgi yarışması (Mermaid).
Kod 7.
stateDiagram-v2 direction LR [*] --> soru soru: Soru kontrol: Cevap kontrolü sonuc: Sonuç soru --> kontrol : şık seçildi / süre doldu kontrol --> soru : sonraki soru kontrol --> sonuc : sorular bitti
Kod bloğu: Tetris (Mermaid).
Kod 8.
stateDiagram-v2 direction LR [*] --> dusuyor dusuyor: Parça düşüyor temizle: Satır temizleme bitti: Oyun bitti dusuyor --> temizle : yere oturdu (satır dolu) temizle --> dusuyor : animasyon bitti dusuyor --> dusuyor : yere oturdu (satır yok) dusuyor --> bitti : tepe doldu
Oyun döngüsünde (draw()) tipik akış:
- Mevcut durumu oku (
oyunDurumu). - Duruma göre güncelle (yalnızca
"oyun"iken hareket, çarpışma). - Duruma göre çiz (menü metni veya oyun sahnesi).
- Olay fonksiyonlarında (
keyPressed) duruma göre geçiş uygula.
2.2. Oyun Durumunu Saklama
Durum değerleri genelde metin (string) olarak tutulur; yazım hatasını azaltmak için const sabitleri tanımlanır (önceki bölümlerde const HEDEF_SKOR örfü).
Kod 9.
const DURUM_MENU = "menu";const DURUM_OYUN = "oyun";const DURUM_BITIS = "bitis"; let oyunDurumu = DURUM_MENU;Tablo 6.
| Sabit | Anlam |
|---|---|
DURUM_MENU |
Başlangıç / ana menü |
DURUM_OYUN |
Aktif oyun |
DURUM_BITIS |
Oyun bitti ekranı |
oyunDurumu değişkeni sketch boyunca güncellenir; setup() içinde başlangıç değeri atanır. Karşılaştırmalarda === kullanılır:
Kod 10.
if (oyunDurumu === DURUM_OYUN) { // yalnızca oyun aşamasında çalışır}Dikkat: Durum string'lerini doğrudan "menu" yazmak da mümkündür; sabitler aynı kelimenin farklı yerlerde tutarlı yazılmasını sağlar. "menü" ile "menu" farklı string'lerdir — karşılaştırma başarısız olur.
Bu tür bir yazım hatası, çalışma zamanında görünür bir hata mesajı üretmez; JavaScript, tanımsız bir string'i sessizce kabul eder ve karşılaştırma yalnızca false döner. Sonuç, oyunun beklenen durumdan çıkmaması ve nedeni belirsiz bir "hiçbir şey olmuyor" davranışıdır — örneğin SPACE tuşuna basıldığında oyun başlamaz, çünkü oyunDurumu === DURUM_MENU koşulu, DURUM_MENU sabiti yanlış yazıldığı için hiçbir zaman doğru olmaz. Sabit kullanmanın asıl kazancı budur: yazım hatası yapıldığında JavaScript, tanımsız bir değişken adı için (sabit tanımlanmamışsa) hata verir; bu da sorunu doğrudan işaret eder ve serbest metin string'lerinde olduğu gibi sessiz kalmaz.
Oyun verileri (skor, oyuncu konumu, top hızı) durumdan bağımsız değişkenlerde tutulabilir; yalnızca hangi kodun çalışacağı duruma bağlanır. Oyun başlarken konumları sıfırlamak için yardımcı fonksiyon kullanılabilir (önceki bölümler, fonksiyonlar):
Kod 11.
function oyunuSifirla() { skor = 0; oyuncuX = width / 2; oyuncuY = height / 2; topX = random(50, width - 50); topY = 40; hizX = random(-120, 120); hizY = 80;}random() önceki bölümlerde tanıtılmıştır; başlangıç top konumu ve hızı her turda farklı olabilir.
2.3. Duruma Göre Çizim ve Girdi
draw() içinde durum dallanması yaygın örüntüdür: her durum için ayrı çizim bloğu veya yardımcı fonksiyon.
Kod bloğu: Duruma göre draw() — iskelet.
Kod 12.
function draw() { if (oyunDurumu === DURUM_MENU) { cizMenu(); } else if (oyunDurumu === DURUM_OYUN) { guncelleOyun(); cizOyun(); } else if (oyunDurumu === DURUM_BITIS) { cizBitis(); }}Tablo 7.
| Fonksiyon | Görev |
|---|---|
cizMenu() |
Arka plan, başlık, talimat metni |
guncelleOyun() |
Hareket, çarpışma, skor (yalnızca oyun aşaması) |
cizOyun() |
Oyuncu, top, arayüz |
cizBitis() |
Son skor, yeniden başlatma talimatı |
Duruma göre hangi fonksiyonların çalıştığı özet tablo:
Tablo 8.
| Durum | draw() içinde |
keyPressed() |
Sürekli girdi (keyIsDown) |
|---|---|---|---|
DURUM_MENU |
cizMenu() |
SPACE → oyuna geç | Yok sayılır |
DURUM_OYUN |
guncelleOyun() + cizOyun() |
— | WASD / ok tuşları |
DURUM_BITIS |
cizBitis() |
R → menüye dön | Yok sayılır |

Görsel 10, draw() içindeki if / else if zincirinin her durumda farklı çizim ve güncelleme fonksiyonlarına yönlendiğini gösterir.
Girdi de duruma bağlı olmalıdır. Örneğin WASD yalnızca DURUM_OYUN iken oyuncuyu hareket ettirmeli; menüde aynı tuşlar farklı iş yapabilir veya yok sayılabilir.
Kod bloğu: keyPressed() — duruma göre geçiş.
Kod 13.
function keyPressed() { if (oyunDurumu === DURUM_MENU && key === " ") { oyunuSifirla(); oyunDurumu = DURUM_OYUN; } if (oyunDurumu === DURUM_BITIS && (key === "r" || key === "R")) { oyunDurumu = DURUM_MENU; }}keyPressed() tek seferlik olaydır; menüde SPACE ve bitişte R için uygundur (Bölüm 3 Ana Başlık 4). Oyun içi sürekli hareket keyIsDown() ile guncelleOyun() içinde kalır.
Dikkat: mousePressed() içinde de if (oyunDurumu === DURUM_MENU) ile yalnızca menüde tıklama işlenmelidir; aksi halde bitiş ekranında tıklama oyun mantığını tetikleyebilir. XOX'ta hamle yalnızca oyun durumundayken kabul edilecektir.
2.4. Geçiş Kuralları
Geçiş kuralları tablo halinde yazıldığında tasarım netleşir; kod bu tabloya karşılık gelir.
Mini oyun (Kaç-Kaç top) geçiş tablosu:
Tablo 9.
| Mevcut durum | Olay / koşul | Yeni durum | Ek işlem |
|---|---|---|---|
DURUM_MENU |
SPACE basıldı | DURUM_OYUN |
oyunuSifirla() |
DURUM_OYUN |
Oyuncu–hedef teması | DURUM_OYUN (değişmez) |
skor artar, hedefYerlestir() |
DURUM_OYUN |
Oyuncu–top çarpışması | DURUM_BITIS |
— |
DURUM_BITIS |
R basıldı | DURUM_MENU |
— |
İkinci satır, her olayın durum değiştirmediğini gösterir: hedef toplamak skoru artırır ama oyun DURUM_OYUN içinde kalır. Durum değişikliği yalnızca tabloda yeni durum yazan satırlarda olur.
Her iki temas da önceki ana başlıktaki daire testiyle bulunur: oyuncu merkezi (oyuncuX + BOYUT/2, oyuncuY + BOYUT/2) ile top veya hedef merkezi arası dist(); toplam yarıçaptan küçükse temas vardır.
Geçersiz geçişler bilinçli olarak yok sayılır: menüdeyken WASD oyuncuyu hareket ettirmemeli (guncelleOyun() yalnızca oyun durumunda çağrılır). Bu, durum makinesinin “her aşamada ne mümkün?” sorusuna yanıt vermesidir.
Bilgi: İleride duraklatma (DURUM_DURAKLAT) eklenecekse geçiş tablosuna yeni satırlar eklenir; mevcut üç durumlu iskelet genişlemeye uygundur.
Geçiş tablosunun kâğıt üzerinde önce yazılması, kodlamadan önce bir tasarım adımı olarak değerli bir alışkanlıktır. Tablo doldurulurken her satır için "bu olay gerçekleştiğinde oyuncu ekranda ne görmeli, hangi tuşlar anlamlı olmalı?" sorusu sorulur. Bu sorular yanıtlanmadan doğrudan kod yazılırsa, genellikle unutulan bir geçiş (örneğin bitiş ekranında yanlışlıkla SPACE'in de menüye dönmesi) ortaya çıkar ve hata ayıklaması, kodun her yerine dağılmış if koşulları arasında zaman alır. Tablo hazır olduğunda ise draw() ve keyPressed() gövdeleri, tablodaki satırların doğrudan çevirisinden ibaret hâle gelir.
XOX için aynı oyunDurumu menü/oyun/bitiş akışına ek olarak tahta verisi (tahta dizisi), sıra ("X" / "O") ayrı değişkenlerde tutulacak; oyun aşaması ile tahta mantığı birbirinden ayrılacaktır.
Yapay Zekâ Etkileşimi: Durum Diyagramı Tahmini süre: 15–20 dakika.
Amaç: Menü–oyun–bitiş geçişlerini kodlamadan önce tasarlamak.
Adım 1: Üç durum ve en az dört geçişi kâğıda çizin. Adım 2: Yapay zekâdan aynı diyagramı metinle isteyin; eksik geçiş var mı bakın. Adım 3: “Pause” eklemek isterseniz hangi yeni durum ve geçişlerin gerekeceğini sorun.
Özet
Durum makinesi, sistemin her an yalnızca bir durumda bulunduğu ve tuş, tıklama, süre veya çarpışma gibi belirli olaylarla başka duruma geçtiği bir modeldir; oyun bağlamında omurga çoğunlukla menü, oyun ve bitiş üçlüsüdür. Aşamaları ayrı boolean değişkenlerle izlemek risklidir, çünkü iki bayrağın aynı anda doğru olması hem çizimi hem girdinin hangi bloğa gideceğini belirsizleştirir. Tek bir oyunDurumu değişkeninde ise her an tek bir değer bulunur ve geçiş tek satırlık bir atamaya iner. Durum değerleri metin olarak tutulur; const sabitleri tanımlamak sessizce başarısız olan yazım hatalarını önler, karşılaştırmalar ise === ile yapılır.
draw gövdesi duruma göre dallanır: menüde yalnızca menü çizimi, oyun aşamasında güncelleme ile sahne çizimi, bitişte sonuç ekranı çalışır. Girdi de aynı biçimde bölünür; menüde SPACE oyunu başlatırken sürekli hareket tuşları yalnızca oyun aşamasında okunur, bitiş ekranında R menüye döndürür. Böylece aynı tuş farklı aşamalarda farklı iş yapabilir veya bilinçli olarak yok sayılır.
Geçişler rastgele değil kurala bağlıdır ve mevcut durum, olay, yeni durum sütunlarıyla tabloya dökülebilir; her olay durumu değiştirmez, örneğin hedefe temas skoru artırır ama oyun aşamasında kalınır. Diyagram veya tablo, koddan önce tasarımı netleştirir; menü–oyun–bitiş akışının tam sketch’i bir sonraki ana başlıkta tamamlanır.
Neler Öğrendik?
Soru 1 Durum makinesinde sistem aynı anda kaç durumda olmalıdır?
A) Sınırsız
B) Tipik olarak tek ana durumda
C) Zorunlu sıfır
D) Yalnızca CSS’te
E) Yalnızca sunucuda
Soru 2
oyunDurumu değişkeninin rolü nedir?
A) Aktif ekran / aşamayı saklamak
B) Tuval DPI’sini silmek
C) Git remote eklemek
D) Yazıcı seçmek
E) DNS yenilemek
Soru 3 Duruma göre girdi ayırmanın gerekçesi nedir?
A) Aynı tuşun menü ve oyunda farklı iş yapabilmesi
B) Matematiği kaldırmak
C) Renkleri yasaklamak
D) setup’ı çoğaltmak
E) EPUB zorunluluğu
Soru 4 Geçiş kuralı neyi tanımlar?
A) Hangi olayın hangi yeni duruma götüreceğini
B) Yalnızca font boyutunu
C) Yalnızca dosya adını
D) Yalnızca batarya seviyesini
E) Yalnızca Wi-Fi şifresini
Neler Öğrendik Yanıt Anahtarı
Soru 1: Doğru Cevap: B
- Çözüm: Tek aktif durum modeli sadedir.
- İlgili Konu: 2.1. Durum Makinesi Kavramı
Soru 2: Doğru Cevap: A
- Çözüm: Durum değişkeni aşamayı tutar.
- İlgili Konu: 2.2. Oyun Durumunu Saklama
Soru 3: Doğru Cevap: A
- Çözüm: Girdi yolları duruma göre ayrılır.
- İlgili Konu: 2.3. Duruma Göre Çizim ve Girdi
Soru 4: Doğru Cevap: A
- Çözüm: Olay → yeni durum eşlemesi.
- İlgili Konu: 2.4. Geçiş Kuralları
Yararlanılan Kaynaklar
Bu içerik aşağıdaki kaynaklardan derlenerek hazırlanmıştır:
- Excalidraw. (n.d.). https://excalidraw.com
- McCarthy, L., Reas, C., & Fry, B. (2015). Make: Getting Started with p5.js. Maker Media.
- Mermaid Live Editor. (n.d.). https://mermaid.live
- Mermaid. (n.d.). State diagrams. https://mermaid.js.org/syntax/stateDiagram.html
- Nystrom, R. (2014). Game Programming Patterns — State. https://gameprogrammingpatterns.com/state.html
- p5.js Foundation. (n.d.). keyPressed. p5.js Reference. https://p5js.org/reference/p5/keyPressed/
- Shiffman, D. (n.d.). Code! Programming with p5.js. The Coding Train. https://thecodingtrain.com/tracks/code-programming-with-p5-js
Ana Başlık 3. Menü–Oyun–Bitiş Akışı ve Kaç-Kaç
Amaç: Durum makinesini menü–oyun–bitiş akışında uygulayarak kaç-kaç benzeri mini oyunu tamamlamak.
Öğrenme Çıktıları:
- Menü, oyun ve bitiş ekranlarını ayrı durumlar olarak çizer.
- Start / yeniden dene geçişlerini kodlar.
- Oyun durumunda hareket ve basit kural uygular.
- Bütünleşik mini oyunu çalışır sketch olarak sunar.
Anahtar Sözcükler: menü, bitiş, geçiş, kaç-kaç, oyun döngüsü, durum
Giriş
Durum, girdi ve geçiş kuralları bilindikten sonra sıra bunları tek sketch’te birleştirmeye gelir. Menü ekranı yönerge ve Start bekler; oyun durumu hareket, çarpışma veya kaçış kuralını çalıştırır; bitiş ekranı skor veya sonucu gösterip yeniden başlatma sunar.
Kaç-kaç benzeri örnek, önceki ana başlıkların (hareket, girdi, çarpışma fikri) durum makinesiyle örülmesidir. Amaç AAA üretim değil; okunabilir oyunDurumu dallarıyla bütünleşik bir akış bitirmektir. Bu alışkanlık, sonraki XOX projesinde menü ve tur yönetimini de kolaylaştırır. Bundan sonra gelen alt başlıklarda önce veri modeli, sonra hamle kuralı, en sonda çizim ve etkileşim kurulur. Her yeni fonksiyon mümkün olduğunca küçük bir örnekte çalıştırılır; böylece hatanın kaynağı daha kolay bulunur. Anlatımda önce ilgili yapının ne işe yaradığı açıklanır, ardından kod satır satır okunur. Terimler ilk geçtikleri yerde kısa bir tanımla verilir; gerekirse tablo veya görsel ile desteklenir. Örnek sketch’ler tek bir mekaniğe odaklanır; böylece yan konular okumayı dağıtmaz. Parametreleri değiştirip yeniden çalıştırmak, kuralın sınırını görmenin en hızlı yoludur. Bu ana başlığın çıktısı, sonraki oyunda yeniden kullanılabilecek bir iskelet oluşturur.
3.1. Kaç-Kaç Top: Kurallar ve Durum Tasarımı
Aşağıdaki Kaç-Kaç Top mini oyunu üç durumu birleştirir: menüde SPACE ile başlama, oyun içinde WASD ile hedef toplama, topa değince bitiş, R ile menüye dönüş. Skor yalnızca hedefe dokununca artar; bu yüzden köşede beklemek işe yaramaz, oyuncu topun yakınına gitmeyi göze almak zorundadır.
Oyun kuralları:
- Menü: “SPACE — başla” metni.
- Oyun: Kare oyuncu WASD/ok ile hareket eder; top duvarlardan sekerek hareket eder (
deltaTime, Bölüm 2 Ana Başlık 4–3). - Ekranda bir hedef (küçük yeşil daire) durur; oyuncu ona değince skor 1 artar ve hedef başka bir yere taşınır.
- Top oyuncuya değerse bitiş ekranı; skor gösterilir.
- Bitiş: R ile menüye dönülür.
3.2. Tam Sketch ve Akışın Okunması
Kod 1.
const DURUM_MENU = "menu";const DURUM_OYUN = "oyun";const DURUM_BITIS = "bitis"; const BOYUT = 36;const TOP_YARICAP = 20;const HEDEF_YARICAP = 12;const HIZ_OYUNCU = 200;const UZAK_MESAFE = 90; // hedef oyuncuya bu kadar uzakta doğar let oyunDurumu;let oyuncuX, oyuncuY;let topX, topY, hizX, hizY;let hedefX, hedefY;let skor; function setup() { createCanvas(520, 360); noStroke(); oyunDurumu = DURUM_MENU;} function draw() { if (oyunDurumu === DURUM_MENU) { cizMenu(); } else if (oyunDurumu === DURUM_OYUN) { guncelleOyun(); cizOyun(); } else if (oyunDurumu === DURUM_BITIS) { cizBitis(); }} function cizMenu() { background(28, 32, 48); fill(255); textSize(28); textAlign(CENTER, CENTER); text("Kac-Kac Top", width / 2, height / 2 - 40); textSize(16); text("Topa degmeden hedefleri topla", width / 2, height / 2); text("SPACE — başla", width / 2, height / 2 + 50);} function guncelleOyun() { let dt = deltaTime / 1000; if (keyIsDown(LEFT_ARROW) || keyIsDown(65)) oyuncuX -= HIZ_OYUNCU * dt; if (keyIsDown(RIGHT_ARROW) || keyIsDown(68)) oyuncuX += HIZ_OYUNCU * dt; if (keyIsDown(UP_ARROW) || keyIsDown(87)) oyuncuY -= HIZ_OYUNCU * dt; if (keyIsDown(DOWN_ARROW) || keyIsDown(83)) oyuncuY += HIZ_OYUNCU * dt; oyuncuX = constrain(oyuncuX, 0, width - BOYUT); oyuncuY = constrain(oyuncuY, 0, height - BOYUT); topX += hizX * dt; topY += hizY * dt; if (topX - TOP_YARICAP < 0) { topX = TOP_YARICAP; hizX = -hizX; } if (topX + TOP_YARICAP > width) { topX = width - TOP_YARICAP; hizX = -hizX; } if (topY - TOP_YARICAP < 0) { topY = TOP_YARICAP; hizY = -hizY; } if (topY + TOP_YARICAP > height) { topY = height - TOP_YARICAP; hizY = -hizY; } let px = oyuncuX + BOYUT / 2; let py = oyuncuY + BOYUT / 2; if (dist(px, py, hedefX, hedefY) < HEDEF_YARICAP + BOYUT / 2) { skor += 1; hedefYerlestir(); } if (dist(px, py, topX, topY) < TOP_YARICAP + BOYUT / 2) { oyunDurumu = DURUM_BITIS; }} function cizOyun() { background(22, 28, 42); fill(120, 230, 140); ellipse(hedefX, hedefY, HEDEF_YARICAP * 2, HEDEF_YARICAP * 2); fill(100, 200, 255); rect(oyuncuX, oyuncuY, BOYUT, BOYUT); fill(255, 190, 70); ellipse(topX, topY, TOP_YARICAP * 2, TOP_YARICAP * 2); fill(255); textSize(16); textAlign(LEFT, TOP); text("Skor: " + skor, 12, 12);} function cizBitis() { background(35, 25, 30); fill(255); textSize(26); textAlign(CENTER, CENTER); text("Oyun bitti", width / 2, height / 2 - 50); textSize(18); text("Skor: " + skor, width / 2, height / 2); textSize(14); text("R — menüye dön", width / 2, height / 2 + 50);} function hedefYerlestir() { let px = oyuncuX + BOYUT / 2; let py = oyuncuY + BOYUT / 2; let kenar = HEDEF_YARICAP + 10; hedefX = random(kenar, width - kenar); hedefY = random(kenar, height - kenar); let deneme = 0; // Güvenlik sınırı: UZAK_MESAFE tuvale göre çok büyük seçilirse uygun konum // bulunamaz ve draw() içindeki bu döngü sketch'i dondurur. while (dist(px, py, hedefX, hedefY) < UZAK_MESAFE && deneme < 50) { hedefX = random(kenar, width - kenar); hedefY = random(kenar, height - kenar); deneme = deneme + 1; }} function oyunuSifirla() { oyuncuX = width / 2 - BOYUT / 2; oyuncuY = height / 2 - BOYUT / 2; topX = random(60, width - 60); topY = 50; hizX = random(-100, 100); hizY = random(80, 140); skor = 0; hedefYerlestir();} function keyPressed() { if (oyunDurumu === DURUM_MENU && key === " ") { oyunuSifirla(); oyunDurumu = DURUM_OYUN; } if (oyunDurumu === DURUM_BITIS && (key === "r" || key === "R")) { oyunDurumu = DURUM_MENU; }}Bu sketch, önceki ana başlıklardaki deltaTime, klavye, constrain, çarpışma (dist) ve önceki bölümlerdeki fonksiyon modülerliğini tek akışta toplar. Sonraki ana başlıkta DURUM_OYUN içinde 3×3 tahta çizimi ve tıklama ile hamle eklenecektir; menü ve bitiş aynı oyunDurumu değişkeniyle yönetilmeye devam edecektir.
draw() her zaman başlangıç noktasıdır: üç if / else if dalından yalnızca biri, oyunDurumu'nun o anki değerine göre çalışır. Oyun aşamasına girildiğinde guncelleOyun() önce klavye durumunu okuyup oyuncu konumunu günceller, ardından topu duvarlardan sekmeli biçimde hareket ettirir, sonra dist() ile önce hedefe değilip değilmediğine (skor + yeni hedef), en son da topa çarpılıp çarpılmadığına bakar. Çarpışma tespit edildiği an fonksiyon içinde oyunDurumu = DURUM_BITIS atanır; bu atamadan sonra aynı frame'de cizOyun() yine çağrılır (son sahneyi göstermek için), fakat bir sonraki draw() çağrısında artık else if (oyunDurumu === DURUM_BITIS) dalı çalışacak ve cizBitis() devreye girecektir. oyunuSifirla() fonksiyonu, yalnızca menüden oyuna geçişte çağrılarak her yeni turun rastgele ama tutarlı bir başlangıç konumuyla başlamasını sağlar; bu, önceki bölümlerde tanıtılan random() fonksiyonunun durum makinesiyle birleştirilmiş hâlidir.
3.3. Geçişlerin Doğrulanması ve Uygulama Etkinlikleri
Aşağıdaki Yapay Zekâ Etkileşimi etkinlikleri kavramdan diyagrama ve koda doğru sıralanır. İlk ikisi kısadır (kavram çıkarımı ve Mermaid diyagramı); ardından gelen Hafıza kartları mini oyun projesi bu zamana kadar öğrenilenleri bir araya getirir. Son etkinlik ise unutulan geçişleri yakalamaya odaklanan kısa bir hata ayıklama alıştırmasıdır. İstenen etkinlik seçilebilir; hepsini yapmak pekiştirir.
Yapay Zekâ Etkileşimi: Oyunlardan durum makinesi çıkarmak Tahmini süre: 20–25 dakika.
Amaç: Tanıdık bir oyunun aşamalarını durum / olay / geçiş diline çevirmek. Bu etkinlikte tam oyun kodu yazmanız beklenmez.
Adım 1 — Önce kendiniz yazın: Yukarıdaki tablodan veya bildiğiniz bir oyundan birini seçin (satranç, hafıza kartları, Tetris, XOX…). En az üç durum bulun. Her durum için iki kısa not: ekranda ne görünür? Hangi tuş / tıklama işe yarar?
Adım 2 — Örnek istem: "Yeni başlayan bir oyun programcısıyım. Şu oyunu durum makinesi gözüyle anlat: [oyun adı]. (1) En az 3–5 anlamlı durum (menü / hazır / oynuyor / duraklatma / bitti vb. — oyuna uygun olanlar). (2) Her durum için: ekranda tipik olarak ne görünür, hangi girdiler anlamlıdır? (3) Geçişleri tablo yap: mevcut durum | olay | yeni durum (en az 5 satır). (4) Bu oyunda durum makinesi olmasa (her şey dağınık boolean / if olsa) hangi tür hatalar kolay çıkar? İki somut örnek ver. Türkçe yaz; kod yazma; formül ezberletme."
Adım 3 — Kontrol ve kendi kararınız: YZ’nin verdiği durum listesini okuyun. Yanlış veya gereksiz bir şey var mı? (Örnek: basit satrançta “duraklatma menüsü” şart değildir; YZ bazen böyle ekstra durum ekler.) Sonra kendi mini oyununuz için (Kaç-Kaç Top veya aklınızdaki küçük oyun) şu üç soruyu yanıtlayın:
- Hangi üç durum şart?
- Her biri ne işe yarar? (birer kısa cümle)
- Neden bu üçü yeterli / gerekli?
Örnek yanıt: “Menü, oyun, bitiş şart. Menüde başlatma, oyunda hareket, bitişte skor gösterilir; üçünü tek ekranda karıştırmak istemem.”
Not: YZ bazen yanlış kural veya uydurma örnek verir. Yanıtı ezberlemeyin; önce kendi bilginizle (veya kısa bir aramayla) kontrol edin, doğru gelenleri kullanın.
Yapay Zekâ Etkileşimi: Mermaid ile durum diyagramı çizdirmek Tahmini süre: 25–35 dakika.
Amaç: Geçiş tablosunu Mermaid metnine çevirmek; Live Editor’da diyagramı görmek; isteğe bağlı olarak ok/kutu renkleri gibi görünümü Mermaid koduyla süslemek. Diyagram p5.js kodu yazmaz; yalnızca “hangi olay hangi duruma götürür?” sorusunu resmeder.
Adım 1 — Önce tabloyu yazın: Kaç-Kaç Top veya kendi mini oyununuz için geçiş tablosu yazın: mevcut durum | olay | yeni durum. En az dört satır. Ayrıca bir olmayan geçiş not edin (ör. menüde R’ye basınca hiçbir şey olmamalı).
Adım 2 — Örnek istem A (diyagram):
"Aşağıdaki durum geçiş tablosunu Mermaid stateDiagram-v2 sözdizimine çevir. Başlangıç için [*] --> ... kullan. Ok etiketlerinde olay adlarını yaz (SPACE, carpisma, R gibi). Yalnızca Mermaid kodu ver; açıklama kısa tut.
[Tabloyu buraya yapıştır]"
Adım 3 — Ekranda kontrol: Çıkan metni Mermaid Live Editor adresine yapıştırın. Diyagram çizilmezse veya ok eksikse YZ’ye “şu hata / şu ok yok, düzelt” diye yazın. Sonucu kitaptaki menü / oyun / bitiş durum diyagramıyla karşılaştırın: menü, oyun, bitiş durumları ve SPACE / çarpışma / R okları var mı?
Adım 4 — Makyaj (görünüm): Diyagram doğruysa görünümü iyileştirmek için YZ’ye sorun. Amaç: okları veya durum kutularını renklendirmek, önemli geçişi (ör. çarpışma → bitiş) vurgulamak. Gelen stil kodunu yine Live Editor’da deneyin; çalışmazsa hata mesajını YZ’ye yapıştırıp düzeltmesini isteyin.
Örnek istem C (makyaj):
"Aşağıdaki Mermaid stateDiagram-v2 kodunu koru; geçişler aynı kalsın. Şunları ekle / ayarla:
(1) menu kutusu yeşilimsi, oyun mavimsi, bitis kırmızımsı olsun (veya benzer net renkler).
(2) oyun --> bitis okunu diğerlerinden daha belirgin / kırmızı yap.
(3) Mümkünse ok kalınlığı veya etiket stilini de biraz ayır.
Yalnızca çalışan Mermaid kodunu ver. Hangi satırların stil için olduğunu kısa madde madde açıkla. Live Editor’da denenecek.
[Adım 2’deki Mermaid kodunu buraya yapıştır]"
İsterseniz kendi listenizi sorun: “yalnızca okları renklendir”, “başlangıç noktasını büyüt”, “Türkçe durum adları kullan (menu → menü)” gibi. Her seferinde çıktıyı Live Editor’da kontrol edin; Mermaid sürümüne göre bazı stil komutları çalışmayabilir — YZ’den alternatif sözdizimi isteyin.
Adım 5 — Örnek istem B (isteğe bağlı, kod bağlantısı):
"Bu Mermaid diyagramındaki her ok, p5.js’te kabaca nereye yazılır? oyunDurumu = ... atamasını draw içinde mi keyPressed içinde mi beklersin? Kod yazma; madde madde eşleştir."
Adım 6 — Dikkat: YZ bazen olmayan bir duruma ok çizer, durum diyagramı yerine akış şeması (flowchart) üretir veya Live Editor’da çalışmayan stil satırı ekler. Sizden istenen önce doğru geçişler, sonra makyajdır. Kutular = durumlar, oklar = olaylı geçişler.
Yapay Zekâ Etkileşimi: Hafıza kartları — durum diyagramından çalışan oyuna Tahmini süre: 60–90 dakika (mekanik öğrenme + kod + YZ ile onarım).
Amaç: Yukarıdaki tabloda ve Hafıza kartları durum diyagramında özetlenen Hafıza kartları oyununu p5.js’te yazmak. Önce mekaniği netleştirin, sonra durum diyagramıyla planlayın, sonra kodu siz yazın. Takıldığınız veya çalışmayan yerlerde YZ’den yardım alın; YZ’yi hem “onarım” hem “öğretmen” gibi kullanın. Bu görev; durum makinesi, diziler, fare tıklaması, fonksiyonlar ve draw / olay ayrımını bir araya getirir. Kaç-Kaç Top ve önceki bölüm sketch’lerindeki desenlerden yararlanın — tüm oyunu YZ’ye baştan yazdırmayın.
Adım 1 — Mekaniği anlayın (YZ’siz + örnek siteler): Bu tür oyunlara İngilizcede Memory, Concentration veya Matching pairs denir. Kapalı kartlardan sırayla iki tanesini açarsınız; eşleşirse açık kalır, değilse kısa süre sonra kapanır; tüm çiftler bulununca biter. Önce en az bir çevrimiçi örneği 2–3 dakika oynayın (kayıt gerekmez):
- MemoryMatching.com — klasik eşleştirme; çeşitli tahta boyutları
- Cognitive Train — Concentration — 4×3 gibi küçük ızgaralar; kurallar sayfada yazılı
Kuralların kısa özeti için: Concentration (card game) — Wikipedia.
İsteğe bağlı istem (mekanik, kod yok): "Hafıza / Memory / Concentration kart oyununu yeni başlayan bir oyun programcısına anlat. (1) Nasıl oynanır? Adım adım. (2) Bu türden bilinen 3–4 oyun veya varyasyon adı ver (ör. Memory, Pairs…). (3) Online ücretsiz oynayabileceğim 2–3 site öner (mümkünse kayıt istemeyen). (4) Programcı gözüyle: hangi anlar ayrı durum olmalı? (ilk kart / ikinci kart / eşleşme kontrolü / bitti gibi) Kod yazma; Türkçe yaz."
Adım 2 — Durum diyagramı (önce plan): Kitaptaki Hafıza kartları satırını ve buna karşılık gelen durum diyagramını temel alın. Kendi geçiş tablonuzu yazın (mevcut durum | olay | yeni durum); ardından Mermaid stateDiagram-v2 ile çizin (Mermaid Live). İsterseniz dışarıda basit bir Menü ve sonda Bitti ekleyin (Kaç-Kaç Top’taki gibi SPACE / R). Diyagram netleşmeden koda geçmeyin.
Adım 3 — Sizin kodunuz (mini oyun): Web Editor’de hedef: küçük bir ızgara (ör. 4×3 → 6 çift). Öneri (zorunlu şablon değil):
constdurum sabitleri +let oyunDurumu(ör. menü, ilk kart, ikinci kart, eşleşme kontrolü, bitti)- Kart verisi: değerler ve açık/kapalı bilgisi için diziler (class / nesne literal yok; Önceki bölümler paralel dizi örfü)
draw(): duruma göre çiz; menü / bitiş metinleri; oyun aşamasında kart dikdörtgenleri (kapalı gri, açıkken sayı veya renk)mousePressed(): yalnızca uygun durumda tıklanan kartı aç; ikinci karttan sonra eşleşme kontrolüne geç- Eşleşmezse kısa bekleme (
millisveya sayaç) sonrası kartları kapatıp İlk karta dön; eşleşirse açık kalsın; tüm çiftler bulununca Bitti - Yeniden başlatma: menüye dönüşte dizileri yeniden karıştırın (
oyunuSifirlabenzeri)
Kaç-Kaç Top’taki oyunDurumu + draw dallanması + oyunuSifirla fikrini yeniden kullanın. Kart karıştırma, tıklanan hücreyi bulma, eşleşme kontrolü sizin yazacağınız kısımlardır.
Adım 4 — Takılınca / çalışmayınca YZ (onarım + öğretmen): Sketch’in tamamını (veya bozulan fonksiyonu) yapıştırın. YZ’den hem düzeltme hem açıklama isteyin; körü körüne yapıştırmayın — gelen her değişikliği okuyun.
Örnek istem — hata / eksik kısım: "p5.js Hafıza kartları sketch’im var (class yok, ek kütüphane yok). Durum makinesi kullanıyorum. Şu sorun var: [ör. ikinci kart açılmıyor / eşleşmeyen kartlar kapanmıyor / tüm çiftler bulununca bitişe geçmiyor / tıklama yanlış kartı seçiyor].
(1) Önce öğretmen gibi anlat: bu hata hangi durum geçişinde veya hangi dizide kaynaklanıyor olabilir?
(2) Sonra yalnızca gerekli satırları düzelt; tüm oyunu baştan yazma.
(3) En sonda: neyi neden değiştirdiğini madde madde, bu ders düzeyinde açıkla (oyunDurumu, dizi, mousePressed, millis…).
Kod:"
(Kendi sketch’inizi yapıştırın. Konsolda kırmızı hata varsa onu da ekleyin.)
Örnek istem — yazamadığınız bir parça:
"p5.js’te class kullanmadan, paralel dizilerle 4×3 hafıza tahtası için yalnızca şu fonksiyonu yaz: kartlariKaristir(). 6 çift (değerler 0–5, her biri iki kez) üretip karıştırsın. Kısa yorum ekle. Başka dosya / kütüphane yok."
Adım 5 — Kontrol listesi:
- Eşleşme kontrolü sırasında yeni kart tıklanabiliyor mu? → Tıklama yok sayılmalı.
- Menüdeyken kart tıklanınca oyun bozuluyor mu? → Bozulmamalı.
- İkinci kart açılmadan “eşleşti mi?” soruluyor mu? → Sorulmamalı.
- Durum adları sabit mi (
DURUM_…), yoksa"ilk"/"İlk kart"karışıyor mu? - Kaç-Kaç Top ile karşılaştırın: YZ neyi gereksiz uzattı, siz neyi daha kısa yazardınız?
Sıra Sizde: Yukarıdaki etkinliğin Adım 2–3’ünü YZ’siz deneyin: Hafıza kartları için geçiş tablosu + Mermaid diyagramı yazın; ardından mümkün olduğunca kendi başınıza küçük bir p5 sketch’i kurun (önce 2×2 = 2 çift bile yeter). Takıldığınız yerde Adım 4’teki YZ istemlerine geçin.
Yapay Zekâ Etkileşimi: Eksik Geçiş Tahmini süre: 15–20 dakika.
Amaç: Unutulan geçiş bug’larını yakalamak.
Adım 1: Menüden oyuna geçiş varken bitişten menüye dönüşü “unutan” bir iskelet yazın veya yazdırın. Adım 2: Yapay zekâya bug’ı buldurun; sizin teşhisinizle karşılaştırın. Adım 3: Düzeltmeyi kendi sketch’inizde uygulayıp üç ekranı da gezin.
Özet
Menü–oyun–bitiş akışı, durum makinesinin tek bir sketch içinde bütünleşik olarak uygulandığı en yaygın biçimdir. Kaç-Kaç Top örneğinde menü ekranı yönergeyi gösterip SPACE bekler; oyun aşamasında kare biçimindeki oyuncu WASD veya ok tuşlarıyla deltaTime’a bağlı hızda hareket eder, top duvarlardan sekerek dolaşır, hedefe temas skoru bir artırıp hedefi yeniden yerleştirir, topa temas ise bitiş ekranına götürür ve orada R tuşu menüye döndürür. Skor yalnızca hedefe dokununca arttığı için köşede beklemek işe yaramaz; kural, topun yakınına gitmeyi göze almayı gerektirir.
Kodun okunma sırası her zaman draw ile başlar: üç dallı if / else if zincirinden yalnızca oyunDurumu’nun o anki değerine karşılık gelen dal çalışır. Oyun dalında önce klavye okunup oyuncu konumu güncellenir ve constrain ile tuval içinde tutulur, ardından top hareket ettirilip kenarlarda hızı ters çevrilir, en sonda dist ile önce hedef, sonra top teması denetlenir. Çarpışma anında atanan yeni durum, aynı frame’de değil bir sonraki draw çağrısında bitiş ekranını devreye sokar. oyunuSifirla yalnızca menüden oyuna geçişte çağrıldığı için her tur rastgele ama tutarlı bir başlangıçla kurulur. Aynı oyunDurumu omurgası, sonraki ana başlıktaki XOX projesinde tur tabanlı tahta verisiyle birleştirilir.
Neler Öğrendik?
Soru 1 Start tuşu tipik olarak hangi geçişi yapar?
A) menü → oyun
B) bitiş → DNS
C) oyun → CSS
D) menü → yazıcı
E) oyun → setup silme
Soru 2 Bitiş ekranında hareket kodu neden genelde çalışmaz?
A) Çünkü güncelleme yalnızca oyun durumunda yapılmalıdır
B) Çünkü p5.js menüyü desteklemez
C) Çünkü dizi yasaktır
D) Çünkü tuval yoktur
E) Çünkü dist yoktur
Soru 3 Kaç-kaç örneğinin pedagojik amacı nedir?
A) Durum + hareket + kuralı bir arada göstermek
B) AAA fizik motoru yazmak
C) Sunucu cluster kurmak
D) SQL öğretmek
E) GPU sürücüsü yazmak
Soru 4 Yeniden dene akışı çoğu zaman nereye döner?
A) menü veya oyun başlangıç durumuna
B) Rastgele CSS dosyasına
C) Git history’ye
D) Yazıcı kuyruğuna
E) DNS cache’e
Neler Öğrendik Yanıt Anahtarı
Soru 1: Doğru Cevap: A
- Çözüm: Start oyunu başlatır.
- İlgili Konu: 3.1. Basit Menü–Oyun–Bitiş Akışı
Soru 2: Doğru Cevap: A
- Çözüm: Durum dışı güncelleme istemeyiz.
- İlgili Konu: 3.1. Basit Menü–Oyun–Bitiş Akışı
Soru 3: Doğru Cevap: A
- Çözüm: Bütünleşik mini örnektir.
- İlgili Konu: 3.1. Basit Menü–Oyun–Bitiş Akışı
Soru 4: Doğru Cevap: A
- Çözüm: Yeniden başlatma menü/oyun başıdır.
- İlgili Konu: 3.1. Basit Menü–Oyun–Bitiş Akışı
Yararlanılan Kaynaklar
Bu içerik aşağıdaki kaynaklardan derlenerek hazırlanmıştır:
- Excalidraw. (n.d.). https://excalidraw.com
- McCarthy, L., Reas, C., & Fry, B. (2015). Make: Getting Started with p5.js. Maker Media.
- Mermaid Live Editor. (n.d.). https://mermaid.live
- Mermaid. (n.d.). State diagrams. https://mermaid.js.org/syntax/stateDiagram.html
- Nystrom, R. (2014). Game Programming Patterns — State. https://gameprogrammingpatterns.com/state.html
- p5.js Foundation. (n.d.). keyPressed. p5.js Reference. https://p5js.org/reference/p5/keyPressed/
- Shiffman, D. (n.d.). Code! Programming with p5.js. The Coding Train. https://thecodingtrain.com/tracks/code-programming-with-p5-js
Ana Başlık 4. Adım Adım: XOX (Tic-Tac-Toe)
Amaç: İki boyutlu dizi, fare tıklaması ve durum makinesini birleştirerek tam bir XOX oyunu kodlamak; Önceki bölümlerde öğrenilen girdi, modüler çizim ve oyun aşamalarını tek projede toplamak.
Öğrenme Çıktıları:
- 3×3 tahtayı iki boyutlu dizi ile modeller.
- Izgara tabanlı tanıdık oyunlarda iki (ve gerektiğinde çok) boyutlu dizinin neden işe yaradığını örneklerle açıklar.
- Modüler fonksiyonlarla tahta çizgileri ve X/O taşlarını çizer.
mousePressed()ile tıklanan hücreye geçerli hamle yerleştirir.- Sıra ve geçersiz hamle kurallarını uygular.
- Kazanan ve beraberlik koşullarını kontrol eder; durum makinesi ile menü–oyun–bitiş akışını tamamlar.
Anahtar Sözcükler: XOX, tic-tac-toe, iki boyutlu dizi, ızgara, matris, hamle, kazanma koşulu, beraberlik, durum makinesi
Giriş
Önceki ana başlıkta durum makinesi ile menü, oyun ve bitiş aşamaları oyunDurumu değişkeniyle yönetilmişti; Kaç-Kaç Top örneğinde SPACE ile başlama, çarpışma ile bitiş ve R ile menüye dönüş kodlanmıştı. XOX (Tic-Tac-Toe) oyunu aynı üç aşamalı iskeleti kullanır; fark, DURUM_OYUN içinde 3×3 ızgara tahtası ve sırayla X/O yerleştirme mantığının çalışmasıdır.
Önceki bölümlerde tek boyutlu diziler, iç içe for döngüleriyle ızgara çizimi ve modüler tahtaCiz / hucreCiz fonksiyonları tanıtılmıştı. Önceki bölümlerde fare tıklaması (mousePressed), klavye (keyPressed) ve durum makinesi eklendi. Bu ana başlıkta tahta verisi iki boyutlu dizi (tahta[satir][sutun]) ile saklanır; her frame'de (her draw() çağrısında) tahta çizilir, hamle yalnızca fare tıklandığında işlenir. Böylece sürekli animasyon ile olay tabanlı girdi aynı sketch'te birleşir; çizim her frame yenilenirken kurallar tıklama anında uygulanır.
Dikkat: p5.js'te frame, draw() fonksiyonunun bir kez çalışmasıdır (Bölüm 2 Ana Başlık 4). XOX tahtasındaki kare (hücre) ise ızgaradaki tek bir oyun alanıdır; burada kare sözcüğü yalnızca tahta hücresi anlamında kullanılır, oyun döngüsü frame'i ile karıştırılmaz.
4.1. Oyun Kuralları ve Veri Yapısı
Tanım: XOX (Tic-Tac-Toe) — İki oyuncunun sırayla 3×3 ızgara üzerinde X ve O işaretleri koyduğu; aynı işaretin yatay, dikey veya çapraz üç hücreyi doldurmasıyla kazanılan, tüm hücreler dolunca kazanan çıkmazsa beraberlikle biten masa oyunudur.
Temel kurallar:
Tablo 1.
| Kural | Açıklama |
|---|---|
| Tahta | 3 satır × 3 sütun = 9 hücre |
| Sıra | Oyuncular sırayla hamle yapar; örnekte X başlar |
| Geçerli hamle | Boş hücreye tıklama |
| Geçersiz hamle | Dolu hücreye veya tahta dışına tıklama — yok sayılır |
| Kazanma | Aynı işaretle üç hücre (8 olası hat) |
| Beraberlik | 9 hücre dolu, kazanan yok |
Klasik XOX kurallarını denemek için kaynaklardaki çevrim içi tahta bağlantısına bakılabilir.
Tahta durumu iki boyutlu dizi ile modellenir. Önceki bölümlerdeki tek boyutlu dizi[0], dizi[1] yapısının satır–sütun karşılığı tahta[satir][sutun] erişimidir:
Kod 1.
let tahta = [ ["", "", ""], ["", "", ""], ["", "", ""]];Tablo 2.
| İfade | Anlam |
|---|---|
tahta[0] |
İlk satır (üç elemanlı dizi) |
tahta[1][2] |
2. satır, 3. sütun (indeks 0'dan) |
"" |
Boş hücre |
"X" / "O" |
Dolu hücre — o karedeki taş |

Görsel 1, tahta[satir][sutun] erişiminde satırın önce, sütunun sonra geldiğini ve her hücrenin boş string veya "X" / "O" tuttuğunu gösterir.
Oyun durumu için önceki ana başlıktaki sabitler korunur; tahta mantığına ek değişkenler eklenir:
Kod 2.
const DURUM_MENU = "menu";const DURUM_OYUN = "oyun";const DURUM_BITIS = "bitis";const HUCRE = 100; let oyunDurumu;let tahta;let sira; // "X" veya "O" — şu an kim oynuyorlet sonuc; // kazanan ("X"/"O") veya "beraberlik"Tablo 3.
| Değişken | Görev |
|---|---|
oyunDurumu |
Menü / oyun / bitiş aşaması (Ana Başlık 2) |
tahta |
3×3 hücre verisi |
sira |
Sıradaki oyuncunun işareti |
sonuc |
Bitiş ekranında gösterilecek sonuç metni |
Tuval boyutu tahta ile uyumludur: createCanvas(300, 300) ve HUCRE = 100 → 3×3 kare tam tuvali kaplar. oyunuSifirla() yeni turda tahtayı boşaltır ve sırayı X'e verir:
Kod 3.
function oyunuSifirla() { tahta = [ ["", "", ""], ["", "", ""], ["", "", ""] ]; sira = "X"; sonuc = "";}Bilgi: İki boyutlu dizi, önceki bölümlerdeki dizinin iç içe kullanımıdır; tahta.length satır sayısını (3), tahta[0].length sütun sayısını verir. XOX sabit 3×3 olduğu için döngülerde 0–2 aralığı yeterlidir.
Neden oyun programlamada iki boyutlu dizi? Birçok oyun dünyası satır–sütun ızgarasıdır: her hücre “burada ne var?” sorusuna tek bir yanıt tutar (boş, taş, duvar, mayın, yem…). tahta[satir][sutun] bu soruyu doğrudan sorar. Komşu hücreler (satir ± 1, sutun ± 1), kazanma çizgileri veya “bu sütunda aşağı düş” gibi kurallar da aynı indeks diline oturur. Aynı veriyi tek boyutlu 9 (veya 64) elemanlı dizide tutmak mümkündür; fakat “2. satır, 3. sütun” her seferinde elle formülle çevrilir — ızgara büyüdükçe hata ve okuma maliyeti artar.
Tanıdık oyunlarda tipik kullanım (hücrede ne tutulduğunun özeti):
Tablo 4.
| Oyun | Tipik ızgara | Hücrede örnek veri |
|---|---|---|
| XOX / üç taş | 3×3 | boş / X / O |
| Satranç, dama | 8×8 | boş veya taş türü |
| Mayın Tarlası | örn. 9×9 | kapalı / açık / mayın / bayrak |
| Connect Four | 6×7 | boş / renkli taş (sütunda aşağı kayar) |
| Tetris | örn. 20×10 | boş veya dolu blok |
| 2048, match-3 (Candy Crush tarzı) | N×N veya N×M | sayı / renk / boş |
| Pac-Man labirenti, birçok platform tile map | geniş ızgara | yol / duvar / nokta / kapı |
| Sudoku | 9×9 | 1–9 veya boş |
Bu örneklerin hepsi “önce tahtayı diziyle modelle, sonra çiz ve kuralları uygula” sırasını paylaşır; XOX o sıranın en küçük tam projesidir. İleri Teknikler kitabında aynı fikir büyür: Yılan ve Connect Four’da daha büyük matris, Mayın Tarlası’nda hücre durumu zenginleşir.
Çok boyutlu dizi (kısa bakış): Üç veya daha fazla indeks bazen işe yarar — örneğin katman[z][y][x] ile Minecraft tarzı blok dünyası, veya kare[satir][sutun][ozellik] ile aynı hücrede birkaç sayı. Bu kitapta önce iki boyutlu tahta yeterlidir; çok boyutlu yapı, ızgara fikrinin doğal uzantısıdır, ayrı bir sihir değildir. Pratikte çoğu 2B oyun tek matris + birkaç yardımcı dizi ile ilerler.
4.2. Tahta ve Taş Çizimi
Tahta çizimi modüler fonksiyonlara ayrılır (Bölüm 2'in 3. ana başlığı): çizgiler, taşlar ve oyun ekranı birleşimi ayrı bloklardadır. draw() içinde DURUM_OYUN iken yalnızca oyun ekranı çizilir; menü ve bitiş Ana Başlık 2'deki gibi ayrı fonksiyonlardır.
Kod bloğu: Tahta çizgileri — line() ile ızgara.
Kod 4.
function cizTahtaCizgileri() { background(245, 242, 235); stroke(40); strokeWeight(4); line(HUCRE, 0, HUCRE, height); line(HUCRE * 2, 0, HUCRE * 2, height); line(0, HUCRE, width, HUCRE); line(0, HUCRE * 2, width, HUCRE * 2); noStroke();}Dört line() çağrısı dikey iki, yatay iki çizgi çizer; hücre sınırları oluşur. Arka plan rengi background() ile her frame'de yenilenir.
Taşlar, tahtadaki dolu hücreler üzerinden iç içe döngüyle çizilir:
Kod 5.
function taslariCiz() { for (let satir = 0; satir < 3; satir = satir + 1) { for (let sutun = 0; sutun < 3; sutun = sutun + 1) { let deger = tahta[satir][sutun]; if (deger !== "") { tasCiz(sutun * HUCRE, satir * HUCRE, HUCRE, deger); } } }}Tablo 5.
| Fonksiyon | Sorumluluk |
|---|---|
cizTahtaCizgileri() |
Arka plan + ızgara çizgileri |
taslariCiz() |
Dolu hücreleri dolaş, tasCiz çağır |
tasCiz(x, y, boyut, deger) |
Tek hücrede X veya O metni |
cizOyunEkrani() |
Tahta + taşlar + sıra metni |
Kod bloğu: Tek taş çizimi — text() ile X/O.
Kod 6.
function tasCiz(x, y, boyut, deger) { textAlign(CENTER, CENTER); textSize(boyut * 0.55); if (deger === "X") { fill(200, 50, 50); } else { fill(50, 80, 200); } text(deger, x + boyut / 2, y + boyut / 2);}Piksel konumu sutun * HUCRE, satir * HUCRE ile hesaplanır: sütun soldan sağa, satır yukarıdan aşağı artar. Metin hücre merkezine textAlign(CENTER, CENTER) ile yerleştirilir. Oyun ekranında sıra bilgisi sol üstte gösterilir:
Kod 7.
function cizOyunEkrani() { cizTahtaCizgileri(); taslariCiz(); fill(30); textSize(14); textAlign(LEFT, TOP); noStroke(); text("Sıra: " + sira, 8, 8);}Dikkat: Çizim her frame'de tahta dizisinin güncel halini yansıtır; hamle mousePressed() içinde diziyi günceller, bir sonraki draw() yeni taşı ekrana yazar. Tahta verisi ile çizim ayrı tutulduğu için aynı tasCiz farklı konumlarda tekrar kullanılabilir.
4.3. Tıklama ile Hamle
Hamle, p5.js olay fonksiyonu mousePressed() ile işlenir (önceki bölümler). Fare koordinatları mouseX, mouseY piksel cinsindendir; hücre indeksine dönüştürmek için floor() kullanılır (önceki bölümler, diziler ana başlığı):
Kod 8.
let sutun = floor(mouseX / HUCRE);let satir = floor(mouseY / HUCRE);Örneğin HUCRE = 100 iken mouseX = 150 → sutun = 1 (orta sütun); mouseY = 220 → satir = 2 (alt satır).
Hamle işleme sırası:
Tablo 6.
| Adım | Kontrol | Başarısızsa |
|---|---|---|
| 1 | Menüdeyse tıklama → oyuna geç | oyunuSifirla(), DURUM_OYUN |
| 2 | oyunDurumu === DURUM_OYUN mu? |
return |
| 3 | satir, sutun 0–2 aralığında mı? |
return |
| 4 | tahta[satir][sutun] === "" mu? |
return (dolu kare) |
| 5 | Hamleyi yaz: tahta[satir][sutun] = sira |
— |
| 6 | Kazanan veya beraberlik var mı? | Bitiş durumuna geç |
| 7 | Sırayı diğer oyuncuya ver | if/else ile X ↔ O |

Görsel 2, piksel koordinatının floor(mouseX / HUCRE) ile hangi kareye denk geldiğini özetler.
Kod bloğu: mousePressed() — hamle ve durum kontrolü.
Kod 9.
function mousePressed() { if (oyunDurumu === DURUM_MENU) { oyunuSifirla(); oyunDurumu = DURUM_OYUN; return; } if (oyunDurumu !== DURUM_OYUN) { return; } let sutun = floor(mouseX / HUCRE); let satir = floor(mouseY / HUCRE); if (satir < 0 || satir > 2 || sutun < 0 || sutun > 2) { return; } if (tahta[satir][sutun] !== "") { return; } tahta[satir][sutun] = sira; let kazanan = kazananKontrol(); if (kazanan !== "") { sonuc = kazanan; oyunDurumu = DURUM_BITIS; return; } if (tahtaDoluMu()) { sonuc = "beraberlik"; oyunDurumu = DURUM_BITIS; return; } if (sira === "X") { sira = "O"; } else { sira = "X"; }}Sıra değişimi üçlü operatör (ternary) yerine if/else ile yazılmıştır; okunabilirlik ve önceki bölümlerdeki dallanma alışkanlığı korunur. Bitiş ekranındayken tıklama erken return ile yok sayılır — Ana Başlık 2'deki “duruma göre girdi” kuralının uygulamasıdır.
Menüden oyuna geçiş hem SPACE (keyPressed) hem tıklama ile mümkündür; ikisi de oyunuSifirla() çağırır.
4.4. Kazanan ve Beraberlik
Kazanma koşulu: üç hücrede aynı işaret ve hücrelerin boş olmaması. 3×3 tahtada toplam 8 kazanma hattı vardır:
Tablo 7.
| # | Tür | Kontrol edilen hücreler |
|---|---|---|
| 1 | Yatay satır 0 | [0][0] — [0][1] — [0][2] |
| 2 | Yatay satır 1 | [1][0] — [1][1] — [1][2] |
| 3 | Yatay satır 2 | [2][0] — [2][1] — [2][2] |
| 4 | Dikey sütun 0 | [0][0] — [1][0] — [2][0] |
| 5 | Dikey sütun 1 | [0][1] — [1][1] — [2][1] |
| 6 | Dikey sütun 2 | [0][2] — [1][2] — [2][2] |
| 7 | Çapraz \ |
[0][0] — [1][1] — [2][2] |
| 8 | Çapraz / |
[0][2] — [1][1] — [2][0] |

Görsel 3, sekiz hattın tahta üzerindeki konumunu ve beraberlik koşulunu özetler.
Kod bloğu: kazananKontrol() — satır, sütun ve çapraz tarama.
Kod 10.
function kazananKontrol() { for (let i = 0; i < 3; i = i + 1) { if (tahta[i][0] !== "" && tahta[i][0] === tahta[i][1] && tahta[i][1] === tahta[i][2]) { return tahta[i][0]; } } for (let j = 0; j < 3; j = j + 1) { if (tahta[0][j] !== "" && tahta[0][j] === tahta[1][j] && tahta[1][j] === tahta[2][j]) { return tahta[0][j]; } } if (tahta[0][0] !== "" && tahta[0][0] === tahta[1][1] && tahta[1][1] === tahta[2][2]) { return tahta[0][0]; } if (tahta[0][2] !== "" && tahta[0][2] === tahta[1][1] && tahta[1][1] === tahta[2][0]) { return tahta[0][2]; } return "";}Fonksiyon kazanan işareti ("X" veya "O") veya kazanan yoksa "" döndürür. İlk for üç yatay satırı, ikinci for üç dikey sütunu tarar; çaprazlar ayrı if bloklarındadır.
Beraberlik: Tüm hücreler dolu ve kazananKontrol() boş string döndürürse oyun berabere biter. Yardımcı fonksiyon:
Kod 11.
function tahtaDoluMu() { for (let satir = 0; satir < 3; satir = satir + 1) { for (let sutun = 0; sutun < 3; sutun = sutun + 1) { if (tahta[satir][sutun] === "") { return false; } } } return true;}Her hamle sonrası sıra önce kazanma, sonra beraberlik kontrol edilir; kazanan bulunursa sıra değiştirilmez (oyun zaten biter). Bitiş ekranı sonuc değişkenine göre mesaj gösterir:
Kod 12.
function cizBitisEkrani() { background(35, 30, 40); fill(255); textAlign(CENTER, CENTER); textSize(22); if (sonuc === "beraberlik") { text("Beraberlik!", width / 2, height / 2 - 20); } else { text("Kazanan: " + sonuc, width / 2, height / 2 - 20); } textSize(14); text("R — menüye dön", width / 2, height / 2 + 30);}4.5. Tam Kod ve Genişletme
Aşağıdaki sketch menü–oyun–bitiş durum makinesi, iki boyutlu tahta, tıklama ile hamle ve kazanma/beraberlik kontrolünü birleştirir; p5.js Web Editor'e yapıştırarak doğrudan çalıştırabilirsiniz.
XOX geçiş tablosu:
Tablo 8.
| Mevcut durum | Olay / koşul | Yeni durum | Ek işlem |
|---|---|---|---|
DURUM_MENU |
SPACE veya tıklama | DURUM_OYUN |
oyunuSifirla() |
DURUM_OYUN |
Geçerli tıklama, kazanan var | DURUM_BITIS |
sonuc = kazanan |
DURUM_OYUN |
Geçerli tıklama, tahta dolu | DURUM_BITIS |
sonuc = "beraberlik" |
DURUM_OYUN |
Geçerli tıklama, oyun sürüyor | DURUM_OYUN |
Sıra X ↔ O |
DURUM_OYUN |
Geçersiz tıklama | DURUM_OYUN |
— |
DURUM_BITIS |
R basıldı | DURUM_MENU |
— |
Oyun kuralları:
- Menü: “SPACE veya tıkla — başla”.
- Oyun: Boş kareye tıklayarak X/O koy; sıra sırayla değişir.
- Kazanan veya beraberlik: Bitiş ekranı.
- Bitiş: R ile menüye dön.
setup içinde yeni bir satır vardır: textFont("sans-serif"). Bu, tuvale yazılacak metnin yazı tipini seçer. "sans-serif" sistemdeki varsayılan sans-serif (tırnaksız) yazı tipini kullanır; menü ve bitiş yazıları daha okunaklı görünür. textSize boyutu, textAlign hizayı ayarlarken textFont aileyi (font) belirler. İlerideki oyunlarda (Mayın Tarlası vb.) aynı satır tekrarlanabilir.
Tanım: textFont(yazitipi) — p5.js’te sonraki text() çağrılarının kullanacağı yazı tipini ayarlar. Argüman genelde bir yazı tipi adı string’idir (ör. "sans-serif", "monospace"); özel fontlar için loadFont ile yüklenen nesne de verilebilir.
Kod 13.
const DURUM_MENU = "menu";const DURUM_OYUN = "oyun";const DURUM_BITIS = "bitis";const HUCRE = 100; let oyunDurumu;let tahta;let sira;let sonuc; function setup() { createCanvas(300, 300); textFont("sans-serif"); oyunDurumu = DURUM_MENU;} function draw() { if (oyunDurumu === DURUM_MENU) { cizMenu(); } else if (oyunDurumu === DURUM_OYUN) { cizOyunEkrani(); } else if (oyunDurumu === DURUM_BITIS) { cizBitisEkrani(); }} function cizMenu() { background(28, 32, 48); fill(255); textAlign(CENTER, CENTER); textSize(32); text("XOX", width / 2, height / 2 - 30); textSize(14); text("SPACE veya tıkla — başla", width / 2, height / 2 + 20);} function cizOyunEkrani() { cizTahtaCizgileri(); taslariCiz(); fill(30); textSize(14); textAlign(LEFT, TOP); noStroke(); text("Sıra: " + sira, 8, 8);} function cizBitisEkrani() { background(35, 30, 40); fill(255); textAlign(CENTER, CENTER); textSize(22); if (sonuc === "beraberlik") { text("Beraberlik!", width / 2, height / 2 - 20); } else { text("Kazanan: " + sonuc, width / 2, height / 2 - 20); } textSize(14); text("R — menüye dön", width / 2, height / 2 + 30);} function cizTahtaCizgileri() { background(245, 242, 235); stroke(40); strokeWeight(4); line(HUCRE, 0, HUCRE, height); line(HUCRE * 2, 0, HUCRE * 2, height); line(0, HUCRE, width, HUCRE); line(0, HUCRE * 2, width, HUCRE * 2); noStroke();} function taslariCiz() { for (let satir = 0; satir < 3; satir = satir + 1) { for (let sutun = 0; sutun < 3; sutun = sutun + 1) { let deger = tahta[satir][sutun]; if (deger !== "") { tasCiz(sutun * HUCRE, satir * HUCRE, HUCRE, deger); } } }} function tasCiz(x, y, boyut, deger) { textAlign(CENTER, CENTER); textSize(boyut * 0.55); if (deger === "X") { fill(200, 50, 50); } else { fill(50, 80, 200); } text(deger, x + boyut / 2, y + boyut / 2);} function mousePressed() { if (oyunDurumu === DURUM_MENU) { oyunuSifirla(); oyunDurumu = DURUM_OYUN; return; } if (oyunDurumu !== DURUM_OYUN) { return; } let sutun = floor(mouseX / HUCRE); let satir = floor(mouseY / HUCRE); if (satir < 0 || satir > 2 || sutun < 0 || sutun > 2) { return; } if (tahta[satir][sutun] !== "") { return; } tahta[satir][sutun] = sira; let kazanan = kazananKontrol(); if (kazanan !== "") { sonuc = kazanan; oyunDurumu = DURUM_BITIS; return; } if (tahtaDoluMu()) { sonuc = "beraberlik"; oyunDurumu = DURUM_BITIS; return; } if (sira === "X") { sira = "O"; } else { sira = "X"; }} function kazananKontrol() { for (let i = 0; i < 3; i = i + 1) { if (tahta[i][0] !== "" && tahta[i][0] === tahta[i][1] && tahta[i][1] === tahta[i][2]) { return tahta[i][0]; } } for (let j = 0; j < 3; j = j + 1) { if (tahta[0][j] !== "" && tahta[0][j] === tahta[1][j] && tahta[1][j] === tahta[2][j]) { return tahta[0][j]; } } if (tahta[0][0] !== "" && tahta[0][0] === tahta[1][1] && tahta[1][1] === tahta[2][2]) { return tahta[0][0]; } if (tahta[0][2] !== "" && tahta[0][2] === tahta[1][1] && tahta[1][1] === tahta[2][0]) { return tahta[0][2]; } return "";} function tahtaDoluMu() { for (let satir = 0; satir < 3; satir = satir + 1) { for (let sutun = 0; sutun < 3; sutun = sutun + 1) { if (tahta[satir][sutun] === "") { return false; } } } return true;} function oyunuSifirla() { tahta = [ ["", "", ""], ["", "", ""], ["", "", ""] ]; sira = "X"; sonuc = "";} function keyPressed() { if (oyunDurumu === DURUM_MENU && key === " ") { oyunuSifirla(); oyunDurumu = DURUM_OYUN; } if (oyunDurumu === DURUM_BITIS && (key === "r" || key === "R")) { oyunDurumu = DURUM_MENU; }}Bu proje önceki bölümlerin kapanış örneğidir: Bölüm 2 Ana Başlık 4'teki frame döngüsü, Bölüm 3 Ana Başlık 4'teki klavye, Ana Başlık 1'deki koordinat mantığı, Ana Başlık 2'deki durum makinesi ve önceki bölümlerdeki diziler ile modüler fonksiyonlar tek XOX oyununda birleşir.
Genişletme fikirleri (İleri Teknikler kitabı): Bilgisayar rakibi (Minimax), Connect Four benzeri tahta — aynı tahta[satir][sutun] iskeleti üzerine. Aşağıdaki etkinlikte ise bu düzeyde kodlanabilir XOX varyantları vardır.
Aşağıdaki Yapay Zekâ Etkileşimi etkinlikleri önce ızgara / dizi fikrini tanıdık oyunlarla pekiştirir; sonra Ana Başlık 2'deki Hafıza projesine benzer biçimde XOX varyantı kodlamanızı ister. Takılınca YZ’den öğretmen / onarım yardımı alın — tüm oyunu baştan yazdırmayın.
Yapay Zekâ Etkileşimi: Izgara oyunları ve çok boyutlu dizi Tahmini süre: 15–25 dakika.
Amaç: İki (ve gerektiğinde çok) boyutlu dizinin oyun tasarımında nerede ortaya çıktığını bilinen oyunlar üzerinden görmek. Kod yazmanız gerekmez.
Adım 1 — YZ’siz: Yukarıdaki tablodan veya bildiğiniz bir oyundan iki örnek seçin. Her biri için birer cümle: “Bu oyunda ızgaranın bir hücresi ne tutuyor?”
Adım 2 — Örnek istem:
"Yeni başlayan bir oyun programcısıyım. Oyun programlamada iki boyutlu dizi (matris / ızgara) neden sık kullanılır?
(1) En az 6 bilinen oyunda (XOX dışında da) tahta veya harita nasıl ızgara gibi düşünülür? Her oyunda hücrede tipik olarak ne tutulur?
(2) Aynı oyunu tek boyutlu diziyle modellemek ne zaman zahmetli olur? Somut bir örnek ver.
(3) Üç boyutlu (veya daha çok indeksli) dizinin işe yarayabileceği 1–2 oyun veya durum örneği ver (ör. katmanlı dünya, aynı hücrede birden fazla özellik). Abartma; giriş düzeyinde tut.
(4) Benim 3×3 XOX tahta[satir][sutun] modelim bu listenin neresine oturur?
Kod yazma; Türkçe yaz."
Adım 3 — Kontrol: YZ’nin oyun örneklerinden ikisini kısa aramayla doğrulayın (uydurma oyun veya yanlış tahta boyutu olmasın). Sonra kendi cümlelerinizle yazın: İleride yapmak istediğiniz küçük bir oyunda ızgara kullanır mısınız, kullanırsanız hücrede ne tutarsınız?
Yapay Zekâ Etkileşimi: XOX varyantlarını keşfet Tahmini süre: 15–20 dakika.
Amaç: Klasik XOX’un yanında hangi kural değişince oyunun “aynı iskelet, farklı tat” olduğunu görmek. Bu adımda tam kod yazmanız gerekmez.
Adım 1 — Klasik tur + okuma: 1–2 tur oynayın; sonra varyant listesine göz atın:
- Oyun: https://playtictactoe.org/
- Oyun: https://www.mathsisfun.com/games/tic-tac-toe.html
- Varyant listesi (Wikipedia): https://en.wikipedia.org/wiki/List_of_tic-tac-toe_variants
Adım 2 — Örnek istem (mekanik, kod yok): "Yeni başlayan bir oyun programcısıyım; elinde klasik 3×3 XOX (p5.js, iki boyutlu dizi, menü–oyun–bitiş) var. Bu iskeletle kodlanabilecek XOX / Tic-Tac-Toe varyantlarını anlat. (1) En az 4 varyant: adı, kuralları (nasıl oynanır, klasik XOX’tan ne farkı var), kim için eğlenceli olduğu. (2) Programcı gözüyle sınıflandır: hangisi yalnızca taş metnini veya sembolünü değiştirmekle biter; hangisi kazanma kontrolünü veya tahta boyutunu değiştirmeyi gerektirir? Kısa tablo yeter. (3) Online ücretsiz (mümkünse kayıtsız) deneyebileceğim 1–2 site adresi. Örnek yönler (bunlarla sınırlı kalma): harf veya sembol değişimi; misère / ters XOX; 4×4 tahtada üçlü ile kazanma; her turda X veya O seçme. Kod yazma; Türkçe yaz; Minimax veya yapay zekâ rakip anlatma."
Adım 3: YZ’nin listesinden bir varyant seçin (bir sonraki etkinlikte kodlayacaksınız). Kâğıda, kitaptaki XOX’a göre kodda nelerin değişeceğini madde madde yazın (en az iki madde). İpucu olarak bakabileceğiniz yerler: sira ve taş metinleri, tasCiz, kazananKontrol, createCanvas ve HUCRE, bitiş mesajı.
Not: YZ bazen uydurma kural veya aşırı karmaşık varyant önerir. Seçiminiz bu ders düzeyinde bitsin: class yok, Minimax yok, ek kütüphane yok.
Yapay Zekâ Etkileşimi: XOX varyantı — sen yaz, YZ öğretmen olsun Tahmini süre: 50–80 dakika (plan + kod + YZ ile onarım).
Amaç: Bu ana başlıktaki çalışan XOX sketch’ini temel alıp bir varyant üretmek. Ana Başlık 2'deki Hafıza projesinde olduğu gibi: planı siz kurun, kodu siz yazın; takıldığınız yerde YZ’den yardım alın. Amaç yeni bir dil öğrenmek değil; aynı oyunDurumu + tahta + mousePressed iskeletinin kural değişince nasıl esnediğini görmek.
Varyant seçenekleri (birini seçin):
Tablo 9.
| Seçenek | Ne değişir? | Zorluk |
|---|---|---|
| A) Sembol / harf | "X"/"O" yerine "A"/"B", "★"/"●" veya iki kısa kelime; menü ve bitiş metinleri uyumlu |
Kolay |
| B) Ters XOX (misère) | Üçlü yapan kaybeder; bitiş metni ve sonuc mantığı tersine döner |
Orta |
| C) 4×4, üçlü kazanır | Tahta 4×4; hâlâ üç aynı işaret yan yana / çapraz kazandırır; HUCRE ve döngü sınırları büyür |
Orta–zor |
| D) Serbest işaret | Sıra “X’ten O’ya otomatik geç” değildir: oyuncu önce taşı seçer (ör. 1 tuşu → X, 2 tuşu → O), sonra boş hücreye tıklayınca o taş yazılır |
Orta–zor |
İsterseniz A ile başlayıp çalışan bir kopya görün; sonra B/C/D’den birine geçin.
Adım 1 — Plan (YZ’siz): Seçtiğiniz varyant için kısa not:
- Hangi sabit / değişken değişir?
kazananKontrolaynı mı kalır, yoksa ne eklenir / çıkarılır?- Bitiş ekranında ne yazılmalı?
- Geçersiz hamle kuralları aynı mı?
Adım 2 — Sizin kodunuz: Web Editor’de kitaptaki XOX sketch’inin bir kopyasını açın; dosya adını varyanta göre değiştirin (ör. xox-yildiz). Önce klasik oyunun kopyada çalıştığını doğrulayın; sonra yalnızca varyant için gereken satırları değiştirin. Class / ek kütüphane / Minimax kullanmayın.
Adım 3 — Takılınca YZ (onarım + öğretmen): Sketch’in tamamını (veya bozulan fonksiyonu) yapıştırın. Körü körüne yapıştırmayın.
Örnek istem — hata / eksik (B: ters XOX):
"p5.js’te kitaptaki XOX’u ters XOX (misère) yaptım: üç aynı işaret yan yana gelince o oyuncu kaybeder, kazanmaz. Class yok, ek kütüphane yok. Sorun: Üçlü oluşunca oyun bitiyor ama sonuc hâlâ ‘X kazandı’ / ‘O kazandı’ diyor; kaybeden tarafı göstermiyor. Beraberlik (tahta dolu, üçlü yok) bozulmasın.
(1) Önce öğretmen gibi anlat: bu hata hangi değişkende veya hangi fonksiyonda olabilir? (sonuc, mousePressed, kazananKontrol…)
(2) Yalnızca gerekli satırları düzelt; tüm oyunu baştan yazma.
(3) Neyi neden değiştirdiğini madde madde, bu ders düzeyinde açıkla.
Kod:"
(Kendi sketch’inizi yapıştırın. Başka bir varyant seçtiyseniz ilk iki cümleyi kendi kuralınıza ve kendi hatanıza göre değiştirin.)
Örnek istem — yalnızca bir parça (C varyantı için):
"p5.js’te class ve ek kütüphane kullanmadan tek bir fonksiyon yaz: kazananKontrol(tahta). tahta 4×4’lük iki boyutlu dizi; her hücre boş string, \"X\" veya \"O\". Kural: klasik XOX’taki gibi üç aynı işaret yan yana gelirse (yatay, dikey veya çapraz) o işaret kazansın. Tahta 4×4 olduğu için bir satırda birden fazla üçlü konumu olabilir; hepsini kontrol et. Kazanan yoksa boş string döndür. Kısa Türkçe yorum ekle. Oyunun geri kalanını yazma; Minimax yazma."
Adım 4 — Kontrol listesi:
- Menü → oyun → bitiş hâlâ
oyunDurumuile mi yönetiliyor? - Dolu hücre / tahta dışı / bitişte tıklama yok sayılıyor mu?
- Varyant kuralı gerçekten hissediliyor mu (A’da harfler, B’de üçlü = kayıp, C’de 16 hücre…)?
- YZ tüm dosyayı yeniden mi yazmış, yoksa küçük bir diff mi vermiş? Gereksiz uzatmayı sadeleştirin.
- Bu ana başlıktaki orijinal XOX ile yan yana koyun: kaç satır gerçekten değişti?
Sıra Sizde: YZ’siz deneyin.
- Tablodaki oyunlardan (veya aklınızdakilerden) üçünü seçin; her biri için yazın: satır×sütun tahmini + hücrede ne tutulur? Hangisinde XOX’taki gibi
tahta[satir][sutun]modeli doğrudan işe yarar? - Kitaptaki XOX kopyasında
"X"/"O"yerine kendi iki sembolünüzü kullanın (ör."A"/"B"veya"1"/"2"); menü başlığı ve bitiş yazısını da uyumlu yapın. Bir tam tur oynayın. Bu değişiklikkazananKontroliçinde neden çoğu zaman hiç dokunulmadan çalışır? - İsterseniz ikinci tur: ters XOX (üçlü yapan kaybeder) için
mousePressed/ bitiş dalında neyi tersine çevireceğinizi 3 maddeyle planlayın; kodlamaya başlayın, takılınca yukarıdaki YZ istemlerine geçin.
Özet
XOX oyunu 3×3 tahtayı iki boyutlu dizi (tahta[satir][sutun]) ile modeller; boş hücre "", dolu hücre "X" veya "O" tutar. Aynı satır–sütun fikri satranç, Mayın Tarlası, Tetris, Connect Four, Pac-Man labirenti gibi ızgara oyunlarının da omurgasıdır; hücrede tutulan veri oyuna göre değişir. Önceki bölümlerdeki tek boyutlu dizi alışkanlığı satır–sütun erişimine genişler: tahta[1][2] orta satırın sağ hücresidir. Tahta çizgileri ve taşlar modüler fonksiyonlarla her frame'de çizilir; hamle mousePressed() ile piksel koordinatından floor(mouseX / HUCRE) ve floor(mouseY / HUCRE) ile kare indeksine dönüştürülerek yapılır. Sınır dışı veya dolu hücreye tıklama erken return ile yok sayılır; geçerli hamlede mevcut sıra işareti yazılır, ardından sıra if/else ile X ve O arasında değişir. İndeks hesabı yanlışsa taş yanlış hücreye düşer. Sekiz kazanma hattı (üç satır, üç sütun, iki çapraz) kazananKontrol() ile taranır; aynı işaretle üç hücre doluysa kazanan döner. Tahta dolu ve kazanan yoksa tahtaDoluMu() ile beraberlik ilan edilir. Menü, oyun ve bitiş Ana Başlık 2'deki oyunDurumu deseniyle yönetilir; SPACE veya tıklama ile başlama, R ile menüye dönüş tamamlanır. Bitiş ekranındayken fare tıklaması hamle üretmez — girdi yalnızca geçerli durumda işlenir. draw() içinde durum dallanması menü metnini, oyun tahtasını ve bitiş sonucunu ayırır; tahta verisi ile çizim fonksiyonları birbirinden bağımsız kaldığı için bilgisayar rakibi veya skor tablosu gibi genişletmeler aynı iskelete eklenebilir. Menüye dönüşte tahta boşaltılır ve sıra yeniden X'e alınır.
Neler Öğrendik?
Soru 1
3×3 XOX tahtasında tahta[1][2] hangi hücreyi ifade eder?
A) Sol üst
B) Orta satır, sağ sütun
C) Alt satır, orta sütun
D) Sağ alt
E) İkinci sütunun tamamı
Soru 2
Dolu bir kareye tıklandığında mousePressed() içinde ne olması beklenir?
A) Taş üzerine yazılır
B) Sıra yine de değişir
C) Erken return ile hamle yok sayılır
D) setup() yeniden çalışır
E) Tuval boyutu değişir
Soru 3
[Kod okuma] kazananKontrol() boş string ("") döndürdüğünde ve tahtaDoluMu() true ise sonuç nedir?
A) Oyun menüye döner
B) Beraberlik — sonuc = "beraberlik"
C) X kazanır
D) Sıra değişmez, oyun sürer
E) Sketch hata verir
Soru 4 Bitiş ekranındayken fare tıklamasının hamle oluşturmaması hangi ilkeye dayanır?
A) draw() her frame çalışmaz
B) Girdi yalnızca geçerli oyun durumunda işlenir
C) mouseX bitiş ekranında tanımsızdır
D) tahta dizisi silinir
E) R tuşu zorunludur
Neler Öğrendik Yanıt Anahtarı
Soru 1: Doğru Cevap: B
- Çözüm: İndeks 0'dan başlar;
[1][2]ikinci satır (orta), üçüncü sütun (sağ) hücredir. - İlgili Konu: 4.1. Oyun Kuralları ve Veri Yapısı
Soru 2: Doğru Cevap: C
- Çözüm:
tahta[satir][sutun] !== ""kontrolü başarısız olunca fonksiyon erken çıkar; geçersiz hamle işlenmez. - İlgili Konu: 4.3. Tıklama ile Hamle
Soru 3: Doğru Cevap: B
- Çözüm: Kazanan yok, tahta dolu → beraberlik koşulu;
sonuc = "beraberlik"veDURUM_BITIS. - İlgili Konu: 4.4. Kazanan ve Beraberlik
Soru 4: Doğru Cevap: B
- Çözüm:
oyunDurumu !== DURUM_OYUNikenmousePressed()erkenreturneder; duruma göre girdi (Ana Başlık 2). - İlgili Konu: 4.3. Tıklama ile Hamle
Yararlanılan Kaynaklar
Bu içerik aşağıdaki kaynaklardan derlenerek hazırlanmıştır:
- MathsIsFun. (n.d.). Tic-Tac-Toe [Çevrim içi oyun]. https://www.mathsisfun.com/games/tic-tac-toe.html
- McCarthy, L., Reas, C., & Fry, B. (2015). Make: Getting Started with p5.js. Maker Media.
- Nystrom, R. (2014). Game Programming Patterns — State. https://gameprogrammingpatterns.com/state.html
- p5.js Foundation. (n.d.). floor. p5.js Reference. https://p5js.org/reference/p5/floor/
- p5.js Foundation. (n.d.). mousePressed. p5.js Reference. https://p5js.org/reference/p5/mousePressed/
- p5.js Foundation. (n.d.). textFont. p5.js Reference. https://p5js.org/reference/p5/textFont/
- PlayTicTacToe. (n.d.). Tic Tac Toe [Çevrim içi oyun]. https://playtictactoe.org/
- Shiffman, D. (n.d.). Code! Programming with p5.js. The Coding Train. https://thecodingtrain.com/tracks/code-programming-with-p5-js
Bölüm 4 — Ek Sorular
Her ana başlık için 10 çoktan seçmeli değerlendirme sorusu. Bölüm sonu sınav veya pekiştirme amaçlıdır.
Ana Başlık 1 için 10 Soru
SORU 1: Aşağıdaki yaklaşımlardan hangisi oyun sketch’inde daha sağlam bir geliştirmedir?
A) Konu dışı teknolojiye (biçim/dil dışı) sapıp temel kuralı atlamak
B) Öğrenilen p5.js API’si ile ölçülebilir bir oyun kuralı eklemek
C) draw içinde createCanvas tekrarlamak
D) Skoru her frame koşulsuz artırmak
E) Hata ayıklamadan uzun kodu olduğu gibi bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme, öğrenilen araçlarla kural eklemeyi hedefler; alandan kopuk şıklar elenir. İlgili Konu: Pekiştirme
SORU 2: İki daire çarpışmasında uygun koşul hangisidir?
A) dist < r1 + r2
B) width === height
C) key === 'a'
D) frameCount < 0
E) mouseX === mouseY
Doğru cevap: A
Genel açıklama: Bu soru ana başlık kazanımını ölçer. İlgili Konu: 1.2
SORU 3: Aşağıdaki yaklaşımlardan hangisi oyun sketch’inde daha sağlam bir geliştirmedir?
A) Konu dışı teknolojiye (biçim/dil dışı) sapıp temel kuralı atlamak
B) Öğrenilen p5.js API’si ile ölçülebilir bir oyun kuralı eklemek
C) draw içinde createCanvas tekrarlamak
D) Skoru her frame koşulsuz artırmak
E) Hata ayıklamadan uzun kodu olduğu gibi bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme, öğrenilen araçlarla kural eklemeyi hedefler; alandan kopuk şıklar elenir. İlgili Konu: Pekiştirme
SORU 4: Aşağıdaki yaklaşımlardan hangisi oyun sketch’inde daha sağlam bir geliştirmedir?
A) Konu dışı teknolojiye (biçim/dil dışı) sapıp temel kuralı atlamak
B) Öğrenilen p5.js API’si ile ölçülebilir bir oyun kuralı eklemek
C) draw içinde createCanvas tekrarlamak
D) Skoru her frame koşulsuz artırmak
E) Hata ayıklamadan uzun kodu olduğu gibi bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme, öğrenilen araçlarla kural eklemeyi hedefler; alandan kopuk şıklar elenir. İlgili Konu: Pekiştirme
SORU 5: «Çarpışma Temelleri ve Sekme» bağlamında hangisi daha iyi bir sonraki adım geliştirmedir?
A) Konu dışı bir CSS animasyonu eklemek
B) Mevcut sketch’e ölçülebilir bir kural (skor, sınır, durum) eklemek
C) Tuvali silip boş bırakmak
D) setup’ı tamamen kaldırmak
E) Rastgele sözdizimi hatası bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme mevcut öğrenilen API ile kural ekler. İlgili Konu: 1.uygulama
SORU 6: Aşağıdaki hangi seçenek tipik bir çeldirici bug senaryosudur?
A) dist ile isabet, ardından skoru bir kez artırmak
B) draw içinde koşulsuz skor artışı
C) createCanvas’ı setup içinde bir kez çağırmak
D) background ile frame temizlemek
E) keyIsDown ile sürekli hareket
Doğru cevap: B
Genel açıklama: Koşulsuz artış her frame şişer — görünür bug. İlgili Konu: 1.uygulama
SORU 7: Kod okuma: if (x > width) { x = 0; } ne yapar?
A) Y’yi sıfırlar
B) X tuval sağını aşınca sola sarar
C) FPS’i sıfırlar
D) Fareyi kilitler
E) Diziyi temizler
Doğru cevap: B
Genel açıklama: Yatay sarma (wrap) kalıbı. İlgili Konu: 1.uygulama
SORU 8: Bu ana başlıkta (Çarpışma Temelleri ve Sekme) hangi uygulama en uygundur?
A) Öğrenilen API’yi bilinçli yok sayıp rastgele hazır kütüphane çağırmak
B) Anlatılan kavramı küçük bir sketch’te görünür çıktıyla denemek
C) Konuyu yalnızca okuyup hiç kod yazmamak
D) Tuval boyutunu her frame rastgele değiştirmek
E) Hata ayıklamadan uzun kod kopyalamak
Doğru cevap: B
Genel açıklama: Seçenek konu başlığıyla örtüşür; diğerleri alandan kopuk. İlgili Konu: 1.uygulama
SORU 9: console.log ayıklamada asıl faydası nedir?
A) Tuval çözünürlüğünü artırır
B) Ara değerleri görüp yanlış varsayımı yakalamayı sağlar
C) Otomatik çarpışma ekler
D) draw’ı durdurur
E) Kaynakça üretir
Doğru cevap: B
Genel açıklama: Gözlemlenebilir ara durum. İlgili Konu: 1.uygulama
SORU 10: Bir fonksiyonu parametreli yazmanın faydası?
A) FPS’i kilitlemek
B) Aynı mantığı farklı argümanlarla yeniden kullanmak
C) setup’ı kaldırmak
D) HTML’i silmek
E) Rengi yasaklamak
Doğru cevap: B
Genel açıklama: Modülerlik ve yeniden kullanım. İlgili Konu: 1.uygulama
Ana Başlık 2 için 10 Soru
SORU 1: Aşağıdaki yaklaşımlardan hangisi oyun sketch’inde daha sağlam bir geliştirmedir?
A) Konu dışı teknolojiye (biçim/dil dışı) sapıp temel kuralı atlamak
B) Öğrenilen p5.js API’si ile ölçülebilir bir oyun kuralı eklemek
C) draw içinde createCanvas tekrarlamak
D) Skoru her frame koşulsuz artırmak
E) Hata ayıklamadan uzun kodu olduğu gibi bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme, öğrenilen araçlarla kural eklemeyi hedefler; alandan kopuk şıklar elenir. İlgili Konu: Pekiştirme
SORU 2: Aşağıdaki yaklaşımlardan hangisi oyun sketch’inde daha sağlam bir geliştirmedir?
A) Konu dışı teknolojiye (biçim/dil dışı) sapıp temel kuralı atlamak
B) Öğrenilen p5.js API’si ile ölçülebilir bir oyun kuralı eklemek
C) draw içinde createCanvas tekrarlamak
D) Skoru her frame koşulsuz artırmak
E) Hata ayıklamadan uzun kodu olduğu gibi bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme, öğrenilen araçlarla kural eklemeyi hedefler; alandan kopuk şıklar elenir. İlgili Konu: Pekiştirme
SORU 3: Aşağıdaki yaklaşımlardan hangisi oyun sketch’inde daha sağlam bir geliştirmedir?
A) Konu dışı teknolojiye (biçim/dil dışı) sapıp temel kuralı atlamak
B) Öğrenilen p5.js API’si ile ölçülebilir bir oyun kuralı eklemek
C) draw içinde createCanvas tekrarlamak
D) Skoru her frame koşulsuz artırmak
E) Hata ayıklamadan uzun kodu olduğu gibi bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme, öğrenilen araçlarla kural eklemeyi hedefler; alandan kopuk şıklar elenir. İlgili Konu: Pekiştirme
SORU 4: Aşağıdaki yaklaşımlardan hangisi oyun sketch’inde daha sağlam bir geliştirmedir?
A) Konu dışı teknolojiye (biçim/dil dışı) sapıp temel kuralı atlamak
B) Öğrenilen p5.js API’si ile ölçülebilir bir oyun kuralı eklemek
C) draw içinde createCanvas tekrarlamak
D) Skoru her frame koşulsuz artırmak
E) Hata ayıklamadan uzun kodu olduğu gibi bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme, öğrenilen araçlarla kural eklemeyi hedefler; alandan kopuk şıklar elenir. İlgili Konu: Pekiştirme
SORU 5: «Durum Makinesi Kavramı ve Geçişler» bağlamında hangisi daha iyi bir sonraki adım geliştirmedir?
A) Konu dışı bir CSS animasyonu eklemek
B) Mevcut sketch’e ölçülebilir bir kural (skor, sınır, durum) eklemek
C) Tuvali silip boş bırakmak
D) setup’ı tamamen kaldırmak
E) Rastgele sözdizimi hatası bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme mevcut öğrenilen API ile kural ekler. İlgili Konu: 2.uygulama
SORU 6: Aşağıdaki hangi seçenek tipik bir çeldirici bug senaryosudur?
A) dist ile isabet, ardından skoru bir kez artırmak
B) draw içinde koşulsuz skor artışı
C) createCanvas’ı setup içinde bir kez çağırmak
D) background ile frame temizlemek
E) keyIsDown ile sürekli hareket
Doğru cevap: B
Genel açıklama: Koşulsuz artış her frame şişer — görünür bug. İlgili Konu: 2.uygulama
SORU 7: Kod okuma: if (x > width) { x = 0; } ne yapar?
A) Y’yi sıfırlar
B) X tuval sağını aşınca sola sarar
C) FPS’i sıfırlar
D) Fareyi kilitler
E) Diziyi temizler
Doğru cevap: B
Genel açıklama: Yatay sarma (wrap) kalıbı. İlgili Konu: 2.uygulama
SORU 8: Bu ana başlıkta (Durum Makinesi Kavramı ve Geçişler) hangi uygulama en uygundur?
A) Öğrenilen API’yi bilinçli yok sayıp rastgele hazır kütüphane çağırmak
B) Anlatılan kavramı küçük bir sketch’te görünür çıktıyla denemek
C) Konuyu yalnızca okuyup hiç kod yazmamak
D) Tuval boyutunu her frame rastgele değiştirmek
E) Hata ayıklamadan uzun kod kopyalamak
Doğru cevap: B
Genel açıklama: Seçenek konu başlığıyla örtüşür; diğerleri alandan kopuk. İlgili Konu: 2.uygulama
SORU 9: console.log ayıklamada asıl faydası nedir?
A) Tuval çözünürlüğünü artırır
B) Ara değerleri görüp yanlış varsayımı yakalamayı sağlar
C) Otomatik çarpışma ekler
D) draw’ı durdurur
E) Kaynakça üretir
Doğru cevap: B
Genel açıklama: Gözlemlenebilir ara durum. İlgili Konu: 2.uygulama
SORU 10: Bir fonksiyonu parametreli yazmanın faydası?
A) FPS’i kilitlemek
B) Aynı mantığı farklı argümanlarla yeniden kullanmak
C) setup’ı kaldırmak
D) HTML’i silmek
E) Rengi yasaklamak
Doğru cevap: B
Genel açıklama: Modülerlik ve yeniden kullanım. İlgili Konu: 2.uygulama
Ana Başlık 3 için 10 Soru
SORU 1: Aşağıdaki yaklaşımlardan hangisi oyun sketch’inde daha sağlam bir geliştirmedir?
A) Konu dışı teknolojiye (biçim/dil dışı) sapıp temel kuralı atlamak
B) Öğrenilen p5.js API’si ile ölçülebilir bir oyun kuralı eklemek
C) draw içinde createCanvas tekrarlamak
D) Skoru her frame koşulsuz artırmak
E) Hata ayıklamadan uzun kodu olduğu gibi bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme, öğrenilen araçlarla kural eklemeyi hedefler; alandan kopuk şıklar elenir. İlgili Konu: Pekiştirme
SORU 2: Bitiş ekranında hareket kodu neden genelde çalışmaz?
A) Çünkü güncelleme yalnızca oyun durumunda yapılmalıdır
B) Çünkü p5.js menüyü desteklemez
C) Çünkü dizi yasaktır
D) Çünkü tuval yoktur
E) Çünkü dist yoktur
Doğru cevap: A
Genel açıklama: Bu soru ana başlık kazanımını ölçer. İlgili Konu: 3.2
SORU 3: Kaç-kaç örneğinin pedagojik amacı nedir?
A) Durum + hareket + kuralı bir arada göstermek
B) AAA fizik motoru yazmak
C) Sunucu cluster kurmak
D) SQL öğretmek
E) GPU sürücüsü yazmak
Doğru cevap: A
Genel açıklama: Bu soru ana başlık kazanımını ölçer. İlgili Konu: 3.3
SORU 4: Aşağıdaki yaklaşımlardan hangisi oyun sketch’inde daha sağlam bir geliştirmedir?
A) Konu dışı teknolojiye (biçim/dil dışı) sapıp temel kuralı atlamak
B) Öğrenilen p5.js API’si ile ölçülebilir bir oyun kuralı eklemek
C) draw içinde createCanvas tekrarlamak
D) Skoru her frame koşulsuz artırmak
E) Hata ayıklamadan uzun kodu olduğu gibi bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme, öğrenilen araçlarla kural eklemeyi hedefler; alandan kopuk şıklar elenir. İlgili Konu: Pekiştirme
SORU 5: «Menü–Oyun–Bitiş Akışı ve Kaç-Kaç» bağlamında hangisi daha iyi bir sonraki adım geliştirmedir?
A) Konu dışı bir CSS animasyonu eklemek
B) Mevcut sketch’e ölçülebilir bir kural (skor, sınır, durum) eklemek
C) Tuvali silip boş bırakmak
D) setup’ı tamamen kaldırmak
E) Rastgele sözdizimi hatası bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme mevcut öğrenilen API ile kural ekler. İlgili Konu: 3.uygulama
SORU 6: Aşağıdaki hangi seçenek tipik bir çeldirici bug senaryosudur?
A) dist ile isabet, ardından skoru bir kez artırmak
B) draw içinde koşulsuz skor artışı
C) createCanvas’ı setup içinde bir kez çağırmak
D) background ile frame temizlemek
E) keyIsDown ile sürekli hareket
Doğru cevap: B
Genel açıklama: Koşulsuz artış her frame şişer — görünür bug. İlgili Konu: 3.uygulama
SORU 7: Kod okuma: if (x > width) { x = 0; } ne yapar?
A) Y’yi sıfırlar
B) X tuval sağını aşınca sola sarar
C) FPS’i sıfırlar
D) Fareyi kilitler
E) Diziyi temizler
Doğru cevap: B
Genel açıklama: Yatay sarma (wrap) kalıbı. İlgili Konu: 3.uygulama
SORU 8: Bu ana başlıkta (Menü–Oyun–Bitiş Akışı ve Kaç-Kaç) hangi uygulama en uygundur?
A) Öğrenilen API’yi bilinçli yok sayıp rastgele hazır kütüphane çağırmak
B) Anlatılan kavramı küçük bir sketch’te görünür çıktıyla denemek
C) Konuyu yalnızca okuyup hiç kod yazmamak
D) Tuval boyutunu her frame rastgele değiştirmek
E) Hata ayıklamadan uzun kod kopyalamak
Doğru cevap: B
Genel açıklama: Seçenek konu başlığıyla örtüşür; diğerleri alandan kopuk. İlgili Konu: 3.uygulama
SORU 9: console.log ayıklamada asıl faydası nedir?
A) Tuval çözünürlüğünü artırır
B) Ara değerleri görüp yanlış varsayımı yakalamayı sağlar
C) Otomatik çarpışma ekler
D) draw’ı durdurur
E) Kaynakça üretir
Doğru cevap: B
Genel açıklama: Gözlemlenebilir ara durum. İlgili Konu: 3.uygulama
SORU 10: Bir fonksiyonu parametreli yazmanın faydası?
A) FPS’i kilitlemek
B) Aynı mantığı farklı argümanlarla yeniden kullanmak
C) setup’ı kaldırmak
D) HTML’i silmek
E) Rengi yasaklamak
Doğru cevap: B
Genel açıklama: Modülerlik ve yeniden kullanım. İlgili Konu: 3.uygulama
Ana Başlık 4 için 10 Soru
SORU 1: tahta[1][2] ifadesi neyi ifade eder?
A) 1. sütun, 2. satır
B) 2. satır, 3. sütun (0'dan indeks)
C) Tuval genişliği
D) Sıradaki oyuncu
E) Kazanan işareti
Doğru cevap: B
Genel açıklama: İlk indeks satır, ikinci indeks sütundur. İlgili Konu: 5.1
SORU 2: Boş XOX hücresi tipik olarak nasıl temsil edilir?
A) 0
B) null
C) "" (boş string)
D) "bos"
E) false (boolean)
Doğru cevap: C
Genel açıklama: Boş hücre boş string; dolu hücre "X" veya "O". İlgili Konu: 5.1
SORU 3: Dolu hücreye tıklandığında tipik davranış nedir?
A) Taş silinir
B) Hamle yok sayılır (return)
C) Sıra otomatik değişir
D) Tuval yeniden oluşturulur
E) setup() tekrar çalışır
Doğru cevap: B
Genel açıklama: Geçersiz hamle erken çıkışla yok sayılır. İlgili Konu: 5.3
SORU 4: [Kod okuma] HUCRE = 100, mouseX = 250, mouseY = 120 iken floor(mouseX / HUCRE) ve floor(mouseY / HUCRE) değerleri sırasıyla nedir?
A) 2 ve 1
B) 250 ve 120
C) 1 ve 2
D) 3 ve 3
E) 0 ve 0
Doğru cevap: A
Genel açıklama: floor(250/100)=2, floor(120/100)=1 → sütun 2, satır 1. İlgili Konu: 5.3
SORU 5: 3×3 XOX tahtasında kaç kazanma hattı vardır?
A) 3
B) 6
C) 8
D) 9
E) 12
Doğru cevap: C
Genel açıklama: 3 yatay + 3 dikey + 2 çapraz = 8 hat. İlgili Konu: 5.4
SORU 6: Beraberlik koşulu aşağıdakilerden hangisidir?
A) sira === "O"
B) Tahta dolu ve kazananKontrol() boş string döndürür
C) mousePressed() hiç çalışmaz
D) DURUM_MENU aktiftir
E) İlk hamle X ile yapılmaz
Doğru cevap: B
Genel açıklama: 9 hücre dolu, kazanan yoksa beraberlik. İlgili Konu: 5.4
SORU 7: [Kod okuma] Aşağıdaki tahtada kazananKontrol() ne döndürür?
Kod 1.
let tahta = [ ["X", "X", "X"], ["O", "", "O"], ["", "O", ""]];A) "O"
B) "X"
C) ""
D) "beraberlik"
E) undefined
Doğru cevap: B
Genel açıklama: Üst satır X-X-X — yatay kazanma hattı. İlgili Konu: 5.4
SORU 8: XOX'ta hamle işleme neden yalnızca DURUM_OYUN iken yapılmalıdır?
A) FPS artırmak için
B) Menü ve bitiş ekranında tıklamanın oyun mantığını tetiklememesi için
C) Diziyi silmek için
D) Klavye girdisini kapatmak için
E) Tuval boyutunu değiştirmek için
Doğru cevap: B
Genel açıklama: Durum makinesi her aşamada farklı girdi anlamı taşır. İlgili Konu: 5.3 ve 5.5
SORU 9: I. oyunuSifirla() tahtayı ve sırayı yeniler.
II. Her geçerli hamle sonrası önce kazanma, sonra beraberlik kontrol edilir.
III. tahta bir boyutlu dizidir.
Hangileri doğrudur?
A) Yalnız I
B) I ve II
C) Yalnız III
D) II ve III
E) I, II ve III
Doğru cevap: B
Genel açıklama: I ve II doğru. III yanlış; tahta iki boyutlu dizidir. İlgili Konu: 5.1–5.4
SORU 10: XOX sketch'inde menüden oyuna geçiş için hangi girdiler desteklenir?
A) Yalnızca WASD
B) SPACE veya fare tıklaması
C) Yalnızca R
D) Yalnızca ok tuşları
E) Tuval dışına tıklama zorunludur
Doğru cevap: B
Genel açıklama: Menüde SPACE veya tıklama oyunuSifirla() ve DURUM_OYUN atar. İlgili Konu: 5.5
Açık Uçlu Pekiştirme Soruları
Bu bölüm sınav formatı dışındadır; tartışma, ödev, sınıf içi etkinlik veya ana başlıklardaki Yapay Zekâ Etkileşimi öğesiyle birlikte kullanılır.
Ana Başlık 1 — Açık Uçlu
A1. «Çarpışma Temelleri ve Sekme» konusundaki merkezi kavramı kendi cümlelerinizle açıklayın ve bunu somut bir mini oyun / sketch örneğine bağlayın.
A2. «Çarpışma Temelleri ve Sekme» için küçük bir varyasyon tasarlayın (yeni kural, sınır durumu veya görsel geri bildirim). Hangi fonksiyonlar değişir? Madde madde yazın.
A3. Bu ana başlıkta sık yapılan bir yanlış varsayımı (yanlış indeks, sıra, durum veya veri modeli) seçin; neden hatalı olduğunu ve doğru yaklaşımı iki–üç cümleyle yazın.
Ana Başlık 2 — Açık Uçlu
A1. «Durum Makinesi Kavramı ve Geçişler» konusundaki merkezi kavramı kendi cümlelerinizle açıklayın ve bunu somut bir mini oyun / sketch örneğine bağlayın.
A2. «Durum Makinesi Kavramı ve Geçişler» için küçük bir varyasyon tasarlayın (yeni kural, sınır durumu veya görsel geri bildirim). Hangi fonksiyonlar değişir? Madde madde yazın.
A3. Bu ana başlıkta sık yapılan bir yanlış varsayımı (yanlış indeks, sıra, durum veya veri modeli) seçin; neden hatalı olduğunu ve doğru yaklaşımı iki–üç cümleyle yazın.
Ana Başlık 3 — Açık Uçlu
A1. «Menü–Oyun–Bitiş Akışı ve Kaç-Kaç» konusundaki merkezi kavramı kendi cümlelerinizle açıklayın ve bunu somut bir mini oyun / sketch örneğine bağlayın.
A2. «Menü–Oyun–Bitiş Akışı ve Kaç-Kaç» için küçük bir varyasyon tasarlayın (yeni kural, sınır durumu veya görsel geri bildirim). Hangi fonksiyonlar değişir? Madde madde yazın.
A3. Bu ana başlıkta sık yapılan bir yanlış varsayımı (yanlış indeks, sıra, durum veya veri modeli) seçin; neden hatalı olduğunu ve doğru yaklaşımı iki–üç cümleyle yazın.
Ana Başlık 4 — Açık Uçlu
A1. kazananKontrol() için üç test tahtası tasarlayın: X kazanır, O kazanır, beraberlik öncesi (henüz kazanan yok, tahta dolu değil).
Örnek yanıt unsurları: 3×3 dizi; beklenen dönüş "X", "O", "".
Değerlendirme: Her senaryo ayırt edilebilir mi?
A2. İki boyutlu dizi ile önceki bölümlerdeki tek boyutlu dizi arasındaki farkı XOX örneğiyle açıklayın.
Örnek yanıt unsurları: tahta[satir][sutun] vs skorlar[i].
Değerlendirme: Satır–sütun erişimi doğru mu?
A3. XOX sketch'ine bilgisayar rakibi eklemeden önce hangi fonksiyonlara dokunmadan yalnızca yeni mantık eklenebilir? Modülerlik açısından tartışın.
Örnek yanıt unsurları: mousePressed yerine sıra O iken rastgeleHamle(); çizim fonksiyonları aynı kalabilir.
Değerlendirme: Veri/çizim/girdi ayrımı düşünülmüş mü?