如何使用mapIndexed从列表返回指定元素?记忆游戏函数优化
解决记忆游戏中turnPlaces函数的不可变List实现问题
问题说明
开发简易记忆游戏时,需要实现一个返回**不可变ListturnPlaces函数,用于记录已翻转正确的猜测位置。最初被迫改用MutableList并修改了main和play的参数类型,不符合设计预期。目标是通过mapIndexed函数实现该功能,避免可变集合的使用。
游戏规则:程序打乱#%XO&等符号的配对并展示,用户猜测两个位置,若配对正确则保留显示对应符号。
修正后的实现代码
以下是使用mapIndexed实现的turnPlaces函数,以及完整的关联代码片段:
fun main() { val pairs = (SYMBOLS+SYMBOLS).toList().shuffled() //println(pairs) println("生成了 ${SYMBOLS.length} 组随机符号配对。") println("开始游戏!") var places: List<Char> = allHiddenPairs(pairs) var trys = 0 do { println("$trys: $places") val first = readPosition("第一个") val second = readPosition("第二个") if ( isValidPositions(first, second, places) ) { places = places.play(first, second, pairs) trys++ } else println("位置无效") } while( ! isAllPairsShowed(pairs, places) ) println("$trys: $places") println("游戏结束,共使用 $trys 次尝试") } /** * 翻转[p1]和[p2]位置的两个元素。 * 若不配对,显示4秒后隐藏。 * @receiver 原始的位置列表 * @param p1 第一个要翻转的位置 * @param p2 第二个要翻转的位置 * @param pairs 原始的符号配对列表 * @return 若配对成功则返回更新后的位置列表,否则返回原始列表 */ fun List<Char>.play(p1: Int, p2: Int, pairs: List<Char>): List<Char> { val turned = turnPlaces(p1, p2, this, pairs) if (turned[p1] != turned[p2]) { print(turned) repeat(4) { print('.'); Thread.sleep(1000) } print("\r \r") return this } return turned } /** * 翻转[p1]和[p2]位置的元素。 * 隐藏状态则显示,显示状态则隐藏。 * @param p1 要翻转的位置 * @param p2 另一个要翻转的位置 * @param places 当前的位置显示列表 * @param pairs 原始的符号配对列表 * @return 翻转后的位置列表(不可变) */ fun turnPlaces(p1: Int, p2: Int, places: List<Char>, pairs: List<Char>): List<Char> { return places.mapIndexed { index, currentChar -> when(index) { p1 -> pairs[p1] p2 -> pairs[p2] else -> currentChar } } }
实现说明
- mapIndexed的核心作用:遍历原
places列表的每个元素,同时获取元素的索引index。通过判断索引是否为目标位置p1或p2,决定替换为原始配对中的对应符号,其余位置保留当前显示的字符。 - 不可变集合的优势:直接生成新的
List<Char>,无需转换为MutableList,符合Kotlin函数式编程风格,也不需要修改main和play函数的参数类型,保持代码简洁性与一致性。 - 参数顺序匹配:修正后的函数将
places作为第三个参数,与play函数中的调用参数顺序完全匹配,确保逻辑清晰且调用正确。
内容的提问来源于stack exchange,提问作者nuno
相关产品推荐
相关产品推荐

