Bölüm 2 · Sunum 2

İç içe döngüler, ızgara ve animasyon

Bir döngü bir sıra çizer. İki döngü bir tahta çizer.

Satır × sütunDama tahtasıframeCount ile hareketsin ve cosDebug

Bir for ile bir sıra kare çizdik. Satranç tahtasını nasıl çizeriz?

8 satır var, her satırda 8 kare. 64 tane rect mi yazacağız?

Döngünün içine bir döngü daha

sutun → satir → 0123 0123 Sarı hücre: satir 1, sutun 2
Izgara (grid)Satır ve sütunlardan oluşan, hücrelere bölünmüş düzlem. Oyun tahtalarının ve seviye tasarımının temel yapısıdır.
  • Dış döngü satırları gezer.
  • İç döngü o satırın sütunlarını gezer.
  • Konum: rect(sutun * boyut, satir * boyut, …)

Önce konsolda: hücreler hangi sırayla geziliyor?

İç döngü, dış döngünün her turunda baştan başlar. Bu yüzden önce bir satırın bütün sütunları, sonra bir sonraki satır gelir.

Aynı sıra, bu kez tuvalde

İç döngü bir satırı baştan sona bitirmeden dış döngü bir sonraki satıra geçmez. Bir kitabı okurken gözünüzün izlediği sıranın aynısı.

Takıldığınızda kâğıt kalem

Döngü başlığını oturtamıyorsanız birkaç hücrenin köşesini elle yazın (hücre 40 piksel). Önce üst satırı, sonra sol sütunu; kural kendiliğinden çıkar.

Örüntüden döngüye

Amaç kodu kâğıtta bitirmek değil, örüntüyü görünür kılmak. Bu bir zorunluluk da değil; yalnızca takıldığınızda başvuracağınız bir yol.

Sektörde de böyle çalışılır

Kernighan’ın uyarısıHata ayıklamak, kodu yazmaktan çoğu zaman daha zordur. Baştan karmaşık yazmak yerine adım adım ilerleyin.
Ördeğe anlatRubber duck debugging: kodu yüksek sesle, adım adım, sessiz bir nesneye anlatmak. Tutarsızlık anlatırken ortaya çıkar.
Kâğıt ve tahtaStüdyolarda ve oyun jam’lerinde karalama ve gri kutu prototip yaygındır. “Satır bitti, sütun başa döndü” diye iz sürmek de bir tür debug’dır.

Günlük hayatta “1. satır, 1. sütun” deriz. Programda neden 0’dan başlıyoruz?

Konsoldaki ilk hücre (0, 0) idi. 1’den başlatsak ne değişirdi?

Çünkü formül sade kalıyor

1’den başlarsak her konum hesabına − 1 eklemek gerekir. 0’dan başlayınca sutun * 40 yeter ve satir < 3 koşulu doğal okunur.

Aynı alışkanlığı dizilerde de göreceksiniz: ilk eleman dizi[0]’dır.

8 × 8 dama tahtası: sabitler ve tuval

Ölçüler en üstte, sabit olarak duruyor. Tuvalin boyutu da onlardan hesaplanıyor: 8 × 50 = 400.

8 × 8 dama tahtası: iki döngü

Renk nasıl dönüşümlü oluyor?

satirsutuntoplam% 2Renk
0000açık
0111koyu
0220açık
1011koyu
1120açık

(satir + sutun) % 2 === 0

  • Toplam çiftse kalan 0: açık kare.
  • Toplam tekse kalan 1: koyu kare.
  • Yan hücreye ya da alt hücreye geçince toplam 1 artar; renk değişir.

Burada üç şey birleşti: döngü, % ve if / else.

Bir hücrenin üstüne gelin

Komşu hücreye geçtiğinizde toplam 1 değişir, kalan 0’dan 1’e ya da 1’den 0’a döner. Renklerin dönüşümlü olmasının tek sebebi bu.

İç içe döngü kaç tur atar?

Dış: satirİç: sutunBu satırda çizilen
00 → 7 (8 tur)8 kare
10 → 7 (8 tur)8 kare
………
70 → 7 (8 tur)8 kare

8 × 8 = 64

Toplam tur, dış tur sayısı ile iç tur sayısının çarpımıdır.

Uzaylı filosu: 5 satır × 11 sütun

Space Invaders’ın (1978) filosu bir ızgaradır. Tetris’in kuyusu 10 × 20, satranç tahtası 8 × 8, Mayın Tarlası’nın büyük boyu 30 × 16 hücredir; hepsi iç içe iki döngüyle çizilir.

