blackjack/Components/Pages/BlackjackGame.razor

313 lines
11 KiB
Plaintext
Raw Permalink Normal View History

2025-04-17 22:25:37 +07:00
@page "/"
@page "/blackjack"
2025-04-16 14:27:41 +07:00
@using БлэкДжек.Components
@implements IDisposable
2025-04-17 22:25:37 +07:00
@rendermode InteractiveServer
2025-04-16 14:27:41 +07:00
<div class="casino-background">
<div class="blackjack-container">
<div class="game-header">
<h1 class="game-title">Blackjack</h1>
<div class="chip-stack"></div>
</div>
2025-04-16 14:27:41 +07:00
@* Область для сообщений игры *@
@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>
}
2025-04-16 14:27:41 +07:00
@* Основной блок игры, отображается после нажатия "Начать" *@
@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)
{
2025-04-17 22:25:37 +07:00
<div class="playing-card card-back"></div>
2025-04-16 14:27:41 +07:00
}
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>
2025-04-16 14:27:41 +07:00
<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>
2025-04-16 14:27:41 +07:00
<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>
2025-04-16 14:27:41 +07:00
@* Кнопки действий *@
<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>
2025-04-16 14:27:41 +07:00
</div>
@code {
// --- Поля состояния игры ---
private Deck GameDeck;
2025-04-16 14:27:41 +07:00
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;
2025-04-16 14:27:41 +07:00
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 = "Ваш ход. Взять карту или стоп?";
2025-04-16 14:27:41 +07:00
IsGameStarted = true;
// Раздаем по 2 карты
PlayerHand.Add(GameDeck.DealCard());
2025-04-16 14:27:41 +07:00
DealerHand.Add(GameDeck.DealCard());
PlayerHand.Add(GameDeck.DealCard());
2025-04-16 14:27:41 +07:00
DealerHand.Add(GameDeck.DealCard());
2025-04-16 14:27:41 +07:00
// Проверка на блэкджек
if (PlayerScore == 21 && DealerHand.Count == 2)
{
2025-04-16 14:27:41 +07:00
if (DealerScore == 21)
{
RevealDealerCardAndEndGame("Ничья! У обоих Блэкджек!");
}
2025-04-16 14:27:41 +07:00
else
{
RevealDealerCardAndEndGame("Блэкджек! Вы выиграли!");
}
}
2025-04-16 14:27:41 +07:00
else if (DealerScore == 21 && DealerHand.Count == 2)
{
RevealDealerCardAndEndGame("Блэкджек у дилера! Вы проиграли.");
}
2025-04-16 14:27:41 +07:00
StateHasChanged();
}
// --- Действие игрока: Взять карту (Hit) ---
private void PlayerHit()
{
2025-04-16 14:27:41 +07:00
if (!IsPlayerTurn || IsGameOver) return;
2025-04-17 22:25:37 +07:00
var newCard = GameDeck.DealCard();
if (newCard != null)
{
2025-04-17 22:25:37 +07:00
PlayerHand.Add(newCard);
if (PlayerScore > 21)
{
EndGame("Перебор! Вы проиграли.");
}
else if (PlayerScore == 21)
{
PlayerStand();
}
}
2025-04-17 22:25:37 +07:00
else
{
2025-04-17 22:25:37 +07:00
// Колода пуста, можно обработать этот случай
GameMessage = "Колода пуста! Создается новая колода...";
GameDeck = new Deck();
GameDeck.Shuffle();
}
2025-04-16 14:27:41 +07:00
StateHasChanged();
}
// --- Действие игрока: Стоп (Stand) ---
private void PlayerStand()
{
2025-04-16 14:27:41 +07:00
if (!IsPlayerTurn || IsGameOver) return;
2025-04-16 14:27:41 +07:00
IsPlayerTurn = false;
GameMessage = "Дилер ходит...";
2025-04-16 14:27:41 +07:00
StateHasChanged();
2025-04-16 14:27:41 +07:00
DealerTurn();
}
// --- Логика хода Дилера ---
private void DealerTurn()
{
while (DealerScore < 17)
{
DealerHand.Add(GameDeck.DealCard());
}
DetermineWinner();
2025-04-16 14:27:41 +07:00
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++;
}
}
2025-04-16 14:27:41 +07:00
// Корректировка значения Тузов
while (score > 21 && aceCount > 0)
{
2025-04-16 14:27:41 +07:00
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)
{
2025-04-16 14:27:41 +07:00
IsPlayerTurn = false;
EndGame(message);
}
private void EndGame(string message)
{
IsGameOver = true;
2025-04-16 14:27:41 +07:00
IsPlayerTurn = false;
GameMessage = message;
}
// --- Вспомогательный метод для определения цвета карты ---
private string GetCardColor(Card card)
{
return (card.Suit == "♥" || card.Suit == "♦") ? "card-red" : "card-black";
}
2025-04-16 14:27:41 +07:00
// --- Реализация IDisposable ---
public void Dispose()
{
2025-04-16 14:27:41 +07:00
// Реализация IDisposable
}
}