[解決済み] ブルガリアソリティアJava
質問
APコンピュータサイエンスのコースで、数日後に以下の課題を提出することになっています。
この課題では、ブルガリアン・ソリティアというゲームをモデル化することになります。このゲームは45枚のカードで始まります。それらをランダムな大きさのいくつかの山にランダムに分割します。例えば、20、5、1、9、10の大きさの山から始めるかもしれない。各ラウンドで、それぞれの山から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の間、つまり最後の反復でリストに入れられた数の合計となります。リストの中の0は、その都度削除されます。
リストが生成されると、リスト内のすべての数値から1を引き、0を取り除き、減ったスタック数に等しい新しい値を追加するステップを実行する。また、カードスタックの順序をリスト{1, 2, 3, 4, 5, 6, 7, 8, 9}に対してチェックし、一致するものを見つけたら、そのソリティアステップを実行しないようにブール型 cont2 を false にセットしています。
そんなところです。助けてくれる人に感謝を捧げます。
解決方法は?
あなたの欠点は、あなたの
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--;
}
}
}
チェックの仕方も複雑すぎる。
ソリティアのステップで、0に等しいはずの値をすべて0に設定してください。
次に、ゼロを削除します(改訂版メソッドで)。 ループの外側 .
そして、配列を並べ替えます。
そして、配列がソートされているので、チェックメソッドで。
public boolean checkCards() {
for(int i = 0; i < cards.size(); i++) {
if(cards.get(i) != i + 1) {
return false;
}
}
return true;
}
もっとシンプルに。そして、うまくいくのです。
関連
-
[解決済み】なぜjava.io.Fileにはcloseメソッドがないのでしょうか?
-
[解決済み】java.io.IOException: 壊れたパイプ
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] JavaでNullPointerExceptionを回避する方法
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Java Mapの各エントリを効率的に反復処理するには?
-
[解決済み] Javaでメモリーリークを発生させるにはどうしたらいいですか?
-
[解決済み] Javaにおけるpublic、protected、package-private、privateの違いは何ですか?
-
[解決済み] JavaでArrayListではなくLinkedListを使用するのはいつですか?
-
[解決済み] JavaでStringをintに変換するにはどうしたらいいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Hibernateエラー:同じ識別子値を持つ別のオブジェクトがすでにセッションに関連付けられました。
-
[解決済み】javaで指定されたファイルが見つからない
-
[解決済み】 java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver [重複]。
-
[解決済み】非閉鎖文字リテラルエラー
-
[解決済み】JLabelのテキストを中央に配置するには?
-
[解決済み】java 'jar'が内部コマンドまたは外部コマンドとして認識されない。
-
[解決済み】Eclipseで「公開型 <<classname>> は独自のファイルで定義する必要があります」エラー【重複あり
-
[解決済み】純粋なJUnitテストにVisibleForTestingを使用する方法
-
[解決済み】Ubuntu: OpenJDK 8 - パッケージを見つけることができません。
-
[解決済み] "java.nio.charset.MalformedInputException" を避けるために、すべての包括的なCharset。入力の長さ= 1"?