Bölüm 3 · Sunum 2

Diziler: birçok değer, tek bir ad

Elli düşmanı elli ayrı değişkende tutmadan yönetmeyi öğreneceğiz.

Dizi ve indeksfor ile dolaşmakParalel dizilerpush ve popYığın

Ekranda 50 düşman var. Konumlarını nerede tutacaksınız?

Peki hepsini 2 piksel sağa kaydırmak için kaç satır yazacaksınız?

Dizi: yan yana duran, numaralı kutular

100
251
402

üstte değerler · altta indeksler

Dizi (array)Köşeli parantez [] ile tanımlanan, indeksle erişilen sıralı veri koleksiyonudur.

Dizi tanımlamak

İfadeAnlamı
[]Boş dizi oluşturur
[a, b, c]Başlangıç elemanlarıyla dizi
dizi[0]İlk eleman (indeks 0)
dizi.lengthEleman sayısı

Envanter çubuğu bir dizidir

Dokuz kutu, tek bir ad. Hangi kutuyu istediğinizi bir sayıyla söylüyorsunuz.

Oyunlarda dizi her yerde

EnvanterMinecraft’ın alt çubuğunda 9 yuva var; her biri numaralı.
Yüksek skor tablosuAtari salonlarındaki ilk 10 listesi: sıralı on sayı.
Sıradaki parçalarTetris’te “sonraki” kutusunda bekleyen parçalar bir sırada durur.
Düşmanlar, mermilerSpace Invaders’taki her uzaylı, her mermi bir listenin elemanı.

Ortak nokta: aynı türden birçok değer ve onları sırayla işleme ihtiyacı.

skorlar[1] hangi değeri verir?

Peki skorlar[3]?

25. Çünkü saymaya 0’dan başlıyoruz

100
251
402
?3

skorlar.length === 3 · son geçerli indeks 2

İndeksler 0’dan başlarskorlar[1] ikinci elemandır.
Dördüncü kutu yokskorlar[3] hata vermez; undefined döner. Hata sessizdir.

Programcıların bitmeyen tartışması

xkcd 163: iki programcı dizi indekslerinin 0’dan mı 1’den mi başlaması gerektiğini tartışıyor
“İndekslerinde tutarsızsın: bazıları birden, bazıları sıfırdan başlıyor.” · Kaynak: xkcd.com/163, Randall Munroe (CC BY-NC 2.5)

Olmayan indekse yazmak: delikli dizi

10
boş1
boş2
443
Boş slot (hole)Araya hiç doldurulmamış hücreler girer. Okununca undefined verirler. Konsolda [1, <2 empty slots>, 44] gibi görünür.

push ya da 0, 1, 2… sırasıyla atama boşluk bırakmaz. Oyun listelerinde bu delikleri oluşturmayın.

Dizi, ilgili değerleri bir arada taşır

İndeksrenkler[indeks]Anlamı
0255Kırmızı
1120Yeşil
280Mavi
3undefinedKarşılığı yok

fill(255, 120, 80) ile aynı sonuç.

Karışık türlerJavaScript aynı dizide farklı türlere izin verir: [1, "iki", true]. Oyun kodunda tek tür tutmak okumayı kolaylaştırır.

Kâğıt kalem

  1. skorlar[0] ve skorlar[2] nedir? skorlar[3] neden sorunlu?
  2. skorlar.length kaçtır? Son geçerli indeks hangisi?
  3. Üç skoru alt alta yazdıracak for döngüsünün koşulunu yazın: i < …

Elemanı okumak ve değiştirmek

70
121
52

↓ tahminler[0] = 8

80
121
52

Her hücre kendi başına bir değişken gibidir: okunur, üstüne yazılır. Diğer hücreler etkilenmez.

for ile diziyi dolaşmak

i < tahminler.length koşulu indeksi dizinin sınırları içinde tutar. Diziye bir sayı daha ekleyin: döngüye dokunmanız gerekmez.

Koşulu i <= tahminler.length yaparsak?

Dizide 4 eleman var. Döngü kaç tur atar? Son turda ne okunur?

Bir tur fazla: son satırda undefined

itahminler[i]
07
112
25
39
4undefined
Sınırda bir fazla (off-by-one)length eleman sayısıdır: 4. Son geçerli indeks ise length - 1: 3.
Kalıpfor (let i = 0; i < dizi.length; i++)
Küçüktür, küçük eşit değil.