İki döngüye aynı adı vermeyin

Gölgelemeİç döngünün i’si, dış döngünün i’sini gölgeler. JavaScript hata vermez; kod çalışır ama sonuç sessizce bozulur.

Satır ve sütun için satir ve sutun, genel sayaçlar için i ve j kullanın.

İç içe döngü + continue: yalnızca köşegen

satir !== sutun ise o hücre atlanır. Geriye (0,0), (1,1), (2,2), (3,3) kalır.

Hücre hücre bir çam ağacı

Hedef: ızgara, yeşil taç hücreleri ve dikdörtgen gövde
  1. Izgara: yatay ve dikey çizgiler (line + for).
  2. Taç: üstte ortada 1 hücre; her alt satırda sola ve sağa birer hücre büyür: 1, 3, 5… triangle kullanmayın; hücreleri rect ile boyayın.
  3. Gövde: yeşilin altında, 3 hücre genişliğinde kahverengi bir rect.
  4. Ağaç tuvalde yatay ve dikey ortalansın.
İpucuOrta sütun mid = floor(SUTUN / 2). Yeşil satır r için aralık mid - r … mid + r. Sıra: ızgara → yeşil → gövde; background bir kez.

9 × 9 Go tahtası

Hedef: 9×9 Go tahtası, köşegenlerde beyaz ve siyah taşlar
  1. Izgara: 9 yatay + 9 dikey çizgi. Her yön için bir for yeter.
  2. Beyaz taşlar: ana köşegen, satir === sutun.
  3. Siyah taşlar: diğer köşegen, satir + sutun === 8.
  4. İki köşegenin kesiştiği (4, 4) boş kalsın: continue ya da if.
  5. Taşlar çizgilerin kesişiminde dursun; çap hücreden biraz küçük.
İpucuconst N = 9; ve const BOYUT = 40; gibi sabitler kullanın. Önce boş tahtayı çizin, sonra taş döngüsünü ekleyin.

Arkadaşınızın tahtasında çizgiler taşların üstünden geçiyor.

Beyaz taşların üstünde ızgara çizgileri görünüyor. Sizce kodda ne ters gitti?

İpucu: tuvalde üstte görünen şekil hangisidir?

Geçen bölümde tek bir daireyi kaydırdık. Beşini birden nasıl kaydırırız?

Elimizde iki araç var: aynı frame’de birçok şekil çizen for ve zamanı sayan frameCount.

Döngü çoğaltır, frameCount hareket ettirir

Formülü parçalayalım

frameCount * 2Hız. Her frame 2 piksel sağa.
i * 70Ofset. Her şerit bir öncekinden 70 piksel ileride başlar.
% widthSonucu 0 … width − 1 arasında tutar. Kenara gelen şerit soldan yeniden girer.

Çekirdek fikir: döngü = aynı frame’de birden fazla nesne · frameCount = zaman.

Şeritler düz gidiyor. Onları dalga gibi yukarı aşağı nasıl oynatırız?

Zamanla artıp azalan, sonra yine artan bir sayıya ihtiyacımız var.

sin(): −1 ile +1 arasında salınan sayı

sin grafiği: bir dönem ve iki yöne devam
sin(açı)Verilen açının sinüs değerini döndürür. Sonuç her zaman −1 ile +1 arasındadır; açı arttıkça değer dalga gibi yükselir ve alçalır.

Animasyonda sin’i “zamanla −1 … +1 arasında gidip gelen bir sayı üreteci” gibi düşünün.

Sayıyı piksele çevirmek

ParçaAralıkAnlamı
sin(...)−1 … +1Ham salınım
* 40−40 … +40Genlik: kaç piksel oynasın?
150 + …110 … 190Merkez: hangi yükseklikte?

+ i her daireye farklı bir faz verir: hepsi aynı anda aynı yükseklikte olmaz, dalga oluşur.

Yatay kayma + dikey salınım

sin() oyunlarda her yerde

Süzülen altınlar, gidip gelen platform, yanıp sönen yazı, nefes alan karakter: dördü de aynı kalıp. orta + genlik * sin(zaman).

Açı birimi: radyan

p5.js’te sin, cos, rotate açıyı varsayılan olarak radyan kabul eder.

