保加利亚纸牌Java

时间:2012-10-25 01:37:22

标签: java algorithm solver

我将在AP计算机科学课程中的几天内完成以下任务:

“在这项任务中你将模仿保加利亚纸牌游戏。游戏以45张牌开始。随机将它们分成若干堆随机大小。例如,你可以从大小为20,5,1的桩开始在每一轮中,你从每一堆中取出一张牌,用这些牌形成一堆新牌。例如,样本开始配置将变成大小为19,4,8​​,10和5的桩。当桩的大小分别为1,2,3,4,5,6,7,8和9时,纸牌已经结束了。

在您的程序中,生成随机启动配置并打印它。然后继续应用纸牌步骤并打印结果。达到纸牌最终配置时停止。“

我想出了一个解决这个问题的程序,但问题是有时需要很长时间。其他时候它会像我预期的那样几乎立即解决它,但有时它可以18,000次或更多次迭代。

根据http://mancala.wikia.com/wiki/Bulgarian_Solitaire,可以在(k ^ 2)-k步或更小的步骤中找到解,在这种情况下k为9。我绝对没有在72个步骤或更少的时间内找到解决方案。我一直在看这个程序几个小时,弄乱不同的东西,看看我是否可以让它更快,我只是不能让它在足够数量的迭代中工作。所以现在我来Stack Overflow,看看你们中是否有人可以帮助我朝着正确的方向发展。

这是我的代码:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

public class BulgarianSolitaire {

    ArrayList<Integer> cards = new ArrayList<Integer>();
    Random rand = new Random();
    boolean cont = true;
    boolean cont2 = true;

    public static void main(String[] args) {
        BulgarianSolitaire game = new BulgarianSolitaire();
    }

    public BulgarianSolitaire() {
        System.out.println("Started");
        int sum = 0;
        while (cont) {
            if (sum < 45) {
                cards.add(rand.nextInt(46 - sum));
            } else {
                cont = false;
            }

            sum = 0;
            for (int i = 0; i < cards.size(); i++) {
                sum += cards.get(i);
            }

            removeZeros(cards);

            System.out.println(cards);
        }

        System.out.println("Finished Generating Start");

        while (cont2) {
            solitaireStep();
            System.out.println(cards);
            if (checkCards()) {
                cont2 = false;
            }
        }

        Collections.sort(cards);
        System.out.println("Cards are sorted");
        System.out.println(cards);
    }

    public void removeZeros(ArrayList<Integer> list) {
        for (int j = 0; j < list.size(); j++) {
            if (list.get(j) == 0) {
                list.remove(j);
            }
        }
    }

    public void solitaireStep() {

        int numberRemoved = 0;

        for (int i = 0; i < cards.size(); i++) {
            int value = cards.get(i);
            cards.set(i, value - 1);
            removeZeros(cards);
            numberRemoved++;
        }

        cards.add(numberRemoved);
    }

    public boolean checkCards() {
        ArrayList<Integer> expectedCards = new ArrayList<Integer>();

        for (int i = 1; i < 10; i++) {
            expectedCards.add(i);
        }

        ArrayList<Integer> sortedCards = cards;
        Collections.sort(sortedCards);
        boolean equal = true;
        if (sortedCards.size() != expectedCards.size()) {
            equal = false;
        }

        for (int i = 0; i < sortedCards.size(); i++) {
            if (sortedCards.size() == expectedCards.size()) {
                if (sortedCards.get(i) != expectedCards.get(i)) {
                    equal = false;
                }
            }
        }

        return equal;
    }
}

所以我基本上从0到45之间生成一个随机数,并将其添加到卡列表中。然后我继续生成随机数并将它们放在列表中,只要总和小于45,这样生成的随机数就在0到45之间 - 即最后一次迭代中数字的总和。列表中的零也随之移除。

生成列表后,它将运行从列表中的每个数字中减去1的步骤,删除零并添加一个等于减少的堆栈数的新值。它还会根据列表{1,2,3,4,5,6,7,8,9}检查卡堆栈的有序版本,一旦找到匹配项,它会将布尔值cont2设置为false,这样它就会停止执行那个单人纸牌的步骤。

就是这样。我向任何有帮助的人表示感谢。

3 个答案:

答案 0 :(得分:2)

你的瑕疵在于你的removeZeros方法。

public void removeZeros(ArrayList<Integer> list) {
    for (int j = 0; j < list.size(); j++) {
        if (list.get(j) == 0) {
            list.remove(j);
        }
    }
}

如果您移除j处的元素,则列表大小会减少1.您还必须减少j

