Bölüm 2 · Sunum 3

Fonksiyonlar ve modüler kod

Uzayıp giden bir draw’ı, her biri tek iş yapan adlandırılmış parçalara böleceğiz.

Tanım ve çağrıParametrereturnYardımcı çizim fonksiyonlarıModüler oyun kodu

draw fonksiyonunuz 60 satır oldu. Tahtanın rengini değiştirmek istiyorsunuz.

İlgili satırı bulmak ne kadar sürer? Tahta, skor ve hedef kodu birbirine karışmışsa?

Her işe bir ad verin

Fonksiyon (function)Belirli bir görevi yerine getiren, isimlendirilmiş ve gerektiğinde tekrar çağrılabilen kod bloğudur.
  • draw artık ne yaptığını bir liste gibi söylüyor.
  • Tahta bozuksa bütün draw’a değil, tahtaCiz’e bakarsınız.
  • Değişiklik tek noktada yapılır; kopyalanmış satırlarda unutulan güncelleme kalmaz.

Aslında fonksiyonları zaten kullanıyoruz

Hazır gelenlerrect(), fill(), dist(), random(). Onları biz çağırıyoruz.
p5.js’in çağırdıklarısetup(), draw(), mousePressed(). Biz yazıyoruz, p5.js belirli anlarda kendisi çağırıyor.
Bugün: kendi fonksiyonlarımızAdını biz koyacağız, biz yazacağız, biz çağıracağız.

Matematikteki f(x) gibi: bir kara kutu

Fonksiyon kara kutusu: girdi, işlem, çıktı

Girdi verirsiniz, içerideki kural çalışır, bir sonuç çıkar. dist(x1, y1, x2, y2) tam böyledir: formülü ezberlemeseniz de sonucu kullanırsınız.

Önce şu soruyu sorunBu fonksiyon ne alır, ne verir, ne yapar? İçini satır satır bilmek şart değil.

Tanımlamak ve çağırmak

KavramBiçimAnlamı
Tanımfunction hedefCiz() { … }Fonksiyonun adı ve gövdesi. Tek başına hiçbir şey çalıştırmaz.
ÇağrıhedefCiz();Tanımlanan bloğu şimdi çalıştırır. Parantezler şart.
p5.js yerleşiksetup(), draw()p5.js belirli anlarda otomatik çağırır.

İlk iki fonksiyonumuz

Çağrı izi: sırayla kim çalışıyor?

AdımÇalışanNot
1draw()p5.js tetikler
2arkaPlanCiz()draw içinden çağrılır
3ortaCizgiCiz()draw içinden çağrılır
4(frame biter)Sonraki frame’de 1’e dönülür
Çağrı yığını (call stack)Fonksiyonlar iç içe çağrılabilir. tahtaCiz bir döngüde hucreCiz’i çağırır; her hucreCiz bitince kontrol tahtaCiz’e döner.
Tanım nerede durmalı?function ad() { … } tanımları, dosyanın neresinde olursa olsun çalışmadan önce tanınır. Çağrı tanımdan önce yazılsa da çalışır.

draw yerine cizimYap yazarsak ne olur?

Hiçbir şey çizilmez

Ad sabitsetup, draw ve mousePressed adlarını p5.js tanır ve belirli anlarda bu adlardaki fonksiyonları arar. cizimYap diye birini aramaz; onu çağıran olmaz.
Kendi fonksiyonlarınızdaAd sizin seçiminizdir. camelCase örfünü kullanıyoruz: hedefCiz, skorGuncelle.

İyi bir fonksiyon nasıl olur?

Tek, net bir işDeğer alır, çoğu zaman değer üretir ya da tek bir işi tamamlar. “Hem skor hesapla hem dosyaya yaz hem menüyü çiz” bakımı zorlaştırır.
Yan etkihedefCiz tuvale çizer; bu bir yan etkidir ama görevi tek ve anlaşılır. Dosya, ağ, konsol gibi işler çoğunlukla başka katmanlara bırakılır.
Dış değişkeni değiştirmekBir fonksiyonun global bir değişkeni güncellemesi de yan etkidir. İdeal olan return ile sonuç vermektir; yine de olay fonksiyonlarında sık görülür.

Fonksiyonlar ekip işini kolaylaştırır

  • Biri tahtaCiz’i yazarken diğeri skorYaz üzerinde çalışabilir.
  • Üzerinde anlaşılması gereken tek şey arayüz: ad, parametreler, dönüş.
  • İki değişiklik aynı satırlarda çakışmaz.
Kara kutu burada da işe yararArkadaşınızın yazdığı fonksiyonun içini bilmeden, ne aldığını ve ne verdiğini biliyorsanız onu çağırabilirsiniz. Tıpkı dist gibi.

