【问题标题】:how to write logic of draw in Tac tac toe, kotlin如何在井字游戏,kotlin 中编写绘图逻辑
【发布时间】:2020-12-19 22:29:53
【问题描述】:

我在 kotlin 上的 android studio 中制作井字游戏,我是新手,我完成了所有事情,但我想做,如果没有任何组合匹配,然后在屏幕上写它是平局但我不能写一些逻辑或者我错过了什么:

这是绘制函数代码:

 private fun draw() {

    if (!firstPLayer.contains(1) && !firstPLayer.contains(2) && !firstPLayer.contains(3)) {
        resultView.text = "Draw!"
    }
    if (!secondPLayer.contains(1) && !secondPLayer.contains(2) && !secondPLayer.contains(3)) {
        resultView.text = "Draw!"
    }

    if (!firstPLayer.contains(4) && !firstPLayer.contains(5) && !firstPLayer.contains(6)) {
        resultView.text = "Draw!"
    }
    if (!secondPLayer.contains(4) && !secondPLayer.contains(5) && !secondPLayer.contains(6)) {
        resultView.text = "Draw!"
    }

    if (!firstPLayer.contains(7) && !firstPLayer.contains(8) && !firstPLayer.contains(9)) {
        resultView.text = "Draw!"
    }
    if (!secondPLayer.contains(7) && !secondPLayer.contains(8) && !secondPLayer.contains(9)) {
        resultView.text = "Draw!"
    }

    if (!firstPLayer.contains(1) && !firstPLayer.contains(4) && !firstPLayer.contains(7)) {
        resultView.text = "Draw!"
    }
    if (!secondPLayer.contains(1) && !secondPLayer.contains(4) && !secondPLayer.contains(7)) {
        resultView.text = "Draw!"
    }

    if (!firstPLayer.contains(2) && !firstPLayer.contains(5) && !firstPLayer.contains(8)) {
        resultView.text = "Draw!"
    }
    if (!secondPLayer.contains(2) && !secondPLayer.contains(5) && !secondPLayer.contains(8)) {
        resultView.text = "Draw!"
    }

    if (!firstPLayer.contains(3) && !firstPLayer.contains(6) && !firstPLayer.contains(9)) {
        resultView.text = "Draw!"
    }
    if (!secondPLayer.contains(3) && !secondPLayer.contains(6) && !secondPLayer.contains(9)) {
        resultView.text = "Draw!"
    }

    if (!firstPLayer.contains(1) && !firstPLayer.contains(5) && !firstPLayer.contains(9)) {
        resultView.text = "Draw!"
    }
    if (!secondPLayer.contains(1) && !secondPLayer.contains(5) && !secondPLayer.contains(9)) {
        resultView.text = "Draw!"
    }

    if (!firstPLayer.contains(3) && !firstPLayer.contains(5) && !firstPLayer.contains(7)) {
        resultView.text = "Draw!"
    }
    if (!secondPLayer.contains(3) && !secondPLayer.contains(5) && !secondPLayer.contains(7)) {
        resultView.text = "Draw!"
    }

}

所以,我是说如果列表中没有这种数字组合,请在 resultView 中写上“draw” 但它会在第一次单击任何按钮时显示绘制。 为什么?

【问题讨论】:

  • 好吧,你会希望所有这些 if 都是一个 when 语句、if-else 或一堆 or 语句在一个 if 中......你拥有它们作为自己的 if 语句的脸会导致问题——也就是说,有更简单的方法可以实现你的目标——如果你发现自己重复了这么多类似的代码,那可能是更好的方法!
  • 我尝试在 if-else 函数中编写这个 if-s 但没有成功。
  • 套用逻辑:“如果 X 不是熊,那么 X 不是动物,如果 X 不是马,那么 X 也不是动物”。如果我们尝试使用 X=horse,它将声称那不是动物,因为它同时不是熊。换个说法,逻辑不通,折腾,重新开始。
  • 你不厌倦写所有这些吗?你有没有想过是否还有其他方法?一个可能涉及循环?

标签: android kotlin tic-tac-toe


【解决方案1】:

以下假设 playerOneplayerTwoList<Int>s,包含玩家在 1-9 的九个方格中放置了标记。

