2012-11-20 13 views
9

Java'da bir oyun için bir minimax algoritması yazıyorum ve hız amaçları için, karar ağacında yinelemeli olarak çalışırken oyun durumunu mutasyona sokuyorum. Ancak, bu, üzerinde yinelemeye başladığım hamlelerin listesini değiştirmeyi içerir.Her yinelemeden sonra özgün durumuna dönerse, yinelemeyi sürdürdüğüm bir diziyi güvenli bir şekilde değiştirebilir miyim?

public int minimax(int currentDepth) { 
    if (currentDepth == depth || board.legalMoves.isEmpty()) { 
     int eval = board.eval(); 
     board.takeBack(1); 
     return eval; 
    } 
    int x = Integer.MIN_VALUE; 
    for (Tuple move : board.legalMoves) { 
     board.move(move); 
     x = max(x, -1*minimax(currentDepth+1)); 
     board.takeBack(1); 
    } 
    return x 
} 

board.move() yöntem ArrayList legalMoves mutasyona uğrar, fakat takeBack(1) geri orijinal haline getirir. Bu herhangi bir soruna neden olabilir mi?

+0

Sadece umulan ağacın üzerinden birden fazla iş parçacığınız yok ... – Reactormonk

+1

Neden burada bir döngü kullanıyorsunuz? Metodu döndürdüğünüz için * asla * başlangıç ​​öğesinin ötesine geçmez. – Vulcan

+1

Yukarıda adı geçen "dönüş" de "board.takeBack (1)" işlevini, sorgunun amacını bir şekilde öldüren ölü kod olarak gösterir. – Vulcan

cevap

5

Tek kelimeyle, evet.

board.legalMoves türünü belirtmezsiniz. Dizinin bu olduğunu söylüyorsun, ama olamazsın, çünkü ona isEmpty() diyorsun. Bu nedenle, ArrayList anlamına geldiğinden şüpheleniyorum. Eğer durum buysa, documentation oldukça açıktır: bu sınıfın iterator ve listIterator yöntemlerle döndü

yineleyiciler başarısız hızlı gibidir: Liste yapısal herhangi bir zamanda değiştirilirse yineleyici hiçbir şekilde oluşturulduktan sonra Yineleyicinin kendi remove veya add yöntemlerinden farklı olarak, yineleyici bir ConcurrentModificationException atar. Bu nedenle, eşzamanlı modifikasyon karşısında, iteratör, gelecekte belirsiz bir zamanda keyfi, deterministik olmayan davranışları riske atmak yerine, hızlı ve temiz bir şekilde başarısız olur.

1) yapısal değişiklikler kaçının:

Bu etrafında iki yol görüyoruz. Başka bir deyişle, öğelerin değerlerini değiştirmek için Tamam, ancak öğeleri eklemek/kaldırmak için Tamam değil.

2) Bıkmadan ArrayList üzerinde kullanarak endeksleri:

for (int i = 0; i < board.legalMoves.size(); i++) { 
    Tuple move = board.get(i); 
    ... 
} 
+0

Argh, bundan korkuyordum. Bunun etrafında bir yolu var mı? Algoritmanın her yinelemesi için dizi listesini klonlamamayı tercih ederim; Bunun önemli ölçüde yavaşlayacağını düşünüyorum ... – mavix

+0

Yapmanız gereken tam değişikliklere bağlı.Eğer listeyi * yapısal olarak değiştirmezseniz, OK olmalısınız (yapısal modifikasyonu neyin oluşturduğuna dair bir açıklama için Javadoc'a bakın). – NPE

+1

Hmm, belki bir bağlantı listesi kullanabilirim ve while (currentNode.hasNext) ... – mavix

0

Evet, yapabilirsin ama tehlikeli. Minmax algoritmasını yeni bir sınıfa taşımayı ve veriyi yapıcıya analiz etmek için aktarmayı öneririm.

Artık verisini kurucuya kopyalayabilir ve yöntemler kopya üzerinde çalışabilir. Algoritma, verileri istediği şekilde değiştirebilir, oyunun diğer bölümlerini veya diğer konuları etkilemez. Ayrıca, herhangi bir probleminiz varsa, bir sınıftaki koddan gelmeleri gerekir. Genel amaç, kodun her bir değiştirici kısmının, sorunlara neden olabilecek bağımlılıkları kesmek için ihtiyaç duyduğu verilerin bir kopyasını vermektir.

İlgili konular