Bu Blogda Ara

yapay zeka etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
yapay zeka etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

24 Kasım 2012 Cumartesi

Yapay Sinir Ağları İleri Besleme & Geri Yayılım Algoritmaları - XOR Örneği




http://scitechdaily.com/ibm-supercomputer-simulates-530-billion-neurons-100-trillion-synapses/


IBM'in yapmış olduğu çalışmanın haberini okuduktan sonra yapay zeka meselesi hakkında küçük bir yazı yazmaya karar verdim. Tabiki haberdeki çalışmaya nazaran bizim yapacağımız örnek çok iptidai kalmaktadır. Lakin buradaki maksadım bir şekilde meseleye giriş yapmak bilahare daha gelişmiş örneklerle konuyu izah etmek şeklinde olacaktır.

Yapay zeka çok geniş bir kavram ve bir çok alt dalları bulunmaktadır (bkz: http://en.wikipedia.org/wiki/List_of_basic_artificial_intelligence_topics). Ben burada giriş mahiyetinde Yapay Sinir Ağları (bkz: http://en.wikipedia.org/wiki/Artificial_neural_network) hususunda ileri besleme (Feed forward bkz: http://en.wikipedia.org/wiki/Feedforward_neural_network) ve geri yayılım (bkz: http://en.wikipedia.org/wiki/Back-propagation) algoritmalarını kullanarak artık klasikleşmiş ve tabiri caizse bıktırmış olan XOR örneğini gerçekleyeceğim. 

Yukarıda verdiğim bağlantılara göz atarsanız algoritmanın nasıl çalıştığını kolayca anlayabilirsiniz. Bu noktada fazla bir teferruat icap etmiyor zira yapacağımız örnekteki XOR problemi 2 neron hidden layer için 1 neron da output layer için kafidir. Mühim bir not; biz bu örnekte BIAS değerini tüm neronlara ayrı ayrı vermek yerine bir kukla neron (dummy neuron, ağırlıkları ve çıktısı değişmeyen) kullanacağız.

Biraz gerçekleme (implementation) detaylarına göz atalım. 

Uygulamayı Java ile yapacağız. Aslınca C gibi bir dil ile çok daha basit ve hızlı bir şekilde gerçeklenebilirdi lakin müstakbel uygulamalarımızda yapacağımız muameleler daha karmaşık olacağından bu yapı ileride bize fayda sağlayacaktır, şu anda aksi gibi görünse dahi.


Temel olarak Object-Oriented yapı:

Neuron (Class)
NN (Class)
IActivation (Interface)
SigmoidActivation (Class) -> IActivation
DummyActivation (Class) -> IActivation


Başlamdan önce belirlenmesi gereken ilk husus neronların ilk ağırlık değerleridir, burada önceden çalıştığı bilinen bir küme de seçilebilir ya da sözde rastgele değerlerde seçilebilir, neticede kötü seçilen değerler sadece sonuca ulaşma süremizi uzatacaktır. Biz rastgele değerler üreteceğiz bu yüzden programı her çalıştırdığınızda farklı bekleme süreleri ile karşılacaksınız. Ayrıca eğitim sürecinde iterasyon sayısını bir hudut koyuyoruz çünkü bazı durumlarda gelen değerler deltaW değeri sıfıra çok yaklaştığı için istenilen değere (desired value) bir türlü yaklaşılamıyor ve çok bekleme yaşanıyor. Bu sebeple azami tekerrür 3.000.000 olarak seçiyoruz, beklenen hata nispetini ise 0.005 olarak seçtim. Bu değerler tamamen keyfi olup siz de istediğiniz gibi değiştirebilirisiniz.

Kaynak kodda herhangi bir dış kütüphane kullanmadım, doğrudan derleyip çalıştırabilisiniz.

Şimdi kaynak kodumuza bir göz atalım:




// Main.java

package ann.xor;

/**
 *
 * @author ramazan
 */
public class Main {

    public static String quantizeResult(float result) {
        return Integer.toString(Math.round(result)) + " (" + Float.toString(result) + ")";
    }
    
    public static void main(String[] args) {
        NN nn = new NN(5E-3f, 1.0f, 0.1f);
        SigmoidActivation sa = new SigmoidActivation();
        DummyActivation da = new DummyActivation();
        float BIAS = -1f;

        Neuron input1 = new Neuron(da, 0);
        Neuron input2 = new Neuron(da, 0);
        Neuron input3 = new Neuron(da, 0); // BIAS.
        Neuron hidden1 = new Neuron(sa, 3);
        Neuron hidden2 = new Neuron(sa, 3);
        Neuron hidden3 = new Neuron(da, 3); // Dummy neuron.
        Neuron output1 = new Neuron(sa, 3);

        nn.addInputNeuron(input1);
        nn.addInputNeuron(input2);
        nn.addInputNeuron(input3);

        nn.addHiddenNeuron(hidden1);
        nn.addHiddenNeuron(hidden2);
        nn.addHiddenNeuron(hidden3);

        nn.addOutNeuron(output1);

        hidden3.setDummy(true);
        input3.setOutput(BIAS);

        System.out.println("All inputs & weights has been set.");
        System.out.println("Training has been started.");
        
        int iteration = 0;
        do {
            iteration++;
            
            input1.setOutput(0);
            input2.setOutput(0);
 
            output1.desired = 0;

            nn.train();

            input1.setOutput(0);
            input2.setOutput(1);

            output1.desired = 1;

            nn.train();

            input1.setOutput(1);
            input2.setOutput(0);

            output1.desired = 1;

            nn.train();

            input1.setOutput(1);
            input2.setOutput(1);

            output1.desired = 0;

            nn.train();
            
            if (iteration % 50000 == 0) {
                System.out.println("-------------------------------");
                System.out.println("Current iteration:" + iteration);
                System.out.println("Current error:" + nn.getE());
                System.out.println("-------------------------------");
            }
        } while(!nn.learnt() && iteration < 3000000);
        
        System.out.println("Training has been completed.");
        System.out.println("Total iteration: " + iteration + ", accepted error: " + nn.getE());
        System.out.println("Test cases are in progress...");
        
        input1.setOutput(1);
        input2.setOutput(0);

        nn.test();

        System.out.println("1 XOR 0 = " + quantizeResult(nn.getOutput(0).getOutput()));

        input1.setOutput(1);
        input2.setOutput(1);

        nn.test();

        System.out.println("1 XOR 1 = " + quantizeResult(nn.getOutput(0).getOutput()));

        input1.setOutput(0);
        input2.setOutput(1);

        nn.test();

        System.out.println("0 XOR 1 = " + quantizeResult(nn.getOutput(0).getOutput()));

        input1.setOutput(0);
        input2.setOutput(0);

        nn.test();

        System.out.println("0 XOR 0 = " + quantizeResult(nn.getOutput(0).getOutput()));
    }
}



// NN.java

package ann.xor;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author ramazan
 */
public class NN {
   
    private List<neuron> inputLayer;
    private List<neuron> hiddenLayer;
    private List<neuron> outputLayer;
    private float E;
    private float e;
    private float lambda;
    private float nu;
    
    public NN(float E, float lambda, float nu) {
        inputLayer = new ArrayList<>();
        hiddenLayer = new ArrayList<>();
        outputLayer = new ArrayList<>();
        this.E = E;
        e = 0;
        this.lambda = lambda;
        this.nu = nu;
    }
    
    public void addInputNeuron(Neuron neuron) {
        inputLayer.add(neuron);
    }
    
    public void addHiddenNeuron(Neuron neuron) {
        hiddenLayer.add(neuron);
    }
    
    public void addOutNeuron(Neuron neuron) {
        outputLayer.add(neuron);
    }
    
    public Neuron getOutput(int index) {
        return outputLayer.get(index);
    } 
    
    public void train() {
        feedForward();
        calculateError();
        backPropagation();
        //System.out.println("Error value: " + e);
    }
    
    public void test() {
        feedForward();
    }
    
    protected void feedForward() {
        for (Neuron nH : hiddenLayer) {
            float inputs = 0;
            for (Neuron nI : inputLayer) {
                int i = inputLayer.indexOf(nI);
                inputs += nI.getOutput() * nH.getWeight(i);
            }
            nH.setInput(inputs);
            nH.activate(lambda);
        }
        
        for (Neuron nO : outputLayer) {
            float inputs = 0;
            for (Neuron nH : hiddenLayer) {
                int i = hiddenLayer.indexOf(nH);
                inputs += nH.getOutput() * nO.getWeight(i);
            }
            nO.setInput(inputs);
            nO.activate(lambda);
        }
    }
    
    protected void calculateError() {
        e = 0;
        for (Neuron nO : outputLayer) {
            nO.error = nO.desired - nO.getOutput();
            e += (float) Math.pow(nO.error, 2);
        }
        
        e = (float)Math.sqrt(e); 
    }
    
    protected void backPropagation() {
        for (Neuron nO : outputLayer) {
            nO.calculateDelta(lambda, nO.error);
            for (Neuron nH : hiddenLayer) {
                int i = hiddenLayer.indexOf(nH);
                nH.calculateDelta(lambda, nO.getDelta() * nO.getWeight(i));
                float diff = nu * nO.getDelta() * nH.getOutput();
                nO.setWeight(i, nO.getWeight(i) + diff);
            }
        }
        
        for (Neuron nH : hiddenLayer) {
            for (Neuron nI : inputLayer) {
                int i = inputLayer.indexOf(nI);
                float diff = nu * nH.getDelta() * nI.getOutput();
                nH.setWeight(i, nH.getWeight(i) + diff);
            }
        }
    }

    public float getE() {
        return e;
    }
    
    public boolean learnt() {
        return (e < E);
    }
}



// Neuron.java

package ann.xor;

import java.util.Random;

/**
 *
 * @author ramazan
 */
public class Neuron {

    private float[] weights;
    private float input;
    private float output;
    private IActivation activation;
    private float delta;
    public float desired;
    public float error;
    private boolean dummy;
    private static final Random random = new Random();

    public Neuron(IActivation activation, int weights) {
        this.weights = new float[weights];
        this.activation = activation;
        delta = 0;
        dummy = false;
        error = desired = 0;
        
        for (int i = 0; i < weights; i++) {
            this.weights[i] = getRandomWeight();
        }
    }
    
    protected final float getRandomWeight() {
        final float r = random.nextFloat();
        final float range = 2.4f / weights.length;

        return (r * 2 * range) - range;
    }

    public float getWeight(int index) {
        return weights[index];
    }

    public void setWeight(int index, float weight) {
        if (!dummy) {
            weights[index] = weight;
        }
    }

    public float getInput() {
        return input;
    }

    public void setInput(float input) {
        this.input = input;
    }

    public float getOutput() {
        return output;
    }

    public void setOutput(float output) {
        this.output = output;
    }

    public float getDelta() {
        return delta;
    }

    public boolean isDummy() {
        return dummy;
    }

    public void setDummy(boolean dummy) {
        this.dummy = dummy;
    }
    
    public void activate(float lambda) {
        float value = input;
        if (!dummy) {
            value *= -lambda;
        }
        output = activation.activate(value);
    }

    public void calculateDelta(float lambda, float error) {
        if (!dummy) {
            delta = error * lambda * activation.derivative(output);
        }
    }
}



// IActivation.java

package ann.xor;

/**
 *
 * @author ramazan
 */
public interface IActivation {
    public float activate(float input);
    public float derivative(float input);
}



// SigmoidActivation.java

package ann.xor;

/**
 *
 * @author ramazan
 */
public class SigmoidActivation implements IActivation {

    @Override
    public float activate(float input) {
        return (float) (1. / (1. + Math.exp(input)));
    }

    @Override
    public float derivative(float input) {
        return input * (1 - input);
    }
    
}



// DummyActivation.java

package ann.xor;

/**
 *
 * @author ramazan
 */
public class DummyActivation implements IActivation {

    @Override
    public float activate(float input) {
        return input;
    }

    @Override
    public float derivative(float input) {
        return input;
    }
}



Şimdi örnek bir çıktı üretelim:

run:
All inputs & weights has been set.
Training has been started.
-------------------------------
Current iteration:50000
Current error:0.02354227
-------------------------------
-------------------------------
Current iteration:100000
Current error:0.014160486
-------------------------------
-------------------------------
Current iteration:150000
Current error:0.011045283
-------------------------------
-------------------------------
Current iteration:200000
Current error:0.009226563
-------------------------------
-------------------------------
Current iteration:250000
Current error:0.008103463
-------------------------------
-------------------------------
Current iteration:300000
Current error:0.0073397583
-------------------------------
-------------------------------
Current iteration:350000
Current error:0.006666307
-------------------------------
-------------------------------
Current iteration:400000
Current error:0.00628476
-------------------------------
-------------------------------
Current iteration:450000
Current error:0.0058559924
-------------------------------
-------------------------------
Current iteration:500000
Current error:0.0055325483
-------------------------------
-------------------------------
Current iteration:550000
Current error:0.0051981094
-------------------------------
Training has been completed.
Total iteration: 586265, accepted error: 0.004999997
Test cases are in progress...
1 XOR 0 = 1 (0.9973595)
1 XOR 1 = 0 (0.004999945)
0 XOR 1 = 1 (0.9919734)
0 XOR 0 = 0 (0.0039330246)

BUILD SUCCESSFUL (total time: 4 seconds)


Bu basit örnek ile konuyu teorik olarak okuduktan sonra pratik olarak uygulamasını görerek daha iyi anlaşılacağı kanaatindeyim. Bir sonraki yazıda, yine klasikleşmiş olan tanıma (recognition) uygulamalarından bir örnek yapabilirim veyahut farklı bir anlada mesela Multi-agent systems simulation bir çalışma olabilir. Henüz karar vermedim. :)

