Android Kotlin开发井字棋应用玩家对战电脑功能实现故障求助
井字棋玩家对战电脑功能问题修复方案
核心问题汇总
- 主线程阻塞:
playGame方法中调用Thread.sleep会阻塞Android主线程,容易触发ANR闪退,且同步循环逻辑不符合点击交互的异步特性,无法等待玩家手动落子。 - 点击事件重复绑定:
update_player方法每次调用都会给所有按钮重新绑定点击事件,会导致单次点击触发多次回调,且绑定事件后直接切换回合,未等待玩家实际落子。 - 电脑落子逻辑错误:子线程生成随机坐标是异步执行,主线程判断坐标状态时子线程还未完成赋值,拿到的永远是初始值
row=0、column=0;随机数计算逻辑简单,完全不需要放到子线程执行,额外开线程反而导致逻辑混乱。 - 状态判断错误:
boardStatus初始值为-1代表未占用,现有占用判断逻辑写反,且未等落子成功就累加turnCount、判断胜负,计数和胜负判定完全失准。 - 递归风险:电脑落子位置占用后递归调用自身,满盘状态下会出现无限递归导致栈溢出。
修复思路
- 移除
playGame中的同步循环和Thread.sleep逻辑,改为异步事件驱动流程:初始化时仅绑定一次按钮点击事件,玩家点击落子完成后,自动触发电脑落子逻辑。 - 电脑落子逻辑去掉无用的子线程,直接在主线程生成随机坐标,循环判断直到找到可用位置即可,不需要递归。
- 胜负判断、回合切换都放在落子成功之后执行,UI延迟切换用
postDelayed实现,不阻塞主线程。
修复后完整代码
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.os.Handler import android.os.Looper import android.widget.Button import kotlinx.android.synthetic.main.activity_computer.* class ComputerActivity : AppCompatActivity() { var player = true var turnCount = 0 var boardStatus = Array(3) { IntArray(3) } lateinit var board: Array<Array<Button>> private val mainHandler = Handler(Looper.getMainLooper()) private var isGameOver = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_computer) board = arrayOf( arrayOf(First, Second, Third), arrayOf(Fourth, Fifth, Sixth), arrayOf(Seventh, Eighth, Ninth) ) initButtonClick() resetBtn.setOnClickListener{ resetGame() } resetGame() } private fun initButtonClick() { // 仅初始化时绑定一次点击事件 for (i in 0..2) { for (j in 0..2) { board[i][j].setOnClickListener{ if (player && !isGameOver && boardStatus[i][j] == -1) { // 玩家落子 updateBoardStatus(i, j, player) afterMove() } } } } } private fun resetGame() { player = true turnCount = 0 isGameOver = false Status.text = "Player's Turn" // 重置棋盘状态 for (i in 0..2) { for (j in 0..2) { boardStatus[i][j] = -1 board[i][j].apply { isEnabled = true text = "" } } } } private fun afterMove() { turnCount++ checkWinner() if (isGameOver) return if (turnCount == 9) { Status.text = "Game Draw" isGameOver = true disableButton() return } // 切换回合 player = !player if (!player) { Status.text = "Computer's Turn" disableButton() // 延迟1秒后电脑落子,模拟思考过程 mainHandler.postDelayed({ computerMove() }, 1000) } else { Status.text = "Player's Turn" enableButton() } } private fun computerMove() { // 生成可用的随机坐标 var row: Int var column: Int do { row = (0..2).random() column = (0..2).random() } while (boardStatus[row][column] != -1) // 电脑落子 updateBoardStatus(row, column, player) afterMove() } private fun updateBoardStatus(row:Int, column:Int, player:Boolean){ val text = if (player) "X" else "0" val value = if (player) 1 else 0 board[row][column].apply { isEnabled = false setText(text) } boardStatus[row][column] = value } private fun checkWinner(){ //Horizontal --- rows for (i in 0..2) { if (boardStatus[i][0] == boardStatus[i][1] && boardStatus[i][0] == boardStatus[i][2] && boardStatus[i][0] != -1) { if (boardStatus[i][0] == 1) { result("Player Won!!") } else if (boardStatus[i][0] == 0) { result("Computer Won") } return } } //Vertical --- columns for (i in 0..2) { if (boardStatus[0][i] == boardStatus[1][i] && boardStatus[0][i] == boardStatus[2][i] && boardStatus[0][i] != -1) { if (boardStatus[0][i] == 1) { result("Player Won!!") } else if (boardStatus[0][i] == 0) { result("Computer Won!!") } return } } //First diagonal if (boardStatus[0][0] == boardStatus[1][1] && boardStatus[0][0] == boardStatus[2][2] && boardStatus[0][0] != -1) { if (boardStatus[0][0] == 1) { result("Player Won!!") } else if (boardStatus[0][0] == 0) { result("Computer won!!") } return } //Second diagonal if (boardStatus[0][2] == boardStatus[1][1] && boardStatus[0][2] == boardStatus[2][0] && boardStatus[0][2] != -1) { if (boardStatus[0][2] == 1) { result("Player Won!!") } else if (boardStatus[0][2] == 0) { result("Computer Won!!") } return } } private fun result(res:String){ Status.text = res isGameOver = true disableButton() } private fun disableButton(){ for(i in board){ for(button in i){ button.isEnabled = false } } } private fun enableButton(){ for(i in 0..2){ for(j in 0..2){ if (boardStatus[i][j] == -1) { board[i][j].isEnabled = true } } } } }
内容的提问来源于stack exchange,提问作者Divyanshu Dobriyal
相关产品推荐
相关产品推荐

