如何在Tic tac toe,kotlin中编写绘制逻辑

how to write logic of draw in Tac tac toe, kotlin

我正在 android studio on kotlin 制作井字游戏,我是新手,我完成了所有内容,但我想制作如果 none 组合匹配然后在屏幕上写下它是平局,但我不能写一些逻辑或者我错过了一些东西:

这是绘图函数代码:

 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” 但它显示在第一次点击任何按钮时绘制。 为什么?

以下假设 playerOneplayerTwoList<Int>,其中包含玩家在 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),
)

然后每次玩家做出标记时,您都可以检查是否有玩家获胜。如果双方均未获胜且已完成 9 步棋,则平局。

// 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()
}

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

有更好的方法来完成您正在做的事情,例如 Tenfour04 的回答,但您的基本方法很好!努力工作,但它有效。只是逻辑并不完全符合您要执行的操作。

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


您的第一个问题是您 运行 的目标 - 如果您单击一个按钮,并且 draw() 被调用,它会告诉您这是平局。怎么会?嗯,想想你在做什么 - 你正在检查是否有人有获胜条件,他们没有,因为这是游戏的开始。所以结果是"draw!"

所以真的,你不能在任何时候调用draw(),因为游戏有四种可能的状态:player1 win, player2 win draw(都是完成状态)和in progress,基本上就是none的结束状态已经达到了。您正在检查获胜状态,但假设如果它们不匹配,则您必须处于 draw 状态。

因此,当您 知道 已经达到其中一个结束状态时,您需要调用 draw()(如果不检查就无法真正知道) ),否则您需要在检查获胜状态的同时显式检查平局状态。 (你可以考虑的一件事是,是否所有的方块都被填满了。)


另一件事是您的逻辑并没有真正正确地处理获胜状态。假设 player 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 是否 赢了 ,而不是他们是否 没赢。通过这种方式,我们正在寻找可以设置标志的特定条件。处理“曾经满足过这个条件”比“从未满足过这些条件中的任何一个”更容易处理。

这因人而异,但有时在纸上解决这些问题会更容易 - 写下您需要提出的问题,以检查是否有人赢了,有人输了,是平局还是游戏还在去。考虑一下!