Umarım faydalı olmuştur, böylelikle uzunca bir aradan sonra yazı yazabilmenin huzuruyla sizlere veda ediyorum, Allah'a emanet olunuz...

15 Kasım 2010 Pazartesi

Tic Tac Toe Oyunu - Yapay Zeka - MiniMax Algo.

Yapay zeka konusuna ilk girişi klasik Minimax algoritmasıyla yapıyorum. Algoritma çok basit ve etkili bir yöntem kullanmaktadır. Oyuncu bir hamle yaptıktan sonra diğer tüm oyunları oynayarak bilgisayarın en az kaybettiği en çok kazandığı hamle tespit edilmiş olur. Uygulamayı Python dilinde gerçeklemeye çalıştım. Doğası itibariyle %100 nesne yönelimli programlandı. Görsel arayüz için OpenGL (pyOpenGL) ve GLUT kütüphanelerini kullandım. Algoritma için daha detaylı bilgiyi http://en.wikipedia.org/wiki/Minimax adresinden edinebilirsiniz. İsterseniz programa ve kodların açıklamasına şöyle bir göz atalım, ardından kaynak kodu vereyim.












# -*- coding: cp1254 -*-


"""
MiniMax algoritmasını kullanarak Tic Tac Toe oyununun gerçeklenmesi

Sakarya Üniversitesi Bilgisayar Mühendisliği Bölümü
Yapay Zeka Dersi Ödevi

Ramazan Bellek - Ekim 2010


"""