为此改变:

  public void removeZeros(ArrayList<Integer> list) {
        for (int j = 0; j < list.size(); j++) {
            if (list.get(j) == 0) {
                list.remove(j);
                j--;
            }
        }
    }

您的检查方法也过于复杂。

在您的单人纸牌步骤中,将所有应该等于零的值设置为零。

然后,删除零(使用修订后的方法)在循环之外

然后,对数组进行排序。

然后,在您的检查方法中,由于数组已排序:

public boolean checkCards() {
    for(int i = 0; i < cards.size(); i++) {
        if(cards.get(i) != i + 1) {
            return false;
        }
    }
    return true;
}

更简单。它有效。

答案 1 :(得分:0)

我已经尝试过上面的代码,但它没有用。 我编写了一个新代码,它可以工作:

import java.util.ArrayList;
import java.util.Collections;


public class P74_BulgarianSolitaire {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    final int MAX_CARD = 45; 
    ArrayList<ArrayList<Integer>> twoDArrayList =  new ArrayList<ArrayList<Integer>>();

    int column = 1; 
    int card = 0;
    int left = MAX_CARD;


    do{ 
        column = (int) (Math.random()*(left)+1);  // 
        System.out.println("Column :"+column);

        ArrayList<Integer> row = new ArrayList<Integer>(); //New row to add. Must declare here. 
        for (int j=0;j<column;j++){
            card++;

            row.add(card);
        }

        twoDArrayList.add(row);

        left = MAX_CARD - card ;


    } while (card <MAX_CARD);
    System.out.println(twoDArrayList);
    System.out.println();

    boolean finish = false;

    while (!finish){
        ArrayList<Integer> row = new ArrayList<Integer>(); //New row

        //remove one card from each row
        for (int i=0;i<twoDArrayList.size();i++){
            row.add(twoDArrayList.get(i).get(0));
            twoDArrayList.get(i).remove(0);  //Remove the first column 
            if (twoDArrayList.get(i).isEmpty()){
                twoDArrayList.remove(twoDArrayList.get(i)); 
                i--;
            }
        }

        twoDArrayList.add(row);

        ArrayList<Integer> size = new ArrayList<Integer>(); // New list
        for (int i=0;i<twoDArrayList.size();i++){
            size.add(twoDArrayList.get(i).size());
        }
        Collections.sort(size);

        for (int i=1;i<size.size();i++){
            if (size.get(i)== size.get(i-1)+1 ) finish = true; 
            else {
                finish = false;
                break;
            }
        }

        for (int i=0;i<twoDArrayList.size();i++) Collections.sort(twoDArrayList.get(i));
        System.out.println(twoDArrayList);
    }
    System.out.println(twoDArrayList);

}

}

答案 2 :(得分:0)

    package learningofAlgorithm;
    import java.util.ArrayList;
    import java.util.Random;
    import java.util.Collections;
    public class bulgarianSolitaire {
    private Random gen;
    private int i=1;
    ArrayList<Integer> bs=new ArrayList<>();


    public bulgarianSolitaire(){
       /**gen=new Random();
       bs.add(gen.nextInt(45)+1);
       int sum=bs.get(0);
       while(sum!=45){
            bs.add(gen.nextInt(45-sum)+1);
            sum=sum+bs.get(i);
            i++;

        }*/
        bs.add(20);
        bs.add(5);
        bs.add(1);
        bs.add(9);
        bs.add(10);
    }

    public void dis(){
        for(Integer element:bs){
            System.out.print(element+" ");
        }
    }


    public void removeCard(ArrayList<Integer> s){
         int i=0;
        while(i<s.size()){
            if(s.get(i)==0){
                s.remove(i);
            }
             else{
                i++;
            }
        }

    }


     public void bsstep(){
         int newheap=0;
         for(int i=0;i<bs.size();i++){
             int key=bs.get(i);
                 bs.set(i, key-1);

             newheap++;

         }
        removeCard(bs);

         bs.add(newheap);   
    }


    public boolean checkCard()
    {   ArrayList<Integer> bscheck=new ArrayList<>();
        for(int i=1;i<10;i++){
        bscheck.add(i);
          }
        boolean flag=true;
        ArrayList<Integer> sortbs=bs;
        Collections.sort(sortbs);
        if(bscheck.size()!=sortbs.size()){
            flag=false;
        }

     for(int i=0;i<bscheck.size();i++){
         if(bscheck.size()==sortbs.size()){
              if(bscheck.get(i)!=sortbs.get(i)){
                  flag=false;
              }
          }
        }
        return flag;

    }


    }