blackjack/Components/Pages/BlackjackGame.razor
2025-04-17 22:25:37 +07:00

313 lines
11 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@page "/"
@page "/blackjack"
@using БлэкДжек.Components
@implements IDisposable
@rendermode InteractiveServer
<div class="casino-background">
<div class="blackjack-container">
<div class="game-header">
<h1 class="game-title">Blackjack</h1>
<div class="chip-stack"></div>
</div>
@* Область для сообщений игры *@
@if (!string.IsNullOrEmpty(GameMessage))
{
<div class="message-box @(IsGameOver && PlayerScore <= 21 && (DealerScore > 21 || PlayerScore > DealerScore) ? "message-win" : IsGameOver ? "message-lose" : "message-info")" role="alert">
<div class="message-content">@GameMessage</div>
</div>
}
@* Основной блок игры, отображается после нажатия "Начать" *@
@if (IsGameStarted)
{
<div class="game-area">
<div class="player-section dealer-section">
<div class="player-info">
<div class="player-avatar dealer-avatar"></div>
<h2 class="player-title">Дилер <span class="score-badge">@(IsPlayerTurn ? "?" : DealerScore.ToString())</span></h2>
</div>
<div class="table-felt">
<div class="hand dealer-hand">
@foreach (var card in DealerHand)
{
<div class="card-container @(DealerHand.IndexOf(card) == 0 && IsPlayerTurn ? "card-hidden" : "")">
@if (DealerHand.IndexOf(card) == 0 && IsPlayerTurn)
{
<div class="playing-card card-back"></div>
}
else
{
<div class="playing-card @GetCardColor(card)">
<div class="card-corner top-left">
<div class="card-rank">@card.Rank</div>
<div class="card-suit">@card.Suit</div>
</div>
<div class="card-center-suit">@card.Suit</div>
<div class="card-corner bottom-right">
<div class="card-rank">@card.Rank</div>
<div class="card-suit">@card.Suit</div>
</div>
</div>
}
</div>
}
</div>
</div>
</div>
<div class="table-divider">
<div class="chip red-chip"></div>
<div class="chip blue-chip"></div>
<div class="chip green-chip"></div>
<div class="chip black-chip"></div>
</div>
<div class="player-section player-section-user">
<div class="player-info">
<div class="player-avatar player-avatar-user"></div>
<h2 class="player-title">Игрок <span class="score-badge">@PlayerScore</span></h2>
</div>
<div class="table-felt">
<div class="hand player-hand">
@foreach (var card in PlayerHand)
{
<div class="card-container">
<div class="playing-card @GetCardColor(card)">
<div class="card-corner top-left">
<div class="card-rank">@card.Rank</div>
<div class="card-suit">@card.Suit</div>
</div>
<div class="card-center-suit">@card.Suit</div>
<div class="card-corner bottom-right">
<div class="card-rank">@card.Rank</div>
<div class="card-suit">@card.Suit</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
@* Кнопки действий *@
<div class="action-buttons">
<button class="btn-3d btn-hit" @onclick="PlayerHit" disabled="@(!IsPlayerTurn || IsGameOver)">
<span class="btn-icon hit-icon"></span>
<span>Взять карту</span>
</button>
<button class="btn-3d btn-stand" @onclick="PlayerStand" disabled="@(!IsPlayerTurn || IsGameOver)">
<span class="btn-icon stand-icon"></span>
<span>Стоп</span>
</button>
<button class="btn-3d btn-new-game" @onclick="StartGame">
<span class="btn-icon new-game-icon"></span>
<span>Новая игра</span>
</button>
</div>
</div>
}
else
{
<div class="start-screen">
<div class="game-logo"></div>
<button class="btn-3d btn-start" @onclick="StartGame">Начать игру</button>
</div>
}
</div>
</div>
@code {
// --- Поля состояния игры ---
private Deck GameDeck;
private List<Card> PlayerHand = new List<Card>();
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();
}
// --- Действие игрока: Взять карту (Hit) ---
private void PlayerHit()
{
if (!IsPlayerTurn || IsGameOver) return;
var newCard = GameDeck.DealCard();
if (newCard != null)
{
PlayerHand.Add(newCard);
if (PlayerScore > 21)
{
EndGame("Перебор! Вы проиграли.");
}
else if (PlayerScore == 21)
{
PlayerStand();
}
}
else
{
// Колода пуста, можно обработать этот случай
GameMessage = "Колода пуста! Создается новая колода...";
GameDeck = new Deck();
GameDeck.Shuffle();
}
StateHasChanged();
}
// --- Действие игрока: Стоп (Stand) ---
private void PlayerStand()
{
if (!IsPlayerTurn || IsGameOver) return;
IsPlayerTurn = false;
GameMessage = "Дилер ходит...";
StateHasChanged();
DealerTurn();
}
// --- Логика хода Дилера ---
private void DealerTurn()
{
while (DealerScore < 17)
{
DealerHand.Add(GameDeck.DealCard());
}
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++;
}
}
// Корректировка значения Тузов
while (score > 21 && aceCount > 0)
{
score -= 10;
aceCount--;
}
return score;
}
// --- Определение победителя ---
private void DetermineWinner()
{
if (PlayerScore > 21)
{
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;
}
// --- Вспомогательный метод для определения цвета карты ---
private string GetCardColor(Card card)
{
return (card.Suit == "♥" || card.Suit == "♦") ? "card-red" : "card-black";
}
// --- Реализация IDisposable ---
public void Dispose()
{
// Реализация IDisposable
}
}