Javascript Scope İncelikleri

Bir fonksiyon veya değişken, oluşturulduğu yerin scopeuna dahildir. Kullanıldığı yerin değil.

var random = function(){
	return Math.floor(Math.random()*100);
}
var sagas = [];
var hero = "faruk"+random(); // faruk7
 
var newSaga = function(){
	var foil = "thefoil"+random();
	sagas.push(function(){
		var deed = "thedeed"+random();
		console.log(hero+deed+foil);
	});
};
 
newSaga();
sagas[0](); // faruk7 thefoil2 thedeed1
sagas[0](); // faruk7 thefoil2 thedeed4
newSaga();
sagas[0]();  // faruk7 thefoil2 thedeed5
sagas[1]();  // faruk7 thefoil9 thedeed6
sagas[0]();  // faruk7 thefoil2 thedeed7
sagas[1]();  // faruk7 thefoil9 thedeed8
 
// burdan anlaşıldığı üzere, bir fonksiyonun scopunu , oluşturulduğu yer belirliyor.
// yani sonrasında kullandıldığı scopre değil
 
// mesela burdaki foil değeri, ilk defa fonksiyonun tanımlandığı foil değeri
// newsagadan sonra, foil güncellenmiyor, yeni foil oluşuyor. 
// sagas[0] eski foil değerini döndürecektir.

Nesne Yönelimli Javascript

Javascriptte, class(sınıf) yoktur. Onun yeri objeler vardır. Bu objeler class olarakta kullanılabilir.

// Örnek sınıflar
 
// Hayvan sınıfı değişkenleri ve constructor
function Hayvan(yaş){
	this.yaş = yaş;
	console.log("Yeni hayvan");
}
 
// Hayvan sınıfı metodları
Hayvan.prototype.büyü = function(){
		this.yaş++;
}
 
// Insan sınıfı değişkenleri ve constructor
function Insan(yaş){
	Hayvan.call(this,yaş); // super classın constructorünü çağır
	console.log("Yeni Insan");
}
 
// Kalıtım - prototipleri birleştir
Insan.prototype = Object.create(Hayvan.prototype);
Insan.prototype.constructor = Insan;
 
// Insanı sınıfının kendine özgü metodları
Insan.prototype.konuş = function(){
	console.log("Ben "+this.yaş+" yaşıdayım");
}
 
// Test
var ahmet = new Insan(16);
ahmet.büyü();
ahmet.konuş();
console.log(ahmet);

Object.create fonksiyonu, bir objeyi kopyalamaz, sadece adresleme yaparak , yeni bir obje oluşturur.(delegasyon) Bunun sayesinde, kalıtım yaparken hafıza kullanımını azaltırız.

this deyimiyle javascriptte, sınıfın kendisi kastedilmez. Bir fonksiyonun hangi obje üzerinde çağrıldığı kastedilir.  obje.fonksiyon(); yani o fonksiyonun içinde this kullanıldıysa, noktanın solundaki ilk ifade olan obje ,this’e karşılık düşer. Buda javascriptin önemli farklarında biridir.

Bir fonksiyondan sonra call kullanılırak, o fonksiyonundaki this ifadesi, istediğimiz obje ile yer değiştirebiliriz.

obje1.fonksiyon(); // burda this=obje1
obje2.fonksiyon.call(obje3); // burda this=obje3

Heap Tree (Yığın Ağacı) ve JS kütüphanesi kodları

İkili bir ağaç yapısıdır. Kök hariç , her düğümün bir ebeveyni vardı. Her ebeveyninde en fazla 2 çocuğu vardı.

2 türü vardır ; Minimum heap, Maximum heap.

Amacı

En yüksek performansta, bir diziden en küçük ve en büyük değerleri teker teker sırasıyla çekebilmektir. Bu dizi, sıralı değildir. Ancak ilk elemanı(kökü) daima en büyük veya en küçük elemandır.

