using System.Collections; using System.Collections.Generic; using System.Text.RegularExpressions; using UnityEngine; using UnityEngine.UI; using TMPro; using UnityEngine.Events; public class CardSpawnTest : MonoBehaviour { [Header("Card Prefabs")] public GameObject[] cardPrefabs; [Header("Card Setting")] public float cardScale = 2f; public Vector3 frontRotation = new Vector3(-90f, 0f, 90f); public Vector3 backRotation = new Vector3(90f, 0f, 90f); [Header("Player Start Cards")] public Transform playerCardPos1; public Transform playerCardPos2; [Header("Dealer Start Cards")] public Transform dealerOpenCardPos; public Transform dealerHiddenCardPos; [Header("Player Hit Card Positions")] public Transform[] playerHitPositions; [Header("Dealer Hit Card Positions")] public Transform[] dealerHitPositions; [Header("UI Buttons")] public Button hitButton; public Button standButton; [Header("Score UI")] public TMP_Text playerScoreText; public TMP_Text dealerScoreText; public TMP_Text resultText; [Header("Dealer Card UI")] public Image[] dealerCardImages; public Sprite dealerCardBackSprite; public Sprite[] cardSprites; [Header("Win Mark UI")] public GameObject[] playerWinMarks; public GameObject[] dealerWinMarks; [Header("Match Setting")] public int targetWinCount = 3; public float nextRoundDelay = 2f; public float matchEndDelay = 3f; [Header("Match End Event")] public UnityEvent onMatchEnded; private List deck = new List(); private List spawnedCards = new List(); private List playerCards = new List(); private List dealerCards = new List(); private Dictionary cardSpriteMap = new Dictionary(); private int playerHitIndex = 0; private int dealerHitIndex = 0; private int playerWinCount = 0; private int dealerWinCount = 0; private GameObject dealerHiddenCard; private bool isPlayerTurn = false; private bool isGameOver = true; private bool isMatchOver = false; private bool hasMatchStarted = false; private bool isEndingMatch = false; void Awake() { BuildCardSpriteMap(); } void Start() { PrepareBeforeStart(); } void BuildCardSpriteMap() { cardSpriteMap.Clear(); foreach (Sprite sprite in cardSprites) { if (sprite == null) { continue; } string key = NormalizeCardName(sprite.name); if (!cardSpriteMap.ContainsKey(key)) { cardSpriteMap.Add(key, sprite); } } } void PrepareBeforeStart() { ClearSpawnedCards(); playerCards.Clear(); dealerCards.Clear(); playerHitIndex = 0; dealerHitIndex = 0; playerWinCount = 0; dealerWinCount = 0; isPlayerTurn = false; isGameOver = true; isMatchOver = false; hasMatchStarted = false; isEndingMatch = false; HideAllWinMarks(); HideDealerCardUI(); if (resultText != null) { resultText.gameObject.SetActive(false); } if (playerScoreText != null) { playerScoreText.text = "Ç÷¹À̾î: 0"; } if (dealerScoreText != null) { dealerScoreText.text = "¼±Àå: ?"; } if (hitButton != null) { hitButton.interactable = false; } if (standButton != null) { standButton.interactable = false; } Debug.Log("ºí·¢Àè Áغñ ¿Ï·á. Ç÷¹À̾ ¾É±â¸¦ ±â´Ù¸®´Â Áß."); } public void StartMatch() { if (hasMatchStarted) { return; } hasMatchStarted = true; playerWinCount = 0; dealerWinCount = 0; isMatchOver = false; isEndingMatch = false; HideAllWinMarks(); StartRound(); Debug.Log("ºí·¢Àè ½ÂºÎ ½ÃÀÛ"); } void StartRound() { ClearSpawnedCards(); HideDealerCardUI(); BuildDeck(); isPlayerTurn = true; isGameOver = false; playerHitIndex = 0; dealerHitIndex = 0; playerCards.Clear(); dealerCards.Clear(); if (resultText != null) { resultText.gameObject.SetActive(false); } if (hitButton != null) { hitButton.interactable = true; } if (standButton != null) { standButton.interactable = true; } DealPlayerCard(playerCardPos1); DealPlayerCard(playerCardPos2); DealDealerCard(dealerOpenCardPos, false); dealerHiddenCard = DealDealerCard(dealerHiddenCardPos, true); UpdateScoreUI(false); Debug.Log("»õ ¶ó¿îµå ½ÃÀÛ"); Debug.Log("Ç÷¹À̾î Á¡¼ö: " + CalculateScore(playerCards)); } void BuildDeck() { deck.Clear(); foreach (GameObject card in cardPrefabs) { if (card != null) { deck.Add(card); } } Debug.Log("µ¦ Ä«µå ¼ö: " + deck.Count); } GameObject DrawRandomCard() { if (deck.Count == 0) { Debug.LogWarning("µ¦ÀÌ ºñ¾î ÀÖ½À´Ï´Ù."); return null; } int index = Random.Range(0, deck.Count); GameObject selectedCard = deck[index]; deck.RemoveAt(index); return selectedCard; } void DealPlayerCard(Transform pos) { GameObject prefab = DrawRandomCard(); if (prefab == null) { return; } playerCards.Add(prefab.name); SpawnCard(prefab, pos, false); } GameObject DealDealerCard(Transform pos, bool faceDown) { GameObject prefab = DrawRandomCard(); if (prefab == null) { return null; } dealerCards.Add(prefab.name); int dealerCardIndex = dealerCards.Count - 1; UpdateDealerCardUI(dealerCardIndex, prefab.name, faceDown); return SpawnCard(prefab, pos, faceDown); } public void Hit() { if (isGameOver || isMatchOver) { return; } if (!isPlayerTurn) { Debug.Log("ÀÌ¹Ì ¸ØÃè½À´Ï´Ù. Ä«µå¸¦ ´õ ¹ÞÀ» ¼ö ¾ø½À´Ï´Ù."); return; } if (playerHitIndex >= playerHitPositions.Length) { Debug.Log("Ç÷¹À̾î Ä«µå À§Ä¡°¡ ´õ ÀÌ»ó ¾ø½À´Ï´Ù."); return; } DealPlayerCard(playerHitPositions[playerHitIndex]); playerHitIndex++; UpdateScoreUI(false); int playerScore = CalculateScore(playerCards); Debug.Log("Ä«µå ¹ÞÀº ÈÄ Ç÷¹À̾î Á¡¼ö: " + playerScore); if (playerScore > 21) { Debug.Log("Ç÷¹ÀÌ¾î ¹ö½ºÆ®! À̹ø ¶ó¿îµå´Â ¼±Àå ½Â¸®."); EndRound(-1, "¹ö½ºÆ®!\n¼±Àå ½Â¸®!"); } } public void Stand() { if (isGameOver || isMatchOver) { return; } if (!isPlayerTurn) { return; } isPlayerTurn = false; if (dealerHiddenCard != null) { dealerHiddenCard.transform.rotation = Quaternion.Euler(frontRotation); } RevealDealerCardsUI(); UpdateScoreUI(true); Debug.Log("½ºÅĵå: ¼±ÀåÀÇ ¼û°ÜÁø Ä«µå °ø°³."); Debug.Log("¼±Àå Á¡¼ö: " + CalculateScore(dealerCards)); DealerTurn(); } void DealerTurn() { while (CalculateScore(dealerCards) < 17) { if (dealerHitIndex >= dealerHitPositions.Length) { Debug.Log("¼±Àå Ä«µå À§Ä¡°¡ ´õ ÀÌ»ó ¾ø½À´Ï´Ù."); break; } DealDealerCard(dealerHitPositions[dealerHitIndex], false); dealerHitIndex++; UpdateScoreUI(true); Debug.Log("¼±ÀåÀÌ Ä«µå¸¦ ¹Þ¾Ò½À´Ï´Ù. ¼±Àå Á¡¼ö: " + CalculateScore(dealerCards)); } JudgeResult(); } void JudgeResult() { int playerScore = CalculateScore(playerCards); int dealerScore = CalculateScore(dealerCards); Debug.Log("ÃÖÁ¾ Ç÷¹À̾î Á¡¼ö: " + playerScore); Debug.Log("ÃÖÁ¾ ¼±Àå Á¡¼ö: " + dealerScore); if (dealerScore > 21) { EndRound(1, "¼±Àå ¹ö½ºÆ®!\nÇ÷¹ÀÌ¾î ½Â¸®!"); } else if (playerScore > dealerScore) { EndRound(1, "Ç÷¹ÀÌ¾î ½Â¸®!"); } else if (playerScore < dealerScore) { EndRound(-1, "¼±Àå ½Â¸®!"); } else { EndRound(0, "¹«½ÂºÎ!\n½ÂÁ¡ ¾øÀ½"); } } void EndRound(int winner, string message) { isGameOver = true; isPlayerTurn = false; if (hitButton != null) { hitButton.interactable = false; } if (standButton != null) { standButton.interactable = false; } if (winner == 1) { if (playerWinCount < playerWinMarks.Length) { playerWinMarks[playerWinCount].SetActive(true); } playerWinCount++; } else if (winner == -1) { if (dealerWinCount < dealerWinMarks.Length) { dealerWinMarks[dealerWinCount].SetActive(true); } dealerWinCount++; } ShowResult(message); if (playerWinCount >= targetWinCount) { isMatchOver = true; ShowResult("ÃÖÁ¾ °á°ú\nÇ÷¹ÀÌ¾î ½Â¸®!"); Debug.Log("ÃÖÁ¾ °á°ú: Ç÷¹ÀÌ¾î ½Â¸®"); StartCoroutine(EndMatchAfterDelay()); return; } if (dealerWinCount >= targetWinCount) { isMatchOver = true; ShowResult("ÃÖÁ¾ °á°ú\n¼±Àå ½Â¸®!\n´Ù½Ã µµÀü!"); Debug.Log("ÃÖÁ¾ °á°ú: ¼±Àå ½Â¸®. ½ÂºÎ¸¦ ´Ù½Ã ½ÃÀÛÇÕ´Ï´Ù."); StartCoroutine(RestartMatchAfterLose()); return; } StartCoroutine(StartNextRoundAfterDelay()); } IEnumerator StartNextRoundAfterDelay() { yield return new WaitForSeconds(nextRoundDelay); if (!isMatchOver) { StartRound(); } } IEnumerator EndMatchAfterDelay() { if (isEndingMatch) { yield break; } isEndingMatch = true; yield return new WaitForSeconds(matchEndDelay); onMatchEnded?.Invoke(); } IEnumerator RestartMatchAfterLose() { if (isEndingMatch) { yield break; } isEndingMatch = true; yield return new WaitForSeconds(matchEndDelay); playerWinCount = 0; dealerWinCount = 0; isMatchOver = false; isGameOver = true; isPlayerTurn = false; isEndingMatch = false; HideAllWinMarks(); StartRound(); Debug.Log("ÆÐ¹è ÈÄ ºí·¢ÀèÀ» ´Ù½Ã ½ÃÀÛÇÕ´Ï´Ù."); } void UpdateScoreUI(bool showDealerFullScore) { int playerScore = CalculateScore(playerCards); if (playerScoreText != null) { playerScoreText.text = "Ç÷¹À̾î: " + playerScore; } if (dealerScoreText != null) { if (showDealerFullScore) { dealerScoreText.text = "¼±Àå: " + CalculateScore(dealerCards); } else { dealerScoreText.text = "¼±Àå: ?"; } } } void ShowResult(string message) { if (resultText != null) { resultText.gameObject.SetActive(true); resultText.text = message; } } void HideAllWinMarks() { foreach (GameObject mark in playerWinMarks) { if (mark != null) { mark.SetActive(false); } } foreach (GameObject mark in dealerWinMarks) { if (mark != null) { mark.SetActive(false); } } } void ClearSpawnedCards() { foreach (GameObject card in spawnedCards) { if (card != null) { Destroy(card); } } spawnedCards.Clear(); } int CalculateScore(List cards) { int total = 0; int aceCount = 0; foreach (string cardName in cards) { int value = GetCardValue(cardName); if (IsAce(cardName)) { aceCount++; } total += value; } while (total > 21 && aceCount > 0) { total -= 10; aceCount--; } return total; } int GetCardValue(string cardName) { string lowerName = cardName.ToLower(); if (lowerName.Contains("ace")) { return 11; } if (lowerName.Contains("jack") || lowerName.Contains("queen") || lowerName.Contains("king")) { return 10; } Match match = Regex.Match(cardName, @"\d+"); if (match.Success) { return int.Parse(match.Value); } Debug.LogWarning("Ä«µå °ªÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù: " + cardName); return 0; } bool IsAce(string cardName) { return cardName.ToLower().Contains("ace"); } GameObject SpawnCard(GameObject prefab, Transform pos, bool faceDown) { if (prefab == null || pos == null) { Debug.LogWarning("Ä«µå ÇÁ¸®ÆÕ ¶Ç´Â À§Ä¡°¡ ºñ¾î ÀÖ½À´Ï´Ù."); return null; } GameObject card = Instantiate(prefab, pos.position, Quaternion.identity); spawnedCards.Add(card); card.transform.localScale = prefab.transform.localScale * cardScale; if (faceDown) { card.transform.rotation = Quaternion.Euler(backRotation); } else { card.transform.rotation = Quaternion.Euler(frontRotation); } return card; } void HideDealerCardUI() { if (dealerCardImages == null) { return; } foreach (Image image in dealerCardImages) { if (image == null) { continue; } image.sprite = null; image.gameObject.SetActive(false); } } void UpdateDealerCardUI(int index, string cardName, bool faceDown) { if (dealerCardImages == null || index < 0 || index >= dealerCardImages.Length) { return; } Image targetImage = dealerCardImages[index]; if (targetImage == null) { return; } targetImage.gameObject.SetActive(true); if (faceDown) { targetImage.sprite = dealerCardBackSprite; return; } targetImage.sprite = GetCardSprite(cardName); } void RevealDealerCardsUI() { for (int i = 0; i < dealerCards.Count; i++) { UpdateDealerCardUI(i, dealerCards[i], false); } } Sprite GetCardSprite(string cardName) { string key = NormalizeCardName(cardName); if (cardSpriteMap.TryGetValue(key, out Sprite sprite)) { return sprite; } Debug.LogWarning("Ä«µå UI À̹ÌÁö¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù: " + cardName); return null; } string NormalizeCardName(string cardName) { if (string.IsNullOrEmpty(cardName)) { return ""; } return cardName .Replace("(Clone)", "") .Replace(" ", "") .Replace("_", "") .Replace("-", "") .Trim() .ToLower(); } }