from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
import time
import math
import copy
from Tkinter import *


# MiniMax algoritmasını gerçekleyen sınıf
class MiniMax:
mevcutDurum = [[]]
def __init__(self, mevcutDurum): # yapılandırıcı metod
self.mevcutDurum = copy.deepcopy(mevcutDurum)

# bilgisayarın bir sonraki yapacağı en mantıklı hareketi belirler
def sonrakiHamleyiHesapla(self):
tahta = self.mevcutDurum
max = [[0 for satir in range(3)] for sutun in range(3)]
for x in range(3):
for y in range(3):
if tahta[x][y] == 0:
tahta[x][y] = 1 # boş alana hamle yap
max[x][y] = self.__tara(tahta, 1) # alt ağaçları tara
tahta[x][y] = 0 # tarama bitince yapılan hamle geri alınır
else:
max[x][y] = -99
sonuc = -99
donusDegeri = [0,0]
for x in range(3):
for y in range(3):
if max[x][y]>sonuc:
sonuc=max[x][y]
donusDegeri = [x, y]
return donusDegeri

# alt oyun ağaçlarını tarar
def __tara(self, t, s):
tahta = copy.deepcopy(t)
sonEl = copy.deepcopy(s)
toplam = [[0 for satir in range(3)] for sutun in range(3)]
for x in range(3):
for y in range(3):
if tahta[x][y] == 0:
tahta[x][y] = sonEl*-1
kontrolSonucu = Hakem.kontrolEt(tahta)
if kontrolSonucu != 5: # -> tahta henüz dolu değil!
return kontrolSonucu
toplam[x][y] = self.__tara(tahta, sonEl*-1)
tahta[x][y] = 0
if sonEl == 1:
return self.Min(toplam)
else:
return self.Max(toplam)

