Как сравнить Arraylist с вложенным Arraylist в kotlin? - PullRequest
3 голосов
/ 08 мая 2020

Я новичок в kotlin. Я пытаюсь создать простое игровое приложение ti c ta c toe.

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


\\ this funtion checks the winner , where player1 and player2 are arraylist.
\\ example : player1 = [1,2,8] and player2 = [4,5,6]

fun checkWinner(player1,player2){

   var possibleCombos = arrayListOf(
            arrayListOf(1,2,3), arrayListOf(4,5,6), arrayListOf(7,8,9),
            arrayListOf(1,4,7), arrayListOf(2,5,8), arrayListOf(3,6,9),
            arrayListOf(7,5,3), arrayListOf(1,5,9))

   for(items in possibleCombos) {

            if(a.containsAll(items)) {

               Toast.makeText(this,"Winner is A $a",Toast.LENGTH_LONG).show()

               }
            else if (b.containsAll(items)) {

               Toast.makeText(this,"Winner is B $b",Toast.LENGTH_LONG).show()

              }
            else {

                Toast.makeText(this,"Game is tie",Toast.LENGTH_SHORT).show()

            }
        }

    }

Он не работает, а часть else выполняется всегда. Я хочу поднять тост за результат.

Любое решение?

Ответы [ 3 ]

1 голос
/ 08 мая 2020

Ну, вы делаете это неправильно, вы проверяете, что каждый элемент в этом списке на самом деле равен player1 или player2.

Итак, если вы выполните, [4,5,6], вы получите 8 тостов, в которых 1 из них будет победителем при проверке на [4,5,6], а остальные 7 будут указывать на условие else, потому что [4,5,6] не является [1,2,3], [7,8,9], et c.

val possibleCombos = sequenceOf( // if want listOf, just add .asSequence() before map below, this way will break the mapping if result is obtained.
    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(7, 5, 3), listOf(1, 5, 9))

fun checkWinner(player1: List<Int>, player2: List<Int>) {
    // this will break the mapping once first non-null value is found, in terminal operation firstOrNull()
    val message = possibleCombos.map {
        when {
            player1.containsAll(it) -> "Winner is A $player1"
            player2.containsAll(it) -> "Winner is B $player2"
            else -> null
        }
    }.filterNotNull().firstOrNull() ?: "Game is tie"
    Toast.makeText(this, message, Toast.LENGTH_LONG).show()
}

// Call this function (test sample)
checkWinner(arrayListOf(1, 2, 8, 3), arrayListOf(5, 4, 6, 7)) // may change to listOf as well

Результат:

Winner is B [5, 4, 6, 7]

PS: Я реорганизовал arrayListOf() на listOf(), потому что это то, что рекомендует использовать Kotlin -stdlib. Однако вы также можете вернуться к arrayListOf()

1 голос
/ 08 мая 2020

Когда вы перебираете список, вам нужно вырваться из l oop, как только вы найдете победителя. И ветвь else должна быть перемещена за пределы l oop, иначе она будет достигнута при любом условии выигрыша, который не был условием выигрыша для этой игры.

fun checkWinner(player1: List<Int>, player2: List<Int>){

    val possibleCombos = arrayListOf(
            arrayListOf(1,2,3), arrayListOf(4,5,6), arrayListOf(7,8,9),
            arrayListOf(1,4,7), arrayListOf(2,5,8), arrayListOf(3,6,9),
            arrayListOf(7,5,3), arrayListOf(1,5,9))

    var winner: List<Int>? = null
    for(items in possibleCombos) {
        if(player1.containsAll(items)) {
            winner = player1
            break
        }
        if(player2.containsAll(items)) {
            winner = player2
            break
        }
    }
    // If no winner was found, winner will still be null

    val resultText = when (winner) {
        player1 -> "Winner is A $player1"
        player2 -> "Winner is B $player2"
        else -> "Game is tie"
    }
    Toast.makeText(this, resultText, Toast.LENGTH_LONG).show()
}

В качестве альтернативы вы можете использовать функции высшего порядка вместо того, чтобы зацикливаться, чтобы он был кратким:

val winner = when {
    possibleCombos.any { player1.containsAll(it) } -> player1
    possibleCombos.any { player2.containsAll(it) } -> player2
    else -> null
}
1 голос
/ 08 мая 2020

Я нашел это { ссылка }:

В Kotlin 1.1 вы можете использовать contentEquals и contentDeepEquals для сравнения двух массивов на предмет структурного равенства. например:

a contentEquals b // true
b contentEquals c // false

В Kotlin 1.0 нет «встроенных функций в Kotlin std-lib, которые проверяют два массива на равенство (значения) для каждого элемента».

«Массивы всегда сравниваются с помощью equals (), как и все другие объекты» (Запрос обратной связи: Ограничения по классам данных | Kotlin Блог).

Таким образом, a.equals (b) вернет true, только если a и b ссылаются на один и тот же массив.

Однако вы можете создать свои собственные методы, удобные для "опций", используя функции расширения. например:

fun Array<*>.equalsArray(other: Array<*>) = Arrays.equals(this, other)
fun Array<*>.deepEqualsArray(other: Array<*>) = Arrays.deepEquals(this, other)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...