2

在我的 AP 计算机科学课程中,我将在几天后完成以下作业:

“在这个作业中,你将模拟保加利亚纸牌游戏。游戏从 45 张牌开始。将它们随机分成若干随机大小的堆。例如,你可能从大小为 20、5、1、9 的堆开始, 10. 在每一轮中,你从每一堆中取出一张牌,用这些牌组成一个新的牌堆。例如,示例起始配置将转换为大小为 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,以便它将停止执行单人纸牌步骤。

就是这样。我感谢任何可以提供帮助的人。

4

3 回答 3

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

简单得多。它有效。

于 2012-10-25T01:59:43.660 回答
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);

}

}
于 2013-12-30T17:10:06.530 回答
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;

    }


    }
于 2015-09-24T15:58:07.800 回答