@* --- НАЧАЛО КОДА ДЛЯ BlackjackGame.razor --- *@ @page "/blackjack" @using БлэкДжек.Components @* <--- ВОТ ЭТУ СТРОКУ НУЖНО ПРОВЕРИТЬ/ЗАМЕНИТЬ *@ @implements IDisposable

Blackjack

@* Область для сообщений игры *@ @if (!string.IsNullOrEmpty(GameMessage)) { } @* Основной блок игры, отображается после нажатия "Начать" *@ @if (IsGameStarted) {

Дилер (@(IsPlayerTurn ? "?" : DealerScore.ToString()))

@foreach (var card in DealerHand) { @* Условие для скрытия первой карты дилера во время хода игрока *@
@((DealerHand.IndexOf(card) == 0 && IsPlayerTurn) ? "???" : card.Display)
}

Игрок (@PlayerScore)

@foreach (var card in PlayerHand) {
@card.Display
}

@* Кнопки действий *@
} else { @* Кнопка для старта игры, видна только до начала *@ } @* Блок с C# кодом *@ @code { // --- Поля состояния игры --- private Deck GameDeck; private List PlayerHand = new List(); // Инициализируем, чтобы избежать null reference до старта private List DealerHand = new List(); // Инициализируем // --- Вычисляемые свойства для счета --- private int PlayerScore => CalculateScore(PlayerHand); private int DealerScore => CalculateScore(DealerHand); // --- Флаги состояния игры --- private bool IsPlayerTurn; private bool IsGameOver; private bool IsGameStarted; // Показывает, была ли нажата кнопка "Начать игру" private string GameMessage = string.Empty; // Инициализируем пустой строкой // --- Инициализация компонента --- protected override void OnInitialized() { // Игра не начинается автоматически при загрузке страницы IsGameStarted = false; } // --- Метод начала новой игры --- private void StartGame() { GameDeck = new Deck(); GameDeck.Shuffle(); PlayerHand = new List(); DealerHand = new List(); IsGameOver = false; IsPlayerTurn = true; GameMessage = "Ваш ход. Взять карту или стоп?"; IsGameStarted = true; // Показываем игровое поле // Раздаем по 2 карты PlayerHand.Add(GameDeck.DealCard()); DealerHand.Add(GameDeck.DealCard()); // Первая карта дилера PlayerHand.Add(GameDeck.DealCard()); DealerHand.Add(GameDeck.DealCard()); // Вторая карта дилера // Проверка на блэкджек у игрока или дилера сразу после раздачи if (PlayerScore == 21 && DealerHand.Count == 2) // У игрока блэкджек { if (DealerScore == 21) // У дилера тоже блэкджек { RevealDealerCardAndEndGame("Ничья! У обоих Блэкджек!"); } else // Только у игрока блэкджек { RevealDealerCardAndEndGame("Блэкджек! Вы выиграли!"); } } else if (DealerScore == 21 && DealerHand.Count == 2) // Только у дилера блэкджек (проверяем после игрока) { RevealDealerCardAndEndGame("Блэкджек у дилера! Вы проиграли."); } // Если ни у кого нет блэкджека, игра продолжается с сообщением "Ваш ход..." StateHasChanged(); // Обновляем UI, чтобы показать начальное состояние } // --- Действие игрока: Взять карту (Hit) --- private void PlayerHit() { if (!IsPlayerTurn || IsGameOver) return; // Нельзя брать карту не в свой ход или если игра окончена PlayerHand.Add(GameDeck.DealCard()); if (PlayerScore > 21) { EndGame("Перебор! Вы проиграли."); } else if (PlayerScore == 21) { // Если игрок набрал ровно 21, его ход автоматически завершается PlayerStand(); } // Если меньше 21, игрок может брать еще StateHasChanged(); // Обновляем UI после взятия карты } // --- Действие игрока: Стоп (Stand) --- private void PlayerStand() { if (!IsPlayerTurn || IsGameOver) return; // Нельзя остановиться не в свой ход или если игра окончена IsPlayerTurn = false; // Передаем ход дилеру GameMessage = "Дилер ходит..."; StateHasChanged(); // Обновим сообщение и откроем карту дилера // Можно добавить небольшую задержку перед ходом дилера для наглядности // await Task.Delay(500); // Если раскомментировать, метод должен быть async Task DealerTurn(); // Начинаем ход дилера } // --- Логика хода Дилера --- // Простая синхронная версия. Для пауз нужен async/await и Task.Delay private void DealerTurn() { // Дилер берет карты, пока его счет меньше 17 while (DealerScore < 17) { // В реальном приложении можно добавить паузу здесь // await Task.Delay(800); DealerHand.Add(GameDeck.DealCard()); // StateHasChanged(); // Обновлять UI после каждой карты дилера, если есть пауза } // После того, как дилер закончил брать карты, определяем победителя DetermineWinner(); StateHasChanged(); // Показать финальный результат } // --- Подсчет очков для руки --- private int CalculateScore(List hand) { if (hand == null || hand.Count == 0) return 0; int score = 0; int aceCount = 0; foreach (var card in hand) { score += card.Value; if (card.Rank == "A") { aceCount++; } } // Корректировка значения Тузов (с 11 на 1 при переборе) while (score > 21 && aceCount > 0) { score -= 10; // Считаем Туз как 1 вместо 11 aceCount--; } return score; } // --- Определение победителя --- private void DetermineWinner() { // Убедимся, что карта дилера видна (IsPlayerTurn уже false) if (PlayerScore > 21) { // Это условие уже должно было быть обработано в PlayerHit, но на всякий случай EndGame("Перебор! Вы проиграли."); } else if (DealerScore > 21) { EndGame("У дилера перебор! Вы выиграли!"); } else if (PlayerScore > DealerScore) { EndGame("Вы выиграли!"); } else if (DealerScore > PlayerScore) { EndGame("Дилер выиграл!"); } else // Очки равны { EndGame("Ничья (Push)!"); } } // --- Метод для завершения игры и установки сообщения --- private void RevealDealerCardAndEndGame(string message) { IsPlayerTurn = false; // Убедимся, что карта дилера видна EndGame(message); } private void EndGame(string message) { IsGameOver = true; IsPlayerTurn = false; // Больше никто не ходит GameMessage = message; // StateHasChanged(); // Обычно вызывается в методе, который вызвал EndGame } // --- Вспомогательный метод для определения цвета карты --- private string GetCardColor(Card card) { return (card.Suit == "♥" || card.Suit == "♦") ? "card-red" : "card-black"; } // --- Реализация IDisposable (пока пустая, но может пригодиться) --- public void Dispose() { // Здесь можно остановить таймеры или отписаться от событий, если они будут добавлены } } @* --- КОНЕЦ КОДА ДЛЯ BlackjackGame.razor --- *@