在我的 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,以便它将停止执行单人纸牌步骤。
就是这样。我感谢任何可以提供帮助的人。