Würfelwurfsimulation in Java
Für eines meiner Labore muss ich ein komplettes Java-Programm schreiben, das ein "sehr einfaches" Würfelwettspiel simuliert. Die Spezifikationen lauten wie folgt: Simulieren Sie den Wurf von 3 Würfeln. Wenn Sie drei Sechser werfen, gewinnen Sie$20; if you throw three of any other value then you win $10; Wenn Sie zwei Würfel werfen, die den gleichen Wert haben, gewinnen Sie$5. If none of the conditions above are met, then you would lose $1.
Beispielläufe: Würfelwurf
Dice 1 : 2 Dice 2 : 1 Dice 3 : 2
Congratulations : You threw TWO - 2s
You win $5 Dice 1 : 2 Dice 2 : 2 Dice 3 : 2 Congratulations : You threw THREE - 2s You win $10
Dice 1 : 4 Dice 2 : 6 Dice 3 : 3
Unfortunately : You did not throw anything of value
You lose $1
Der resultierende Code, den ich geschrieben habe, um dieses Problem zu lösen, lautet wie folgt:
/**
* SRN: 507-147-9
*/
public class Lab6_part3 {
public static void main(String[] args) {
// define vars
int round = 1;
int dice1, dice2, dice3;
while (round <= 3) {
dice1 = 1 + (int)(Math.random() * 6);
dice2 = 1 + (int)(Math.random() * 6);
dice3 = 1 + (int)(Math.random() * 6);
System.out.println();
System.out.println("Dice 1 : " + dice1 + " Dice 2 : " + dice2 + " Dice 3 : " + dice3);
// Three of a kind
if ((dice1 == dice2) && (dice1 == dice3)) { // 3-of-a-kind (D1)
// Rolls three sixes
if (dice1 == 6) {
System.out.println("Congratulations : You threw THREE - 6s");
System.out.println("You win $20");
} else {
// Rolls three of anything else
System.out.println("Congratulations : You threw THREE - " + dice1 + "s");
System.out.println("You win $10"); } } // Two of a kind (PRINT "dice1") else if (dice1 == dice2 || dice1 == dice3) { System.out.println("Congratulations : You threw TWO - " + dice1 + "s"); System.out.println("You win $5");
}
// Two of a kind (PRINT "dice2")
else if (dice2 == dice1 || dice2 == dice3) {
System.out.println("Congratulations : You threw TWO - " + dice2 + "s");
System.out.println("You win $5"); } // Two of a kind (PRINT "dice3") else if (dice3 == dice1 || dice3 == dice2) { System.out.println("Congratulations : You threw TWO - " + dice3 + "s"); System.out.println("You win $5");
}
// Did not throw anything of value
else {
System.out.println("Unfortunately : You did not throw anything of value");
System.out.println("You lose $1");
}
round++;
}
}
}
Das Problem, auf das ich bei diesem Ansatz stoße, ist, dass ich, obwohl der Code so funktioniert, wie er soll, eine einfachere Möglichkeit haben möchte, die Zwei-aus-einer zu schreiben, anstatt drei "if" -Anweisungen zu haben. Mein Ziel dabei ist es, eine Drei-Wege-Anweisung "oder" zu erstellen, anstatt Würfel1 mit Würfeln 2 und 3 und Würfel 2 mit Würfeln 1 und 3 usw. zu vergleichen.
else if (dice1 == dice2 || dice1 == dice3 || dice2 == dice3) {
System.out.println("Congratulations : You threw TWO - " + somethings?? + "s");
System.out.println("You win $5");
Wenn ich das tun würde, wie könnte ich dann den Wert des Paares ausdrucken, das ich identifiziert habe?
Antworten
Willkommen bei CodeReview. In Bezug auf Ihr Problem ist eine schnelle Lösung:
else if (dice1 == dice2 || dice1 == dice3 || dice2 == dice3) {
int doubleNum = dice1 == dice2 ? dice1 : dice1 == dice3 ? dice1 : dice3;
System.out.println("Congratulations : You threw TWO - " + doubleNum + "s");
System.out.println("You win $5");
}
Der ternäre Operator macht den Code kompakter, aber in diesem Fall ist er meiner Meinung nach etwas weniger lesbar als eine Kette von if-else.
Einige andere Vorschläge:
- Die while-Schleife kann durch eine bequemere for-Schleife ersetzt werden. Von:
Zu:int round = 1; while(round<=3){ //... round++; }for(int round = 1; round <= 3; round++) { //... } - Das Deklarieren mehrerer Variablen in einer Zeile
int dice1, dice2, dice3;wird in Java nicht als bewährte Methode angesehen. - Anstatt einen Zufall
floatzuintgenerieren und ihn dann in einen zu verwandeln , generieren Sie direkt einenintmitThreadLocalRandom.current().nextInt(6). Docs . - Sie können die erste Zeile mit drucken
System.out.format. Von:
Zu:System.out.println(); System.out.println("Dice 1 : " + dice1 + " Dice 2 : " + dice2 + " Dice 3 : " + dice3);System.out.format("%nDice 1 : %d Dice 2 : %d Dice 3 : %n", dice1, dice2, dice3) - Klassennamen sollten Pascal sein . Stattdessen
Lab6_part3können Sie es benennenLab6Part3. - Deklarieren Sie eine Konstante für die Anzahl der Runden, um das Ändern zu erleichtern. Beispielsweise:
public class Lab6Part3 { private static final int ROUNDS = 3; public static void main(String[] args) { for(int round = 1; round <= ROUNDS; round++) { //... } }
Ein anderer Ansatz besteht darin, drei Zahlen mit Random#intsden Frequenzen zu generieren und diese zu berechnen:
Random r = new Random();
// Generate three random numbers from 1 to 6
IntStream diceRolls = r.ints(3, 1, 7);
// Generate map of frequencies
Map<Integer, Long> freq = diceRolls.boxed()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
boolean winner = false;
for (Entry<Integer, Long> entry : freq.entrySet()) {
int number = entry.getKey();
long times = entry.getValue();
if (times == 3) {
// Three of a kind ...
winner = true;
} else if (times == 2) {
// Two of a kind...
System.out.println("Congratulations : You threw TWO - " + number + "s");
System.out.println("You win $5");
winner = true;
}
}
if(!winner) {
// Did not throw anything of value
}
Sie müssen keine 3 else_if-Anweisungen haben. Es gibt 3 Szenarien, in denen Sie sich in einem "Zwei-für-eine-Art" -Fall befinden. Würfel1 == Würfel2, Würfel1 == Würfel3, Würfel2 == Würfel3. Ihr erster if-Block fängt zwei dieser Szenarien ab. Die einzige andere Option ist, wenn dice2 == dice3.
Wenn Sie darüber nachdenken, würde Ihr dritter else_If-Block immer eine echte Auswertung in einem der ersten beiden Blöcke erstellen, sodass Ihr Code ihn niemals erreichen wird.
// Two of a kind (PRINT "dice1")
else if (dice1 == dice2 || dice1 == dice3) {
System.out.println("Congratulations : You threw TWO - " + dice1 + "s");
System.out.println("You win $5"); } // Two of a kind (PRINT "dice2") else if (dice2 == dice3) { System.out.println("Congratulations : You threw TWO - " + dice2 + "s"); System.out.println("You win $5");
}
} // Two of a kind (PRINT "dice1") else if (dice1 == dice2 || dice1 == dice3) {
Bitte tu das nicht. Wenn Sie das halb gekuschelte verwenden möchten else, schreiben Sie es bitte immer in zwei aufeinander folgenden Zeilen.
}
else if (dice1 == dice2 || dice1 == dice3) {
// Two of a kind (PRINT "dice1")
Es gibt zwei Gründe.
- Wenn ich wissen möchte, dass die Struktur fertig ist, kann ich auf diese Weise nur eine Zeile hinter dem sehen
}. Bei Ihrem Original müsste ich eine beliebige Anzahl von Zeilen bis zur nächsten Aussage suchen. Dies wird besonders schlimm, wenn die Kommentarblöcke länger werden. Es ist durchaus möglich, einen Kommentar zu schreiben, der größer als ein einzelner Bildschirm ist. Das heißt, anstatt einfach ein wenig weiter zu scrollen, müsste ich über den Kommentar hinaus blättern, um zu sehen, dass es einenelseBlock gibt. - Wenn jemand etwas verwendet, das den Code neu formatiert, um ihn
elsein dieselbe Zeile wie den zu setzen}, muss er den Kommentar trotzdem verschieben. Selbst wenn sie es zurück formatieren, wird der Kommentar verschoben. Dies führt zu Verwirrung bei der Quellcodeverwaltung. Sagen Sie es einfach so, wie es der Reformatter von Anfang an tun würde.
Sprachen im C-Stil haben im Allgemeinen eine verwirrende Blockbehandlung. Weil sie }beide verwenden, um die Struktur zu beenden und nur um den Block in einer fortlaufenden Struktur zu beenden. Das heißt, sie können nicht sagen, dass die ifStruktur endet, anstatt mit elseirgendeiner Art fortzufahren. Um dies zu kompensieren, müssen wir Codierungskonventionen verwenden. Und eine der einfachsten Konventionen, die über den Stil hinausgeht, besteht darin, niemals eine geschweifte Klammer ( }oder {) mehr als eine Zeile vom zugehörigen Schlüsselwort entfernt zu setzen, wenn es eine gibt.