Ana Başlık 3. Fonksiyonlar ve Modüler Kod Yazımı

Amaç: Fonksiyon tanımlama, parametre ve dönüş değeri kavramlarını öğreterek kodu modüler hale getirmek.

Öğrenme Çıktıları:

Anahtar Sözcükler: fonksiyon, parametre, argüman, dönüş değeri, return, modülerlik, yeniden kullanılabilirlik, kapsam, global değişken, yerel değişken, gölgeleme

Giriş

Döngüler tekrarlayan aynı kodu kısaltır; fonksiyonlar ise anlamlı iş parçalarını isimlendirilmiş bloklara ayırır. draw() içinde onlarca satır büyüdüğünde "tahta çiz", "skor yaz", "hedefi güncelle" gibi görevler birbirine karışır. Fonksiyonlar, her görevi ayrı bir isim altında toplayarak okunabilirliği artırır ve aynı işlemi farklı yerlerden tekrar çağırmayı mümkün kılar. Böylece bir değişiklik tek noktada yapılır; kopyalanmış satırlarda unutulan güncellemeler azalır.

p5.js’te setup() ve draw() zaten özel fonksiyonlardır; p5.js bunları belirli zamanlarda otomatik çağırır. mousePressed() de önceki ana başlıklarda benzer biçimde tanıtılmıştır. Bu ana başlıkta kullanıcı tanımlı fonksiyonlar ele alınacak: geliştiricinin kendi adını verdiği, parametre alabilen ve değer döndürebilen bloklar. Parametreler dış veri taşır; return hem erken çıkış hem de hesaplanmış sonuç için kullanılır. Modüler yapı, ileride XOX tahtası çizimi ve Daire Tıklama oyunundaki hedef konumu güncelleme gibi görevlerin düzenlenmesine zemin hazırlar.

Fonksiyonlar yalnızca kod tekrarını azaltmaz; soyutlama sağlar. draw() içinde tahtaCiz() yazmak, «tahtayı çiz» niyetini kodu inceleyene iletir; hücre renginin nasıl seçildiği hucreCiz içinde kalır. Oyun büyüdükçe hangi fonksiyonun ne yaptığını bilmek, hata ayıklamayı hızlandırır: tahta bozuksa önce tahtaCiz ve hucreCiz incelenir, tüm draw() taranmaz.

Modüler yazım aynı zamanda hata ayıklamayı ve ekip çalışmasını kolaylaştırır. Bir oyunda skor hesaplaması hatalıysa, tüm draw() gövdesini satır satır izlemek yerine doğrudan skorArtir gibi anlamlı adlandırılmış fonksiyona bakmak yeterli olur; fonksiyon adı zaten hangi görevi üstlendiğini belirtir. Birden fazla kişi aynı sketch üzerinde çalıştığında da fonksiyonlara bölünmüş kod, kimin hangi parçayı değiştirdiğini ayırt etmeyi kolaylaştırır: biri tahtaCiz üzerinde çalışırken diğeri skorGuncelle üzerinde çalışabilir, iki değişiklik aynı satırlarda çakışmaz.

3.1. Fonksiyon Kavramı ve Sözdizimi

Tanım: Fonksiyon (function) — Belirli bir görevi yerine getiren, isimlendirilmiş ve gerektiğinde tekrar çağrılabilen kod bloğudur.

Matematik dersindeki f(x) = x * x gibi bir fonksiyonu düşünün: dışarıdan bir girdi verirsiniz, içerideki kural çalışır, bir sonuç çıkar. Programlamada da benzer bir bakış yaygındır: çağıran taraf çoğu zaman fonksiyonun içini satır satır bilmek zorunda değildir — adı, girdi ve çıktı yeter; gövde bir kara kutu gibi kalabilir. dist(x1, y1, x2, y2) tam böyle çalışır: mesafe formülünü ezberlemeseniz de sonucu kullanırsınız. Kendi yazdığınız icindeMi veya topla için de aynı alışkanlık geçerlidir: önce «ne alır, ne verir / ne yapar?» sorusunu netleştirin.

Görsel 1. Fonksiyon kara kutusu — girdi, işlem, çıktı
Görsel 1. Fonksiyon kara kutusu — girdi, işlem, çıktı

Görsel 1 fonksiyonu girdi → kara kutu → çıktı olarak özetler: topla(3, 5) çağrısında önemli olan argümanlar ve dönen 8’dir; kutunun içindeki satırlar çağıran için gizli kalabilir.