SabitDereceAnlamı
HALF_PI≈ 90°Çeyrek tur
PI≈ 180°Yarım tur
TWO_PI≈ 360°Tam tur
Dönüşümp5.js
Derece → radyanradians(90) → PI/2
Radyan → derecedegrees(HALF_PI) → 90

angleMode(DEGREES) ile bütün sketch dereceye çevrilebilir; o zaman sin(90) yazılır. Örneklerimiz radyanla kalıyor.

20 köşeli düzgün bir çokgeni nasıl çizeriz?

20 köşenin 20 çift koordinatını tek tek hesaplamak istemiyoruz. Köşelerin ortak özelliği ne?

Bütün köşeler aynı çemberin üstünde

Birim çember: cos yatay, sin dikey
  • Köşeler çember üzerinde eşit açıyla dizilir.
  • Tam tur TWO_PI. 20 köşe için adım: TWO_PI / 20 (18°).
  • i. köşenin açısı: i * adım.
Açıdan koordinatax = merkezX + r * cos(açı)
y = merkezY + r * sin(açı)

cos yatay, sin dikey izdüşümü verir; ikisi de −1 … +1 arasındadır.

for ile düzgün yirmigen

KOSE’yi 3 yapın: üçgen. 6 yapın: altıgen. -HALF_PI ilk köşeyi tepeye, saat 12 yönüne taşır.

Köşe sayısını siz seçin

Fareyi sağa götürdükçe köşe sayısı artar; çokgen çembere yaklaşır. Mavi nokta aynı formülle çemberde dolaşır: oyunlardaki yörüngeler, saat ibreleri ve daire biçimli mermi dizilimleri böyle hesaplanır.

Aynı döngü while ile

Kod çıktısı: düzgün yirmigen
20 eşit kenar. Yalnızca bir sabit değişince şekil değişir.

Örnek olay: XOX tahtası

Gelecek bölümde bir tic-tac-toe (XOX) oyunu yazacağız. 3 × 3 tahtayı döngülerle çizeceğiz.

  1. 3 × 3 tahta için iç içe döngü rect()’i kaç kez çağırır?
  2. HUCRE_BOYUTU iki katına çıkarsa createCanvas boyutu nasıl etkilenir?
  3. frameCount olmadan döngü yalnızca konum çeşitliliği mi sağlar, hareket mi?
  4. Kayan şerit örneği ile sin’li daire örneğinin ortak yanı ne?
  5. Yirmigende TWO_PI / 20 neyi temsil eder? KOSE 6 olursa şekil ne olur?

Yapay zekâyla: döngüden ızgara

  1. 4 × 4, 6 × 6 ya da 10 × 10 bir ızgara hedefi belirleyin.
  2. Yapay zekâdan, draw() içinde iç içe for ile bu ızgarayı çizen kodu isteyin. Dama deseni için (satir + sutun) % 2 kullanmasını, her satırı yorumla açıklamasını söyleyin.
  3. Kodu Web Editor’da çalıştırın.
  4. Hücre sayısının satır × sütun olduğunu console.log ile doğrulayın.

Debug: programı çalışırken izlemek

Debug (hata ayıklama)Programın çalışırken ne yaptığını kontrollü biçimde gözlemektir: nerede durdu, değişkenler o anda kaç, hangi dal seçildi?

“Çalışmıyor” demek yetmez; neden çalışmadığını görmek gerekir.

  • p5.js tarayıcıda çalışır. Chrome, Firefox, Edge, Safari’nin Geliştirici Araçları (DevTools) bu işin doğal yeridir.
  • Breakpoint: programı o satırda durdurur.
  • Step over: bir satır ilerletir.
  • Scope / Watch: değişkenlerin o anki değerini gösterir.

İç içe for’da satir ve sutun’un tur tur değişmesini izlemek, çoğu zaman console.log yağmurundan daha öğreticidir.

Deftere yapıştırılan “bug”

1947 tarihli kayıt defteri sayfası; sayfaya bantla yapıştırılmış bir güve
Kaynak: Wikimedia Commons, ABD Deniz Kuvvetleri arşivi (kamu malı)

9 Eylül 1947, Harvard Mark II bilgisayarı arıza yapar.

  • Ekip makineyi açar: bir rölenin arasına güve sıkışmıştır.
  • Güveyi kayıt defterine bantlayıp altına not düşerler: “Gerçek bir böceğin (bug) bulunduğu ilk vaka.”
Sözcük daha eskiydiMühendisler arızalara zaten “bug” diyordu; espri de buradan geliyor. Hatayı ayıklamaya bugün de “debug” diyoruz.