Her hedefin bir x’i ve bir y’si var. Tek bir dizi yeter mi?

Ekranda üç hedef daire olacak. Altı sayıyı nasıl düzenlersiniz ki hangisinin hangi daireye ait olduğu karışmasın?

Paralel diziler: aynı indeks, aynı nesne

hedefXListesi

800
2001
3202

hedefYListesi

1000
1501
2002

1 numaralı hedef: (200, 150)

Paralel diziBir nesnenin özelliklerini ayrı dizilerde, aynı indekste tutma modeli. hedefXListesi[i] ile hedefYListesi[i] aynı hedefin koordinatlarıdır.

İleride nesneler ve iki boyutlu diziler gibi başka yollar da göreceğiz. Şimdilik paralel dizi yeterli.

Konum listesinden hedef çizmek

Aynı i hem x’i hem y’yi okur; döngü her turda bir hedef çizer. İki diziye birer sayı daha ekleyin: dördüncü hedef kendiliğinden belirir.

Biz ve düşmanlar

Düşman konumları: paralel diziler ve iki boyutlu sahne
  1. dusmanX.length kaç? Sahnede gerçekten kaç düşman var?
  2. (dusmanX[0], dusmanY[0]) neresi? [2] neden sahnede yok?
  3. Bize en yakın düşman hangi indekste? for ile −1 olanları atlayıp dist ile en küçüğü bulun.

Oyuncu her tıkladığında listeye yeni bir eleman eklenecek.

Dizinin kaç eleman tutacağını baştan bilmiyoruz. Çalışırken nasıl büyütürüz?

push() ve pop()

push()Dizinin sonuna eleman ekler. length bir artar.
pop()Dizinin son elemanını çıkarır ve o değeri döndürür. length bir azalır.
İşlemÖrnekÖnceSonra
Sona ekleliste.push(42)[10, 20][10, 20, 42]
Sondan çıkarliste.pop()[10, 20, 42][10, 20]; 42 döner
Eleman sayısıliste.length[10, 20]2

push(9): önce ve sonra

push ile sona eleman ekleme ve for ile dolaşma
Üstte dizi büyüyor; altta for döngüsü her turda bir sonraki hücreyi okuyor.

Tahmin geçmişi: her tıklamada bir eleman

floor(): aşağı yuvarla

floor()Verilen sayıyı aşağı yuvarlayan p5.js fonksiyonu. Tam sayı elde etmek için random() ile birlikte kullanılır.
İfadeSonuç
random(1, 11)1.00 … 10.99
floor(7.93)7
floor(random(1, 11))1, 2, … 10
OyunlardaZar atmak: floor(random(1, 7)). Rastgele bir düşman türü seçmek, rastgele bir hücreye ödül koymak hep aynı kalıptır.

Rastgele sayı demişken

xkcd 221: her zaman 4 döndüren getRandomNumber fonksiyonu
“Adil bir zar atışıyla seçildi. Rastgele olduğu garanti.” · Kaynak: xkcd.com/221, Randall Munroe (CC BY-NC 2.5)

pop() adım adım

AdımİşlemlisteDönen
Başlangıç—[10, 20, 42]—
1liste.pop()[10, 20]42
2liste.pop()[10]20
3liste.pop()[]10
4liste.pop()[]undefined
Boş dizide pop()Hata vermez ama anlamlı bir değer de vermez. Önce length > 0 diye bakın.
push da bir değer döndürürEklemeden sonraki yeni eleman sayısını. Örneklerimizde kullanmıyoruz; var olduğunu bilmek yeter.

Bir tabak yığınından tabak alırken hangisini alırsınız?

En alttakini mi, en üsttekini mi? En üstteki, yığına ne zaman konmuştu?

Yığın (stack): son giren ilk çıkar

Yığın (stack)push ve pop birlikte kullanıldığında dizi bir yığın gibi davranır. Kural LIFO’dur: last in, first out. En son eklenen, ilk çıkarılır.

Ayrı bir Stack sınıfı şart değil; sıradan bir dizi ve push / pop çoğu zaman yeter.

Tanıdık bir yığınFonksiyon çağrıları da bir çağrı yığını üzerinde tutulur: en son çağrılan fonksiyon önce biter. Derleyiciler ve yorumlayıcılar bu modeli kullanır.

Yığın oyunlarda nerede?