Bilgi — Girdi, çıktı ve yan etki: İyi tasarlanmış bir fonksiyon genelde değer alır (parametre) ve çoğu zaman değer üretir (return) veya tek, net bir işi tamamlar. Dosya okuma, ağ isteği, konsola yazdırma gibi girdi/çıktı (I/O) işleri fonksiyon gövdesinde sık sık biriktirilmez; bunlar programın başka katmanlarına bırakılır. Elbette istisna vardır: p5.js’te arkaPlanCiz veya hedefCiz gibi yardımcılar tuvale çizim yapar — bu bir yan etkidir, yine de görevleri tek ve anlaşılırdır. Pratik kural: bir fonksiyon mümkün olduğunca tek, net tanımlanmış bir işe karşılık gelsin; «hem skor hesapla hem dosyaya yaz hem de menüyü çiz» gibi karışık sorumluluklar bakımı zorlaştırır.

Dikkat — dış değişkeni değiştirmek: Burada global, kabaca setup / draw dışında (dosyanın üstünde) tanımlanan değişkendir — örn. let secili = "gunes";. Bir fonksiyonun böyle bir değişkeni güncellemesi (secili = "agac") yan etkidir; ideal olan çoğu zaman return ile sonuç vermektir. Yine de olay fonksiyonlarında bu kalıp sık görülür ve bazen gerekir. Global / yerel ayrımının ayrıntısı 3.6’da; örnek kullanım ise bu ana başlığın sonundaki YZ etkinliğinde.

Bilgi — Ekip çalışması: Fonksiyonlar, işi kişilere bölmeyi kolaylaştırır. Biri tahtaCiz yazarken diğeri skorYaz üzerinde çalışabilir; arayüz (ad, parametre, dönüş) üzerinde anlaşılırsa gövdeler birbirinden bağımsız ilerler. Kara kutu burada da işe yarar: ekip arkadaşınızın yazdığı fonksiyonun satır satır içini bilmeden, «ne aldığını / ne verdiğini / ne yaptığını» biliyorsanız onu çağırabilirsiniz — tıpkı dist gibi.

Temel sözdizimi:

Kod 1.