Uzun bir draw’ı bölün

  1. Daha önce yazdığınız uzun bir draw() seçin (örneğin Daire Tıklama).
  2. En az iki anlamlı fonksiyona bölün: arkaplanCiz, skorYaz gibi.
  3. Her fonksiyonun tek sorumluluğunu bir satırla yazın.

Biri kırmızı, biri mavi iki dikdörtgen çizeceğiz. İki ayrı fonksiyon mu yazalım?

kirmiziDikdortgenCiz() ve maviDikdortgenCiz()… Peki ya on farklı renk ve konum olursa?

Parametre: fonksiyona dışarıdan değer vermek

Tek fonksiyon, farklı değerlerle iki kez çağrılıyor. Üçüncü bir dikdörtgen eklemek tek satır.

Parametre ve argüman

Parametre (parameter)Fonksiyon tanımında parantez içine yazılan yer tutucu. Dışarıdan gelecek değeri bekler.
function dikdortgenCiz(x, y, w, h)
Argüman (argument)Çağrı sırasında verilen somut değer.
dikdortgenCiz(50, 50, 80, 60)
Sıra önemliİlk argüman ilk parametreye gider: ilk 50 x’e, ikinci 50 y’ye. Argüman eksikse karşılığı olmayan parametreler undefined olur; fazlaysa fazlası yok sayılır.

dist() bize bir sayı veriyor. Kendi fonksiyonumuz da bir şey geri verebilir mi?

sonuc kutusuna 8 girmesini istiyoruz.

return: sonucu çağırana geri gönder

Dönüş değeri (return value)Fonksiyonun return ile geri gönderdiği sonuç. Çağrı ifadesinin yerine geçer.
BiçimAnlamıÖrnek
return;Değer yok; fonksiyon hemen biter.mousePressed içinde erken çıkış
return değer;Hesaplanan değeri çağırana verir.return a + b;

Boolean döndüren fonksiyon: acikKareMi

acikKareMi(3) → false, acikKareMi(6) → true. Dönen değer doğrudan if koşulunda kullanılıyor.

Oyun mantığında return: içinde mi?

icindeMi(mouseX, mouseY, hedefX, hedefY, 40) ifadesi true ya da false üretir.

Tanıdık geldi mi?Daire Tıklama’daki dist(...) < hedefYaricap satırının fonksiyona taşınmış hâli. Okuması kolay: if (icindeMi(…)).

Bir fonksiyon başka bir fonksiyonu çağırabilir: icindeMi, mesafeHesapla’yı kullanıyor.

“İçinde mi?” testini fonksiyona taşıyın

  1. Bölüm 1’deki iki örneği açın: fare yaklaşınca renk değiştiren daire ve Daire Tıklama.
  2. “Nokta dairenin içinde mi?” denetimini icindeMi fonksiyonuna taşıyın; eski yerlerde bu fonksiyonu çağırın.
  3. Davranış değişmemeli.
  4. İsterseniz: genişliği ve yüksekliği farklı bir elips için ayrı bir fonksiyon yazmayı deneyin.

Tahtayı fonksiyonlarla çizmek (1/3)

draw yalnızca iki satır: tahtayı çiz, merkez işaretini çiz.

Tahtayı fonksiyonlarla çizmek (2/3)

tahtaCiz tahtayı gezer; her hücrenin konumunu hesaplayıp işi hucreCiz’e bırakır.

Tahtayı fonksiyonlarla çizmek (3/3)

tahtaCiz farklı argümanlarla yeniden çağrılabilir; yalnızca boyut ve konum değişir. Bu yapı, ileride yazacağımız XOX oyununun zeminidir.

2 × 2 tahtada çağrı sırası

satirsutunhucreCiz çağrısıHücre rengi
00hucreCiz(0, 0, 50, 0, 0)açık (toplam çift)
01hucreCiz(50, 0, 50, 0, 1)koyu
10hucreCiz(0, 50, 50, 1, 0)koyu
11hucreCiz(50, 50, 50, 1, 1)açık

Her (satır, sütun) ikilisi için hucreCiz bir kez çağrılır. Toplam çağrı: satirSayisi * sutunSayisi.

Modülerlik

ModülerlikProgramın bağımsız, yeniden kullanılabilir parçalara (fonksiyonlara, ileride sınıflara) ayrılmasıdır.
GörevÖrnek adNe zaman çağrılır?
ÇizimtahtaCiz, hedefCizdraw() içinde, her frame
GirdimousePressed (p5.js olayı)Fare tıklanınca
MantıkskorArtir, oyunBittiMiOlay ya da draw() içinde
Yardımcı hesaprastgeleKonum, icindeMiİhtiyaç duyulduğunda

draw işleri dağıtır

Modüler kod: draw ve yardımcı fonksiyonlar
draw() görevleri ayrı fonksiyonlara devreder; tahtaCiz de hucreCiz’i çağırır.

Daire Tıklama’yı toparlayalım