Kuralları

  • Eğer minimum heap ise, ebeveyn çocuklarında daima küçük olmalıdır. Maximum heapde tam tersi geçerlidir.
  • Çocuklar arası ilişki yoktur.
  • Tek indeks sahip düğüm solda, çift indekse sahip düğüm sağdadır. (yani 3>sol; 4>sağ)
  • Ebeveyninin indeksinin 2 katının 1 fazlası sol çocuğun indeksi, 2 katının 2 fazlası sağ çocuğun indeksidir. (2nin sol çocuğu 5, sağ çocuğu 6′tir)
  • Yeni eklenen düğüm, her zaman ağacın en alt sol tarafına eklenir. (Yani dizinin en sağına eklenir)
NOT : Kökün indeksi 0'dır.

p : ebeveyn indeksi
x : herhangi bir düğümün indeksi
sol : sol çocuk indeksi
sağ : sağ çocuk indeksi
---
sol = 2*p+1
sağ = 2*p+2
--
x%2 = 0 ise => sağdadır.
p = x / 2 - 1
x%2 = 1 ise => soldadır.
p = (x - 1) / 2

Ekleme

  • Değer dizinin sonuna(en sağına), eklenir.
  • Eklenen değer ebeveyni ile kıyaslanır. Ebeveyninden küçük ise, onunla yer değiştiri ve bu işlemin aynısı ebeveynlerininin ebeveynleri ilede yapılır.

Çıkarma

  • Heapda, daima kök değer çıkartılır. Yani dizinin ilk elemanı çıkartılır.
  • Çıkartılan bu değer ile yeni ağaç oluşur.
  • Bu ağaçta kökten başlayan, çocuğu olmayan düğüme kadar, en küçük değere sahip çocuk ile kıyaslanır, eğer en küçük çocuktan büyük ise yer değiştirilir. Yer değiştirilen çocuk ile aynı işlem ağacın o dalı boyunca tekrarlanır.

Bu işlemi yapan, yeni yazdığım bir Heap sınıfı.

function Heap(sortFunc){
    this.nodes = [];
    this.sortFunc= sortFunc || function(a,b){return a-b;};
 
    this.func = function(a,b){
            return this.sortFunc(a,b) < 0;
    }
}
 
 
 
Heap.prototype = {
    add : function(e){
        var x = this.nodes.length;
        this.nodes.push(e);
        var p = this.parent(x);
 
        // heapify2up
        while(this.func(this.nodes[x],this.nodes[p]) && x!=0){
            this.nodes[x]=this.nodes[p];
            this.nodes[p]=e;
 
            x=p;
            e = this.nodes[x];
            p=this.parent(x);
        }
 
        return this.nodes;
 
    },
    get : function(){
        var r = this.nodes.shift();
 
        //heapify2down
        var x = 0;
        var childs = this.childs(x);
        var min;
        while(childs.length!=0){
            min=childs[0];
            if(childs.length==2 && !this.func(this.nodes[childs[0]],this.nodes[childs[1]])){
                min = childs[1];
            }
 
            if(this.func(this.nodes[min],this.nodes[x])){
                var temp = this.nodes[x];
                this.nodes[x] = this.nodes[min];
                this.nodes[min] = temp;
                x = min;
                childs = this.childs(x);
            }
            else childs=[]
        }
        return r;
    },
    isEmpty : function(){
        return this.nodes.length==0;
    },
    parent : function(x){
        if(this.right(x)) return x/2-1;
        return (x-1)/2;
    },
    childs : function(x){
      var a = [];
      if(this.nodes[2*x+1]){
          a.push(2*x+1);
          if(this.nodes[2*x+2])
              a.push(2*x+2);
      }
      return a;
    },
    right : function(x){
        return x%2==0;
    }
};

 

A* Algoritması (A yıldız arama algoritması)

Amacı : Bir düğümden, diğer düğüme en az maliyetli çözümü bulmak

Türü : Arama Algoritması, Sezgisel Algoritma (Yapay zeka)

Kâşifleri : Nils Nilsson,Bertram Raphael , Peter E. Hart

