diff --git a/.gitignore b/.gitignore index 8ee226b..a23fe3f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ CMakeFiles .cache a[1-5] +Makefile +target diff --git a/a1-Schiebeparkplatz/README.md b/a1-Schiebeparkplatz/README.md index 701ec82..7dc7817 100644 --- a/a1-Schiebeparkplatz/README.md +++ b/a1-Schiebeparkplatz/README.md @@ -185,3 +185,72 @@ N: Q 1 links, R 1 links O: Q 2 links, R 2 links, S 2 links P: Q 1 links, R 1 links, S 1 links ``` + +## Quelltext + +``` +func main() { + for i := range querAutos { + var currentMoves []movedCar // enthält die Verschiebungen der Autos in die Richtung in der weniger Autos verschoben werden müssen + var carLeastSteps uint32 + for _, direction := range []int{-1, 1} { // -1 steht für links und 1 für rechts + movedCars, steps, success := move(i, direction, []movedCar{}, 0, 0) + + /* Wenn das Verschieben der Autos in der jeweiligen Richtung erfolgreich ist und noch keine + Verschiebungen abgespeichert wurden, d. h. gerade die Verschiebungen für links berechnet + wurden oder das Verschieben nach links nicht erfolgreich war, da das Ende das Parkplatzes + erreicht wurde, dann werden die Verschiebungen abgespeichert. + Sollten allerdings bereits Verschiebungen für links vorhanden sein, wird das Verschieben nach + rechts bevorzugt, wenn weniger Autos verschoben werden mussten oder die Autos weniger Plätze + verschoben werden mussten. */ + if success && (currentMoves == nil || len(movedCars) < len(currentMoves) || len(movedCars) == len(currentMoves) && steps < carLeastSteps) { + currentMoves = movedCars + carLeastSteps = steps + } + } + } +} + +// Funktion zur Berechung der Autos, die für einen Parkplatz verschoben werden müssen. +func move(i, direction int, movedCars []movedCar, lastMoved byte, totalSteps uint32) ([]movedCar, uint32, bool) { + querAuto := querAutos[i] + + /* Wenn querAuto gleich 0 ist, ist kein Auto vor dem Parkplatz. + Wenn es das gleiche Auto ist wie das zuletzt verschobene, ist auch das Verschieben beendet, + da dieses Auto bereits ausreichend verschoben wurde. */ + if querAuto == 0 || querAuto == lastMoved { + return movedCars, totalSteps, true + } + + /* Wenn neben unserem Auto in der jeweiligen Richtung kein Parkplatz mehr ist, + dann können auch keine Autos in diese Richtung verschoben werden. */ + if outOfBounds(querAutos, i + direction) { + return movedCars, totalSteps, false + } + var steps int + /* Wenn sich eins nach der Verschiebungsrichtung auch unserer quer parkendes Auto befindet, + muss es nur um einen Platz verschoben werden, ansonsten um zwei. */ + if querAutos[i + direction] == querAuto { + steps = 1 + } else { + steps = 2 + } + endCar := i + direction * 2 // ist das Ende des verschobenen Autos, das realtiv zur verschobenen Richtung, vorne ist. + + /* müsste das Auto ausserhalb des Parkplatzes geschoben werden, + damit unser normale Parkplatz frei wird, ist das Verschieben in diese Richtung nicht möglich. */ + if outOfBounds(querAutos, endCar) { + return movedCars, totalSteps, false + } + // fügt das gerade verschobene Auto der Slice mit den verschobenen Autos hinzu. + movedCars = append(movedCars, movedCar{querAuto, steps, direction}) + /* ruft die Funktion recursive auf, mit dem Index des Parkplatzes an dem + noch ein quer stehendes Auto stehen könnte, das verschoben werden müsste. */ + return move(endCar, direction, movedCars, querAuto, totalSteps + uint32(steps)) +} + +// Funktion um zu überprüfen, ob ein Index innerhalb einer Slice liegt. +func outOfBounds(slice []byte, i int) bool { + return i < 0 || i >= len(slice) +} +``` diff --git a/a2-Vollgeladen/README.md b/a2-Vollgeladen/README.md new file mode 100644 index 0000000..f488194 --- /dev/null +++ b/a2-Vollgeladen/README.md @@ -0,0 +1,107 @@ +# Vollgeladen + +## Lösungsidee + +Da die niedrigste Bewertung möglichst hoch sein soll, sollte zuerst versucht +eine Route mit einer Mindestbewertung von 5.0 zu bilden. Scheitert dies wird +es mit 4.9, 4.8, ..., 0.1 versucht. Das Routenbildung mit einer bestimmten +Mindestbewertung kann aus zwei Gründen fehlschlagen: + +- innerhalb der 6 Stunden Fahrzeit gibt es kein Hotel mit der Mindestbewertung +- an mehr als 4 Hotels muss gehalten werden + +## Umsetzung + +Die Lösungsidee wird in C implementiert. Eine Hilfsfunktion der +"advanced C standard library", die Textdateien ausliest, wird außerdem verwendet. +Der Quelltext der Library ist im Ordner "lib/advanced_C_standard_library" oder +[online](https://git.zinkel.org/MrGeorgen/advanced_C_standard_library) erhältlich. +Das Programm erhält als Argumente eine beliebige Anzahl Dateipfade zu Eingabedateien. +Mit einer for-Schleife wird über die Dateipfade iteriert. In der Schleife wird die +Eingabedatei ausgelesen. Die Anzahl der Hotels und die Gesamtfahrzeit werden jeweils +in einer Variable abgespeichert. Anschließend wird ein Array mit Strukturen die Hotels +darstellen befüllt. In einer do-while-Schleife wird mit einer Bewertung von +5.0, 4.9, ..., 0.1 eine Route zu bilden. Wenn dies bei einer Bewertung erfolgreich +ist wird die Schleife beendet. In dieser Schleife ist wiederum eine for-Schleife +die über die Hotels iteriert, worin das letzte Hotel gespeichert wird, das +mindestens die angestrebte Bewertung hat. +Ist das Hotel allerdings mehr als 6 Stunden vom letzten Haltepunkt entfernt, +muss das letzte Hotel verwendet werden an dem das Halten möglich ist, falls dieses +vorhanden ist und höchtens an drei Hotels schon gehalten wurde, +ansonsten muss mit der nächsten Bewertung fortgefahren werden. +Nachdem eine Route gefunden wurde, wird diese ausgeben und eventuell mit der +näcshten Eingabedatei fortgefahren. + +## Beispiele + +Ergebnisse für die Beispieldaten: + +``` +hotels1.txt: +Entfernung vom Start: 347 Minuten, Bewertung: 2.7 +Entfernung vom Start: 687 Minuten, Bewertung: 4.4 +Entfernung vom Start: 1007 Minuten, Bewertung: 2.8 +Entfernung vom Start: 1360 Minuten, Bewertung: 2.8 +hotels2.txt: +Entfernung vom Start: 341 Minuten, Bewertung: 2.3 +Entfernung vom Start: 700 Minuten, Bewertung: 3.0 +Entfernung vom Start: 1053 Minuten, Bewertung: 4.8 +Entfernung vom Start: 1380 Minuten, Bewertung: 5.0 +hotels3.txt: +Entfernung vom Start: 360 Minuten, Bewertung: 1.0 +Entfernung vom Start: 717 Minuten, Bewertung: 0.3 +Entfernung vom Start: 1076 Minuten, Bewertung: 3.8 +Entfernung vom Start: 1433 Minuten, Bewertung: 1.7 +hotels4.txt: +Entfernung vom Start: 340 Minuten, Bewertung: 4.6 +Entfernung vom Start: 676 Minuten, Bewertung: 4.6 +Entfernung vom Start: 1032 Minuten, Bewertung: 4.9 +Entfernung vom Start: 1316 Minuten, Bewertung: 4.9 +hotels5.txt: +Entfernung vom Start: 317 Minuten, Bewertung: 5.0 +Entfernung vom Start: 636 Minuten, Bewertung: 5.0 +Entfernung vom Start: 987 Minuten, Bewertung: 5.0 +Entfernung vom Start: 1286 Minuten, Bewertung: 5.0 +``` + +## Quelltext + +``` +int main() { + uint_least8_t rating = 50; + do { + // Minuten die das letzte Hotel, bei dem angehalten wurde, vom Start entfertn ist + uint_least16_t lastHotelMinutes = 0; + // Zeiger zum letzten Hotel, dessen Bewertung mindestens "rating" ist. + struct hotel *possibleStop = NULL; + stoppedHotels = 0; // setzt Anzahl der Stops zurück + + // iteriert über die Hotels + for(struct hotel *currentHotel = hotels; currentHotel - hotels < numberHotels; ++currentHotel) { + + /* Wenn das aktuelle Hotel mehr als 360 Minuten vom letzten Hotel entfernt ist, + * muss das letzte Hotel verwendet werden an dem das Halten möglich war.*/ + if(currentHotel->minutes - lastHotelMinutes > 360) { + /* Wenn das Halten nicht möglich ist oder bereits schon viermal + * gehalten wurde, muss es mit einer niedrigeren Bewertung versucht + * werden.*/ + if(possibleStop == NULL || stoppedHotels >= 4) break; + // hängt das Hotel der Route an + hotelRoute[stoppedHotels] = *possibleStop; + lastHotelMinutes = possibleStop->minutes; + // springt in der Schleife zurück zum Hotel, an dem gestoppt wurde + currentHotel = possibleStop; + ++stoppedHotels; + } + // Wenn die Bewertung hoch genug ist, kann gestoppt werden. + if(currentHotel->rating >= rating) possibleStop = currentHotel; + } + --rating; + /* Schleife läuft solange "rating" mindestens Eins ist, da es keine niedrigeren Bewertungen + * gibt. Wenn das letzte Hotel höchtens 360 Minuten vom Zielort entfernt ist, wurde + * erfolgreich eine Route gefunden und die Schleife wird beendet. Allerdings wird dies nur + * überprüft, wenn überhaupt an einem Hotel gehalten wurde, um den Zugriff auf nicht + * definierten Speicher zu vermeiden.*/ + } while(rating && (!stoppedHotels || totalMinutes - hotelRoute[stoppedHotels - 1].minutes > 360)); +} +``` diff --git a/a4-Wuerfelglueck/Cargo.lock b/a4-Wuerfelglueck/Cargo.lock new file mode 100644 index 0000000..705c9ab --- /dev/null +++ b/a4-Wuerfelglueck/Cargo.lock @@ -0,0 +1,85 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "a4-Wuerfelglueck" +version = "0.1.0" +dependencies = [ + "rand", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" + +[[package]] +name = "ppv-lite86" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741" + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/a4-Wuerfelglueck/Cargo.toml b/a4-Wuerfelglueck/Cargo.toml new file mode 100644 index 0000000..4eb1e84 --- /dev/null +++ b/a4-Wuerfelglueck/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "a4-Wuerfelglueck" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rand = "0.8.4" diff --git a/a4-Wuerfelglueck/README.md b/a4-Wuerfelglueck/README.md new file mode 100644 index 0000000..4b7ecd6 --- /dev/null +++ b/a4-Wuerfelglueck/README.md @@ -0,0 +1,5 @@ +# Würfelglück + +## Lösungsidee + + diff --git a/a4-Wuerfelglueck/src/main.rs b/a4-Wuerfelglueck/src/main.rs new file mode 100644 index 0000000..ce4b49b --- /dev/null +++ b/a4-Wuerfelglueck/src/main.rs @@ -0,0 +1,260 @@ +use std::env; +use std::fs; +use std::vec; +use rand::distributions::{Distribution, Uniform}; +use std::collections::HashSet; + +// Struktur für die Würfel +struct Dice { + wins: u32, + defeats: u32, + sides: vec::Vec, + + // Iterator über Zufallszahlen von der "rand" Bibliothek + rand_iter: rand::distributions::DistIter, rand::rngs::ThreadRng, usize>, + different_sides_count: u8 // wird benötigt, um festzustellen, ob ein Spieler stecken geblieben ist +} + +/* 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 + * Spieler 1. Diesen Spielern sind keine Farben zugeordnet. Wichtig ist nur, dass sie gegenüber + * liegen. */ +struct Field { + b: [u8; 2], // Anzahl der Figuren auf den B Feldern + + /* Laufbahn: Feld A von Spieler 0 ist bei Index 0 und von Spieler 1 bei Index 20. + * 0 und 1 repräsentieren die Spieler und -1 ein leeres Feld. */ + main: [i8; 40], + destination: [[i8; 4]; 2], // Zielfelder + + /* Indexe der Figuren: 0-39 für die Laufbahn. -1 ist das Zielfeld, das man am schnellsten + * erreicht und -4 das Letzte. -5 ist eine Figur auf Feld B. */ + pieces: [[i8; 4]; 2] +} +impl Field { + + // Methode, die die Figuren laufen lässt. piece ist der Index im piece Array. + fn step(&mut self, turn: usize, piece: usize, steps: u8) -> bool { + let i_start = self.pieces[turn][piece]; // Feld auf dem die Figur momentan steht + let i_end = if i_start >= 0 { + + // Feld auf das Figur nach dem Zug steht, solange es keine Besonderheiten gibt. + let i = i_start + steps as i8; + if turn == 0 { + let end = self.main.len() as i8 - 1; + + // Sollte i abseits der Laufbahn liegen, so läuft Spieler 0 ins Ziel. + if i > end {end - i} else {i} + } + else { + if i >= 20 && i_start < 20 {19 - i} // Nach Index 19 ist für Spieler 1 das Ziel. + + // Nach Index 39 muss Spieler 1 wieder bei Index 0 anfangen. + else if i >= self.main.len() as i8 {i - self.main.len() as i8} else {i} + } + } + else if i_start == -5 {(20 * turn) as i8} // startet die Figur auf einem B-Feld, muss sie auf Feld A. + + /* ist die Figur bereits auf einem Zielfeld, muss sie in negativer Richtung laufen, da die + * Zielfelder Indexe auch negativ sind. */ + else {i_start - steps as i8}; + + /* Würde die Figur außerhalb des Spielfelds laufen oder das Feld wird von einer eignen + * Figur blockiert, kann sie nicht laufen. */ + if i_end < -4 || *self.at(turn, i_end) == turn as i8 { + return false; + } + self.beat(turn, i_end); // schlägt mögliche gegnerische Figuren + + // setzt die Figur an die neue Position + self.pieces[turn][piece] = i_end; + if i_start == -5 {self.b[turn] -= 1;} + else {*self.at(turn, i_start) = -1;} + *self.at(turn, i_end) = turn as i8; + return true; + } + + // Methode, die gegnerische Figuren schlägt, wenn eine an der angebenen Position steht. + fn beat(&mut self, turn: usize, position: i8) { + let not_turn = other_player(turn); + if position >= 0 && self.main[position as usize] == not_turn as i8 { + for piece in self.pieces[not_turn].iter_mut() { + if *piece == position { + *piece = -5; + self.b[not_turn] += 1; + } + } + } + } + + // Methode, welche eine Referenz zu der Figur mit dem entsprechenden Index zurückgibt. + fn at(&mut self, player: usize, position: i8) -> &mut i8 { + if position >= 0 {&mut self.main[position as usize]} + else {&mut self.destination[player][(-position - 1) as usize]} + } + + // sucht eine Figur mit der entsprechenden Position und gibt den piece Array Index zurück. + fn field_i_to_piece_i(&self, player: usize, position: i8) -> Option { + for (i, piece) in self.pieces[player].iter().enumerate() { + if *piece == position {return Some(i);} + } + return None; + } +} + +fn main() { + let runs = 100000; // Anzahl der Spiele, die für jede mögliche Würfelkombination simuliert wird + for filepath in env::args().skip(1) { // for-Schleife, die über Dateipfade der Eingabedateien iteriert + let mut dices: vec::Vec; + let content = fs::read_to_string(&filepath).unwrap(); // Eingabedatei wird gelesen. + let mut line_iter = content.lines(); // Iterator über die Zeilen der Datei + let mut no_move_possible: [HashSet; 2] = [HashSet::with_capacity(20), HashSet::with_capacity(20)]; + + // Speicher für die Würfel wird reserviert. + dices = vec::Vec::with_capacity(line_iter.next().unwrap().parse().unwrap()); + for line in line_iter { + let mut dice: Dice; + { + let mut dice_sides = line.split(" "); // Die Zahlen für einen Würfel werden mit einem Leerzeichen getrennt. + let dice_sides_count = dice_sides.next().unwrap().parse().unwrap(); + dice = Dice { + wins: 0, + defeats: 0, + sides: vec::Vec::with_capacity(dice_sides_count), + + /* Zufallszahleniterator wird erstellt, der Zahlen von 0 (inklusive) bis zur + * Anzahl der verschieden Seiten des Würfels (exklusive) generiert. */ + rand_iter: Uniform::new(0, dice_sides_count).sample_iter(rand::thread_rng()), + different_sides_count: 0 + }; + for side in dice_sides { + // Die Augenzahlen des Würfels werden im einen Vector gespeichert. + dice.sides.push(side.parse().unwrap()); + } + + // bestimmt die Anzahl der verschiedenen Augenzahlen + { + let mut different_sides_count = 0; + let mut last_side: Option = None; + for side in dice.sides.iter() { + if last_side != Some(*side) {different_sides_count += 1;} + last_side = Some(*side); + } + dice.different_sides_count = different_sides_count as u8; + } + } + + // der Würfel tritt gegen alle bereits verarbeiteten 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], + main: [-1; 40], + destination: [[-1; 4]; 2], + pieces: [[-5; 4]; 2], + }; + let mut win = false; + while !win { // Schleife solange niemand gewonnen hat. + + // würfelt mittels Zufallsgenerator. + let dice_result = selected_dices[turn].sides[selected_dices[turn].rand_iter.next().unwrap()]; + let field_0_blocked = field.main[turn * 20] == turn as i8; + + // Wenn eine Figur gezogen wurde + if field.b[turn] != 0 && (field_0_blocked && // ist Feld A blockiert ... + + // ... wird das Feld freigeräumt. + field.step(turn, field.field_i_to_piece_i(turn, (turn * 20) as i8).unwrap() , dice_result) || + + // Bei einer 6 wird eine neue Figur herrausgezogen. + dice_result == 6 && field.step(turn, field.field_i_to_piece_i(turn, -5).unwrap(), dice_result)) || { + let mut result = false; + + // die Figuren werden sortiert; die nah am Ziel sind kommen zuerst. + field.pieces[turn].sort_by(|a, b| { + let mut values = [*a, *b]; + if turn == 1 { + for value in values.iter_mut() { + if *value >= 0 && *value < 20 {*value += 40;} + } + } + values[1].partial_cmp(&values[0]).unwrap() + }); + + // Es wird versucht die Figuren zu ziehen. + let pieces_turn = field.pieces[turn]; + for (i, position) in pieces_turn.iter().enumerate() { + if *position == -5 {break;} + if field.step(turn, i, dice_result) {result = true; break;} + } + result + } { + + // 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. + selected_dices[turn].wins += 1; + selected_dices[other_player(turn)].defeats += 1; + } + + /* Da wieder eine Figur gezogen wurde, muss der HashSet mit den + * Augenzahlen bei denen nicht gezogen werden kann, zurückgesetzt + * werden. */ + for map in no_move_possible.iter_mut() { + map.clear(); + } + } + else { + + /* 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 + * 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. + } + } + } + } + dices.push(dice); + } + + // sotiert die Würfel nach Gewinnen + dices.sort_unstable_by(|a, b| b.wins.partial_cmp(&a.wins).unwrap()); + + + // gibt das Ergebnis aus + let games_per_dice = ((dices.len() - 1) * runs * 2) as u32; + println!("{}:", filepath); + for (i, dice) in dices.iter().enumerate() { + let ties = games_per_dice - dice.wins - dice.defeats; + println!(concat!("{i}. Würfel: Würfelseiten: {würfelseiten:?}, ", + "Siege: {siege}, Siegwahrscheinlichkeit: {siegwahrscheinlichkeit}, ", + "Niederlagen: {niederlagen}, Niederlagewahrscheinlichkeit: {niederlagewahrscheinlichkeit}, ", + "Unentschieden: {unentschieden}, Unentschiedenwahrscheinlichkeit: {unentschiedenwahrscheinlichkeit}"), + i = i + 1, würfelseiten = dice.sides, + siege = dice.wins, siegwahrscheinlichkeit = dice.wins as f64 / games_per_dice as f64, + niederlagen = dice.defeats, niederlagewahrscheinlichkeit = dice.defeats as f64 / games_per_dice as f64, + unentschieden = ties, unentschiedenwahrscheinlichkeit = ties as f64 / games_per_dice as f64 + ); + } + } +} + +// Funktion, um den anderen Spieler zu erhalten +fn other_player(player: usize) -> usize { + if player == 0 {1} else {0} +}