using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; namespace Casino { public partial class Busfahrer : Window { public class Card { public int Id { get; set; } public string WertRaw { get; set; } = string.Empty; public string FarbeRaw { get; set; } = string.Empty; public ImageSource Image { get; set; } = null!; public int NumericValue { get; set; } public bool IsRed => FarbeRaw.Equals("Hearts", StringComparison.OrdinalIgnoreCase) || FarbeRaw.Equals("Diamonds", StringComparison.OrdinalIgnoreCase) || FarbeRaw.Equals("Diamond", StringComparison.OrdinalIgnoreCase) || FarbeRaw.Equals("Herz", StringComparison.OrdinalIgnoreCase) || FarbeRaw.Equals("Karo", StringComparison.OrdinalIgnoreCase); public Card(int id, string wert, string farbe, byte[] imgBytes) { Id = id; WertRaw = wert; FarbeRaw = farbe; NumericValue = ParseValue(wert); if (imgBytes != null && imgBytes.Length > 0) { Image = ByteArrayToImage(imgBytes); } } private static int ParseValue(string wert) { return wert.Trim() switch { "Jack" or "Bube" => 11, "Queen" or "Dame" => 12, "King" or "König" => 13, "Ace" or "Ass" => 14, _ => int.TryParse(wert, out int value) ? value : 0 }; } private static BitmapImage ByteArrayToImage(byte[] bytes) { BitmapImage image = new BitmapImage(); using (MemoryStream ms = new MemoryStream(bytes)) { image.BeginInit(); image.CacheOption = BitmapCacheOption.OnLoad; image.StreamSource = ms; image.EndInit(); } image.Freeze(); return image; } } private readonly Database db = new Database(); private ObservableCollection users; private List deck = new List(); private List handCards = new List(); private ImageSource cardBackImage = null!; Audioplayer music = new Audioplayer(); private int currentPhase = 0; private decimal currentBet = 0; private decimal currentProfit = 0; private bool roundRunning = false; public Busfahrer() { InitializeComponent(); users = db.GetUser(); UpdateAccountDisplay(); ShowWaitingState(); music.PlayLoopingSound_2(db.GetSound(20)); } private User CurrentUser => users[MainWindow.currentUser]; // ========================= // KONTO // ========================= private void UpdateAccountDisplay() { Konto.Text = CurrentUser.Geld.ToString(); } private void SaveAccount() { db.UpdateGeld(CurrentUser.ID, CurrentUser.Geld); UpdateAccountDisplay(); } // ========================= // SPIEL STARTEN // ========================= private void BtnStart_Click(object sender, RoutedEventArgs e) { StartGameFromInput(); } private void StartGameFromInput() { if (roundRunning) { return; } if (!int.TryParse(TxtBet.Text, out int bet) || bet <= 0) { MessageBox.Show( "Bitte gib einen gültigen Einsatz ein.", "Ungültiger Einsatz", MessageBoxButton.OK, MessageBoxImage.Warning); return; } if (bet > CurrentUser.Geld) { MessageBox.Show( "Du hast nicht genug Geld für diesen Einsatz.", "Zu wenig Geld", MessageBoxButton.OK, MessageBoxImage.Warning); return; } currentBet = bet; StartRound(); } private void StartRound() { if (currentBet <= 0 || currentBet > CurrentUser.Geld) { ShowWaitingState(); return; } // Einsatz vom Konto abziehen CurrentUser.Geld -= Convert.ToInt32(currentBet); SaveAccount(); currentProfit = 0; currentPhase = 0; roundRunning = true; TxtBet.IsEnabled = false; LoadCards(); UpdateHandUI(); UpdateWinDisplay(); SetPhaseUI(); } private void LoadCards() { deck = db.GetAllCards() .OrderBy(_ => Random.Shared.Next()) .ToList(); byte[] backBytes = db.GetCardBackImage(); if (backBytes != null && backBytes.Length > 0) { cardBackImage = ByteArrayToImage(backBytes); } handCards.Clear(); for (int i = 0; i < 4 && deck.Count > 0; i++) { handCards.Add(DrawCard()); } } private Card DrawCard() { Card card = deck[0]; deck.RemoveAt(0); return card; } // ========================= // KARTEN ANZEIGEN // ========================= private void UpdateHandUI() { Bild_1.Source = cardBackImage; Bild_2.Source = cardBackImage; Bild_3.Source = cardBackImage; Bild_4.Source = cardBackImage; if (handCards.Count < 4) { return; } if (currentPhase >= 1) { Bild_1.Source = handCards[0].Image; } if (currentPhase >= 2) { Bild_2.Source = handCards[1].Image; } if (currentPhase >= 3) { Bild_3.Source = handCards[2].Image; } if (currentPhase >= 4) { Bild_4.Source = handCards[3].Image; } } private void RevealCurrentCard() { if (handCards.Count < 4) { return; } switch (currentPhase) { case 0: Bild_1.Source = handCards[0].Image; break; case 1: Bild_2.Source = handCards[1].Image; break; case 2: Bild_3.Source = handCards[2].Image; break; case 3: Bild_4.Source = handCards[3].Image; break; } } // ========================= // SPIELLOGIK // ========================= private async Task ProcessGuessAsync(bool success) { if (!roundRunning) { return; } RevealCurrentCard(); if (!success) { roundRunning = false; currentProfit = 0; UpdateWinDisplay(); SetPhaseUI(); await Task.Delay(1000); // Nächste Runde mit demselben Einsatz if (currentBet <= CurrentUser.Geld) { StartRound(); } else { ShowWaitingState(); } return; } currentPhase++; currentProfit = CalculateCurrentProfit(); UpdateHandUI(); UpdateWinDisplay(); SetPhaseUI(); // Vierte Frage richtig -> automatisch auszahlen if (currentPhase == 4) { roundRunning = false; PayoutCurrentProfit(); await Task.Delay(1000); // Neue Runde automatisch starten if (currentBet <= CurrentUser.Geld) { StartRound(); } else { ShowWaitingState(); } } } private decimal CalculateCurrentProfit() { return currentPhase switch { 1 => currentBet * 1.75m, 2 => currentBet * 2.5m, 3 => currentBet * 5.0m, 4 => currentBet * 20.0m, _ => 0 }; } // ========================= // FRAGEN // ========================= private async void ColorButton_Click(object sender, RoutedEventArgs e) { if (sender is not Button button) { return; } CardColor chosenColor = button.Tag?.ToString() == "Red" ? CardColor.Red : CardColor.Black; Card card = handCards[0]; bool success = chosenColor == CardColor.Red ? card.IsRed : !card.IsRed; await ProcessGuessAsync(success); } private async void HigherLowerButton_Click(object sender, RoutedEventArgs e) { if (sender is not Button button) { return; } bool higher = button.Tag?.ToString() == "Higher"; Card firstCard = handCards[0]; Card secondCard = handCards[1]; bool success = higher ? secondCard.NumericValue > firstCard.NumericValue : secondCard.NumericValue < firstCard.NumericValue; await ProcessGuessAsync(success); } private async void InsideOutsideButton_Click(object sender, RoutedEventArgs e) { if (sender is not Button button) { return; } bool inside = button.Tag?.ToString() == "Inside"; int firstValue = handCards[0].NumericValue; int secondValue = handCards[1].NumericValue; int thirdValue = handCards[2].NumericValue; int min = Math.Min(firstValue, secondValue); int max = Math.Max(firstValue, secondValue); bool isBetween = thirdValue > min && thirdValue < max; bool success = inside ? isBetween : !isBetween; await ProcessGuessAsync(success); } private async void BtnSuit_Click(object sender, RoutedEventArgs e) { if (sender is not Button button || button.Tag == null) { return; } string chosenSuit = button.Tag.ToString()!; Card card = handCards[3]; bool success = IsSameSuit(card.FarbeRaw, chosenSuit); await ProcessGuessAsync(success); } private static bool IsSameSuit(string cardSuit, string chosenSuit) { if (cardSuit.Equals(chosenSuit, StringComparison.OrdinalIgnoreCase)) { return true; } return chosenSuit switch { "Hearts" => cardSuit.Equals("Herz", StringComparison.OrdinalIgnoreCase), "Diamonds" => cardSuit.Equals("Karo", StringComparison.OrdinalIgnoreCase) || cardSuit.Equals("Diamond", StringComparison.OrdinalIgnoreCase), "Spades" => cardSuit.Equals("Pik", StringComparison.OrdinalIgnoreCase), "Clubs" => cardSuit.Equals("Kreuz", StringComparison.OrdinalIgnoreCase), _ => false }; } private enum CardColor { Red, Black } // ========================= // CASH OUT // ========================= private void BtnCashOut_Click(object sender, RoutedEventArgs e) { if (!roundRunning || currentProfit <= 0) { return; } roundRunning = false; decimal payout = currentProfit; PayoutCurrentProfit(); MessageBox.Show( $"Du hast ${payout:F2} ausgezahlt bekommen!", "Cash Out", MessageBoxButton.OK, MessageBoxImage.Information); ShowWaitingState(); } private void PayoutCurrentProfit() { if (currentProfit <= 0) { return; } CurrentUser.Geld += Convert.ToInt32(currentProfit); SaveAccount(); } // ========================= // UI // ========================= private void SetPhaseUI() { PanelRedBlack.Visibility = Visibility.Collapsed; PanelHigherLower.Visibility = Visibility.Collapsed; PanelInsideOutside.Visibility = Visibility.Collapsed; PanelSuit.Visibility = Visibility.Collapsed; BtnCashOut.Visibility = Visibility.Collapsed; BtnStart.Visibility = Visibility.Collapsed; if (!roundRunning) { return; } switch (currentPhase) { case 0: PanelRedBlack.Visibility = Visibility.Visible; break; case 1: PanelHigherLower.Visibility = Visibility.Visible; BtnCashOut.Visibility = Visibility.Visible; break; case 2: PanelInsideOutside.Visibility = Visibility.Visible; BtnCashOut.Visibility = Visibility.Visible; break; case 3: PanelSuit.Visibility = Visibility.Visible; BtnCashOut.Visibility = Visibility.Visible; break; } } private void ShowWaitingState() { roundRunning = false; currentPhase = 0; currentProfit = 0; UpdateWinDisplay(); SetPhaseUI(); BtnStart.Visibility = Visibility.Visible; TxtBet.IsEnabled = true; } private void UpdateWinDisplay() { BtnCashOut.Content = $"Cash Out (${currentProfit:F2})"; } // ========================= // HAUPTMENÜ // ========================= private void Hauptmenue(object sender, RoutedEventArgs e) { music.Stop(); Close(); } // ========================= // BILD AUS BYTE[] // ========================= private static BitmapImage ByteArrayToImage(byte[] bytes) { BitmapImage image = new BitmapImage(); using (MemoryStream ms = new MemoryStream(bytes)) { image.BeginInit(); image.CacheOption = BitmapCacheOption.OnLoad; image.StreamSource = ms; image.EndInit(); } image.Freeze(); return image; } // ========================= // EINSATZ VALIDIERUNG // ========================= private static readonly Regex NumberRegex = new Regex("^[0-9]+$"); private void TxtBet_PreviewTextInput(object sender, TextCompositionEventArgs e) { e.Handled = !NumberRegex.IsMatch(e.Text); } private void TxtBet_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Space) { e.Handled = true; } } private void TxtBet_Pasting(object sender, DataObjectPastingEventArgs e) { if (!e.DataObject.GetDataPresent(typeof(string))) { e.CancelCommand(); return; } string text = (string)e.DataObject.GetData(typeof(string)); if (!NumberRegex.IsMatch(text)) { e.CancelCommand(); } } } }