Aynı iki satır hem setup’ta hem mousePressed’te vardı. Artık tek bir yerde: yeniHedefKonumu().

KazançHedefin nasıl seçildiğini değiştirmek isterseniz tek bir fonksiyona dokunursunuz.

Çalışan kodu davranışını bozmadan düzenlemeye refaktör denir.

İleriye bakış: XOX taşı çizmek

  • tasCiz bir hücrenin ortasına “X” ya da “O” yazar.
  • xoxTahtasiniCiz tahtayı gezer; boş hücrelerde tasCiz’i çağırmaz.
  • Veri (tahta) ile görüntü (tasCiz) birbirinden ayrı.
  • tahta[satir][sutun] yazımını diziler konusunda öğreneceğiz.

Örnek olay: 40 satırlık draw

3 × 3 tahta çizen kod tek bir draw() içinde 40 satıra ulaşmış. Tahtanın rengi değiştirilmek isteniyor ama ilgili satırlar bulunamıyor.

  1. return; ile erken çıkış ve return değer; arasındaki fark ne?
  2. Aynı fonksiyonu farklı argümanlarla çağırmak kod tekrarını neden azaltır?
  3. draw() içinde kaç yardımcı fonksiyon çağrısı makul sayılır?
  4. Bu kodu hangi fonksiyonlara bölerdiniz? Taş çizimi nereye gider?

Yapay zekâyla: kara kutu ile ekipçe sketch (1/2)

  1. Çizim fonksiyonlarını yazdırın. Yapay zekâdan gunesCiz, insanCiz, agacCiz, evCiz, kusCiz isteyin. Hepsi (merkezX, merkezY) alsın, yalnızca temel şekillerle çizsin, sabit piksel adresi kullanmasın.
  2. Seçim fonksiyonunu yazdırın. Global let secili = "gunes" olsun. keyPressed tuşa göre değiştirsin: G güneş, I insan, A ağaç, E ev, K kuş.
Klavyeyi henüz işlemedik, sorun değilkeyPressed’in içini bilmeniz gerekmiyor. Sözleşme belli: doğru tuşa basınca secili doğru metin olur. Bu bir kara kutu.

Yapay zekâyla: kara kutu ile ekipçe sketch (2/2)

  1. Sizin işiniz: tıklayınca seçili şekli fare konumuna çizmek. Sol üst köşeye tıklamak tuvali temizler.
  2. Tuşla seçin, tıklayarak yerleştirin: birkaç ağaç, bir ev, güneş…
  3. Eleştirel bakın: kara kutu işe yaradı mı? Global secili’yi değiştirmek ideal mi? Yapay zekâ hangi şekli bozuk çizdi, neden?

Kod zamanı

  1. yildizCiz(x, y) yazın (basit bir artı işareti de olur). Tuvale 5 farklı yerde çağırın.
  2. kareAlan(kenar) yazın; alanı döndürsün. Sonucu ekrana yazdırın.
  3. buyukOlan(a, b) yazın; iki sayıdan büyük olanı döndürsün.
  4. tuvalIcindeMi(x, y) yazın; boolean döndürsün. Fare tuvalin içindeyken arka plan yeşil, dışındayken gri olsun.
  5. Zorlu: cicekCiz(x, y, yaprakSayisi). Yaprakları bir döngü, cos ve sin ile dizin.

Ekrana ne yazılır?

  1. 10
  2. 5
  3. undefined
  4. Hata verir

Hesap yapılıyor ama sonuç geri gönderilmiyor: return yok. return olmayan fonksiyon undefined verir.

Hangi dikdörtgen çizilir?

  1. (100, 20) konumunda 50 × 50 bir kare
  2. Düzgün çizilmez: h parametresi undefined kalır
  3. Program hata verip durur

Dört parametre var, üç argüman verildi. JavaScript hata vermez; eksik parametre undefined olur. Hata sessizdir.

“B” konsola yazılır mı?

  1. Evet
  2. Hayır

can 0 olduğu için return çalışır ve fonksiyon orada biter. Yalnızca “A” yazılır.

Bugün ne öğrendik?

  • Fonksiyon: adı olan, tekrar çağrılabilen kod bloğu. Tanım ayrı, çağrı ayrı.
  • setup, draw, mousePressed adları sabittir; p5.js onları kendisi çağırır.
  • Parametre tanımdaki yer tutucu, argüman çağrıdaki değerdir. Sıra önemlidir.
  • return; erken çıkar; return değer; sonucu çağırana verir.
  • Modüler kod: çizim, girdi, mantık ve yardımcı hesap ayrı fonksiyonlarda.
  • Fonksiyon bir kara kutudur: ne aldığını ve ne verdiğini bilmek yeter.

Sıradaki ders

Bu x hangi x?

Global ve yerel değişkenler, kapsam ve gölgeleme.