final commit
This commit is contained in:
@ -2,4 +2,170 @@
|
||||
|
||||
## Lösungsidee
|
||||
|
||||
Mithilfe eines Zufallsgenerators kann eine Seite des Würfels und somit die
|
||||
Augenzahl bestimmt werden. Dann muss entschieden werden welche Figur gezogen
|
||||
wird. In der folgenden Reihenfolge wird probiert, die Figuren zu ziehen:
|
||||
|
||||
1. Wenn eine Figur auf Feld A steht, muss diese gezogen werden.
|
||||
2. Wurde eine 6 gewürfelt, wird eine neue Figur rausgebracht.
|
||||
3. Die vorderste Figur auf der Laufbahn, die gezogen werden kann, wird gezogen.
|
||||
4. Die Figur auf dem Zielfeld, die der Laufbahn am nächsten ist, wird gezogen.
|
||||
Welche Figur auf dem Zielfeld gezogen wird, ist nicht in den Regeln festgelegt.
|
||||
Es wäre auch möglich so zu ziehen, dass möglichst keine Figur vor dem Ziel
|
||||
blockiert wird, d. h. sie mit keinem möglichen Augenzahl gezogen werden kann.
|
||||
Allerdings wird der Fall, dass zwei verschiedene Figuren auf den Zielfelder
|
||||
gezogen werden können, selten auftreten. Außerdem wird durch Regeländerung
|
||||
zu einer festen Priorität der Figuren auf der Laufbahn klar, dass so weit
|
||||
vorausschauende Lösungen nicht in dieser Aufgabe erwartet werden.
|
||||
|
||||
Sollte der Spieler eine 6 würfeln, ist er nochmal dran, ansonsten der andere.
|
||||
Allerdings stellt sich die Frage, ob dieser auch nochmal dran ist, wenn er
|
||||
mit der 6 nicht ziehen kann. Nach der Anmerkung gilt "Wenn kein Stein bewegt
|
||||
werden kann, verfällt der Zug". Hier ist fraglich, was mit "Zug" gemeint ist.
|
||||
Einerseits können mehrere bewegte Figuren hintereinander als ein Zug angesehen
|
||||
werden, da der gleiche Spieler dran ist. Allerdings werden zwei Figuren gezogen,
|
||||
weshalb es auch als zwei Züge angesehen werden kann. Mit "Wer eine „6“ würfelt,
|
||||
hat nach seinem Zug einen weiteren Wurf frei." wird letzteres unterstützt, weil
|
||||
"nach seinem Zug" bedeutet, dass bereits ein Zug beendet ist, bevor das zweite Mal
|
||||
gewürfelt wird. Es sind also zwei Züge sind und nur der erste der beiden verfällt, sodass der
|
||||
Spieler auch nach Verfallen eines Wurfes mit einer 6 nochmal würfeln darf.
|
||||
|
||||
Es ist auch möglich, dass ein Spiel unentschieden ausgeht. Wenn beide Spieler z. B.
|
||||
keine 1 auf dem Würfel haben, diese aber brauchen, um ins Ziel zu kommen. Stellt
|
||||
sich die Frage, wie unentschiedene Spiele gezählt werden. Eine Möglichkeit wäre die
|
||||
Spiele zu wiederholen. Allerdings steht in der Aufgabenstellung: "[...] wie gut diese
|
||||
Würfel geeignet sind, um das Spiel zu gewinnen". D. h., dass es irrelavant ist, ob
|
||||
ein Würfel verloren oder unentschieden gespielt hat, sondern nur, wie oft gewonnen
|
||||
wurde.
|
||||
|
||||
## Umsetzung
|
||||
|
||||
Das Programm wird in Rust implementiert. Als Argumente müssen Dateipfade zu den
|
||||
Eingabedateien übergeben werden. Das Spielfeld ist in einer Struktur gespeichert.
|
||||
Die Laufbahn wird einem 40er-Array innerhalb der Struktur gespeichert. Die
|
||||
Figuren der beiden Spieler werden durch 0 und 1 dargestellt. Die Spieler werden
|
||||
auch Spieler 0 und Spieler 1 genannt. Ist an der entsprechenden Stelle keine
|
||||
Figur, wird dies durch -1 dargestellt. Mit dem gleichen Format hat die Struktur zwei
|
||||
Arrays für die Zielfelder für die beiden Spieler. Außerdem hat die Struktur ein Attribut, das
|
||||
die Anzahl der Figuren auf den B-Feldern der beiden Spieler in einem Array speichert.
|
||||
Schließich hat die Struktur noch ein Attribut, das in einem 2d-Array die Positionen
|
||||
der Figuren abgespeichert, der erste Index 0 oder 1 entsprechend der beiden Spieler und
|
||||
der zweite Index für die Figuren des jeweiligen Spielers. Dies ist notwendig, damit schnell
|
||||
die Figuren gezogen werden können, ohne das das ganze Laufbahn-Array durchsucht werden muss.
|
||||
Die Methode "step" der "Field"-Struktur zieht die Figuren unter Angabe einer
|
||||
Figur und dem Würfelergebnis, wenn es möglich ist, und gibt je nach Erfolg
|
||||
einen Boolean zurück. Außerdem ruft sie die "beat" Methode auf, um die Figur zu
|
||||
schlagen, die dem Zug im Weg stehen.
|
||||
|
||||
In der main Funktion wird mit einer for-Schleife über die Eingabedateien iteriert.
|
||||
In einer weiteren for-Schleife werden alle möglichen Würfelkombinationen ermittelt.
|
||||
Wie oft gespielt wird, kann durch die "runs" Variable verändert werden.
|
||||
Eine while-Schleife läuft solange das Spiel läuft. Mit der "rand"
|
||||
Bibliothek werden Zufallszahlen erstellt und die Augenzahl bestimmt. Dann wird
|
||||
entsprechend des oben beschriebenen Algorithmus die "step" Methode aufgerufen.
|
||||
Wurde erfolgreich ein Zug gemacht, wird überpruft, ob der Spieler gewonnen hat.
|
||||
Konnte nicht gezogen werden, wird in einem HashSet die Augenzahl gespeichert.
|
||||
Kann bei keiner Augenzahl bei beiden Spielern eine Figur bewegt werden, wird das Spiel
|
||||
für Unentschieden erklärt. Wurden alle Spiele simuliert, wird das Ergebnis ausgegeben.
|
||||
|
||||
## Beispiele
|
||||
|
||||
Ergebnisse für die Beispieldaten:
|
||||
|
||||
```
|
||||
beispieldaten/wuerfel0.txt:
|
||||
1. Würfel: Würfelseiten: [1, 1, 1, 6, 6, 6], Siege: 977293, Siegwahrscheinlichkeit:
|
||||
0.977293, Niederlagen: 22707, Niederlagewahrscheinlichkeit: 0.022707, Unentschieden:
|
||||
0, Unentschiedenwahrscheinlichkeit: 0
|
||||
2. Würfel: Würfelseiten: [1, 2, 3, 4, 5, 6], Siege: 640526, Siegwahrscheinlichkeit:
|
||||
0.640526, Niederlagen: 359474, Niederlagewahrscheinlichkeit: 0.359474, Unentschieden:
|
||||
0, Unentschiedenwahrscheinlichkeit: 0
|
||||
3. Würfel: Würfelseiten: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], Siege: 537390,
|
||||
Siegwahrscheinlichkeit: 0.53739, Niederlagen: 462610, Niederlagewahrscheinlichkeit:
|
||||
0.46261, Unentschieden: 0, Unentschiedenwahrscheinlichkeit: 0
|
||||
4. Würfel: Würfelseiten: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], Siege: 528348,
|
||||
Siegwahrscheinlichkeit: 0.528348, Niederlagen: 471652,
|
||||
Niederlagewahrscheinlichkeit: 0.471652, Unentschieden: 0,
|
||||
Unentschiedenwahrscheinlichkeit: 0
|
||||
5. Würfel: Würfelseiten: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20], Siege: 316443, Siegwahrscheinlichkeit: 0.316443, Niederlagen:
|
||||
683557, Niederlagewahrscheinlichkeit: 0.683557, Unentschieden: 0,
|
||||
Unentschiedenwahrscheinlichkeit: 0
|
||||
6. Würfel: Würfelseiten: [1, 2, 3, 4], Siege: 0, Siegwahrscheinlichkeit: 0,
|
||||
Niederlagen: 1000000, Niederlagewahrscheinlichkeit: 1, Unentschieden: 0
|
||||
Unentschiedenwahrscheinlichkeit: 0
|
||||
```
|
||||
|
||||
Der Würfel ohne eine 6, kann natürlich nicht gewinnen.
|
||||
|
||||
```
|
||||
beispieldaten/wuerfel1.txt:
|
||||
1. Würfel: Würfelseiten: [1, 2, 3, 4, 5, 6], Siege: 580726,
|
||||
Siegwahrscheinlichkeit: 0.580726, Niederlagen: 419274,
|
||||
eiederlagewahrscheinlichkeit: 0.419274, Unentschieden: 0,
|
||||
Unentschiedenwahrscheinlichkeit: 0
|
||||
2. Würfel: Würfelseiten: [2, 3, 4, 5, 6, 7], Siege: 568755,
|
||||
Siegwahrscheinlichkeit: 0.568755, Niederlagen: 327638,
|
||||
Niederlagewahrscheinlichkeit: 0.327638, Unentschieden: 103607,
|
||||
Unentschiedenwahrscheinlichkeit: 0.103607
|
||||
3. Würfel: Würfelseiten: [3, 4, 5, 6, 7, 8], Siege: 497753,
|
||||
Siegwahrscheinlichkeit: 0.497753, Niederlagen: 325580,
|
||||
Niederlagewahrscheinlichkeit: 0.32558, Unentschieden: 176667,
|
||||
Unentschiedenwahrscheinlichkeit: 0.176667
|
||||
4. Würfel: Würfelseiten: [4, 5, 6, 7, 8, 9], Siege: 406054,
|
||||
Siegwahrscheinlichkeit: 0.406054, Niederlagen: 363332,
|
||||
Niederlagewahrscheinlichkeit: 0.363332, Unentschieden: 230614,
|
||||
Unentschiedenwahrscheinlichkeit: 0.230614
|
||||
5. Würfel: Würfelseiten: [5, 6, 7, 8, 9, 10], Siege: 247830,
|
||||
Siegwahrscheinlichkeit: 0.24783, Niederlagen: 463716, Niederlagewahrscheinlichkeit:
|
||||
0.463716, Unentschieden: 288454, Unentschiedenwahrscheinlichkeit: 0.288454
|
||||
6. Würfel: Würfelseiten: [6, 7, 8, 9, 10, 11], Siege: 141690,
|
||||
Siegwahrscheinlichkeit: 0.14169, Niederlagen: 543268,
|
||||
Niederlagewahrscheinlichkeit: 0.543268, Unentschieden: 315042,
|
||||
Unentschiedenwahrscheinlichkeit: 0.315042
|
||||
beispieldaten/wuerfel2.txt:
|
||||
1. Würfel: Würfelseiten: [1, 6, 6, 6, 6, 6], Siege: 783608,
|
||||
Siegwahrscheinlichkeit: 0.97951, Niederlagen: 16392, Niederlagewahrscheinlichkeit:
|
||||
0.02049, Unentschieden: 0, Unentschiedenwahrscheinlichkeit: 0
|
||||
2. Würfel: Würfelseiten: [1, 1, 6, 6, 6, 6], Siege: 604274,
|
||||
Siegwahrscheinlichkeit: 0.7553425, Niederlagen: 195726,
|
||||
Niederlagewahrscheinlichkeit: 0.2446575, Unentschieden: 0, Unentschiedenwahrscheinlichkeit: 0
|
||||
3. Würfel: Würfelseiten: [1, 1, 1, 6, 6, 6], Siege:
|
||||
e03792, Siegwahrscheinlichkeit: 0.50474, Niederlagen: 396208,
|
||||
Niederlagewahrscheinlichkeit: 0.49526, Unentschieden: 0, Unentschiedenwahrscheinlichkeit: 0
|
||||
4. Würfel: Würfelseiten: [1, 1, 1, 1, 6, 6], Siege: 205269,
|
||||
Siegwahrscheinlichkeit: 0.25658625, Niederlagen: 594731,
|
||||
Niederlagewahrscheinlichkeit: 0.74341375, Unentschieden: 0, Unentschiedenwahrscheinlichkeit: 0
|
||||
5. Würfel: Würfelseiten: [1, 1, 1, 1, 1, 6], Siege: 3057, Siegwahrscheinlichkeit:
|
||||
0.00382125, Niederlagen: 796943, Niederlagewahrscheinlichkeit: 0.99617875,
|
||||
Unentschieden: 0, Unentschiedenwahrscheinlichkeit: 0
|
||||
beispieldaten/wuerfel3.txt:
|
||||
1. Würfel: Würfelseiten: [1, 2, 5, 6], Siege: 752618, Siegwahrscheinlichkeit: 0.752618,
|
||||
Niederlagen: 247382, Niederlagewahrscheinlichkeit: 0.247382, Unentschieden:
|
||||
0, Unentschiedenwahrscheinlichkeit: 0
|
||||
2. Würfel: Würfelseiten: [1, 2, 3, 4, 5, 6, 7, 8], Siege: 612183,
|
||||
Siegwahrscheinlichkeit: 0.612183, Niederlagen: 387817,
|
||||
Niederlagewahrscheinlichkeit: 0.387817, Unentschieden: 0,
|
||||
Unentschiedenwahrscheinlichkeit: 0
|
||||
3. Würfel: Würfelseiten: [1, 2, 3, 4, 5, 6], Siege: 593636, Siegwahrscheinlichkeit:
|
||||
0.593636, Niederlagen: 406364, Niederlagewahrscheinlichkeit: 0.406364, Unentschieden:
|
||||
0,
|
||||
Unentschiedenwahrscheinlichkeit: 0
|
||||
4. Würfel: Würfelseiten: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], Siege: 447023,
|
||||
Siegwahrscheinlichkeit: 0.447023, Niederlagen: 552977, Niederlagewahrscheinlichkeit:
|
||||
0.552977, Unentschieden: 0, Unentschiedenwahrscheinlichkeit: 0
|
||||
5. Würfel: Würfelseiten: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], Siege:
|
||||
440511, Siegwahrscheinlichkeit: 0.440511, Niederlagen: 559489,
|
||||
Niederlagewahrscheinlichkeit: 0.559489, Unentschieden: 0,
|
||||
Unentschiedenwahrscheinlichkeit: 0
|
||||
6. Würfel: Würfelseiten: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20], Siege: 154029, Siegwahrscheinlichkeit: 0.154029, Niederlagen:
|
||||
845971, Niederlagewahrscheinlichkeit: 0.845971, Unentschieden: 0,
|
||||
Unentschiedenwahrscheinlichkeit: 0
|
||||
```
|
||||
|
||||
Allgemein sind die Würfel mit der größten Wahrscheinlichkeit eine 6 zu würfeln
|
||||
am besten. Zum einem, da eine 6 benötigt wird, um raus zu kommen. Außerdem kann man
|
||||
nochmal würfeln, auch wenn man mit der 6 nicht ziehen konnte. Sehr große Augenzahlen
|
||||
dagegen sind zwar gut, um viele Schritte auf einmal zu gehen. Allerdings sind sie
|
||||
kurz vor dem Ziel von Nachteil, da man mit ihnen nicht mehr gehen kann.
|
||||
|
||||
@ -17,7 +17,7 @@ struct Dice {
|
||||
|
||||
/* Struktur, die das Spielfeld darstellt. Die Member b, destination und pieces sind 2er-Arrays von
|
||||
* den eigentlichen Arrays (Die Elemente von b sind kein Array. Für diese gilt allerdings das
|
||||
* gleiche.) Das Array mit dem Index 0 gehört jeweils zu Spieler 0 und das andere zu
|
||||
* Gleiche.) Das Array mit dem Index 0 gehört jeweils zu Spieler 0 und das andere zu
|
||||
* Spieler 1. Diesen Spielern sind keine Farben zugeordnet. Wichtig ist nur, dass sie gegenüber
|
||||
* liegen. */
|
||||
struct Field {
|
||||
@ -145,18 +145,24 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
// der Würfel tritt gegen alle bereits verarbeiteten an.
|
||||
// der Würfel tritt gegen alle bereits verarbeiteten Würfel an.
|
||||
for dice_other in dices.iter_mut() {
|
||||
let mut selected_dices = [&mut dice, dice_other]; // der Würfel mit dem Index 0, ist auch Spieler 0 und der andere Spieler 1.
|
||||
for begin in [0, 1] { // das Spiel wird von beiden Spieler gleich oft angefangen
|
||||
for _ in 0..runs {
|
||||
let mut turn = begin;
|
||||
let mut field = Field { // Spielfeld in der Ausgangsstellung
|
||||
b: [4; 2],
|
||||
b: [3; 2],
|
||||
main: [-1; 40],
|
||||
destination: [[-1; 4]; 2],
|
||||
pieces: [[-5; 4]; 2],
|
||||
};
|
||||
|
||||
// setzte jeweils eine Figur auf Feld A
|
||||
field.pieces[0][0] = 0;
|
||||
field.main[0] = 0;
|
||||
field.pieces[1][0] = 20;
|
||||
field.main[20] = 1;
|
||||
let mut win = false;
|
||||
while !win { // Schleife solange niemand gewonnen hat.
|
||||
|
||||
@ -194,12 +200,12 @@ fn main() {
|
||||
result
|
||||
} {
|
||||
|
||||
// ein Spieler hat gewonnen wenn alle seine Figuren im Ziel sind.
|
||||
// Ein Spieler hat gewonnen, wenn alle seine Figuren im Ziel sind.
|
||||
win = true;
|
||||
for piece in field.destination[turn] {
|
||||
win &= piece == turn as i8;
|
||||
}
|
||||
if win { // hat jemand gewonnen, werden die Sieges- und Niederlagenzähler erhöht.
|
||||
if win { // Wenn jemand gewonnen hat, werden die Sieges- und Niederlagenzähler erhöht.
|
||||
selected_dices[turn].wins += 1;
|
||||
selected_dices[other_player(turn)].defeats += 1;
|
||||
}
|
||||
@ -213,18 +219,19 @@ fn main() {
|
||||
}
|
||||
else {
|
||||
|
||||
/* Konnte keine Figur gezogen werden, wird die Augenzahl in einem
|
||||
/* konnte keine Figur gezogen werden, wird die Augenzahl in einem
|
||||
* HashSet abgespeichert. */
|
||||
no_move_possible[turn].insert(dice_result);
|
||||
|
||||
/* Kann bei keiner möglichen Augenzahl gezogen beider Spieler
|
||||
/* Kann bei keiner möglichen Augenzahl beider Spieler
|
||||
* gezogen werden, ist das Spiel unentschieden. */
|
||||
if no_move_possible[turn].len() as u8 == selected_dices[turn].different_sides_count &&
|
||||
no_move_possible[other_player(turn)].len() as u8 == selected_dices[other_player(turn)].different_sides_count {
|
||||
break;
|
||||
}
|
||||
}
|
||||
turn = other_player(turn); // beim nächsten Zug ist der andere Spieler dran.
|
||||
// beim nächsten Zug ist der andere Spieler dran, außer bei einer 6.
|
||||
if dice_result != 6 {turn = other_player(turn);}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -232,7 +239,7 @@ fn main() {
|
||||
dices.push(dice);
|
||||
}
|
||||
|
||||
// sotiert die Würfel nach Gewinnen
|
||||
// sortiert die Würfel nach Gewinnen
|
||||
dices.sort_unstable_by(|a, b| b.wins.partial_cmp(&a.wins).unwrap());
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user