2017-05-12 51 views
0

我正在使用java的freecell solitaire求解器,我遇到了問題。我的求職者似乎工作正常,但運行後我沒有得到我期待的答案。我重新編程了兩次,從頭開始,似乎問題是某些卡正在消失,同時創建新狀態freecell solitare人工智能

這是一個深度優先算法和卡(或2在某些情況下),如果最後狀態產生(當前正在創建一個前)只消失了深度相同或更低。我用我的算法的一部分發布我的狀態類(只有兩種類型的動作可用:堆棧到基礎和堆棧到空閒單元)。

搜索在「父」狀態的構造函數內部運行。如果可以,請提供幫助,因爲卡片消失只能由魔術師在您面前而不是您的計算機上進行遊戲。

這是我的代碼。

import java.util.ArrayList; 

public class State { 

public static ArrayList<State> stateHistory = new ArrayList<State>(); // containing all the states met so far, used to avoid duplicates and endless loops 

public static State bestReached = null; // this state is used to print the best state reached 

// unique elements of the state 
ArrayList<ArrayList<Card>> stackList = new ArrayList<ArrayList<Card>>(); 
ArrayList<ArrayList<Card>> foundationList = new ArrayList<ArrayList<Card>>(); 
ArrayList<Card> freecellList = new ArrayList<Card>(); 
ArrayList<String> previousMoves = new ArrayList<String>(); 
State parent = null; 
int depth; 

// elements used for new state creation 

protected ArrayList<ArrayList<Card>> tempStackList = new ArrayList<ArrayList<Card>>(); 
protected ArrayList<ArrayList<Card>> tempFoundationList = new ArrayList<ArrayList<Card>>(); 
protected ArrayList<Card> tempFreecellList = new ArrayList<Card>(); 
protected Card tempCard; 
protected String tempLastMove = null; 

public State(State s) { 
    this.stackList = s.stackList; 
    this.foundationList = s.foundationList; 
    this.freecellList = s.freecellList; 
} 

public State(ArrayList<ArrayList<Card>> stack, ArrayList<ArrayList<Card>> found, ArrayList<Card> free) { 
    this.stackList = stack; 
    this.foundationList = found; 
    this.freecellList = free; 
    System.out.println("Just created a State successfully!"); 
} 

//the following constructor only works for Depth First search 
public State(ArrayList<ArrayList<Card>> xCardLists, ArrayList<ArrayList<Card>> xFoundationList, ArrayList<Card> xFreecells, ArrayList<String> xPreviousMoves, String xLastMove, State xParent, int xDepth, boolean xIsDepthFirst) { 

    // setting the elements 
    this.stackList = new ArrayList<ArrayList<Card>>(xCardLists); 
    this.foundationList = new ArrayList<ArrayList<Card>>(xFoundationList); 
    this.freecellList = new ArrayList<Card>(xFreecells); 
    if (xPreviousMoves != null) { 
     this.previousMoves = new ArrayList<String>(xPreviousMoves); 
    } 
    if (xLastMove != null) { 
     this.previousMoves.add(xLastMove); 
    } 
    this.parent = xParent; 
    this.depth = xDepth; 

    // checking if it's the best state reached 

    checkIfBestReached(); 

    if (parent != null && parent.totalStateCards() > this.totalStateCards()) { 
     System.out.println(" - ! - WARNING: Cards have been lost! -> Before: " + parent.totalStateCards() + ", Now: " + totalStateCards() + ", Last Move: " + xLastMove); 
    } 

    // delay between state creations for easier error monitoring 

    try { 
     Thread.sleep(2); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    String allPrevious = ""; 

    for (String move : previousMoves) { 
     allPrevious += move + ", "; 
    } 

    // checking the state history and moving on 

    if (shouldHaveChildren() == false) { 
     System.out.println(this.depth + "-> BAD: (total card count: " + totalStateCards() + ", last moves: " + allPrevious + ")"); 
    } else { 

     System.out.println(this.depth + "-> GOOD: (total card count: " + totalStateCards() + ", last moves: " + allPrevious + ")"); 

     // checking for stack to foundation moves 

     for (ArrayList<Card> alc : stackList) { 

      if (alc.isEmpty() == false) { 

       tempCard = alc.get(alc.size()-1); // creating a pointer with the card that is currently being checked 

       if (tempCard.value == GUI.maxN) { 

        // creating the required ArrayLists 
        tempStackList = new ArrayList<ArrayList<Card>>(stackList); 
        tempFoundationList = new ArrayList<ArrayList<Card>>(foundationList); 
        tempFreecellList = new ArrayList<Card>(freecellList); 

        // moving the card 
        tempFoundationList.get(tempCard.type).add(tempCard); 
        tempStackList.get(stackList.indexOf(alc)).remove(tempCard); 

        // creating the last move String 
        tempLastMove = "foundation " + tempCard.fullName; 

        new State(tempStackList, tempFoundationList, tempFreecellList, previousMoves, tempLastMove, this, depth+1, true); 

        // setting all temps to null 

        tempStackList = null; 
        tempFoundationList = null; 
        tempFreecellList = null; 
        tempCard = null; 
        tempLastMove = null; 


       } else { 
        if (foundationList.get(tempCard.type).isEmpty() == false) { 
         if (tempCard.value - foundationList.get(tempCard.type).get(foundationList.get(tempCard.type).size()-1).value == -1) { 

          // creating the required ArrayLists 
          tempStackList = new ArrayList<ArrayList<Card>>(stackList); 
          tempFoundationList = new ArrayList<ArrayList<Card>>(foundationList); 
          tempFreecellList = new ArrayList<Card>(freecellList); 

          // moving the card 
          tempFoundationList.get(tempCard.type).add(tempCard); 
          tempStackList.get(stackList.indexOf(alc)).remove(tempCard); 

          // creating the last move String 
          tempLastMove = "foundation " + tempCard.fullName; 

          new State(tempStackList, tempFoundationList, tempFreecellList, previousMoves, tempLastMove, this, depth+1, true); 

          // setting all temps to null 

          tempStackList = null; 
          tempFoundationList = null; 
          tempFreecellList = null; 
          tempCard = null; 
          tempLastMove = null; 

         } 
        } 
       } 

      } 
     } // here ends the stack to foundation for loop 

     //checking for stack to freecell moves 

     for (ArrayList<Card> alc : stackList) { 

      if (alc.isEmpty() == false) { 

       tempCard = alc.get(alc.size()-1); // creating a pointer with the card that is currently being checked 

       if (freecellList.size() < 4) { 

        // creating the required ArrayLists 
        tempStackList = new ArrayList<ArrayList<Card>>(stackList); 
        tempFoundationList = new ArrayList<ArrayList<Card>>(foundationList); 
        tempFreecellList = new ArrayList<Card>(freecellList); 

        // moving the card 
        tempFreecellList.add(tempCard); 
        tempStackList.get(stackList.indexOf(alc)).remove(tempCard); 

        // creating the last move String 
        tempLastMove = "freecell " + tempCard.fullName; 

        new State(tempStackList, tempFoundationList, tempFreecellList, previousMoves, tempLastMove, this, depth+1, true); 

        // setting all temps to null 

        tempStackList = null; 
        tempFoundationList = null; 
        tempFreecellList = null; 
        tempCard = null; 
        tempLastMove = null; 

       } 

      } 
     } 

    } 

    // setting all temps to null 

    tempStackList = null; 
    tempFoundationList = null; 
    tempFreecellList = null; 
    tempCard = null; 
    tempLastMove = null; 

} 

public boolean shouldHaveChildren() { 

    if (stateHistory.isEmpty() == true) { 
     stateHistory.add(this); 
     return true; 
    } else { 
     for (State state : stateHistory) { 
      if (statesAreEqual(state, this) == true) { 
       return false; 
      } 
     } 
     stateHistory.add(this); 
     return true; 
    } 

} 

public static boolean statesAreEqual(State s1, State s2) { // checks if 2 states are equal or not 

    // checking foundationList equality 

    if (s1.foundationList.size() != s2.foundationList.size()) { 
     return false; 
    } else { 

     for (int i = 0; i < s1.foundationList.size(); i++) { 

      if (s1.foundationList.get(i).size() != s2.foundationList.size()) { 
       return false; 
      } else { 

       for (int j = 0; j < s1.foundationList.get(i).size(); j++) { 

        if (s1.foundationList.get(i).get(j) != s2.foundationList.get(i).get(j)) { 
         return false; 
        } 

       } 

      } 

     } 

    } 

    // checking stackList equality 

    if (s1.stackList.size() != s2.stackList.size()) { 
     return false; 
    } else { 

     for (int i = 0; i < s1.stackList.size(); i++) { 

      if (s1.stackList.get(i).size() != s2.stackList.size()) { 
       return false; 
      } else { 

       for (int j = 0; j < s1.stackList.get(i).size(); j++) { 

        if (s1.stackList.get(i).get(j) != s2.stackList.get(i).get(j)) { 
         return false; 
        } 

       } 

      } 

     } 

    } 

    // checking for freecellList equality 

    if (s1.freecellList.size() != s2.freecellList.size()) { 
     return false; 
    } else { 

     for (Card c : s1.freecellList) { 
      if (s2.freecellList.contains(c) == false) { 
       return false; 
      } 
     } 

    } 

    return true; 
} 

// checks if the current state is the best state reached (most cards in the foundations) 

public void checkIfBestReached() { 

    if (stateHistory.isEmpty()) { 

     bestReached = this; 

    } else { 

     int sum = 0; 

     for (ArrayList<Card> alc : foundationList) { 

      sum += alc.size(); 

     } 

     int sum2 = 0; 

     for (ArrayList<Card> alc : bestReached.foundationList) { 

      sum2 += alc.size(); 

     } 

     if (sum > sum2) { 

      bestReached = this; 

     } 

    } 

} 

public int totalStateCards() { 

    int sum = 0; 

    for (ArrayList<Card> alc : stackList) { 
     sum += alc.size(); 
    } 
    for (ArrayList<Card> alc : foundationList) { 
     sum += alc.size(); 
    } 
    sum += freecellList.size(); 

    return sum; 

} 

} 
+0

這是你的。你是魔術師。 –

+0

更嚴肅的說明,請儘量縮小您的問題範圍。您剛剛在我們身上丟棄了幾百行代碼,而您沒有分析或顯示任何努力。 –

+0

它不是一個複雜的算法。正在創建一個「州」樹,當上一個分支(一個州不能有孩子)時,最後一張卡移動消失。 –

回答

0

我發現問題所在。我創建臨時數組的方式是錯誤的。構造函數

ArrayList<ArrayList<Type>> newArray = ArrayList<ArrayList<Type>>(anotherArray);  

將anotherArray的內部陣列複製到newArray,這意味着兩個數組-的陣列將有他們內部的確切陣列。所以通過從一個數組中刪除一個對象(一張卡片),它也會從另一個數組中刪除。情況發生導致本,我創建了一個名爲copyTheDoubleArray方法:

public void copyTheDoubleArray(ArrayList<ArrayList<Card>> array1, ArrayList<ArrayList<Card>> array2) { 

    for (int i = 0; i < array1.size(); i++) { 
     array2.add(new ArrayList<Card>()); 
     for (int j = 0; j < array1.get(i).size(); j++) { 
      array2.get(i).add(array1.get(i).get(j)); 
     } 
    } 

} 

這將複製陣列的陣列和唯一的新數組股舊的是卡,它們分別同無論如何。希望這有助於如果有人得到同樣的問題。

***這個職位的importanting的事情是,你不應該使用的第一個構造函數來複制陣列的陣列,但只有單一陣列狀

ArrayList<Card> newCardArray = new ArrayList<Card>(oldCardArray);