264 lines
10 KiB
Plaintext
264 lines
10 KiB
Plaintext
![]() |
@* --- НАЧАЛО КОДА ДЛЯ BlackjackGame.razor --- *@
|
|||
|
|
|||
|
@page "/blackjack"
|
|||
|
@using БлэкДжек.Components @* <--- ВОТ ЭТУ СТРОКУ НУЖНО ПРОВЕРИТЬ/ЗАМЕНИТЬ *@
|
|||
|
@implements IDisposable
|
|||
|
|
|||
|
<h3>Blackjack</h3>
|
|||
|
|
|||
|
@* Область для сообщений игры *@
|
|||
|
@if (!string.IsNullOrEmpty(GameMessage))
|
|||
|
{
|
|||
|
<div class="alert @(IsGameOver && PlayerScore <= 21 && (DealerScore > 21 || PlayerScore > DealerScore) ? "alert-success" : "alert-info")" role="alert">
|
|||
|
@GameMessage
|
|||
|
</div>
|
|||
|
}
|
|||
|
|
|||
|
@* Основной блок игры, отображается после нажатия "Начать" *@
|
|||
|
@if (IsGameStarted)
|
|||
|
{
|
|||
|
<div>
|
|||
|
<h4>Дилер (@(IsPlayerTurn ? "?" : DealerScore.ToString()))</h4>
|
|||
|
<div class="hand">
|
|||
|
@foreach (var card in DealerHand)
|
|||
|
{
|
|||
|
@* Условие для скрытия первой карты дилера во время хода игрока *@
|
|||
|
<div class="card @GetCardColor(card)">
|
|||
|
@((DealerHand.IndexOf(card) == 0 && IsPlayerTurn) ? "???" : card.Display)
|
|||
|
</div>
|
|||
|
}
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
<hr />
|
|||
|
|
|||
|
<div>
|
|||
|
<h4>Игрок (@PlayerScore)</h4>
|
|||
|
<div class="hand">
|
|||
|
@foreach (var card in PlayerHand)
|
|||
|
{
|
|||
|
<div class="card @GetCardColor(card)">
|
|||
|
@card.Display
|
|||
|
</div>
|
|||
|
}
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
<hr />
|
|||
|
|
|||
|
@* Кнопки действий *@
|
|||
|
<div class="actions">
|
|||
|
<button class="btn btn-primary" @onclick="PlayerHit" disabled="@(!IsPlayerTurn || IsGameOver)">Взять карту (Hit)</button>
|
|||
|
<button class="btn btn-secondary" @onclick="PlayerStand" disabled="@(!IsPlayerTurn || IsGameOver)">Стоп (Stand)</button>
|
|||
|
<button class="btn btn-warning" @onclick="StartGame">Новая игра</button>
|
|||
|
</div>
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
@* Кнопка для старта игры, видна только до начала *@
|
|||
|
<button class="btn btn-success btn-lg" @onclick="StartGame">Начать игру</button>
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
@* Блок с C# кодом *@
|
|||
|
@code {
|
|||
|
// --- Поля состояния игры ---
|
|||
|
private Deck GameDeck;
|
|||
|
private List<Card> PlayerHand = new List<Card>(); // Инициализируем, чтобы избежать null reference до старта
|
|||
|
private List<Card> DealerHand = new List<Card>(); // Инициализируем
|
|||
|
|
|||
|
// --- Вычисляемые свойства для счета ---
|
|||
|
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<Card>();
|
|||
|
DealerHand = new List<Card>();
|
|||
|
|
|||
|
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<Card> 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 --- *@
|