任何时候您看到您多次复制粘贴代码(例如resultView.text = "Draw!" 和所有类似的 if 语句),您应该重新考虑设计以简化它。

我会创建一个包含所有可能获胜条件的集合:

private val winConditions = listOf(
    listOf(1, 2, 3),
    listOf(4, 5, 6),
    listOf(7, 8, 9),
    listOf(1, 4, 7),
    listOf(2, 5, 8),
    listOf(3, 6, 9),
    listOf(1, 5, 9),
    listOf(3, 5, 7),
)

然后,每次有玩家得分时,您都可以检查是否有任何玩家获胜。如果双方均未获胜且未走九步,则游戏为平局。

// In a function called right after a player makes a move:
when {
    winConditions.any { playerOne.containsAll(it) } -> showPlayerOneWins()
    winConditions.any { playerTwo.containsAll(it) } -> showPlayerTwoWins()
    playerOne.size + playerTwo.size == 9 -> showGameIsDraw()
    else -> startNextPlayerTurn()
}

为了更花哨,你可以让它只检查刚刚移动的玩家。如果这是一个复杂的算法来确定获胜者,这可能是有道理的,但井字游戏是微不足道的,所以我认为简单地检查它们会更简单,这样你就可以使用相同的代码而无需额外的参数。

【讨论】:

  • 谢谢!我会试试你的方法,它真的很复杂,但我会练习。
【解决方案2】:

有更好的方法来做你正在做的事情,就像在 Tenfour04 的回答中一样,但你的基本方法很好!努力工作,但它确实有效。只是逻辑不完全符合您要执行的操作。

所以,我假设 firstPlayer 是一个列表(或其他一些集合),其中包含 player1 用 X 或 O 标记的平方数,@987654322 也是如此@。而且我认为你正在做的是检查所有获胜组合,如果没有人拥有这些组合,那么游戏就是平局。对吗?


你的第一个问题是你遇到了什么——如果你点击一个按钮,draw() 被调用,它告诉你这是平局。怎么会?好吧,想想你在做什么——你正在检查是否有人有获胜条件,而他们没有,因为这是游戏的开始。所以结果是“draw!”

所以说真的,你不能在任何时候打电话给draw(),因为游戏有四种可能的状态:player1 winplayer2 windraw (都是完成状态)和进行中,这基本上意味着还没有达到任何最终状态。您正在检查获胜状态,但假设如果它们不匹配,则您必须处于 draw 状态。

因此,当您知道已达到其中一种最终状态(如果不检查您无法真正知道)时,您需要致电 draw(),或者您需要明确检查平局状态以及获胜状态检查。 (你可以考虑一件事,是否所有的方块都被填满了。)


另一件事是你的逻辑并没有真正正确地处理胜利状态。想象一下玩家 2 已经填满了顶行。第一个if 确认玩家1 没有那条线。他们当然不会,所以它会打印 "draw!" 如果您考虑一下,最多 一个 可以匹配这些获胜状态,因此其他所有检查都是将通过并将结果文本设置为 "draw!"

通常,您处理此类事情的方式是将布尔标志设置为默认值,如果您愿意,可以在检查“触发警报”时设置它。你只设置了一种方式,所以一旦它从默认翻转到被设置,另一个检查不会把它翻转回来

// assuming a draw until we know otherwise
var draw = true

// checking if player 1 has WON
if (firstPLayer.contains(1) && firstPLayer.contains(2) && firstPLayer.contains(3)) {
    // when we know someone's won, we can say things like it's not a draw, maybe record who won
    draw = false
}
...

// set the text either way, ensuring it always displays the correct thing
resultView.text = if (draw) "draw!" else ""

请注意,我交换了if 条件来检查玩家 1 是否赢了,而不是他们是否没有赢。通过这种方式,我们正在寻找可以设置标志的特定条件。处理“是否曾满足此条件”比处理“从未满足任何这些条件”更容易。

这取决于个人,但有时将这些事情写在纸上会更容易 - 写下您需要提出的问题,以检查是否有人赢了、有人输了、是平局还是比赛仍在进行。考虑一下!

【讨论】:

  • 感谢您的回答!我非常感谢你的工作。我已经解决了这个逻辑,但真的,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
  • 1970-01-01
  • 2022-01-06
相关资源
最近更新 更多