Lastik ördek yöntemi

Kodum çalışmıyor. Sana satır satır anlatacağım.
🧑‍💻
programcı, masadaki ördeğe
Burada i sıfırdan başlıyor, sonra iç döngüde yine i… Bir dakika!
💡
dördüncü satırda
…
🦆
ördek · tek kelime etmedi, hata bulundu

Kodu birine (ya da bir şeye) yüksek sesle anlatmak, ne yaptığını sandığınız ile gerçekte ne yaptığı arasındaki farkı ortaya çıkarır.

Yapay zekâyla: tarayıcıda debug

  1. Tarayıcınızı not edin. Küçük bir ızgara sketch’i açık olsun.
  2. Sorun: “p5.js sketch’imi [tarayıcı] üzerinde debug etmek istiyorum. Sources / Debugger panelini nasıl açarım? Breakpoint, Step over, Step into, Continue ve Scope / Watch’u kısaca anlat.”
  3. En az bir breakpoint koyun; satir ve sutun’un tur tur değiştiğini görün.
  4. Hata avı: yapay zekâdan içinde 1–2 mantık hatası olan kısa bir ızgara sketch’i isteyin; hatayı söylemesin. Debugger ile kendiniz bulun, sonra teşhisinizi doğrulatın.
  5. Bir cümle yazın: “Debug bana …… gösterdi.”

Yapay zekâyla: döngü ve animasyon

  1. İç içe for ile 6 × 6 daire ızgarası isteyin: ellipse(sutun * 60, satir * 60, 30).
  2. Hareket ekletin: her dairenin y konumuna sin(frameCount * 0.05 + satir + sutun) * 12 kadar kayma. Dalganın satır ve sütun boyunca ilerleyişini izleyin.
  3. sutun yerine sabit bir sayı yazın: ellipse(3 * 60, …). Ne değişti? Aynısını satir için deneyin.
  4. Bir cümle yazın: “Döngü değişkenini sabitleyince …… oldu; demek ki o değişken ……yi taşıyor.”

Kod zamanı

  1. 10 × 10 bir ızgara çizin; hücrelerin rengi soldan sağa kırmızılaşsın, yukarıdan aşağı mavileşsin.
  2. Dama tahtasında yalnızca köşegendeki hücreleri sarıya boyayın.
  3. Kayan şeritler bu kez yukarıdan aşağı aksın.
  4. sin’li dairelerin yalnızca y’si değil, çapı da salınsın.
  5. Zorlu: yirmigenin köşe sayısı her saniye 1 artsın: üçgenden başlayıp 20’ye çıksın, sonra başa dönsün.

console.log kaç kez çalışır?

  1. 16
  2. 12
  3. 10
  4. 4

İç döngünün sınırı dış değişkene bağlı: 1 + 2 + 3 + 4 = 10. Çam ağacındaki üçgenin sırrı da bu.

Hücre boyutu 50. (satir = 2, sutun = 5) hücresinin sol üst köşesi nerede?

  1. (100, 250)
  2. (250, 100)
  3. (2, 5)
  4. (300, 150)

x sütundan, y satırdan gelir: rect(sutun * 50, satir * 50, …). İkisini karıştırmak en sık yapılan ızgara hatası.

y = 200 + sin(frameCount * 0.1) * 60. y hangi aralıkta gezer?

  1. 0 … 200
  2. −60 … 60
  3. 140 … 260
  4. 200 … 260

sin −1 … +1 arasında. 60 ile çarpınca −60 … +60; 200 eklenince 140 … 260.

Merak edenler için kaynaklar

Bugün ne öğrendik?

  • İç içe döngüde dış sayaç satırı, iç sayaç sütunu gezer; toplam tur ikisinin çarpımıdır.
  • Konum: x = sutun * boyut, y = satir * boyut. 0’dan saymak formülü sade tutar.
  • (satir + sutun) % 2 dama desenini üretir.
  • Döngü çoğaltır, frameCount hareket ettirir, % width başa döndürür.
  • sin −1 … +1 arasında salınır; genlikle çarpılır, merkeze eklenir.
  • Düzgün çokgen: açı adımı TWO_PI / köşe; köşeler cos ve sin ile bulunur.
  • Takılınca: kâğıt kalem ya da tarayıcının debugger’ı.

Sıradaki ders

Kodu parçalara ayırmak

Fonksiyonlar, parametreler ve return.