# Katardaki azami değeri tespit eder.
def Max(self, t):
tahta = copy.deepcopy(t)
deger = -99
for x in range(3):
for y in range(3):
if tahta[x][y]>deger:
deger = tahta[x][y]
return deger

# Katardaki asgari değeri tespit eder.
def Min(self, t):
tahta = copy.deepcopy(t)
deger = 99
for x in range(3):
for y in range(3):
if tahta[x][y] deger = tahta[x][y]
return deger

class Hakem:
@staticmethod
def bosMu(t):
tahta = copy.deepcopy(t)
for x in range(3):
for y in range(3):
if tahta[x][y] == 0:
return True
return False
@staticmethod
def kontrolEt(t):
tahta = copy.deepcopy(t)

# oyuncu hamleleri --------------

# yatay kontrol --
if tahta[0][0] == tahta[1][0] == tahta[2][0] == -1:
return -1
elif tahta[0][1] == tahta[1][1] == tahta[2][1] == -1:
return -1
elif tahta[0][2] == tahta[1][2] == tahta[2][2] == -1:
return -1
# ----------------

# dikey kontrol --
elif tahta[0][0] == tahta[0][1] == tahta[0][2] == -1:
return -1
elif tahta[1][0] == tahta[1][1] == tahta[1][2] == -1:
return -1
elif tahta[2][0] == tahta[2][1] == tahta[2][2] == -1:
return -1
# ----------------

