我将在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,这样它就会停止执行那个单人纸牌的步骤。
就是这样。我向任何有帮助的人表示感谢。
答案 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;
}
}