Kullanım yerleri :

  • Yol bulma
  • Oyunlarda aktörün hedefe doğru izleyeceği yolların tespiti
  • Gezgin satıcı probleminin çözümü
  • Labirentten en kısa çıkışı bulma

 

f(x) : durum fonksiyonu. Az olması, o durumun daha az maliyetli olduğunu belirtir.

f(x) = g(x) + h(x)

g(x) : Başlangıç durumuna göre maliyetimiz.

h(x) : Bitiş duruma olan sezgisel maliyet.

Algoritma

OPEN -> // fCost'a göre sıralı dizi

OPEN.ekle(başlangıç_düğümü)

DÖNGÜ - OPEN dizi boyutu 0 olmadığı müddetçe
    şuanki_düğüm <- OPEN.ilk elemanı
    OPEN.sil(şuanki düğüm)
    EĞER şuanki_düğüm, hedef düğüm ise
        DÖNGÜden çık // HEDEFE ULAŞTI
    şuanki_düğüm.closed=true
    şuanki_düğüm.gCostHesapla()
    komşular = şuanki_düğüm.komşular
    DÖNGÜ komşu <- komşular
        EĞER komşu.closed ise SONRAKİ_KOMŞUYA_GEÇ
        maliyet = şuanki_düğüm.gCost + komşuya_uzaklık
        komşu.gCostHesapla()
        EĞER komşu.OPENdaDeğilse veya maliyet<komşu.gCost ise
            komşu.gCost = maliyet
            komşu.hCostHesapla()
            komşu.ebeveyn = şuanki_düğüm
            EĞER komşu.OPENdaDeğilse
                OPEN.ekle(komşu)
OPEN dizi boyutu 0 olduğu için DÖNGÜden çıkıldıysa // HEDEFE ULAŞAMADI

Javascript Kodu

FIND (Yol bulmayı başlat)
RELOAD (Gridi yeniden yükle)
ilk tık -> başlangıç karesi
2. tık -> hedef kare
sonraki tıklar -> engel oluştur

See the Pen A* Algoritması by farukcan (@farukcan) on CodePen.

3 taş oyunu için Yapay Zeka

Bu oyunda YZ, oyuncunun yaptığı hamlenin ardından, kendi yapacağı hamlelerin durum uzayını oluşturup sezgisel fonksiyon ile ileriye yönelik hamleleri bir puan vermektedir. Bunu yaparken, rakibinin bir sonraki hamlesini de göz önüne alır.

/**
 * Created by Faruk Can on 6.4.2016.
 */
 
var ç = new CanvasRender("canvas1");
 
var canvasboyut = 500;
 
var tahta = [
    [0,0,0],
    [0,0,0],
    [0,0,0]
];
// 1 : X
// diğer : O
// 0 : boş
 
 
 
// kontrol mekanizması
ç.addClickListener(function(x,y){
    console.log(x,y);
});
var hamleyapmakiçinarray = [];
for(var m=0;m<3;m++)
    for(var n=0;n<3;n++){
        hamleyapmakiçinarray.push({
            "height" : canvasboyut/3,
            "width" : canvasboyut/3,
            "top" : canvasboyut/3*m,
            "left" : canvasboyut/3*n
        });
    }
hamleyapmakiçinarray[0].func = function (){hamleyap(0,0)};
hamleyapmakiçinarray[1].func = function (){hamleyap(0,1)};
hamleyapmakiçinarray[2].func = function (){hamleyap(0,2)};
hamleyapmakiçinarray[3].func = function (){hamleyap(1,0)};
hamleyapmakiçinarray[4].func = function (){hamleyap(1,1)};
hamleyapmakiçinarray[5].func = function (){hamleyap(1,2)};
hamleyapmakiçinarray[6].func = function (){hamleyap(2,0)};
hamleyapmakiçinarray[7].func = function (){hamleyap(2,1)};
hamleyapmakiçinarray[8].func = function (){hamleyap(2,2)};
ç.clickElement = hamleyapmakiçinarray;
 
 
 