# çapraz kontrol --
elif tahta[0][0] == tahta[1][1] == tahta[2][2] == -1:
return -1
elif tahta[2][0] == tahta[1][1] == tahta[0][2] == -1:
return -1
# -----------------

# ------------------------------------

# Bilgisayar hamleleri --------------

# yatay kontrol --
if tahta[0][0] == tahta[1][0] == tahta[2][0] == 1:
return 1
elif tahta[0][1] == tahta[1][1] == tahta[2][1] == 1:
return 1
elif tahta[0][2] == tahta[1][2] == tahta[2][2] == 1:
return 1
# ----------------

# dikey kontrol --
elif tahta[0][0] == tahta[0][1] == tahta[0][2] == 1:
return 1
elif tahta[1][0] == tahta[1][1] == tahta[1][2] == 1:
return 1
elif tahta[2][0] == tahta[2][1] == tahta[2][2] == 1:
return 1
# ----------------

# çapraz kontrol --
elif tahta[0][0] == tahta[1][1] == tahta[2][2] == 1:
return 1
elif tahta[2][0] == tahta[1][1] == tahta[0][2] == 1:
return 1
# -----------------

# ------------------------------------

# Eşitlik durumu
if Hakem.bosMu(tahta) == False:
return 0
return 5 # -> tahta henüz dolu değil!