Geri al (Undo)Son hamleler bir yığında durur. Ctrl+Z bir pop’tur. Super Mario Maker’ın seviye düzenleyicisi, bulmaca oyunları.
Menü yığınıDuraklat → Ayarlar → Kontroller. Kapatınca bir üst menüye dönersiniz: pop.
Kart destesiSolitaire’de desteden kart çekmek üstten pop; kart koymak push.
Envanter“Son alınan eşyayı geri ver” gibi kısa geçmişler.

Sık kullanılan bir kalıp: en büyüğü bulmak

  • İlk elemanı “şimdilik en büyük” kabul et.
  • Geri kalanları tek tek gez; daha büyüğünü görürsen onu tut.
  • Boş dizi için önceden karar ver: burada 0 dönüyor.
  • enBuyuk(skorlar) en yüksek skoru verir.

for + karşılaştırma kalıbı toplam, ortalama, en küçük gibi birçok özet hesapta tekrar eder.

Mini kule savunma: tıkla, kule kur

Her tıklama, konumu iki diziye birden push eder. Birkaç kule kurun, sonra sol üstteki GERİ AL’a basın.

GERİ AL’a bastınız. Kule kalkmadı, üstelik yeni bir kule eklendi. Neden?

GERİ AL’ı çalıştırın

  1. Kâğıtta: kuleX = [10, 20], kuleY = [30, 40]. (50, 60)’a bir kule kurun, sonra bir kez geri alın. Diziler nasıl kalır?
  2. GERİ AL dalında, length > 0 ise her iki dizide pop çağırın.
  3. Birkaç kule kurup geri alın. Ekrandaki kule sayısı kuleX.length ile uyumlu mu?
İpucuYalnızca if’in içine pop yazmak yetmez. GERİ AL’a basınca alttaki push satırına ulaşılmaması gerekir.

Yapay zekâyla: dolaşma hatası

  1. i <= dizi.length yazan hatalı bir döngü düşünün. Ne olur? Önce kendiniz yazın.
  2. Bu hatayı ve düzeltmesini bir yapay zekâya sorun; gerekçesini sizinkiyle karşılaştırın.
  3. Kısa bir diziyle editörde hem hatalı hem doğru sınırı deneyin.

Kod zamanı

  1. Beş yıldızın konumunu paralel dizilerde tutup çizin. Tıklanan yere yeni bir yıldız eklensin.
  2. ortalama(degerler) fonksiyonu yazın; skor listesinin ortalamasını döndürsün.
  3. Kule oyununda en fazla 8 kule kurulabilsin; 9. tıklama yok sayılsın ve ekranda “Kule hakkı bitti” yazsın.
  4. Zorlu: “Biz ve düşmanlar” sahnesini çizin; bize en yakın düşmanı farklı renkte gösterin. Biz fareyi takip edelim.

Sonunda d nasıl görünür?

  1. [3, 6, 1]
  2. [3, 1]
  3. [1, 3]
  4. [3, 6, 9, 1]

[3, 6, 9] → [3, 6] → [3] → [3, 1]. Ekleme de çıkarma da hep sondan.

liste[liste.length] neyi verir?

  1. Son elemanı
  2. İlk elemanı
  3. undefined
  4. Eleman sayısını

Son eleman liste[liste.length - 1]’dir. length her zaman son geçerli indeksten bir fazladır.

Ekranda ne olur?

  1. Üç daire çizilir.
  2. İki daire düzgün çizilir; üçüncüsü çizilemez.
  3. Hiçbir şey çizilmez.

Üçüncü turda ys[2] undefined. Paralel dizilerin uzunlukları her zaman eşit olmalı.

Merak edenler için kaynaklar

Bugün ne öğrendik?

  • Dizi: köşeli parantezle tanımlanan, indeksle erişilen sıralı koleksiyon.
  • İndeksler 0’dan başlar; son geçerli indeks length - 1.
  • Dolaşma kalıbı: for (let i = 0; i < dizi.length; i++).
  • Paralel diziler: aynı indeks aynı nesneyi gösterir; uzunluklar eşit kalmalı.
  • push sona ekler, pop sondan çıkarır; birlikte bir yığın (LIFO) oluştururlar.
  • Boş dizide pop ve sınır dışı indeks undefined verir; hata sessizdir.

Sıradaki ders

Beş yuvalı bir envanter

Sabit kapasiteli diziler ve paralel dizilerle balon sahnesi.