javascript
function fonksiyonAdi() {  // gövde — çağrıldığında çalışan satırlar}

Çağrı (call): fonksiyonAdi(); — parantezler fonksiyonun şimdi çalıştırılması gerektiğini belirtir.

Tablo 1.

Kavram Biçim Anlam
Tanım function hedefCiz() { … } Fonksiyonun adı ve gövdesi
Çağrı hedefCiz(); Tanımlanan bloğu çalıştırır
p5.js yerleşik setup(), draw() p5.js belirli anlarda otomatik çağırır

Kod bloğu: Basit yardımcı fonksiyon — arka plan rengini sabitleyen arkaPlanCiz.

Kod 2.

javascript
function setup() {  createCanvas(400, 400);} function draw() {  arkaPlanCiz();  ortaCizgiCiz();} function arkaPlanCiz() {  background(35, 40, 55);} function ortaCizgiCiz() {  stroke(200);  strokeWeight(2);  line(width / 2, 0, width / 2, height);  noStroke();}

draw() artık ne yaptığını okunaklı biçimde listeler; ayrıntılar fonksiyon gövdelerinde saklanır. p5.js draw() her frame'de çalıştığı için içinde çağrılan arkaPlanCiz() ve ortaCizgiCiz() de her frame'de yeniden çalışır.

Bilgi: Kendi yazdığınız fonksiyonlarda camelCase örfi kullanılır: hedefCiz, skorGuncelle. setup, draw ve mousePressed ise farklı bir kategoridedir: p5.js bu adları sabit olarak tanır ve sketch çalışırken bu isimdeki fonksiyonları belirli anlarda otomatik çağırır. Örneğin draw yerine cizimYap yazarsanız p5.js her frame'de o fonksiyonu aramaz; tuval güncellenmez. Yani camelCase burada tercih meselesi değil, p5.js'in tanıdığı yerleşik olay adlarıdır; kütüphane dokümantasyonunda bu isimlerle tanımlanır.

Fonksiyon çağrı izi: Aşağıdaki sketch'te draw() çalıştığında çağrı sırası şöyledir:

Tablo 2.

Adım Çalışan fonksiyon Not
1 draw() p5.js tarafından tetiklenir
2 arkaPlanCiz() draw() içinden çağrılır
3 ortaCizgiCiz() draw() içinden çağrılır
4 (frame biter) Bir sonraki frame'de 1. adıma dönülür

Fonksiyon iç içe çağrılabilir: tahtaCiz döngü içinde hucreCiz çağırır; her hucreCiz tamamlanınca kontrol tahtaCiz'e döner. Bu «çağrı yığını» (call stack) kavramının basit hâlidir; derin özyineleme (Mayın Tarlası Flood Fill) ileride aynı mantığı kullanır.

Bilgi: JavaScript'te function fonksiyonAdi() { … } biçiminde yazılan tanımlar, dosyanın neresinde durduğuna bakılmaksızın çalıştırılmadan önce tanınır; bu nedenle draw() içindeki arkaPlanCiz() çağrısı, arkaPlanCiz tanımından önce yazılsa da hatasız çalışır. Yine de okunabilirlik açısından ilgili fonksiyonları çağrıldıkları yere yakın veya dosyanın sonunda düzenli biçimde tutmak tercih edilir.

Sıra Sizde: Uzun bir draw() bloğunu en az iki anlamlı fonksiyona bölecek şekilde isimlendirin (ör. arkaplanCiz, skorYaz). Her fonksiyonun tek sorumluluğunu bir satırla yazın.

3.2. Parametreli Fonksiyonlar

Tanım: Parametre (parameter) — Fonksiyon tanımında parantez içine yazılan, dışarıdan alınan değer yer tutucusudur. Çağrı sırasında verilen somut değere argüman (argument) denir.

Kod 3.

javascript
function dikdortgenCiz(x, y, w, h, renkR, renkG, renkB) {  fill(renkR, renkG, renkB);  noStroke();  rect(x, y, w, h);} function draw() {  background(20);  dikdortgenCiz(50, 50, 80, 60, 255, 100, 100);   // kırmızımsı  dikdortgenCiz(200, 120, 100, 40, 100, 200, 255); // mavimsi}

Aynı fonksiyon farklı argümanlarla birden çok kez kullanılır; kod tekrarı azalır.

Tablo 3.

Kavram Tanım yeri Örnek
Parametre function dikdortgenCiz(x, y, w, h) x, y, w, h
Argüman Çağrı satırı 50, 50, 80, 60

Dikkat: Parametre sırası önemlidir. dikdortgenCiz(50, 50, 80, 60, …) ifadesinde ilk 50 x'e, ikinci 50 y'ye gider. Argüman sayısı parametre sayısından azsa karşılık gelmeyen parametreler undefined olur; fazlaysa fazladan değerler yok sayılır.

3.3. return ile Değer Döndürme

mousePressed() içinde return; ifadesi fonksiyondan erken çıkış için kullanılır; oyun bittiğinde geri kalan satırlar çalışmaz. return aynı zamanda bir değer üretip çağıran yere iletebilir.

Kod 4.

javascript
function acikKareMi(satirSutunToplami) {  return (satirSutunToplami % 2 === 0);} function draw() {  background(50);  for (let satir = 0; satir < 4; satir = satir + 1) {    for (let sutun = 0; sutun < 4; sutun = sutun + 1) {      if (acikKareMi(satir + sutun)) {        fill(230, 220, 200);      } else {        fill(60, 55, 50);      }      rect(sutun * 50, satir * 50, 50, 50);    }  }}

Fonksiyon, dama deseninde satır ve sütun toplamının çift olduğu hücreleri açık renge ayırır: acikKareMi(3) çağrısı false, acikKareMi(6) çağrısı true döndürür. Çağıran satır bu boolean değeri if koşulunda kullanır.

Tablo 4.

return biçimi Anlam Örnek
return; Değer yok; fonksiyon hemen biter mousePressed içinde erken çıkış
return değer; Hesaplanan değeri çağıran yere verir return (a + b);

Tanım: Dönüş değeri (return value) — Fonksiyonun return ile geri gönderdiği sonuç; çağrı ifadesinin yerine geçer.

Kod 5.

javascript
let sonuc = topla(3, 5); // sonuc değişkeni 8 olur function topla(a, b) {  return a + b;}

Kod bloğu: Oyun mantığında return — mesafe ve «içinde mi» testi (daire çarpışmasında kullanılan dist() ile uyumlu).

Kod 6.

javascript
function mesafeHesapla(x1, y1, x2, y2) {  return dist(x1, y1, x2, y2);} function icindeMi(fareX, fareY, merkezX, merkezY, yaricap) {  let m = mesafeHesapla(fareX, fareY, merkezX, merkezY);  return m < yaricap;}

icindeMi(mouseX, mouseY, hedefX, hedefY, 40) ifadesi true veya false üretir; if koşulunda doğrudan kullanılabilir. Daire Tıklama oyunundaki dist(...) < hedefYaricap satırı bu yapının satır içi hâlidir; fonksiyona taşımak okunabilirliği artırır.

Sıra Sizde: Bölüm 1 Ana Başlık 3'teki «nokta daire / elips içinde mi?» kontrollerini (renk örneği ve Daire Tıklama) davranışı değiştirmeden yardımcı fonksiyonlara taşıyın; eski yerlerde bu fonksiyonları çağırın. Daire için yukarıdaki icindeMi yeterli olabilir. İsterseniz genişlik ve yüksekliği farklı bir elips için ayrı bir fonksiyon da yazmayı deneyin.

3.4. p5.js'te Yardımcı Çizim Fonksiyonları

Izgara ve şekil çizimini fonksiyonlara ayırmak, draw() gövdesini sade tutar.

Kod bloğu: Parametreli hücre ve tahta çizimi.

Kod 7.

javascript
const HUCRE = 50;const SUTUN = 3;const SATIR = 3; function setup() {  createCanvas(SUTUN * HUCRE, SATIR * HUCRE);  noStroke();} function draw() {  background(30, 35, 45);  tahtaCiz(0, 0, SATIR, SUTUN, HUCRE);  merkezIsaretiCiz(width / 2, height / 2);} function tahtaCiz(baslangicX, baslangicY, satirSayisi, sutunSayisi, hucreBoyutu) {  for (let satir = 0; satir < satirSayisi; satir = satir + 1) {    for (let sutun = 0; sutun < sutunSayisi; sutun = sutun + 1) {      hucreCiz(        baslangicX + sutun * hucreBoyutu,        baslangicY + satir * hucreBoyutu,        hucreBoyutu,        satir,        sutun      );    }  }} function hucreCiz(x, y, boyut, satir, sutun) {  if ((satir + sutun) % 2 === 0) {    fill(240, 235, 220);  } else {    fill(70, 65, 60);  }  rect(x, y, boyut, boyut);} function merkezIsaretiCiz(merkezX, merkezY) {  fill(255, 80, 80);  ellipse(merkezX, merkezY, 12, 12);}

tahtaCiz üç kez farklı boyutta çağrılabilir; yalnızca argümanlar değişir. Bu yapı ilerleyen bölümlerdeki XOX oyununun görsel zeminini oluşturur.

Çağrı sırası izlemesi: SATIR = 2, SUTUN = 2 olan daha küçük bir tahtada tahtaCiz çağrısının ürettiği hucreCiz çağrıları sırasıyla şöyledir:

Tablo 5.

satir sutun hucreCiz çağrısı Hücre rengi
0 0 hucreCiz(0, 0, 50, 0, 0) açık (satir + sutun çift)
0 1 hucreCiz(50, 0, 50, 0, 1) koyu
1 0 hucreCiz(0, 50, 50, 1, 0) koyu
1 1 hucreCiz(50, 50, 50, 1, 1) açık

Dış döngü satir değerini, iç döngü sutun değerini değiştirir; her ikili için hucreCiz bir kez çağrılır. Toplam çağrı sayısı satirSayisi * sutunSayisi kadardır.

3.5. Modüler Kod ve Oyun Mimarisi

Tanım: Modülerlik — Programın bağımsız, yeniden kullanılabilir parçalara (fonksiyonlara, ileride sınıflara) ayrılmasıdır.

Oyun kodunda yaygın işlev ayrımı:

Tablo 6.

Fonksiyon görevi Örnek ad Ne zaman çağrılır
Çizim tahtaCiz, hedefCiz draw() içinde her frame
Girdi mousePressed (p5.js olayı) Fare tıklanınca
Mantık skorArtir, oyunBittiMi Olay veya draw() içinde
Yardımcı hesap rastgeleKonum, icindeMi İhtiyaç duyulduğunda

Görsel 2. Modüler kod — draw() ve yardımcı fonksiyonlar
Görsel 2. Modüler kod — draw() ve yardımcı fonksiyonlar

Görsel 2 draw() fonksiyonunun çizim, tahta ve skor gibi görevleri ayrı fonksiyonlara devretmesini; tahtaCiz içinde hucreCiz gibi iç içe çağrıları gösterir.

Kod bloğu: Daire Tıklama için hedef konumu güncelleme — artık fonksiyon kullanılabilir (bu ana başlıktan sonra refaktör örneği).

Kod 8.

javascript
function yeniHedefKonumu() {  hedefX = random(50, width - 50);  hedefY = random(50, height - 50);} function mousePressed() {  if (oyunBitti) {    return;  }  let mesafe = dist(mouseX, mouseY, hedefX, hedefY);  if (mesafe < hedefYaricap) {    skor = skor + 1;    if (skor >= HEDEF_SKOR) {      oyunBitti = true;    } else {      yeniHedefKonumu();    }  }}

Bu parça, sayı tahmin oyununda satır satır draw() ve mousePressed() içinde yazılmış mantığın modüler hâlidir; yeniHedefKonumu() yalnızca koordinat atamasından sorumludur.

Kod bloğu: XOX taşı çizimi — parametreli tasCiz (ilerleyen bölümlerin 5. ana başlığına hazırlık).

Kod 9.

javascript
function tasCiz(satir, sutun, hucre, oyuncu) {  let x = sutun * hucre + hucre / 2;  let y = satir * hucre + hucre / 2;  textAlign(CENTER, CENTER);  textSize(hucre * 0.55);  fill(30);  text(oyuncu, x, y);} function xoxTahtasiniCiz(tahta, hucre) {  for (let satir = 0; satir < 3; satir = satir + 1) {    for (let sutun = 0; sutun < 3; sutun = sutun + 1) {      if (tahta[satir][sutun] !== "") {        tasCiz(satir, sutun, hucre, tahta[satir][sutun]);      }    }  }}

Boş hücrelerde tasCiz çağrılmaz; dolu hücrelerde "X" veya "O" metni çizilir. Tahta verisi (tahta dizisi) ile görselleştirme (tasCiz) ayrılmış olur.

3.6. Değişken Kapsamı: Global ve Yerel

Fonksiyonlar büyüdükçe «bu x hangisi?» sorusu sık çıkar. Cevap kapsam (scope) kurallarındadır: bir değişkenin adı, yalnızca tanımlandığı bölgede geçerlidir. Yanlış yerde tanımlanan skor frame sonunda yok olur; yanlış adlandırılmış parametre ise global skoru güncellemezmiş gibi görünür.

Tanım: Kapsam (scope) — Bir değişken adının geçerli olduğu kod bölgesidir. Bu bölgenin dışında aynı ad ya tanımsızdır ya da başka bir değişkeni işaret eder.

Global değişkenler

setup() ve draw() dışında, sketch dosyasının üst düzeyinde let / const ile tanımlanan değişkenler global kabul edilir. Bunlara setup, draw, mousePressed ve kullanıcı tanımlı yardımcılardan erişilebilir; değer frame’ler arasında kalır.

Kod 10.

javascript
let skor = 0;          // global — setup/draw dışındalet hedefX;let hedefY; function setup() {  createCanvas(400, 400);  hedefX = width / 2;  hedefY = height / 2;} function draw() {  background(240);  text("Skor: " + skor, 20, 30); // global skor okunur  circle(hedefX, hedefY, 40);} function skorArtir(artisMiktari) {  skor = skor + artisMiktari;    // global skor güncellenir}

Oyun durumu (skor, hedefX, oyunBitti) bu yüzden üst düzeyde tutulur: draw her frame yeniden çalışsa da global değer silinmez.

Tablo 7.

Nerede tanımlanır? Tür Örnek kullanım
setup / draw dışında (üst düzey) Global skor, hedefX, oyunBitti
Fonksiyon gövdesinde let / const Yerel Geçici hesap, döngü değişkeni
Fonksiyon parametresi Yerel dikdortgenCiz(x, y, w, h) içindeki x

Yerel değişkenler ve draw()

Fonksiyon içinde let x = 5 yazılırsa x yalnızca o fonksiyon gövdesinde geçerlidir; fonksiyon bittiğinde yerel değişken yok olur. Parametreler de yerel kapsamdadır.

Dikkat: draw() her frame bir kez çağrılır ve biter. draw içinde tanımlanan yerel değişken her frame’in başında yeniden yaratılır, sonunda yok olur. Kalıcı oyun durumu için kullanılamaz:

Kod 11.

javascript
let skor = 0; // global — doğru yer function draw() {  let geciciX = mouseX; // yerel — yalnızca bu frame’de geçerli  // let skor = 0;     // YANLIŞ: her frame sıfırdan başlar, skor birikmez  background(240);  text(skor, 20, 30);  circle(geciciX, 200, 20);}

geciciX her frame fare konumuna göre yeniden hesaplanır; bunu global tutmaya gerek yoktur. Buna karşılık skor birikmeli olduğu için global (veya ileride nesne/dizi) olmalıdır.

Argüman ile parametre aynı şey değildir

Çağrı satırındaki değer argüman, fonksiyon tanımındaki yer tutucu parametredir. İsimler aynı olsa bile bunlar iki ayrı değişkendir: çağrı anında argümanın değeri parametreye kopyalanır.

Kod 12.

javascript
function konumYaz(x) {  // buradaki x, çağıranın x'i değil — kopya (yerel parametre)  x = x + 50;  text(x, 20, 40);} function draw() {  background(255);  let x = 100;       // draw'ın yerel x'i  konumYaz(x);       // argüman: 100 → parametreye kopyalanır  text(x, 20, 80);   // hâlâ 100 — konumYaz içindeki atama burayı değiştirmez}

Tablo 8.

Ad Nerede? Bu örnekte
Argüman Çağrı: konumYaz(x) draw içindeki x değeri (100)
Parametre Tanım: function konumYaz(x) Fonksiyonun kendi yerel x'i (önce 100, sonra 150)

Ekranda üst satır 150, alt satır 100 görünür. Parametre adı x olsa da çağıranın x'i ile bağlantılı değildir; sayısal değerler kopyalanır. Bu yüzden dikdortgenCiz(x, y, w, h) içindeki x, çağrı sırasında gelen argümanın kopyasıdır — fonksiyon gövdesinde x'i değiştirmek, çağıran taraftaki değişkeni otomatik güncellemez.

Bilgi: İsimler bilerek farklı seçilebilir: function konumYaz(ekranX) { … } ve konumYaz(x);. Davranış aynıdır; okuyan kişi parametre ile çağıran değişkeni daha kolay ayırır.

Gölgeleme (shadowing)

Parametre veya yerel let adı, üst düzeydeki global ile aynı olursa fonksiyon içinde yerel olan kazanır; global o isimle görünmez. Buna gölgeleme (shadowing) denir.

Kod 13.

javascript
let skor = 10; // global function skorArtir(skor) {   // parametre adı da skor — gölgeleme  skor = skor + 1;           // yalnızca yerel parametre artar  // global skor hâlâ 10} function draw() {  skorArtir(skor);           // argüman: 10 → yerel parametreye kopyalanır  text(skor, 20, 30);        // hâlâ 10 — beklenen artış olmaz}

Karışıklığı önlemek için parametre adını globalden ayırmak önerilir:

Kod 14.

javascript
let skor = 10; function skorArtir(artisMiktari) {  skor = skor + artisMiktari; // global skor bilinçli güncellenir} function draw() {  // …  skorArtir(1);}

Dikkat: Global skoru güncelleyecek yardımcıda parametreye skor demek yaygın bir hatadır. Ya parametreyi artisMiktari gibi adlandırın ya da globali doğrudan (parametresiz) güncelleyin; ikisini aynı isimle karıştırmayın.

Örnek Olay: Fonksiyonlara Ayırma Tahmini etkinliği tamamlama süresi: 35–40 dakika.

Senaryo: 3×3 tahta çizen kod tek bir draw() içinde 40 satıra ulaşmıştır; tahta rengi değiştirilmek istendiğinde ilgili satırlar bulunamamaktadır.

Durum Tespiti:

Problem Durumu: Tek blok hâlindeki kod, ekip çalışmasında ve hata ayıklamada yavaşlatıcıdır.

Tartışma Soruları:

Yapay Zekâ Etkileşimi: Kara Kutu ile Ekipçe Sketch Tahmini etkinliği tamamlama süresi: 40–50 dakika.

Amaç: (1) YZ’den çizim fonksiyonları ve klavye ile secili seçen bir yardımcı almak; (2) sizin tarafınızda yalnızca bildiğiniz mousePressed ile tuvale çizmek; (3) kara kutu, ekip paylaşımı ve «global değiştiren fonksiyon» eleştirisini yaşayarak görmek.

Önemli — klavyeyi henüz işlemedik. keyPressed / key bu kitapta sistematik olarak Bölüm 2’de gelir. Yine de YZ’den (veya bir ekip arkadaşından) «tuşa göre secili değiştir» kodunu alıp içini satır satır bilmeden kullanabilirsiniz — tıpkı Görsel 1’deki kara kutu gibi. Davranış garantisi netse (G → secili === "gunes"), gövdeyi bilmek zorunda değilsiniz.

Adım 1 — Çizim fonksiyonlarını YZ’ye yazdırın.

Örnek İstem: "p5.js için şu yardımcı fonksiyonları yaz: gunesCiz(merkezX, merkezY), insanCiz(merkezX, merkezY), agacCiz(merkezX, merkezY), evCiz(merkezX, merkezY), kusCiz(merkezX, merkezY). Her fonksiyon yalnızca ellipse, rect, line, triangle gibi temel şekillerle çizsin. Tüm parçalar merkezX / merkezY’ye göre konumlandırılsın; sabit piksel adresleri kullanma."

Üretilen kodu yapıştırın; bir kez gunesCiz(width/2, height/2) ile deneyin.

Adım 2 — Seçim fonksiyonunu YZ’ye yazdırın (klavye — sizin bilmeniz gerekmez). Global secili değişkeni olacak; tuşa göre değeri değişecek.

Örnek İstem: "p5.js’te global let secili = 'gunes' var. keyPressed yaz: g/G → secili = 'gunes', i/I → 'insan', a/A → 'agac', e/E → 'ev', k/K → 'kus'. Başka bir şey çizme; yalnızca secili’yi güncelle. Kısa yorum ekle."

Bu parçayı da sketch’e ekleyin. Şimdilik keyPressed’in nasıl çalıştığını ezberlemeniz beklenmiyor — sözleşme şu: doğru tuşa basınca secili doğru string olur.

Adım 3 — Sizin işiniz: tıklayınca çiz. Yalnızca Bölüm 1 Ana Başlık 3'ten bildiğiniz fare ile ilerleyin:

Kod 15.

javascript
let secili = "gunes"; function setup() {  createCanvas(400, 400);  background(230); // bir kez} function draw() {  // boş — şekiller tıklamayla birikir} function mousePressed() {  if (mouseX < 40 && mouseY < 40) {    background(230); // temizle    return;  }  if (secili === "gunes") {    gunesCiz(mouseX, mouseY);  } else if (secili === "insan") {    insanCiz(mouseX, mouseY);  } else if (secili === "agac") {    agacCiz(mouseX, mouseY);  } else if (secili === "ev") {    evCiz(mouseX, mouseY);  } else if (secili === "kus") {    kusCiz(mouseX, mouseY);  }} // keyPressed — YZ / ekip arkadaşı yazdı; siz içini bilmeden kullanıyorsunuz

İş bölümü (ekip analojisi): Biri (burada YZ) «tuş → secili» kutusunu yazar; siz «secili → tuvalde çiz» kutusunu yazarsınız. Ortak dil: secili string değerleri. Bu, fonksiyonların ekip çalışmasındaki faydasıdır — görevler ayrılır, arayüz üzerinde anlaşılır.

Adım 4 — Sahne kurun. Tuşa basın (seçim), sonra tuvale tıklayın (yerleştirme). Birkaç ağaç, bir ev, güneş… Aynı çizim fonksiyonunu farklı (mouseX, mouseY) ile çağırmanın parametre gücünü not edin.

Adım 5 — Eleştirel bakış (iki katman).

  1. Kara kutu işe yaradı mı? Klavye konusunu bilmeden seçim yapabildiniz mi? Davranış sözü tutulduysa (G → güneş seçilir) gövdeyi bilmek zorunda değildiniz — Görsel 1’i hatırlayın.
  2. Global secili güncellemesi: Ideal olan çoğu zaman değer alıp değer döndürmektir; burada ise olay fonksiyonu dışarıdaki bir değişkeni değiştiriyor. Bu «en temiz» tasarım sayılmaz — yine de keyPressed / mousePressed gibi olaylarda sık görülür ve bazen pratik olarak gerekir. Kara kutu kullanmak ile her kara kutunun mükemmel tasarlandığı aynı şey değildir; yine de işe yarar bir paylaşım biçimidir.
  3. YZ gerçekten düzgün çizebiliyor mu? YZ metin ve kod iskeletinde sık işe yarar; görsel şekil üretiminde ise özellikle karmaşık figürlerde (insan, kuş, detaylı ev) sıklıkla zayıf kalır veya saçmalayabilir. Olası sorunlar:

Basit güneş (daire + ışınlar) çoğu zaman idare eder; karmaşık silüetlerde YZ çıktısını körü körüne güvenmeyin. En az bir çizim fonksiyonunu kendiniz düzelterek veya sadeleştirerek (ör. insanı daire + iki rect) tekrar deneyin.

Kısa not (3–5 cümle): (a) kara kutu / ekip, (b) global güncellemenin «ideal değil ama bazen gerekir» yanı, (c) hangi şekil bozuldu, neden.

Özet

Fonksiyonlar, adlandırılmış ve gerektiğinde tekrar çağrılabilen kod bloklarıdır. Tanım function ad() { … } biçimindedir; çağrı ad(); ile yapılır — parantezler bloğun o anda çalıştırılacağını belirtir. p5.js’in setup() ve draw() fonksiyonları kütüphane tarafından otomatik çağrılır; mousePressed gibi olay fonksiyonları da benzerdir. Kullanıcı tanımlı fonksiyonlar ise geliştiricinin açıkça çağırdığı yardımcı bloklardır. Modülerlik, uzun draw() gövdelerini çizim, girdi, mantık ve hesap görevlerine ayırarak okunabilirliği ve bakımı artırır; tahta bozuksa tüm draw() yerine tahtaCiz incelenir. Yeniden kullanılabilirlik, aynı yardımcının farklı argümanlarla tekrar çağrılmasından doğar. Parametreler fonksiyona dış veri taşır; çağrı sırasındaki somut değerler argümandır (dikdortgenCiz(50, 80, 100, 40)). Aynı fonksiyon farklı argümanlarla birçok kez kullanılabilir; böylece kopyala-yapıştır azalır. return hem koşul sağlanmadığında erken çıkış (if (oyunBitti) { return; }) hem de topla, acikKareMi, icindeMi gibi yardımcılarda hesaplanmış değer döndürme için kullanılır. Dönüş değeri atama veya koşul ifadesinde tüketilir. Kapsam (scope), bir değişken adının geçerli olduğu bölgedir. setup/draw dışında tanımlanan skor, hedefX gibi değişkenler globaldir; frame’ler arasında kalır ve yardımcılardan okunup yazılabilir. Fonksiyon içindeki let ve parametreler yereldir; fonksiyon (veya draw frame’i) bitince yok olur. Bu yüzden skor draw içinde let skor = 0 ile tanımlanmaz. Argüman ile parametre aynı isimde olsa bile ayrıdır: çağrıda değer kopyalanır; parametreyi değiştirmek çağıranın değişkenini otomatik güncellemez. Parametre adı global ile örtüşürse gölgeleme olur; skorArtir(artisMiktari) gibi ayırt edici adlar tercih edilir. p5.js’te tahtaCiz, hucreCiz, hedefCiz, arkaPlanCiz gibi görevler ayrı fonksiyonlara bölündüğünde draw() kısa ve niyet odaklı kalır; iç içe çağrılar (tahtaCiz → hucreCiz) görev hiyerarşisini yansıtır.

Neler Öğrendik?

Soru 1 Aşağıdakilerden hangisi fonksiyon çağrısıdır?

A) function hedefCiz() { }

B) let x = 10;

C) hedefCiz();

D) return false;

E) if (skor > 0)

