Python ile Yapay Zekâ için Minimax Algoritmasını Uygulama
Python’da Minimax algoritmasını kullanarak yenilmez bir XOX yapay zekâsı kodlamayı öğrenin. Bu eğitim; kuram, uygulama ve optimizasyonu kapsar ve oyun yapay zekâsına ilgi duyanlar için idealdir.
Mini-Max algoritması, 1920’lere uzanan zengin bir yapay zekâ geçmişine sahiptir. O dönemde bilgisayar algoritmaları için “yapay zekâ” terimi kullanılmasa da, bu temel algoritma, makinelerin çekişmeli senaryolarda nasıl en iyi kararları verebileceğine dair en erken içgörüleri sağlamıştır. Algoritma ilk olarak John von Neumann tarafından 1928 tarihli “Zur Theorie der Gesellschaftsspiele” (Strateji Oyunları Kuramı Üzerine) makalesinde resmileştirilmiş ve modern oyun kuramı ile karar verme algoritmalarının temelini atmıştır.
1997’de IBM’in Deep Blue’su, Mini-max’in gelişmiş varyantlarını kullanarak dünya satranç şampiyonu Garry Kasparov’u yendi. O zamandan beri algoritma, Monte Carlo Ağaç Araması (MCTS) ve pekiştirmeli öğrenme gibi daha sofistike yaklaşımların belkemiği olmuştur.
Bu yazıda, satranç için ünlü Deep Blue’yu yeniden inşa etmeyeceğiz; bunun yerine Python’da çok daha basit bir sürüm olan XOX için bir versiyon geliştireceğiz. Bu süreçte, algoritmanın nasıl çalıştığına ve onu daha karmaşık gerçek dünya oyunlarına nasıl uygulayacağınıza dair güçlü bir sezgi kazanacaksınız.
Minimax Algoritması Nedir?
Minimax genellikle iki oyunculu oyunlar (satranç, XOX veya dama gibi) için bir karar verme algoritmasıdır. Bilgisayarların, rakibinizin her zaman mümkün olan en iyi hamleyi yapacağını varsayarak birkaç hamleyi önden planlamasını sağlar. Bu bölümde, algoritmaya XOX örneği üzerinden genel bir bakış atacağız.
Minimax algoritmasına genel bakış
Gerçek bir XOX oyununda, sıra size geldiğinde en iyi hamleyi yapmaya çalışır ve rakibinizin de en iyi oyunu oynayacağını varsayarsınız. Minimax algoritması tam olarak bunu yapar — bilgisayarın tüm olası hamleleri önden düşünerek yapabileceği en iyi hamleyi bulmasına yardımcı olur.
Minimax adı, çalışma biçiminden gelir:
“Mini”, rakibin sizin puanınızı en aza indirmeye çalışmasını temsil eder
“Max”, sizin puanınızı en üst düzeye çıkarmaya çalışmanızı temsil eder
Sıra sizdeyken, size kazanma şansı en yüksek hamleleri yapmak istersiniz (maksimizasyon). Sıra rakibinizdeyken, size en kötü sonucu getirecek hamleleri yapacağını varsayarsınız (minimizasyon).
Yapay zekâda Minimax’in önemi
Minimax, yapay zekâda çeşitli nedenlerle son derece önemlidir:
Bilgisayarların iki oyunculu oyunlarda akıllı kararlar almasına yardımcı olur
Birçok modern oyun oynayan yapay zekâ sisteminin temelidir
Bilgisayarlara önden düşünmeyi ve hamle planlamayı öğretir
En güzel yanı? Aynı fikir, gerçek dünyadaki birçok uygulamada da kullanılır:
Video oyunlarındaki yapay zekâ rakipleri
Satranç ve dama gibi strateji oyunları
Hatta bazı iş karar destek araçları
Minimax kulağa karmaşık gelse de, aslında bir bilgisayara karar vermeden önce hem kendi hamlelerini hem de rakibinin hamlelerini dikkate alan dikkatli bir oyuncu gibi düşünmeyi öğretmektir.
Minimax Algoritmasını Anlamak
Minimax’in nasıl çalıştığını basit bir XOX örneğiyle adım adım inceleyelim. Siz X, bilgisayar ise O olarak oynuyor olun.
Bilgisayar nasıl düşünür
Sıra bilgisayara geldiğinde şu adımları izler:
Yapabileceği tüm olası hamlelere bakar
Her hamle için, sizin bir sonraki hamlede ne yapabileceğinizi hayal eder
Bir sonuca ulaşana kadar (biri kazanır ya da beraberlik olur) önden düşünmeye devam eder
Kendisine kazanma şansı en yüksek hamleyi seçer
Oyunu puanlamak
Bilgisayar basit bir puanlama sistemi kullanabilir:
Bilgisayar kazanırsa +10 puan
Siz kazanırsanız -10 puan
Beraberlik olursa 0 puan
Bunu bir olasılıklar ağacı gibi düşünün:
En üstte mevcut oyun tahtası vardır
Her dal bir olası hamleyi temsil eder
En altta tüm olası sonuçlar yer alır
Sıra değişimi
Bilgisayar iki düşünme modu arasında geçiş yapar:
1. Maksimizasyon modu (bilgisayarın sırası):
En yüksek puanı getiren hamleleri arar
Kazanmayı ya da beraberliği zorlamayı dener
2. Minimizasyon modu (oyuncunun sırası):
Sizin en düşük puanı getiren hamleleri yapacağınızı varsayar
Sizin yapabileceğiniz en iyi hamlelere hazırlanır
Basit bir örnek
Diyelim ki oyunda sıra bilgisayarda (X):
Bilgisayar şunları yapacaktır:
Seçebileceği 3 boş alan olduğunu görür
Her boş alan için tüm olası gelecek hamleleri hayal eder
En iyi sonuca götüren hamleyi seçer
Bu durumda, sizin kazanmanızı engellemek için alt-orta köşeyi seçmelidir
Bu önden düşünme biçimi, bilgisayarın her seferinde kusursuz bir XOX oyunu oynamasına yardımcı olur!
Minimax Algoritması Sözde Kod
Minimax algoritmasını adım adım nasıl yazacağımızı inceleyelim. Sözde koda yeniyseniz endişelenmeyin — onu, gerçek koda dönüştürmeden önce adımları sade bir dille yazmak gibi düşünebilirsiniz!
Adım adım açıklama
Minimax fonksiyonunun çalışması için üç temel şeye ihtiyacı vardır:
Mevcut oyun tahtası
Derinlik (önden kaç hamleyi incelediğimiz)
Sıranın maksimize eden oyuncuda mı (bilgisayar) yoksa minimize eden oyuncuda mı (insan) olduğu
Temel sözde kod şu şekildedir:
function minimax(board, depth, isMaximizingPlayer):# First, check if the game is overif game is won:return+10if computer wins,-10if human wins
if game is tied:return0# If it's the computer's turn (maximizing)if isMaximizingPlayer:
bestScore =-infinity
for each empty spot on board:
make the move
score = minimax(board, depth +1, false)
undo the move
bestScore =max(score, bestScore)return bestScore
# If it's the human's turn (minimizing)else:
bestScore =+infinity
for each empty spot on board:
make the move
score = minimax(board, depth +1, true)
undo the move
bestScore =min(score, bestScore)return bestScoreAltyapı:
Çoğu sözde kod örneği İngilizce okunur ve gayet anlaşılırdır; ancak yukarıdaki örnek, özyineleme (recursion) kullandığı için biraz farklıdır. Özyineleme, bir fonksiyonun daha büyük bir problemi çözmek için kendisini tekrar tekrar çağırmasıdır. Bir aynanın başka bir aynayı yansıtmasına bakmak gibidir — aynı görüntüyü birçok kez, her seferinde küçülerek görürsünüz.
Minimax algoritmamızda özyineleme gerekir; çünkü oyundaki tüm olası gelecek hamleleri incelemeye çalışıyoruz. Fonksiyon her kendini çağırdığında, bir sonraki olası hamleyi değerlendirir.
Bu, oyunun tüm olası gidişatlarını kontrol ederek en iyi hamleyi bulmamıza yardımcı olur; tıpkı “Ben bunu yaparsam, o şunu yapar, sonra ben bunu yaparım…” diye düşünen çok akıllı bir oyuncu gibi, oyun bitene kadar devam eder. Özyineleme hakkında daha fazla bilgi için ayrı özyineleme eğitimimize bakabilirsiniz.
Örnekleyici açıklama
Basit bir oyun durumunda bunun nasıl çalıştığını görelim:
1. Başlangıç Konumu:
2. Bilgisayar düşünür:
“X’i herhangi bir boş alana koyarsam…”
“İnsan bir sonraki hamlede ne yapar?”
“Peki ben ondan sonra ne yapabilirim?”
“Hangi hamle bana en iyi nihai puanı getirir?”
3. Her boş alan için bilgisayar:
Bir hamle yapar
Oyunun bitip bitmediğini kontrol eder
Bitmediyse, insanın en iyi hamlesini hayal eder
Bir sona ulaşana kadar devam eder
En yüksek puanı getiren hamleyi seçer
Bunu satranç gibi düşünün — hep “Ben buraya gidersem, o şuraya gider, sonra ben buraya…” diye düşünürsünüz; ancak bilgisayar TÜM olası hamleleri aynı anda düşünebilir!
Bu algoritmanın güzel yanı, her iki tarafın da kusursuz oynadığı varsayımı altında her zaman mümkün olan en iyi hamleyi bulmasıdır. Oyunun tüm olası geleceklerini gösteren bir kristal küreye sahip olmak gibi!
XOX için Minimax’i Adım Adım Uygulama
Bu bölümde, saf Python ile Mini-max algoritması tarafından güçlendirilen yenilmez bir XOX yapay zekâsı oluşturacağız. Uygulamayı basit adımlara bölecek, her birinin arkasındaki sezgiyi ve oyunun büyük resmindeki yerini açıklayacağız.
Adım 1: TicTacToe sınıfını tanımlama
Önce, bilgisayarımızla bir XOX oyunu oynamak için ihtiyaç duyduğumuz tüm mantık ve yöntemleri içeren bir sınıf tanımlıyoruz:
classTicTacToe:def__init__(self):# Initialize empty board (using ' ' for empty squares)
self.board =[" "for _ inrange(9)]
self.human_player ="O"
self.ai_player ="X"defprint_board(self):"""Print the current state of the board"""for i inrange(0,9,3):print(f"{self.board[i]} | {self.board[i+1]} | {self.board[i+2]}")if i <6:print("---------")defavailable_moves(self):"""Returns list of available moves (indices of empty squares)"""return[i for i, spot inenumerate(self.board)if spot ==" "]Altyapı:
Yukarıda, __init__ metodu, 9 boş alandan (" " boşlukla temsil edilir) oluşan yeni bir oyun tahtası başlatır; 0–8 indeksleri soldan sağa, yukarıdan aşağıya tahta konumlarını temsil eder. Ayrıca iki oyuncu sembolünü belirler — insan oyuncu için "O", yapay zekâ için "X".
print_board metodu, tahtanın mevcut durumunu görselleştirmenin bir yolunu sunar. Her oyuncunun hamlesini ilgili konumlarda göstererek satırlar arasında bölücü çizgilerle 3x3 ızgarayı yazdırır.
available_moves metodu, hâlâ yapılabilecek tüm geçerli hamlelerin bir listesini döndürür. Bunu, tahtadaki hangi konumların hâlâ boş (" ") olduğunu kontrol ederek ve indekslerini döndürerek yapar. Bu, minimax algoritmasının hangi hamleleri değerlendirebileceğini bilmesi açısından kritik olacaktır.
Bu yöntemler, minimax algoritmasını kullanarak yapay zekâ oyuncumuzu oluşturmak için üzerine inşa edeceğimiz temeli oluşturur.
Hızlıca test edelim:
>>> game = TicTacToe()>>> game.print_board()||---------||---------||>>> game.available_moves()[0,1,2,3,4,5,6,7,8]Altyapı:
Beklendiği gibi, şu anda tahta boş ve tüm hamleler mevcut.
Adım 2: Hamle yapma ve tahta durumlarını kontrol etme yöntemlerini uygulama
Şimdi, bir hamle yapma yöntemi ekleyelim:
classTicTacToe:...defmake_move(self, position, player):"""Make a move on the board"""if self.board[position]==" ":
self.board[position]= player
returnTruereturnFalseAltyapı:
make_move metodunu ekledik; bu yöntem:
Girdi olarak bir konum (0–8) ve oyuncu sembolü (“X” veya “O”) alır
Seçilen konumun boş (“ ”) olup olmadığını kontrol eder
Boşsa, oyuncunun sembolünü yerleştirir ve True döndürür
Konum doluysa, hiçbir değişiklik yapmadan False döndürür
Birkaç hamle yapalım ve kalan hamleleri kontrol edelim:
>>> game = TicTacToe()>>> game.make_move(0,"X")>>> game.make_move(1,"O")>>> game.print_board()
X | O |-----------||-----------||>>> game.available_moves()[2,3,4,5,6,7,8]Altyapı:
Gayet iyi çalışıyor. Sıradaki adım, tahtanın dolu olup olmadığını kontrol eden bir yöntem eklemek:
classTicTacToe:...defis_board_full(self):"""Check if the board is full"""return" "notin self.boardAltyapı:
is_board_full, tahtada hiç boş alan kalıp kalmadığını kontrol eden bir boole yöntemidir.
Sırada, bir kazanç durumu oluşup oluşmadığını kontrol eden bir yöntem eklemek var:
classTicTacToe:...defcheck_winner(self):"""Check if there's a winner. Returns winner symbol or None"""# Check rowsfor i inrange(0,9,3):if self.board[i]== self.board[i +1]== self.board[i +2]!=" ":return self.board[i]# Check columnsfor i inrange(3):if self.board[i]== self.board[i +3]== self.board[i +6]!=" ":return self.board[i]# Check diagonalsif self.board[0]== self.board[4]== self.board[8]!=" ":return self.board[0]if self.board[2]== self.board[4]== self.board[6]!=" ":return self.board[2]returnNoneAltyapı:
check_winner metodu, XOX tahtasının mevcut durumunu değerlendirerek bir kazanan olup olmadığını belirler. Tüm olası kazanma kombinasyonlarını kontrol eder:
1. Satırlar (3 olasılık):
Üst sıra (indeksler 0,1,2)
Orta sıra (indeksler 3,4,5)
Alt sıra (indeksler 6,7,8)
2. Sütunlar (3 olasılık):
Sol sütun (indeksler 0,3,6)
Orta sütun (indeksler 1,4,7)
Sağ sütun (indeksler 2,5,8)
3. Çaprazlar (2 olasılık):
Sol üstten sağ alta (indeksler 0,4,8)
Sağ üstten sol alta (indeksler 2,4,6)
Her kombinasyon için, üç konumun da aynı oyuncu sembolünü (X veya O) içerip içermediğini ve boş olmadığını kontrol eder. Bir kazanma kombinasyonu bulunursa, kazanan oyuncunun sembolünü döndürür. Tüm olasılıklar kontrol edildikten sonra kazanan yoksa None döner.
Fonksiyonu, kazanç ve kazanç olmayan durumlarda test edelim:
game = TicTacToe()# Winning state
game.make_move(0,"X")
game.make_move(1,"X")
game.make_move(2,"X")>>> game.print_board()
X | X | X
-----------||-----------||>>> game.check_winner()'X'
game = TicTacToe()# Non-winning state
game.make_move(0,"X")
game.make_move(1,"O")
game.make_move(2,"O")
game.make_move(3,"X")>>> game.print_board()
X | O | O
-----------
X ||-----------||>>> game.check_winner()isNoneTrueAltyapı:
Son olarak, oyunun bitip bitmediğini belirtmek için başka bir boole yöntemi ekleyelim:
classTicTacToe:...defgame_over(self):"""Check if the game is over"""return self.check_winner()isnotNoneor self.is_board_full()Altyapı:
Bu yöntem, ya bir kazanan bulunduğunda ya da tahta dolu olduğunda True döndürür.
Bu noktada, tüm temel oyun mekaniğini oluşturduk:
Tahta, boş olarak başlatılan 9 karelik bir listeyle temsil edilir
print_board() mevcut oyun durumunu görsel olarak gösterir
available_moves() boş karelerin indekslerini döndürür
check_winner() her hamlede satırları, sütunları ve çaprazları kazanç için inceler
is_board_full() hamle kalıp kalmadığını belirler
game_over() kazanan kontrolü ile tahta dolu kontrolünü birleştirir
Bu yöntemler, hamle yapma ve oyun durumunu belirleme gibi tüm temel işlemleri ele alarak oynanabilir bir oyun için gereken temeli sağlar.
Şimdi kritik kısma geliyoruz — bilgisayara Minimax ile “zeka” kazandırmak.
Adım 3: XOX için Minimax’i uygulama
Şimdi, algoritmayı oyuna yeni bir yöntem olarak uygulayalım:
classTicTacToe:...defminimax(self, depth, is_maximizing):"""
Minimax algorithm implementation
Returns the best score possible for the current board state
"""# Base cases
winner = self.check_winner()if winner == self.ai_player:return1if winner == self.human_player:return-1if self.is_board_full():return0Altyapı:
Fonksiyon iki parametre alır:
depth — Özyinelemede kaç seviye derine indiğimizi takip eder. Çok karmaşık oyunlar için arama derinliğini sınırlamakta kullanılabilir; ancak XOX için sınırlamaya gerek yoktur.
is_maximizing — Şu anda maksimum puanı (YZ’nin sırası) mı yoksa minimum puanı (insanın sırası) mı aradığımızı belirten boole bayrağıdır. Oyuncular sıra aldıkça her özyinelemeli çağrıda bu değer değişir.
Fonksiyon gövdesinde, temel durumları tanımlayarak başlarız: Oyun YZ tarafından kazanılmışsa (winner == ai_player), YZ için en iyi sonuç olduğundan 1 döndürürüz. İnsan kazanırsa (winner == human_player), YZ için en kötü sonuç olduğundan -1 döndürürüz. Tahta dolu ve kazanan yoksa, beraberlik için 0 döndürürüz.
defminimax(self, depth, is_maximizing):...# if it is the maximizing player's turn (AI), we want to maximize the scoreif is_maximizing:
best_score =float("-inf")for move in self.available_moves():# Make a calculating move
self.board[move]= self.ai_player
# Recursively call minimax with the next depth and the minimizing player
score = self.minimax(depth +1,False)# Reset the move
self.board[move]=" "# Update the best score
best_score =max(score, best_score)return best_scoreAltyapı:
is_maximizing True olduğunda YZ’nin sırasını simüle ederiz ve en yüksek puana götüren hamleyi bulmak isteriz. best_score’u eksi sonsuza ayarlarız ki gerçek herhangi bir puan daha iyi olsun. Ardından her mevcut hamle için:
YZ’nin sembolünü geçici olarak tahtaya koyarız
Bu hamleyi yaparsak ne olacağını, is_maximizing=False ile minimax çağırarak özyinelemeli değerlendiririz (çünkü sıradaki hamle insanındır)
Geçici hamleyi geri alır, tahtayı eski hâline getiririz
Gördüğümüz en yüksek puanı max() ile takip ederiz
Bu, YZ’nin yapabileceği her olası hamleyi kontrol etmemizi sağlar. Her hamle için, birinin kazanmasına ya da oyunun berabere bitmesine kadar neler olabileceğine bakarız. Ardından geriye doğru çalışarak ilk hamlelerden hangisinin YZ’ye en iyi kazanma şansını verdiğini buluruz.
Şimdi, insan için minimize etme kısmını yapalım:
defminimax(self, depth, is_maximizing):...# if it is the maximizing player's turn (AI), we want to maximize the scoreif is_maximizing:...else:# if it is the minimizing player's turn (human), we want to minimize the score
best_score =float("inf")for move in self.available_moves():# Make a calculating move
self.board[move]= self.human_player
# Recursively call minimax with the next depth and the maximizing player
score = self.minimax(depth +1,True)# Reset the move
self.board[move]=" "# Update the best score
best_score =min(score, best_score)return best_scoreAltyapı:
is_maximizing False olduğunda, insan oyuncunun sırasını simüle ederiz ve en düşük puana götüren hamleyi bulmak isteriz (çünkü yüksek puan YZ’nin kazanması demektir). best_score’u artı sonsuzla başlatırız ki gerçek herhangi bir puan daha düşük olsun. Her mevcut hamle için:
İnsanın sembolünü geçici olarak tahtaya koyarız
Ne olacağını, is_maximizing=True ile minimax çağırarak özyinelemeli değerlendiririz (çünkü sıradaki hamle YZ’nindir)
Geçici hamleyi geri alırız
Gördüğümüz en düşük puanı min() ile takip ederiz
Bu, insan oyuncunun YZ’nin kazanmasını önlemek için en iyi hamleleri yapmaya çalışmasını simüle eder. İnsan, puanları en aza indirmek ister; çünkü pozitif puanlar YZ zaferlerini temsil eder. Maksimizasyon ve minimizasyon turları arasında dönüşümlü ilerleyerek algoritma, her iki oyuncu için de en iyi hamle dizisini belirleyebilir.
Adım 4: Minimax ile YZ için en iyi hamleyi bulma
Artık algoritma hazır olduğuna göre, her insan hamlesinden sonra YZ için en iyi hamleyi belirlemek üzere minimax yöntemini kullanan başka bir yönteme ihtiyacımız var:
classTicTacToe:...defget_best_move(self):"""Find the best move for AI using minimax"""
best_score =float("-inf")
best_move =Nonefor move in self.available_moves():# Make a calculating move
self.board[move]= self.ai_player
# Recursively call minimax with the next depth and the minimizing player
score = self.minimax(0,False)# Reset the move
self.board[move]=" "# Update the best scoreif score > best_score:
best_score = score
best_move = move
return best_moveAltyapı:
get_best_move yöntemi, minimax algoritmasını kullanarak YZ oyuncusu için en uygun hamleyi belirlemekten sorumludur. Şöyle çalışır:
1. En iyi puan olarak eksi sonsuz ve seçili bir hamle olmadan başlar
2. Tahtadaki her mevcut hamle için:
YZ’nin sembolünü geçici olarak o konuma yerleştirir
Minimax’i kullanarak geri kalan oyunu simüle eder ve hamlenin ne kadar iyi olduğunu değerlendirir
Geçici hamleyi geri alır
Bu hamle daha önce gördüğümüzden daha iyi bir puana yol açarsa, hem en iyi puanı hem de en iyi hamleyi günceller
3. Son olarak en yüksek puana yol açan hamleyi döndürür
Bu yaklaşım, insan oyuncunun da en iyi şekilde oynadığı varsayımı altında, YZ’nin kendisine en iyi kazanma şansını veren hamleyi seçmesini sağlar. Yöntem, tüm olası gelecek oyun durumlarını dikkate alır ve YZ’nin şansını maksimize ederken insanın kazanma şansını en aza indiren yolu seçer.
Bunu örnek bir oyun durumunda test edelim:
game = TicTacToe()# Make a couple of moves
game.make_move(0,"X")
game.make_move(1,"O")# Print the board>>> game.print_board()
X | O |---------||---------||>>> game.get_best_move()3# AI moves>>> game.make_move(3,"X")# I move>>> game.make_move(4,"O")>>> game.print_board()
X | O |---------
X | O |---------||# Get the best move for AI>>> game.get_best_move()6Altyapı:
Gördüğünüz gibi, YZ benim hamlelerime göre kazanan kombinasyonu buldu (örnek durumdu ama algoritmamızın çalıştığını kanıtlıyor).
Adım 5: Bir oyun döngüsü uygulama
Artık minimax algoritmamızı uygulayıp test ettiğimize göre, YZ’ye karşı oynamamıza olanak tanıyan bir oyun döngüsü oluşturalım.
classTicTacToe:...defplay_game(self):"""Main game loop"""print("Welcome to Tic Tac Toe!")print("You are 'O' and the AI is 'X'")print("Enter positions (0-8) as shown below:")print("0 | 1 | 2")print("---------")print("3 | 4 | 5")print("---------")print("6 | 7 | 8")print("\n")Altyapı:
play_game metodu, bir karşılama mesajı ve oyuncuya yönelik talimatları göstererek başlar. İnsan oyuncunun ‘O’, YZ’nin ise ‘X’ kullandığını belirtir. Ardından, oyuncuya tahtadaki hangi konumun hangi sayıya karşılık geldiğini göstermek için numaralandırılmış bir ızgara (0–8) yazdırır. Bu, oyuncuların istedikleri hamle için doğru sayıyı girmelerini kolaylaştırır.
# ... the rest of the classdefplay_game(self):...# Randomly decide who goes firstimport random
ai_turn = random.choice([True,False])whilenot self.game_over():
self.print_board()if ai_turn:print("\nAI's turn...")
move = self.get_best_move()
self.make_move(move, self.ai_player)else:whileTrue:try:
move =int(input("\nYour turn (0-8): "))if0<= move <=8and self.make_move(move, self.human_player):breakelse:print("Invalid move! Try again.")except ValueError:print("Please enter a number between 0 and 8!")
ai_turn =not ai_turnAltyapı:
Başlangıç talimatlarını gösterdikten sonra oyun ana döngüsüne girer. Oyun, her oyunun başında adil ve öngörülemez bir başlangıç oluşturmak için random.choice([True, False]) kullanarak ilk kimin oynayacağına (YZ ya da insan) rastgele karar verir.
Ana oyun döngüsü, game_over() True dönene kadar (biri kazanır ya da tahta dolar) devam eder. Her turda, print_board() ile tahtanın mevcut durumu gösterilir.
Eğer sıra YZ’deyse (ai_turn True ise), program:
YZ’nin düşündüğünü belirten bir mesaj yazdırır
get_best_move() çağrısıyla minimax algoritmasını kullanarak en uygun hamleyi belirler
Seçilen konuma YZ’nin sembolünü (‘X’) yerleştirerek hamleyi yapar
Sıra insandaysa (ai_turn False ise), program:
1. Oyuncudan geçerli bir girdi almak için bir döngüye girer2. 0–8 arasında bir hamle numarası ister3. Girdiyi doğrular:
Geçerli bir tam sayı mı (try/except ile)
0–8 aralığında mı
Tahtada boş bir konuma mı işaret ediyor
4. Geçerli giriş alınana kadar sormaya devam eder. Seçilen konuma oyuncunun sembolünü (‘O’) yerleştirerek hamleyi yapar
ai_turn, her turdan sonra not kullanılarak tersine çevrilir ve oyuncular arasında sırayla ilerlenir. Bu, biri kazanana ya da oyun berabere bitene kadar oyunun karşılıklı ilerleyişini sağlar.
Girdi doğrulaması, geçersiz kullanıcı girdilerinin oyunu çökertmesini engeller ve oyuncuyu doğru hamleleri girmeye yönlendiren faydalı hata mesajları sağlar. Bu da sağlam ve kullanıcı dostu bir oyun deneyimi yaratır.
defplay_game(self):...# Game over
self.print_board()
winner = self.check_winner()if winner == self.ai_player:print("\nAI wins!")elif winner == self.human_player:print("\nCongratulations! You win!")else:print("\nIt's a tie!")Altyapı:
Oyun bittiğinde, print_board() ile son tahta durumu gösterilir ve check_winner() ile kazanan belirlenir. Oyun üç şekilde bitebilir:
YZ kazanır — check_winner() YZ’nin sembolünü (‘X’) döndürürse, YZ’nin bir kazanç hattı elde ettiği anlamına gelir
İnsan kazanır — check_winner() insanın sembolünü (‘O’) döndürürse, oyuncunun bir kazanç hattı elde ettiği anlamına gelir
Beraberlik — Hiçbir oyuncu kazanmadıysa ve tahta doluysa, artık hamle yapılamaz
Oyun sonucunu duyurmak için uygun mesaj gösterilir. Böylece oyunun nasıl sonuçlandığı oyuncuya net biçimde bildirilir.
Adım 6: Her şeyi bir araya getirmek
Şimdiye kadar yazdığımız tüm kodu, en sonda aşağıdaki if/main koşuluyla birlikte bir Python betiğine koyma zamanı:
# Start the gameif __name__ =="__main__":
game = TicTacToe()
game.play_game()Altyapı:
Bu, betiği python script.py ile çalıştırdığınız anda oyunun başlamasını sağlar. Tüm açıklamalar ve kod blokları arasında kaybolduysanız, oyunun tam kodunu bu GitHub gist’inde bulabilirsiniz.
İşte oynadığım örnek bir oyun:
❯ python tic-tac-toe.py
Welcome to Tic Tac Toe!
You are 'O'and the AI is'X'
Enter positions (0-8)as shown below:0|1|2---------3|4|5---------6|7|8||---------||---------||
Your turn (0-8):4||---------| O |---------||
AI's turn...
X ||---------| O |---------||
Your turn (0-8):5
X ||----------| O | O
----------||
AI's turn...
X ||---------
X | O | O
---------||
Your turn (0-8):6
X ||---------
X | O | O
---------
O ||
AI's turn...
X || X
---------
X | O | O
---------
O ||
Your turn (0-8):1
X | O | X
---------
X | O | O
---------
O ||
AI's turn...
X | O | X
---------
X | O | O
---------
O | X |
Your turn (0-8):8
X | O | X
---------
X | O | O
---------
O | X | O
It's a tie!Altyapı:
Unutmayın, XOX basit bir oyun olduğundan YZ’yi yenme şansı yoktur. Oyun ya berabere biter ya da kaybedersiniz!
Mini-max Algoritmasını Biçimselleştirme
Şimdi, basit XOX örneğinin ötesinde algoritmanın genel tanımını gözden geçirelim.
Minimax algoritması, sıfır toplamlı bir oyundaki konumları değerlendiren özyinelemeli bir fonksiyon olarak biçimsel şekilde tanımlanabilir. Biçimsel bileşenlerini ve özelliklerini inceleyelim.
Matematiksel tanım
Bir oyun durumu s için minimax değeri V(s) şu şekilde tanımlanır:
V(s)=
utility(s)if s is terminal
max(V(s')) for all s'in S if player = MAX
min(V(s')) for all s'in S if player = MINAltyapı:
Burada:
s’, s’nin ardıl durumlarını temsil eder
S, s durumundan yapılan tüm yasal hamlelerin kümesidir
utility(s), terminal durumlar için değerlendirme fonksiyonudur
Temel özellikler
1. Mükemmel bilgi
Tüm oyuncular oyun durumunu tamamen bilir
Gizli bilgi veya şans unsuru yoktur
Sonuçlar deterministiktir
2. Sıfır toplamlı yapı
Bir oyuncunun kazancı, diğerinin kaybına tam olarak eşittir
Tüm oyuncuların faydalarının toplamı her zaman sıfırdır
İki oyunculu oyunlarda faydalar genellikle {-1, 0, 1} şeklindedir
3. Optimal oyun
Her iki oyuncunun da en iyi kararları verdiği varsayılır
Kusursuz oyuna karşı en iyi mümkün sonucu garanti eder
Oyun kuramı açısından Nash dengesine götürür
Karmaşıklık analizi
Zaman karmaşıklığı: O(b^m)
b = dallanma faktörü (her durumda yasal hamle sayısı)
m = oyun ağacının en büyük derinliği
Uzay karmaşıklığı: O(bm)
Her seviyede oyun durumunun saklanması gerekir
Yinelemeli derinleştirme ile optimize edilebilir
Değerlendirme fonksiyonu
Terminal olmayan durumlar için değerlendirme fonksiyonu f(s) şunları sağlamalıdır:
Kazanma olasılığıyla ilişkili olmalı
Hesaplama açısından verimli olmalı
Oyun boyunca tutarlı bir ölçeklendirme sürdürmeli
Biçimsel tanım:
f(s) = w₁x₁ + w₂x₂ + ... + wₙxₙ
Burada:
wᵢ farklı özellikler için ağırlıklardır
xᵢ oyun durumundan elde edilen özellik değerleridir
n, değerlendirilen özelliklerin sayısıdır
Optimalite garantisi
Minimax algoritması şu koşullar altında optimal oyunu garanti eder:
Mükemmel bilgi
Deterministik sonuçlar
Terminal durumlara kadar eksiksiz arama
Doğru terminal durum değerlendirmesi
Bu da onu, bu koşulların sağlandığı satranç, XOX ve dama gibi oyunlar için özellikle uygun kılar.
Gelişmiş Varyasyonlar ve Sınırlamalar
Minimax, XOX gibi basit oyunlar için harikadır; ancak daha büyük oyunlarda bazı sorunları vardır. Nasıl hızlandırılabileceğine ve nerelerde zorlandığına bakalım.
Minimax’i hızlandırmak: Alfa-beta budama
Satranç oynarken hamlelerinizi düşünün. Kazandıran bir hamle bulduysanız, diğer tüm olası hamleleri incelemeniz gerekmez, değil mi? Alfa-Beta Budama da aynı şekilde çalışır — bulduğumuzdan daha iyi olmayacağını bildiğimiz hamleleri kontrol etmeyi atlamaya yardımcı olur.
Şöyle düşünün:
En ucuz çikolatayı arıyorsunuz
Harcamak için 1$’ınız var
50¢’lik bir çikolata bulursanız, 1$’dan pahalı olanların hiçbirine bakmanıza gerek yok
Bu da size zaman kazandırır!
Derinlik sınırları: Fazla ileriye bakmamak
Satranç gibi büyük oyunlarda tüm olası hamleleri kontrol etmek için çok fazla olasılık vardır. Bu nedenle bir derinlik sınırı ekleriz:
Oyunun sonuna kadar değil, yalnızca 4–5 hamle öteye bakın
O noktadaki konumun ne kadar iyi olduğuna dair iyi bir tahmin yapın
Bu tahminlere göre en iyi hamleyi seçin
Oyunun sonuna kadar tüm hamleleri planlayamazsınız; ama birkaç hamleyi önden planlayabilirsiniz!
Minimax’in zorlandığı yerler
Minimax kusursuz değildir. Başlıca sorunları şunlardır:
1. Fazla seçenek
Go gibi oyunlarda aşırı sayıda olası hamle vardır
Hızlı bilgisayarlar bile hepsini kontrol edemez
Bu yüzden çok karmaşık oyunlar için başka yöntemlere ihtiyaç duyarız
2. Zaman sorunları
Ne kadar fazla hamleyi önden incelerseniz, o kadar uzun sürer
Satrançta bilgisayarlar her olası hamleyi inceleyemez
Hangi hamlelerin kontrol edileceği konusunda akıllı davranmaları gerekir
3. Belirsiz oyunlar için uygun değil
Minimax, her şeyi görebildiğiniz durumlarda en iyi çalışır
Diğerlerinin hangi kartlara sahip olduğunu bilmediğiniz kart oyunları için uygun değildir
Zar atışı gibi rastgele olayları iyi yönetemez
Modern çözümler
Günümüzün oyun yapay zekâları sıklıkla Minimax’i başka yöntemlerle birleştirir:
1. Makine öğrenimi
Bilgisayarlar çok sayıda oyunu izleyerek öğrenebilir
Bu da iyi hamleler hakkında daha iyi tahminler yapmalarını sağlar
AlphaGo gibi oyunlar, insan şampiyonları yenmek için bunu kullanır
2. Örüntü tanıma
Her hamleyi kontrol etmek yerine örüntülere bakın
Tıpkı insanların iyi hamleleri tanıması gibi
Bu, bilgisayarı çok daha hızlı yapar
3. Bellek bankası
Daha önce görülen konumları hatırlayın
Aynı şeyi iki kez hesaplayarak zaman kaybetmeyin
İyi hamleler için bir “ipuçları kâğıdı”na sahip olmak gibi!
En güzel yanı? Bu iyileştirmeler, bilgisayarların oyunları insanlar kadar iyi, hatta bazen daha iyi oynamasına yardımcı olur! Ama unutmayın — tüm bu gelişmiş eklemelere rağmen, Minimax hâlâ her şeyin temelini oluşturan yöntemdir.
Sonuç
Bu eğitimde, Minimax algoritmasını temel kavramlarından pratik uygulamaya kadar inceledik. Öğrendiklerimiz:
1. Temel kavramlar
Minimax’in bilgisayarların oyunlarda karar vermesine nasıl yardımcı olduğu
Minimize eden ve maksimize eden oyuncu arasındaki fark
Neden “minimax” olarak adlandırıldığı ve nasıl çalıştığı
2. Uygulama becerileri
Sıfırdan bir XOX oyunu geliştirme
Python’da Minimax algoritmasını yazma
Oyun mantığını test etme ve hata ayıklama
3. İleri konular
Algoritmayı Alfa-Beta Budama ile hızlandırma
Karmaşık oyunlardaki sınırlamaları ele alma
Makine öğrenimi ile modern iyileştirmeler
Sırada ne var?
Minimax algoritması, yapay zekâ bulmacasının yalnızca bir parçasıdır. Yapay zekâ ve algoritmalar hakkında daha fazla öğrenmek istiyorsanız, yolculuğunuza devam etmek için harika kaynaklar burada:
Unutmayın, ister basit bir oyun ister karmaşık bir YZ sistemi geliştiriyor olun, Minimax gibi algoritmaları anlamak yapay zekâda daha ileri konular için güçlü bir temel sağlar. Pratik yapmaya, öğrenmeye ve en önemlisi kod yazmaya devam edin!
Minimax Algoritması SSS
Minimax algoritmasını anlamak ve uygulamak ne kadar zor?⌄
Minimax algoritması, özellikle XOX gibi basit oyunlar için uygulandığında anlaşılması görece kolaydır. Özyineleme kavramı yeni başlayanlar için zorlayıcı olabilir; ancak hamleleri sırayla maksimize etme ve minimize etme fikri sezgiseldir. Bu eğitim, uygulamayı yönetilebilir adımlara ayırarak temel Python bilgisine sahip programcılar için erişilebilir kılar.
Bu algoritmayı XOX dışında başka oyunlarda da kullanabilir miyim?⌄
Evet, Minimax algoritması, Satranç, Dama veya Connect Four gibi mükemmel bilgiye sahip iki oyunculu, sıfır toplamlı birçok oyuna uyarlanabilir. Ancak daha karmaşık oyunlar için, olası hamle sayısı katlanarak arttığından Alfa-Beta budama ve derinlik sınırlama gibi ek optimizasyonları uygulamanız gerekir.
YZ XOX’ta nasıl oluyor da hiç kaybetmiyor?⌄
Minimax algoritması, tüm olası gelecek oyun durumlarını simüle ederek ve en iyi sonuca götüren hamleleri seçerek çalışır. XOX gibi basit bir oyunda, olası hamle sayısı görece azdır; bu da YZ’nin her durumda en iyi hamleyi hesaplamasına olanak tanır. XOX “çözümlenmiş bir oyun” olduğundan, iki taraf da kusursuz oynarsa oyun her zaman berabere biter; bu yüzden YZ asla kaybetmez.
Bu eğitimi takip etmek için önceden hangi bilgileri bilmeliyim?⌄
Temel Python programlama bilgisine sahip olmalısınız, bunlar dahil:
Fonksiyonlar ve sınıflar hakkında anlayış
Listeler ve temel veri yapılarıyla aşinalık
Temel kontrol akışı (if ifadeleri, döngüler)
Özyineleme bilgisi faydalıdır ancak şart değildir; eğitim bu kavramı açıklar.
Bu algoritma YZ geliştirme için neden önemlidir?⌄
Minimax algoritması, oyun kuramını ve yapay zekâda karar vermeyi anlamanın temelidir. Özyinelemeli ağaç araması, karşıt düşünme ve mükemmel bilgi altında optimal karar verme gibi önemli kavramları tanıtır. Bu ilkeler; oyun oynamadan stratejik planlama ve karar destek sistemlerine kadar modern uygulamalarda kullanılan daha gelişmiş YZ algoritmalarının temelini oluşturur.
Algoritmalar, sistem tasarımı ve davranışsal senaryoları kapsayan bu temel sorularla teknik mülakat sürecine hakim olun. Uzman cevapları, kod örnekleri ve kanıtlanmış hazırlık stratejileri edinin.
Git deponuzu temiz tutmak için .gitignore’u nasıl kullanacağınızı öğrenin. Bu eğitim; temelleri, yaygın kullanım durumlarını ve başlamanıza yardımcı olacak pratik örnekleri kapsar!
Yapay zekanın temellerini keşfedin, yapay zekayı işinizde etkili bir şekilde kullanmayı öğrenin ve dinamik yapay zeka dünyasında yolunuzu bulmak için ChatGPT gibi modellere dalın.
Mini-Max algoritması, 1920’lere uzanan zengin bir yapay zekâ geçmişine sahiptir. O dönemde bilgisayar algoritmaları için “yapay zekâ” terimi kullanılmasa da, bu temel algoritma, makinelerin çekişmeli senaryolarda nasıl en iyi kararları verebileceğine dair en erken içgörüleri sağlamıştır. Algoritma ilk olarak John von Neumann tarafından 1928 tarihli “Zur Theorie der Gesellschaftsspiele” (Strateji Oyunları Kuramı Üzerine) makalesinde resmileştirilmiş ve modern oyun kuramı ile karar verme algoritmalarının temelini atmıştır.
1997’de IBM’in Deep Blue’su, Mini-max’in gelişmiş varyantlarını kullanarak dünya satranç şampiyonu Garry Kasparov’u yendi. O zamandan beri algoritma, Monte Carlo Ağaç Araması (MCTS) ve pekiştirmeli öğrenme gibi daha sofistike yaklaşımların belkemiği olmuştur.
Bu yazıda, satranç için ünlü Deep Blue’yu yeniden inşa etmeyeceğiz; bunun yerine Python’da çok daha basit bir sürüm olan XOX için bir versiyon geliştireceğiz. Bu süreçte, algoritmanın nasıl çalıştığına ve onu daha karmaşık gerçek dünya oyunlarına nasıl uygulayacağınıza dair güçlü bir sezgi kazanacaksınız.
Minimax Algoritması Nedir?
Minimax genellikle iki oyunculu oyunlar (satranç, XOX veya dama gibi) için bir karar verme algoritmasıdır. Bilgisayarların, rakibinizin her zaman mümkün olan en iyi hamleyi yapacağını varsayarak birkaç hamleyi önden planlamasını sağlar. Bu bölümde, algoritmaya XOX örneği üzerinden genel bir bakış atacağız.
Minimax algoritmasına genel bakış
Gerçek bir XOX oyununda, sıra size geldiğinde en iyi hamleyi yapmaya çalışır ve rakibinizin de en iyi oyunu oynayacağını varsayarsınız. Minimax algoritması tam olarak bunu yapar — bilgisayarın tüm olası hamleleri önden düşünerek yapabileceği en iyi hamleyi bulmasına yardımcı olur.
Minimax adı, çalışma biçiminden gelir:
Sıra sizdeyken, size kazanma şansı en yüksek hamleleri yapmak istersiniz (maksimizasyon). Sıra rakibinizdeyken, size en kötü sonucu getirecek hamleleri yapacağını varsayarsınız (minimizasyon).
Yapay zekâda Minimax’in önemi
Minimax, yapay zekâda çeşitli nedenlerle son derece önemlidir:
En güzel yanı? Aynı fikir, gerçek dünyadaki birçok uygulamada da kullanılır:
Minimax kulağa karmaşık gelse de, aslında bir bilgisayara karar vermeden önce hem kendi hamlelerini hem de rakibinin hamlelerini dikkate alan dikkatli bir oyuncu gibi düşünmeyi öğretmektir.
Minimax Algoritmasını Anlamak
Minimax’in nasıl çalıştığını basit bir XOX örneğiyle adım adım inceleyelim. Siz X, bilgisayar ise O olarak oynuyor olun.
Bilgisayar nasıl düşünür
Sıra bilgisayara geldiğinde şu adımları izler:
Oyunu puanlamak
Bilgisayar basit bir puanlama sistemi kullanabilir:
Bunu bir olasılıklar ağacı gibi düşünün:
Sıra değişimi
Bilgisayar iki düşünme modu arasında geçiş yapar:
1. Maksimizasyon modu (bilgisayarın sırası):
2. Minimizasyon modu (oyuncunun sırası):
Basit bir örnek
Diyelim ki oyunda sıra bilgisayarda (X):
Bilgisayar şunları yapacaktır:
Bu önden düşünme biçimi, bilgisayarın her seferinde kusursuz bir XOX oyunu oynamasına yardımcı olur!
Minimax Algoritması Sözde Kod
Minimax algoritmasını adım adım nasıl yazacağımızı inceleyelim. Sözde koda yeniyseniz endişelenmeyin — onu, gerçek koda dönüştürmeden önce adımları sade bir dille yazmak gibi düşünebilirsiniz!
Adım adım açıklama
Minimax fonksiyonunun çalışması için üç temel şeye ihtiyacı vardır:
Temel sözde kod şu şekildedir:
Çoğu sözde kod örneği İngilizce okunur ve gayet anlaşılırdır; ancak yukarıdaki örnek, özyineleme (recursion) kullandığı için biraz farklıdır. Özyineleme, bir fonksiyonun daha büyük bir problemi çözmek için kendisini tekrar tekrar çağırmasıdır. Bir aynanın başka bir aynayı yansıtmasına bakmak gibidir — aynı görüntüyü birçok kez, her seferinde küçülerek görürsünüz.
Minimax algoritmamızda özyineleme gerekir; çünkü oyundaki tüm olası gelecek hamleleri incelemeye çalışıyoruz. Fonksiyon her kendini çağırdığında, bir sonraki olası hamleyi değerlendirir.
Bu, oyunun tüm olası gidişatlarını kontrol ederek en iyi hamleyi bulmamıza yardımcı olur; tıpkı “Ben bunu yaparsam, o şunu yapar, sonra ben bunu yaparım…” diye düşünen çok akıllı bir oyuncu gibi, oyun bitene kadar devam eder. Özyineleme hakkında daha fazla bilgi için ayrı özyineleme eğitimimize bakabilirsiniz.
Örnekleyici açıklama
Basit bir oyun durumunda bunun nasıl çalıştığını görelim:
1. Başlangıç Konumu:
2. Bilgisayar düşünür:
3. Her boş alan için bilgisayar:
Bunu satranç gibi düşünün — hep “Ben buraya gidersem, o şuraya gider, sonra ben buraya…” diye düşünürsünüz; ancak bilgisayar TÜM olası hamleleri aynı anda düşünebilir!
Bu algoritmanın güzel yanı, her iki tarafın da kusursuz oynadığı varsayımı altında her zaman mümkün olan en iyi hamleyi bulmasıdır. Oyunun tüm olası geleceklerini gösteren bir kristal küreye sahip olmak gibi!
XOX için Minimax’i Adım Adım Uygulama
Bu bölümde, saf Python ile Mini-max algoritması tarafından güçlendirilen yenilmez bir XOX yapay zekâsı oluşturacağız. Uygulamayı basit adımlara bölecek, her birinin arkasındaki sezgiyi ve oyunun büyük resmindeki yerini açıklayacağız.
Adım 1: TicTacToe sınıfını tanımlama
Önce, bilgisayarımızla bir XOX oyunu oynamak için ihtiyaç duyduğumuz tüm mantık ve yöntemleri içeren bir sınıf tanımlıyoruz:
Yukarıda,
__init__metodu, 9 boş alandan (" " boşlukla temsil edilir) oluşan yeni bir oyun tahtası başlatır; 0–8 indeksleri soldan sağa, yukarıdan aşağıya tahta konumlarını temsil eder. Ayrıca iki oyuncu sembolünü belirler — insan oyuncu için "O", yapay zekâ için "X".print_boardmetodu, tahtanın mevcut durumunu görselleştirmenin bir yolunu sunar. Her oyuncunun hamlesini ilgili konumlarda göstererek satırlar arasında bölücü çizgilerle 3x3 ızgarayı yazdırır.available_movesmetodu, hâlâ yapılabilecek tüm geçerli hamlelerin bir listesini döndürür. Bunu, tahtadaki hangi konumların hâlâ boş (" ") olduğunu kontrol ederek ve indekslerini döndürerek yapar. Bu, minimax algoritmasının hangi hamleleri değerlendirebileceğini bilmesi açısından kritik olacaktır.Bu yöntemler, minimax algoritmasını kullanarak yapay zekâ oyuncumuzu oluşturmak için üzerine inşa edeceğimiz temeli oluşturur.
Hızlıca test edelim:
Beklendiği gibi, şu anda tahta boş ve tüm hamleler mevcut.
Adım 2: Hamle yapma ve tahta durumlarını kontrol etme yöntemlerini uygulama
Şimdi, bir hamle yapma yöntemi ekleyelim:
make_movemetodunu ekledik; bu yöntem:Birkaç hamle yapalım ve kalan hamleleri kontrol edelim:
Gayet iyi çalışıyor. Sıradaki adım, tahtanın dolu olup olmadığını kontrol eden bir yöntem eklemek:
is_board_full, tahtada hiç boş alan kalıp kalmadığını kontrol eden bir boole yöntemidir.Sırada, bir kazanç durumu oluşup oluşmadığını kontrol eden bir yöntem eklemek var:
check_winnermetodu, XOX tahtasının mevcut durumunu değerlendirerek bir kazanan olup olmadığını belirler. Tüm olası kazanma kombinasyonlarını kontrol eder:1. Satırlar (3 olasılık):
2. Sütunlar (3 olasılık):
3. Çaprazlar (2 olasılık):
Her kombinasyon için, üç konumun da aynı oyuncu sembolünü (X veya O) içerip içermediğini ve boş olmadığını kontrol eder. Bir kazanma kombinasyonu bulunursa, kazanan oyuncunun sembolünü döndürür. Tüm olasılıklar kontrol edildikten sonra kazanan yoksa None döner.
Fonksiyonu, kazanç ve kazanç olmayan durumlarda test edelim:
Son olarak, oyunun bitip bitmediğini belirtmek için başka bir boole yöntemi ekleyelim:
Bu yöntem, ya bir kazanan bulunduğunda ya da tahta dolu olduğunda True döndürür.
Bu noktada, tüm temel oyun mekaniğini oluşturduk:
print_board()mevcut oyun durumunu görsel olarak gösteriravailable_moves()boş karelerin indekslerini döndürürmake_move()oyuncunun sembolünü tahtaya yerleştirircheck_winner()her hamlede satırları, sütunları ve çaprazları kazanç için inceleris_board_full()hamle kalıp kalmadığını belirlergame_over()kazanan kontrolü ile tahta dolu kontrolünü birleştirirBu yöntemler, hamle yapma ve oyun durumunu belirleme gibi tüm temel işlemleri ele alarak oynanabilir bir oyun için gereken temeli sağlar.
Şimdi kritik kısma geliyoruz — bilgisayara Minimax ile “zeka” kazandırmak.
Adım 3: XOX için Minimax’i uygulama
Şimdi, algoritmayı oyuna yeni bir yöntem olarak uygulayalım:
Fonksiyon iki parametre alır:
depth— Özyinelemede kaç seviye derine indiğimizi takip eder. Çok karmaşık oyunlar için arama derinliğini sınırlamakta kullanılabilir; ancak XOX için sınırlamaya gerek yoktur.is_maximizing— Şu anda maksimum puanı (YZ’nin sırası) mı yoksa minimum puanı (insanın sırası) mı aradığımızı belirten boole bayrağıdır. Oyuncular sıra aldıkça her özyinelemeli çağrıda bu değer değişir.Fonksiyon gövdesinde, temel durumları tanımlayarak başlarız: Oyun YZ tarafından kazanılmışsa (
winner == ai_player), YZ için en iyi sonuç olduğundan 1 döndürürüz. İnsan kazanırsa (winner == human_player), YZ için en kötü sonuç olduğundan -1 döndürürüz. Tahta dolu ve kazanan yoksa, beraberlik için 0 döndürürüz.is_maximizingTrue olduğunda YZ’nin sırasını simüle ederiz ve en yüksek puana götüren hamleyi bulmak isteriz. best_score’u eksi sonsuza ayarlarız ki gerçek herhangi bir puan daha iyi olsun. Ardından her mevcut hamle için:is_maximizing=Falseile minimax çağırarak özyinelemeli değerlendiririz (çünkü sıradaki hamle insanındır)max()ile takip ederizBu, YZ’nin yapabileceği her olası hamleyi kontrol etmemizi sağlar. Her hamle için, birinin kazanmasına ya da oyunun berabere bitmesine kadar neler olabileceğine bakarız. Ardından geriye doğru çalışarak ilk hamlelerden hangisinin YZ’ye en iyi kazanma şansını verdiğini buluruz.
Şimdi, insan için minimize etme kısmını yapalım:
is_maximizingFalse olduğunda, insan oyuncunun sırasını simüle ederiz ve en düşük puana götüren hamleyi bulmak isteriz (çünkü yüksek puan YZ’nin kazanması demektir).best_score’u artı sonsuzla başlatırız ki gerçek herhangi bir puan daha düşük olsun. Her mevcut hamle için:is_maximizing=Trueile minimax çağırarak özyinelemeli değerlendiririz (çünkü sıradaki hamle YZ’nindir)min()ile takip ederizBu, insan oyuncunun YZ’nin kazanmasını önlemek için en iyi hamleleri yapmaya çalışmasını simüle eder. İnsan, puanları en aza indirmek ister; çünkü pozitif puanlar YZ zaferlerini temsil eder. Maksimizasyon ve minimizasyon turları arasında dönüşümlü ilerleyerek algoritma, her iki oyuncu için de en iyi hamle dizisini belirleyebilir.
Adım 4: Minimax ile YZ için en iyi hamleyi bulma
Artık algoritma hazır olduğuna göre, her insan hamlesinden sonra YZ için en iyi hamleyi belirlemek üzere
minimaxyöntemini kullanan başka bir yönteme ihtiyacımız var:get_best_move yöntemi, minimax algoritmasını kullanarak YZ oyuncusu için en uygun hamleyi belirlemekten sorumludur. Şöyle çalışır:
1. En iyi puan olarak eksi sonsuz ve seçili bir hamle olmadan başlar
2. Tahtadaki her mevcut hamle için:
3. Son olarak en yüksek puana yol açan hamleyi döndürür
Bu yaklaşım, insan oyuncunun da en iyi şekilde oynadığı varsayımı altında, YZ’nin kendisine en iyi kazanma şansını veren hamleyi seçmesini sağlar. Yöntem, tüm olası gelecek oyun durumlarını dikkate alır ve YZ’nin şansını maksimize ederken insanın kazanma şansını en aza indiren yolu seçer.
Bunu örnek bir oyun durumunda test edelim:
Gördüğünüz gibi, YZ benim hamlelerime göre kazanan kombinasyonu buldu (örnek durumdu ama algoritmamızın çalıştığını kanıtlıyor).
Adım 5: Bir oyun döngüsü uygulama
Artık minimax algoritmamızı uygulayıp test ettiğimize göre, YZ’ye karşı oynamamıza olanak tanıyan bir oyun döngüsü oluşturalım.
play_game metodu, bir karşılama mesajı ve oyuncuya yönelik talimatları göstererek başlar. İnsan oyuncunun ‘O’, YZ’nin ise ‘X’ kullandığını belirtir. Ardından, oyuncuya tahtadaki hangi konumun hangi sayıya karşılık geldiğini göstermek için numaralandırılmış bir ızgara (0–8) yazdırır. Bu, oyuncuların istedikleri hamle için doğru sayıyı girmelerini kolaylaştırır.
Başlangıç talimatlarını gösterdikten sonra oyun ana döngüsüne girer. Oyun, her oyunun başında adil ve öngörülemez bir başlangıç oluşturmak için
random.choice([True, False])kullanarak ilk kimin oynayacağına (YZ ya da insan) rastgele karar verir.Ana oyun döngüsü,
game_over()True dönene kadar (biri kazanır ya da tahta dolar) devam eder. Her turda,print_board()ile tahtanın mevcut durumu gösterilir.Eğer sıra YZ’deyse (
ai_turnTrue ise), program:get_best_move()çağrısıyla minimax algoritmasını kullanarak en uygun hamleyi belirlerSıra insandaysa (
ai_turnFalse ise), program:1. Oyuncudan geçerli bir girdi almak için bir döngüye girer2. 0–8 arasında bir hamle numarası ister3. Girdiyi doğrular:
4. Geçerli giriş alınana kadar sormaya devam eder. Seçilen konuma oyuncunun sembolünü (‘O’) yerleştirerek hamleyi yapar
ai_turn, her turdan sonranotkullanılarak tersine çevrilir ve oyuncular arasında sırayla ilerlenir. Bu, biri kazanana ya da oyun berabere bitene kadar oyunun karşılıklı ilerleyişini sağlar.Girdi doğrulaması, geçersiz kullanıcı girdilerinin oyunu çökertmesini engeller ve oyuncuyu doğru hamleleri girmeye yönlendiren faydalı hata mesajları sağlar. Bu da sağlam ve kullanıcı dostu bir oyun deneyimi yaratır.
Oyun bittiğinde,
print_board()ile son tahta durumu gösterilir vecheck_winner()ile kazanan belirlenir. Oyun üç şekilde bitebilir:check_winner()YZ’nin sembolünü (‘X’) döndürürse, YZ’nin bir kazanç hattı elde ettiği anlamına gelircheck_winner()insanın sembolünü (‘O’) döndürürse, oyuncunun bir kazanç hattı elde ettiği anlamına gelirOyun sonucunu duyurmak için uygun mesaj gösterilir. Böylece oyunun nasıl sonuçlandığı oyuncuya net biçimde bildirilir.
Adım 6: Her şeyi bir araya getirmek
Şimdiye kadar yazdığımız tüm kodu, en sonda aşağıdaki if/main koşuluyla birlikte bir Python betiğine koyma zamanı:
Bu, betiği python script.py ile çalıştırdığınız anda oyunun başlamasını sağlar. Tüm açıklamalar ve kod blokları arasında kaybolduysanız, oyunun tam kodunu bu GitHub gist’inde bulabilirsiniz.
İşte oynadığım örnek bir oyun:
Unutmayın, XOX basit bir oyun olduğundan YZ’yi yenme şansı yoktur. Oyun ya berabere biter ya da kaybedersiniz!
Mini-max Algoritmasını Biçimselleştirme
Şimdi, basit XOX örneğinin ötesinde algoritmanın genel tanımını gözden geçirelim.
Minimax algoritması, sıfır toplamlı bir oyundaki konumları değerlendiren özyinelemeli bir fonksiyon olarak biçimsel şekilde tanımlanabilir. Biçimsel bileşenlerini ve özelliklerini inceleyelim.
Matematiksel tanım
Bir oyun durumu
siçin minimax değeriV(s)şu şekilde tanımlanır:Burada:
Temel özellikler
1. Mükemmel bilgi
2. Sıfır toplamlı yapı
3. Optimal oyun
Karmaşıklık analizi
Zaman karmaşıklığı: O(b^m)
Uzay karmaşıklığı: O(bm)
Değerlendirme fonksiyonu
Terminal olmayan durumlar için değerlendirme fonksiyonu f(s) şunları sağlamalıdır:
Biçimsel tanım:
f(s) = w₁x₁ + w₂x₂ + ... + wₙxₙ
Burada:
Optimalite garantisi
Minimax algoritması şu koşullar altında optimal oyunu garanti eder:
Bu da onu, bu koşulların sağlandığı satranç, XOX ve dama gibi oyunlar için özellikle uygun kılar.
Gelişmiş Varyasyonlar ve Sınırlamalar
Minimax, XOX gibi basit oyunlar için harikadır; ancak daha büyük oyunlarda bazı sorunları vardır. Nasıl hızlandırılabileceğine ve nerelerde zorlandığına bakalım.
Minimax’i hızlandırmak: Alfa-beta budama
Satranç oynarken hamlelerinizi düşünün. Kazandıran bir hamle bulduysanız, diğer tüm olası hamleleri incelemeniz gerekmez, değil mi? Alfa-Beta Budama da aynı şekilde çalışır — bulduğumuzdan daha iyi olmayacağını bildiğimiz hamleleri kontrol etmeyi atlamaya yardımcı olur.
Şöyle düşünün:
Derinlik sınırları: Fazla ileriye bakmamak
Satranç gibi büyük oyunlarda tüm olası hamleleri kontrol etmek için çok fazla olasılık vardır. Bu nedenle bir derinlik sınırı ekleriz:
Oyunun sonuna kadar tüm hamleleri planlayamazsınız; ama birkaç hamleyi önden planlayabilirsiniz!
Minimax’in zorlandığı yerler
Minimax kusursuz değildir. Başlıca sorunları şunlardır:
1. Fazla seçenek
2. Zaman sorunları
3. Belirsiz oyunlar için uygun değil
Modern çözümler
Günümüzün oyun yapay zekâları sıklıkla Minimax’i başka yöntemlerle birleştirir:
1. Makine öğrenimi
AlphaGogibi oyunlar, insan şampiyonları yenmek için bunu kullanır2. Örüntü tanıma
3. Bellek bankası
En güzel yanı? Bu iyileştirmeler, bilgisayarların oyunları insanlar kadar iyi, hatta bazen daha iyi oynamasına yardımcı olur! Ama unutmayın — tüm bu gelişmiş eklemelere rağmen, Minimax hâlâ her şeyin temelini oluşturan yöntemdir.
Sonuç
Bu eğitimde, Minimax algoritmasını temel kavramlarından pratik uygulamaya kadar inceledik. Öğrendiklerimiz:
1. Temel kavramlar
2. Uygulama becerileri
3. İleri konular
Sırada ne var?
Minimax algoritması, yapay zekâ bulmacasının yalnızca bir parçasıdır. Yapay zekâ ve algoritmalar hakkında daha fazla öğrenmek istiyorsanız, yolculuğunuza devam etmek için harika kaynaklar burada:
1. İlgili Algoritmalar
2. Makine Öğrenimi Uygulamaları
3. Tam Öğrenim Yolları
Unutmayın, ister basit bir oyun ister karmaşık bir YZ sistemi geliştiriyor olun, Minimax gibi algoritmaları anlamak yapay zekâda daha ileri konular için güçlü bir temel sağlar. Pratik yapmaya, öğrenmeye ve en önemlisi kod yazmaya devam edin!