// ilk durum
var oyunKimde = "X";
var sıra = 0;
tahtayıÇiz();
hamleleriÇiz(true);
 
 
 
 
 
function hamleyap(m,n){
    if(oyunKimde == "X" && tahta[m][n]==0){
        tahta[m][n] = 1;
        oyunKimde = "O";
        ç.clear();
        tahtayıÇiz();
        hamleleriÇiz();
        sıra++;
        if(!oyunsonu())
            setTimeout(YZhamleyap,500);
    }
}
 
function oyunsonu(){
    if(sıra>8) return beraber();
    var taraf = 1;
    kontrolEdilecekYerler.forEach(function(yerler){
        var kactane1var = 0;
        yerler.every(function(y){
            var n= (y-1)%3;
            var m= Math.floor((y-1)/3);
            if(tahta[m][n]*taraf==-1) {
                kactane1var=0;
                return false;
            }
            if(tahta[m][n]*taraf==1) kactane1var++;
            return true;
        });
        if(kactane1var==3) {
            Xkazandı();
        }
    });
    var taraf = -1;
    kontrolEdilecekYerler.forEach(function(yerler){
        var kactane1var = 0;
        yerler.every(function(y){
            var n= (y-1)%3;
            var m= Math.floor((y-1)/3);
            if(tahta[m][n]*taraf==-1) {
                kactane1var=0;
                return false;
            }
            if(tahta[m][n]*taraf==1) kactane1var++;
            return true;
        });
        if(kactane1var==3) {
            Okazandı();
        }
    });
 
}
 
function Xkazandı(){
    alert("X kazandı");
    reload();
}
function Okazandı(){
    alert("O kazandı");
    reload();
}
function beraber(){
    alert("Berabere");
    reload();
}
 
function reload(){
    setTimeout(function(){location.reload();},2000);
}
 
 
var kontrolEdilecekYerler = [
    [1,2,3],
    [4,5,6],
    [7,8,9],
    [1,4,7],
    [2,5,8],
    [3,6,9],
    [1,5,9],
    [3,5,7]
];
 
// # tek taraf sezgisel fonksiyon h2
// -- her satır, sutun ve 2çarpraz için
// --- Eğer -1 varsa : 0 puan
// --- Eğer 1 tane 1 varsa : 1 puan
// --- Eğer 2 tane 1 varsa : 3 puan
// --- Eğer 3 tane 1 varsa : 99 puan
function h2(taraf,durum){
    var puan=0;
    kontrolEdilecekYerler.forEach(function(yerler){
        var kactane1var = 0;
        yerler.every(function(y){
            var n= (y-1)%3;
            var m= Math.floor((y-1)/3);
            if(durum[m][n]*taraf==-1) {
                kactane1var=0;
                return false;
            }
            if(durum[m][n]*taraf==1) kactane1var++;
            return true;
        });
        if(kactane1var==3) puan+=999;
        else if(kactane1var==2)  puan+=3;
        else puan+=kactane1var;
    });
    return puan;
}
 
// rahibin sonraki el en iyi hamlesinin puanını belirle
var h3iterasyon=0;
function h3(taraf,durum){
 
    if(++h3iterasyon==100) return 0;
 
    var olasıHamleler = [];
    /*
     {
     m: (x)
     n: (y)
     h:(sayı) // hamlenin sezgisel fonksiyon değeri
     }
     */
    for(var m=0;m<3;m++)
        for(var n=0;n<3;n++){
            if(durum[m][n]==0){
                // boş olan yerlere hamle yapılabilir
                var d = JSON.parse(JSON.stringify(durum)) // dunyayı klonla
                d[m][n] = taraf; //hamleyi duruma dahil et
                olasıHamleler.push(
                    {
                        "m" : m,
                        "n" : n,
                        "h" : h(taraf,d)
                    }
                );
            }
        }
 
    // en iyi hamleleri sırala
    olasıHamleler.sort(function(a,b){
        return b.h - a.h;
    });
    if(typeof olasıHamleler[0] == "undefined") return 0;
    return olasıHamleler[0].h;
}
 