class Tahta:
"""Oyun tahtası sınıfı"""
tahta = [ [0 for satir in range(3)] for sutun in range(3)]
siraBilgisayarda = False
oyunBitti = False

def __init__(self):
oyunBitti = False
self.ilkDefa = True

def ciz(self):
if self.oyunBitti == True:
glColor(0.9, 0.6, 0.1)
drawText("Oyun bitti... :|", 10 ,5 ,250, 250)
elif self.ilkDefa == True:
glColor(0.9, 0.6, 0.1)
drawText("Oynamaya hazirim, lütfen bir hamle yapiniz... :)", 10 ,5 ,250, 250)
else:
glColor(0.9, 0.6, 0.1)
drawText("Sizin siraniz ?", 10 ,5 ,250, 250)

if self.ilkDefa == True:
self.ilkDefa = False
Tahta.cerceveCiz()
self.__oyunCiz()


@staticmethod
def cerceveCiz():
glLineWidth(2.5)
glColor(0.0, 0.0, 1.0)
glBegin(GL_LINES)

# dış çerçeve ------------
glVertex(-0.9, 0.9, 0.0)
glVertex(0.9, 0.9, 0.0)
glVertex(-0.9, 0.9, 0.0)
glVertex(-0.9, -0.9, 0.0)
glVertex(-0.9, -0.9, 0.0)
glVertex(0.9, -0.9, 0.0)
glVertex(0.9, -0.9, 0.0)
glVertex(0.9, 0.9, 0.0)
# -------------------------

# ızgaralar ---------------
glVertex(-0.3, -0.9, 0.0)
glVertex(-0.3, 0.9, 0.0)
glVertex(0.3, -0.9, 0.0)
glVertex(0.3, 0.9, 0.0)
glVertex(-0.9, -0.3, 0.0)
glVertex(0.9, -0.3, 0.0)
glVertex(-0.9, 0.3, 0.0)
glVertex(0.9, 0.3, 0.0)
# -------------------------
glEnd()

def __xCiz(self, x, y):
x =0.6*x-0.6
y =-1*(0.6*y-0.6)
glLineWidth(8.5)
glColor(0.0, 1.0, 0.0)
glBegin(GL_LINES)
glVertex(x-0.175, y-0.175)
glVertex(x+0.175, y+0.175)
glVertex(x-0.175, y+0.175)
glVertex(x+0.175, y-0.175)
glEnd()

def __oCiz(self, x, y):
x =0.6*x-0.6
y =-1*(0.6*y-0.6)
glLineWidth(1.5)
glColor(1.0, 0.0, 0.0)
glPushMatrix()
glTranslate(x, y, 0.0)
glBegin(GL_LINES)
for i in range(0, 1080):
glVertex(math.sin(i)*0.2,math.cos(i)*0.2)
glEnd()
glPopMatrix()

def __oyunCiz(self):
for x in range(3):
for y in range(3):
if self.tahta[x][y] == -1:
self.__xCiz(x, y)
elif self.tahta[x][y] == 1:
self.__oCiz(x, y)

''' tüm hamleler bu metod üzerinden gerçekleştirilir.
kullanıcı girişleri bu metoda yönlendirilerek kullanıcının hamle yapması
sağlanırken, her hamleden sonra öz yinelemeli olarak bilgisayar kendi hamlesini yapar.
Yapacağı hamleyi MiniMax algoritmasınını kullanarak tespit etmeye çalışır.
'''
def oyna(self, x, y):
try:
if self.oyunBitti == True:
## Mesaj.msj("Oyun bittiği için hamle yapamazsınız.","Üzgünüm... :(")
return
if x not in range(40, 760):
return
if y not in range(30, 560):
return
x = (x-40)/240
y = (y-30)/176
if self.tahta[x][y] == 0:
if self.siraBilgisayarda:
self.siraBilgisayarda = ~self.siraBilgisayarda
self.tahta[x][y] = 1
self.ciz()
glFlush ()
glutSwapBuffers()
self.__kontrolEt()
else:
self.siraBilgisayarda = ~self.siraBilgisayarda
self.tahta[x][y] = -1
self.ciz()
glFlush ()
glutSwapBuffers()
self.__kontrolEt()
if self.oyunBitti == True:
return
mm = MiniMax(self.tahta)
time.sleep(0.5)
xy = mm.sonrakiHamleyiHesapla()
self.oyna(xy[0]*240+40, xy[1]*176+30)
glutPostRedisplay()
except:
print "Beklenmeyen bir hata meydana geldi. Lütfen tekrar deneyiniz."
raise

