Цикл игры в блэкджек иногда зависает после стойки.

Вопрос или проблема

Для задания я создаю игру в блэкджек на Kotlin. Загвоздка в том, что у каждого игрока есть навык игрока, который позволяет им изменять результаты следующего розыгрыша.

Вот важный игровой цикл:

while (!PlayerOneStands || !PlayerTwoStands)
        {
            // Ход игрока 1
            if (!PlayerOneStands)
            {
                if (p1HandNames[0] == p1HandNames[1]) {
                    println("Хотите разделить? Введите Да или Нет")
                    val splitChoice = scanner.next().toLowerCase()
                    if (splitChoice == "да") {
                        p1HandNames.removeAt(1)
                        p1Hand = Player.readCards(p1HandNames)
                        PlayerOne.hand = p1Hand
                        PlayerOne.cardNames = p1HandNames // Предполагая, что `CardNames` - это имя свойства в Player для массива названий карт
                        SplitPot = betPot / 2
                        SplitHandName = ArrayList(listOf(p1HandNames[0])) // Присваиваем только первое значение p1HandNames переменной SplitHandName
                    }
                }

                print("${PlayerOne.name}, хотите взять карту (h), остановиться (s) или удвоить ставку (d)?")
                val decision = scanner.next()[0]
                when (decision) {
                    'h' -> {
                        p1HandNames.add(Player.drawCard())
                        p1Hand = Player.readCards(p1HandNames)
                        PlayerOne.hand = p1Hand
                        PlayerOne.hand = Player.gambleCheck(PlayerOne)
                        PlayerOneStands = Player.checkHand(PlayerOne)
                        PlayerOne.hand = p1Hand
                        println(p1HandNames)
                        if (PlayerOne.hand > 20)
                        {
                            PlayerTwoStands = true
                        }
                    }
                    's' ->
                        PlayerOneStands = true
                    'd' -> {
                        var availableWealth = PlayerOne.wealth.coerceAtMost(betAmount1)
                        PlayerOne.wealth -= availableWealth
                        betPot += availableWealth
                        availableWealth = PlayerTwo.wealth.coerceAtMost(betAmount2)
                        PlayerTwo.wealth -= availableWealth
                        betPot += availableWealth
                        p1HandNames.add(Player.drawCard())
                        p1Hand = Player.readCards(p1HandNames)
                        PlayerOne.hand = p1Hand
                        PlayerOne.hand = Player.gambleCheck(PlayerOne)
                        println(p1HandNames)
                        PlayerOneStands = true
                        if (PlayerOne.hand > 20)
                            PlayerTwoStands = true
                    }
                    else ->
                        println("Неверный выбор. Пожалуйста, введите взять карту (h), остановиться (s) или удвоить ставку. (d)")
                }
            }
            // Ход игрока 2 (логика дилера)
            while (PlayerTwo.hand < 17 && PlayerOne.hand < 21 && PlayerOneStands)
            {
                if(PlayerOne.hand < PlayerTwo.hand || PlayerTwoStands)
                    break
                p2HandNames.add(Player.drawCard())
                p2Hand = Player.readCards(p2HandNames)
                PlayerTwo.hand = p2Hand
                PlayerTwo.hand = Player.gambleCheck(PlayerTwo)
                PlayerTwoStands = Player.checkHand(PlayerTwo)
                PlayerTwo.hand = p2Hand
                println(p2HandNames)
            }
        }

Вот некоторые методы из Player:

fun drawCard(): String
        {
            if (STANDARD_PLAYING_CARDS.isEmpty())
            {
                println("Карты закончились. Игра окончена")
                System.exit(0)
                return "Карт не осталось"
            }

            // Генерируем случайный индекс в пределах доступных карт
            val index = rand.nextInt(STANDARD_PLAYING_CARDS.size)

            // Получаем тип карты по выбранному индексу
            val cardType = STANDARD_PLAYING_CARDS[index]

            // Удаляем вытянутую карту из списка доступных карт
            STANDARD_PLAYING_CARDS.removeAt(index)

            return cardType
        }
        fun readCards(french: ArrayList): Int
        {
            var totalValue = 0
            var aceCount = 0
            for (currentCard in french)
            {
                when
                {
                    currentCard == "Валет" || currentCard == "Дама" || currentCard == "Король" -> totalValue += 10
                    currentCard == "Туз" ->
                    {
                        totalValue += 11
                        aceCount++
                    }
                    else -> totalValue += currentCard.toIntOrNull() ?: 0
                }
            }
            while (totalValue > 21 && aceCount > 0)
            {
                totalValue -= 10
                aceCount--
            }
            return totalValue
        }

        fun gambleCheck(rngPlayer: Player): Int
        {
            val handValue = rngPlayer.hand
            val randomInt = rand.nextInt(101)
            return when {
                randomInt > rngPlayer.gamblingSkill * 2 ->
                {
                    println(rngPlayer.name + " не повезло!")
                    val lastCardIndex = rngPlayer.cardNames.lastIndex
                    rngPlayer.cardNames[lastCardIndex] = "10" // Фактически меняет их руку, чтобы соответствовать.
                    handValue + 10
                }
                handValue < 22 -> handValue
                randomInt < rngPlayer.gamblingSkill ->
                {
                    println(rngPlayer.name + " повезло!")
                    var lastCardValue = 0
                    val lastCard = rngPlayer.cardNames.last() // Преобразуем название последней карты в Int или по умолчанию 0
                    if(lastCard == "Валет" || lastCard == "Король" || lastCard == "Дама")
                        lastCardValue = 10
                    else
                        lastCardValue = lastCard.toIntOrNull() ?:0
                    val winDifference = 21 - rngPlayer.hand + lastCardValue
                    rngPlayer.cardNames[rngPlayer.cardNames.lastIndex] = winDifference.toString()
                    21
                }
                else -> handValue //Это мера безопасности на случай, если ничего больше не действительно.
            }
        }

        fun resetGame(Play1: Player, Play2: Player)
        {
            Play1.hand = 0
            Play1.winner = false
            Play2.hand = 0
            Play2.winner = false
        }
    }

Проблема с кодом в том, что иногда (но не всегда), если игрок 1 останавливается или удваивается, не сходя с ума сначала; либо дилер вытягивает карту, и программа зависает, либо программа просто зависает. В чем причина зависания?

Ответ или решение

Вопрос, связанный с зависанием игрового цикла в вашей игре Blackjack на Kotlin, может возникать из-за нескольких факторов, связанных с логикой проверки условий и управлением состоянием игроков. Рассмотрим подробнее основные моменты, которые могут вызывать эту проблему.

Понимание игрового цикла

Исходный цикл работает с условием while (!PlayerOneStands || !PlayerTwoStands). Это означает, что игра продолжается до тех пор, пока хотя бы один из игроков не закончит свой ход. Важный момент здесь — корректное управление состояниями PlayerOneStands и PlayerTwoStands.

Варианты зависания игрового цикла

  1. Неправильная последовательность действий:

    • Состояние PlayerTwoStands устанавливается только внутри цикла, который проверяет, что рука игрока не достигла 17, и рука игрока одного (PlayerOne) меньше 21, что может привести к ситуации, когда игрок 2 не может завершить свой ход, если рука игрока 1 уже требует завершения.
  2. Проблемы с логикой проверки руки:

    • Проверка, попадает ли рука игрока под условие окончания игры (PlayerOne.hand < 21), может создавать бесконечный цикл, если состояние игрока не обновляется должным образом. Например, если PlayerTwo получает новую карту, его активность не обновляет правильно состояние, и программа может застрять.
  3. Стратегия раздачи карт:

    • Метод drawCard() может приводить к полной остановке, если колода карт опустела. Если программа продолжает пытаться раздавать карты после опустошения колоды, это также может привести к зависанию.

Как избежать зависания

  • Проверка состояния карты: Убедитесь, что состояние игрока обновляется должным образом, и остановите цикл, если карты закончились. В методе drawCard() добавьте проверку и сообщение об ошибке перед попыткой раздачи.

  • Оптимизация логики игры: Проверьте и отладьте условие выхода из цикла. Возможно, стоит использовать if и отдельные методы для обработки каждого состояния игрока вместо объединения их всех в один большой цикл. Это поможет лучше контролировать логику игры и избежать ситуаций, когда игра зависает из-за несоответствия условий.

  • Добавление логов и отладочной информации: Включите логи для отслеживания состояния игроков и значений их рук в каждый момент времени. Это поможет понять, на каком этапе происходит зависание, и какие переменные имеют неожиданные значения.

Заключение

Проблема зависания цикла в вашей игре Blackjack на Kotlin может вызывать множество факторов, включая неправильные проверки условий выхода из игры и управление состоянием игроков. Внимательно проверьте логику условий в цикле и убедитесь, что все состояния обновляются корректно. Следуя приведенным рекомендациям, вы сможете устранить это поведение и улучшить взаимодействие с игроками, сделав игру более плавной и предсказуемой.

Оцените материал
Добавить комментарий

Капча загружается...