// # çift taraf sezgisel fonksiyon h
// -- h = h2 - h3
function h(taraf,durum){
    return h2(taraf,durum) - h3(-taraf,durum);
}
 
function YZhamleyap(){
 
    h3iterasyon=0;
    sıra++;
 
    var olasıHamleler = [];
    /*
    {
        m: (x)
        n: (y)
        h:(sayı) // hamlenin sezgisel fonksiyon değeri
    }
     */
    for(var m=0;m<3;m++)
        for(var n=0;n<3;n++){
            if(tahta[m][n]==0){
                // boş olan yerlere hamle yapılabilir
                var durum = JSON.parse(JSON.stringify(tahta)) // dunyayı klonla
                durum[m][n] = -1; //hamleyi duruma dahil et
                olasıHamleler.push(
                    {
                        "m" : m,
                        "n" : n,
                        "h" : h(-1,durum)
                    }
                );
            }
        }
 
    // en iyi hamleleri sırala
    olasıHamleler.sort(function(a,b){
       return b.h - a.h;
    });
 
    tahta[olasıHamleler[0].m][olasıHamleler[0].n] = -1;
    console.log(olasıHamleler);
    oyunKimde = "X";
    ç.clear();
    tahtayıÇiz();
    hamleleriÇiz(true);
    oyunsonu();
}
 
 
function tahtayıÇiz(){
    // tik tak to tahtası
    for(var i=1;i<3;i++){
        ç.line(canvasboyut/3*i,20,canvasboyut/3*i,canvasboyut-20);
        ç.line(20,canvasboyut/3*i,canvasboyut-20,canvasboyut/3*i);
    }
 
}
 
function hamleleriÇiz(num){
    // tahta üzerinde yazan meretler
    var sira = 0;
    for(var m=0;m<3;m++)
        for(var n=0;n<3;n++){
            sira++;
            if(tahta[m][n]==0){
                if(num){
                    ç.font(ç.standartFont);
                    ç.text(sira,canvasboyut/6+canvasboyut/3*n,canvasboyut/6+canvasboyut/3*m);
                }
            }
            else if(tahta[m][n]==1){
                ç.font("233px Arial");
                ç.text("X",canvasboyut/3*n,canvasboyut/3+canvasboyut/3*m);
            }else{
                ç.font("213px Arial");
                ç.text("O",canvasboyut/3*n,canvasboyut/3+canvasboyut/3*m-5);
            }
        }
 
 
    ç.font(ç.standartFont);
}

Astroloji ve Burçların Yıkıcı Etkisi ve Zararları

Astroloji gök cisimlerinin insan kişiliği etkilediğine dair bir inançtır. Burçlarda 12 adet olan, Dünyanın güneş yörüngesindeki takım yıldızların isimleridir. Bu inanışa göre doğduğunuz zaman dünya hangi takım yıldıza yakınsa o yıldızlara göre bir kişilik sahibi oluyorsunuz. Mesela 27 ağustosta doğduysanız, başak yıldız kümesine yakındınız. Ve hala onun etkisi altındasınız (!)

Astronomi bilen birine göre buradaki ilk yanlış 12 burcun olmasıdır. Güneş etrafındaki yörüngemiz üzerinde 13 tane takım yıldızı vardır. Fakat nedense bir tanesini görmezden geliniyor.

Elbette yıldızların bizim üzerimizde etkisi vardır, bize en yakın yıldız olan “Güneş”, dünyaya hayat verir. Dünyanın dönüş çizgisinde bulunan kuzey yıldızları yön bulmamıza yarar.

Fakat bize en yakın yıldız olan Güneşin ışığı bile 1 milyon yıl önce üretilip, 8 dakika da bize ulaşıyorsa, 1 milyar ışık yılı uzaklıktaki, -belki ölmüş -yıldızların hayaletinin bizim kişiliğimize etki etmesi ne kadar mantıklıdır?