def __kontrolEt(self):
durum = Hakem.kontrolEt(self.tahta)
if durum == 0:
self.oyunBitti = True
Mesaj.msj("Berabere bitti!", "Eşitlik durumu")
glEnable(GL_LIGHTING)
glutPostRedisplay()
return

# Bilgisayarın hamleleri --------------
mesaj = "Bilgisayar kazandı! :/\nBiraz daha dikkatli olmalısınız..."
if durum == 1:
self.oyunBitti = True
Mesaj.msj(mesaj, "Oyun bitti...")
glEnable(GL_LIGHTING)
glutPostRedisplay()
return
# ------------------------------------

# oyuncu hamleleri --------------
mesaj = "Tebrikler, siz kazandınız... :)"
if durum == -1:
self.oyunBitti = True
Mesaj.msj(mesaj, "Oyun bitti...")
glEnable(GL_LIGHTING)
glutPostRedisplay()
return
# ------------------------------------
if durum == 5: # -> tahta henüz dolu değil
return

# Mesaj sınıfı ----
class Mesaj:
root = None
def __init__(self, root):
self.root = root
@staticmethod
def msj(yazi, baslik):
root = Tk()
root.title(unicode(baslik, encoding="cp1254"))
root.withdraw()
mesaj = Mesaj(root)
mesaj.top = Toplevel(root)
Label(mesaj.top, text=unicode(yazi, encoding="cp1254")).pack()
Button(mesaj.top, text="OK", command=mesaj.tamam).pack(pady=5)
root.wait_window(mesaj.top) # pencere Tamam komutu verene kadar bekler.
root.destroy()
def tamam(self):
self.top.destroy()
# -----------------

# Yazı yazma fonksiyonu (pyOpenGL - örneğinden alınmıştır!)
def drawText( value, x,y, windowHeight, windowWidth, step = 18 ):
value = unicode(value, encoding="cp1254")
glMatrixMode(GL_PROJECTION);
matrix = glGetDouble(GL_PROJECTION_MATRIX)
glLoadIdentity();
glOrtho(0.0, windowHeight or 32, 0.0, windowWidth or 32, -1.0, 1.0)
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glRasterPos2i(x, y);
lines = 0
for character in value:
if character == '\n':
glRasterPos2i(x, y-(lines*18))
else:
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, ord(character));
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glLoadMatrixd(matrix)
glMatrixMode(GL_MODELVIEW);
# --------------------------------

# uygulama giriş fonsiyonları ---------------

resX,resY = (800,600 ) # ekran çözünürlüğü
oyunTahtasi = Tahta() # tahta sınıfı

def goster( ): # openGL render fonksiyonu
glutSetWindow(window);
glClearColor (1.0, 1.0, 1.0, 1.0)
glClear (GL_COLOR_BUFFER_BIT)
oyunTahtasi.ciz()
glFlush ()
glutSwapBuffers()

def ayarla():
''' yumuşak çizim '''
glShadeModel(GL_SMOOTH)
glDisable(GL_LIGHTING)



def fare(button, state, x, y):
if button == 0 and state == 1:
oyunTahtasi.oyna(x, y)


if __name__ == "__main__":
glutInit([])
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)

glutInitWindowSize(resX, resY) # pencere genişliği
glutInitWindowPosition(0, 0)
window = glutCreateWindow("Tic Tac Toe Oyunu / MiniMax Yapay Zeka Uygulaması - Ramazan Bellek | Ekim 2010")
glutMouseFunc(fare)
ayarla()


glutDisplayFunc(goster)
glutMainLoop()