Search code examples
androidkotlintic-tac-toe

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


I am making tic tac toe in android studio on kotlin, I am new at this, I complete everything but i want to make that if none of combinations matchs then write on screen that it's draw but i cant write some logic or i missed something:

this is draw function code:

 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!"
    }

}

so, I am saying that if there isn't this combinations of number in lists, write "draw" in resultView but it shows draw on first click on any button. why?


Solution

  • The following assumes that playerOne and playerTwo are List<Int>s containing which of the nine squares from 1-9 the players have placed marks in.

    Any time you see that you're copy-pasting code more than once (like resultView.text = "Draw!" and all the similar-looking if statements), you should rethink the design to simplify it.

    I would create a collection of all possible win conditions:

    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),
    )
    

    Then each time a player makes a mark, you can check if either player won. If neither player won and nine moves have been made, the game is a draw.

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

    To get more fancy, you could have it only check the player who just made a move. That might make sense if it was a complicated algorithm to determine the winner, but Tic Tac Toe is trivial so I think it's just simpler to simply check them both so you can use the same code without extra parameters.