Astroloji inanışı ,tamamen bilimden uzaktır, sahte-bilim ve batıl inançtır. Deneysel olarak olarak yalanlanmıştır.

Bu batıl inancın bu kadar yaygın olmasının sebebini psikoloji bilimi Forer/Barnum etkisi ile açıklar. İnsanların çoğu, maalesef kendi kişiliklerini bilmiyor , ancak kendini tanımlama ihtiyacı duyuyor.

Burçların zararları

  • Kişi burcun bütün özelliklere sahip olmasa bile, kendini o burcun özelliklerine kendini şartlar ve kişiliğini o burcun kalıplarına oturtur. (Örnek; Benim çok kaba bir arkadaşım vardı. Bir gün çok şaşırtıcı bir şekilde nazik davrandığını gördüm ve dedim ki “Ahmet, sen çok nazik bir insansın”. Ondan sonra Ahmet, bir anda dünyanın en nazik insanı oldu. İnsanlar kendini tanımaması sebebiyle, kendini kalıplara sokmaya çalışır.)
  • İnsanlara karşı ön yargı besletmek. (Örnek: X kişisi, Y kişisinin burcunu öğrenir ve Y kişisine o burcun özelliklere göre davranır. Bu ön yargı ileride çok büyük çatışmalara sebep olur.)
  • Ayrımcılık ve Düşmanlık. (Eğer burçlarla ilgilendiyseniz, her burcun ,Dost burcu ve Düşman burcu vardır. Bundan dolayı çok iyi anlaşabilecek iki insan, burçlar yüzünden birbirinden uzak durabilir.)
  • İnsan ve dünya merkezli evren safsatası.  (Astroloji inancı, çıktığı devirdeki “dünya evrenin merkezidir ve her şey insan içindir” safsatasının ürünüdür. Dünya maalesef evrenin merkezinde değil, kenar mahallelerden birindedir. Evrenin çoğu (%99.9999999 u) insan için gereksizdir.)

İyilik İdeası Üzerine

Bu makalem İyilik ideası üzerine bir düzeltmedir. İyilik ile iyi ideası arasında farkı bilmek gerekir. İyilik kelimesi ile “Karşılık beklenilmeden yapılan yardım, kayra, lütuf, kerem, ihsan, inayet“(1) anlamını kast edeceğim.

Bu iyilik ideası hakkında günümüzde çok büyük yanılgılar vardır.  İyilik ile Hizmet anlam bakımından karıştırılmaktadır. İyilik ile Hizmet arasındaki en büyük fark “karşılık beklenilmeden yapılmaktır“.

Çoğu zaman insanlar hizmet kavramı yerine iyiliği kullanmaktadır. Fakat hizmet bir menfaat beklenerek yapılır.

Eğer sen, birini yardım ettiysen ; ister anlaşmalı olarak, ister üstü kapalı olarak bir karşılık bekliyorsan yaptığın iyilik değildir. Bu hizmettir. Bir kafede müşteriye çay verip, müşteri kalktığında ücretini almaktan farkı yoktur.

En büyük sapmalar ise , iyilik ideasının manevi anlamlarında olmuştur. Eğer sen bir iyilik yapıp, sonuç olarak bir cennet vaadine ulaşmayı amaçlıyor isen ya da bunun karşılığının diğer tarafta alınma şartı gözetiyor isen, bu yaptığın şey iyilik değildir. Bir uzun vadeli hizmet anlaşmasıdır.

Bunu bir insanın gözüne iyi gözüküp, onun önünde iyilik yapmaya benzetebiliriz. Aslında iyilik yapmayız, bir amacımız ve beklentimiz vardır, Bu menfaatte o insanın rızasını kazanmaktır. Kısacası iyilik yapmazsınız, iki yüzlülük yaparsınız.

”Menfaattir insanları getiren vecde; Cennet vaad etmeseydi Rahmân, kimse etmezdi secde.” -M. Âkif Ersoy

(1) TDK : Büyük Türkçe Sözlük