2017-05-12 1 views
0

나는 자바가있는 freecell solitaire solver에서 일하고 있는데 문제가있다. 내 솔버가 잘 작동하는 것처럼 보였지만 실행 한 후에 내가 찾은 답을 얻지 못했습니다. 처음부터 두 번 다시 프로그래밍했는데 문제가있는 것처럼 보였습니다 새로운 상태 인을 만드는 동안 일부 카드가 사라졌습니다.freecell solitare 인공 지능

이것은 깊이 우선 알고리즘이며 카드 (또는 경우에 따라 2)가 마지막으로 생성 된 상태 (현재 작성중인 상태)가 같거나 더 낮은 경우에만 사라집니다.. 내 알고리즘의 일부로 내 State 클래스를 게시하고 있습니다 (단 두 가지 유형의 이동 만 가능합니다 : 기초로 스택하고 프리셀로 스택).

"상위"상태의 생성자에서 검색이 실행 중입니다. 카드가 사라지는 것은 마술사가 컴퓨터가 아닌 당신 앞에서 그것을 수행하는 것만으로 재미있을 수 있기 때문에 가능하면 도움을주십시오.

여기 내 코드입니다.

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);  

배열이 배열 - 중 - 그들 내부의 정확한 배열을해야합니다 모두 의미하는 newArray에 anotherArray의 내부 배열을 복사합니다. 따라서 한 배열에서 객체 (카드)를 삭제하면 다른 배열에서도 삭제됩니다. 이런 일이 발생 무효화하기 위해, 나는 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);