Вопрос или проблема
Для задания я создаю игру в блэкджек на 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
.
Варианты зависания игрового цикла
-
Неправильная последовательность действий:
- Состояние
PlayerTwoStands
устанавливается только внутри цикла, который проверяет, что рука игрока не достигла 17, и рука игрока одного (PlayerOne
) меньше 21, что может привести к ситуации, когда игрок 2 не может завершить свой ход, если рука игрока 1 уже требует завершения.
- Состояние
-
Проблемы с логикой проверки руки:
- Проверка, попадает ли рука игрока под условие окончания игры (
PlayerOne.hand < 21
), может создавать бесконечный цикл, если состояние игрока не обновляется должным образом. Например, еслиPlayerTwo
получает новую карту, его активность не обновляет правильно состояние, и программа может застрять.
- Проверка, попадает ли рука игрока под условие окончания игры (
-
Стратегия раздачи карт:
- Метод
drawCard()
может приводить к полной остановке, если колода карт опустела. Если программа продолжает пытаться раздавать карты после опустошения колоды, это также может привести к зависанию.
- Метод
Как избежать зависания
-
Проверка состояния карты: Убедитесь, что состояние игрока обновляется должным образом, и остановите цикл, если карты закончились. В методе
drawCard()
добавьте проверку и сообщение об ошибке перед попыткой раздачи. -
Оптимизация логики игры: Проверьте и отладьте условие выхода из цикла. Возможно, стоит использовать
if
и отдельные методы для обработки каждого состояния игрока вместо объединения их всех в один большой цикл. Это поможет лучше контролировать логику игры и избежать ситуаций, когда игра зависает из-за несоответствия условий. -
Добавление логов и отладочной информации: Включите логи для отслеживания состояния игроков и значений их рук в каждый момент времени. Это поможет понять, на каком этапе происходит зависание, и какие переменные имеют неожиданные значения.
Заключение
Проблема зависания цикла в вашей игре Blackjack на Kotlin может вызывать множество факторов, включая неправильные проверки условий выхода из игры и управление состоянием игроков. Внимательно проверьте логику условий в цикле и убедитесь, что все состояния обновляются корректно. Следуя приведенным рекомендациям, вы сможете устранить это поведение и улучшить взаимодействие с игроками, сделав игру более плавной и предсказуемой.