Soru 2 function topla(a, b) { return a + b; } tanımında a ve b ne olarak adlandırılır?

A) Argüman

B) Parametre

C) Boolean

D) Yerleşik değişken

E) Döngü değişkeni

Soru 3 mousePressed() içinde if (oyunBitti) { return; } satırının amacı nedir?

A) Oyunu kazanmış olmak

B) Fonksiyondan değer döndürerek skor artırmak

C) Oyun bittiyse fonksiyonun geri kalanını çalıştırmamak

D) draw() fonksiyonunu durdurmak

E) Tuval boyutunu değiştirmek

Soru 4 I. Parametreli fonksiyonlar kod tekrarını azaltır. II. return a + b; ifadesi toplamı çağıran yere iletir. III. Modüler kod, görevleri isimlendirilmiş parçalara ayırır.

Hangileri doğrudur?

A) Yalnız I

B) I ve II

C) Yalnız III

D) II ve III

E) I, II ve III

Neler Öğrendik Yanıt Anahtarı

Soru 1: Doğru Cevap: C

Soru 2: Doğru Cevap: B

Soru 3: Doğru Cevap: C

Soru 4: Doğru Cevap: E

Yararlanılan Kaynaklar

Bu içerik aşağıdaki kaynaklardan derlenerek hazırlanmıştır: