我在jetpack composeKotlin上创建了一个跳棋游戏,但我遇到了结果不显示在屏幕上的问题。也就是说,检查器在日志中移动,但不在屏幕上移动。
enum class Piece {
EMPTY,
BLACK,
WHITE
}
@Composable
fun CheckersScreen(navHostController: NavHostController) {
val context = LocalContext.current
var selectedChecker by remember { mutableStateOf<Pair<Int, Int>?>(null) }
val board = remember { mutableStateOf(Array(8) { Array(8) { Piece.EMPTY } }) }
var localSelectedChecker by remember { mutableStateOf<Pair<Int, Int>?>(null) }
for (i in 0 until 3) {
for (j in 0 until 8) {
if ((i + j) % 2 == 1) {
board.value[i][j] = Piece.WHITE
}
}
}
for (i in 5 until 8) {
for (j in 0 until 8) {
if ((i + j) % 2 == 1) {
board.value[i][j] = Piece.BLACK
}
}
}
Column(
Modifier
.fillMaxSize()
.padding(bottom = 30.dp)
) {
Box(
modifier = Modifier
.padding(top = 152.dp)
.fillMaxWidth()
.padding(start = 5.dp, end = 5.dp)
.size(400.dp)
.shadow(4.dp, shape = RectangleShape)
) {
Column {
for (row in 0 until 8) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
for (column in 0 until 8) {
val color =
if ((row + column) % 2 == 0) Color.White else Color(139, 69, 19)
val isWhitePiece = board.value[row][column] == Piece.WHITE
val isBlackPiece = board.value[row][column] == Piece.BLACK
Box(
modifier = Modifier
.size(50.dp)
.background(color)
.clickable {
if (isBlackPiece) {
localSelectedChecker = Pair(row, column)
} else if (localSelectedChecker != null) {
val (fromRow, fromColumn) = localSelectedChecker!!
if (!isValidMove(
fromRow,
fromColumn,
row,
column,
board.value
)
) {
board.value[row][column] =
board.value[fromRow][fromColumn]
board.value[fromRow][fromColumn] = Piece.EMPTY
board.value[row][column] = Piece.BLACK
localSelectedChecker = null
Log.d(
"pizda",
"Board state: ${
board.value.joinToString("\n") {
it.joinToString(" ")
}
}"
)
}
}
},
) {
val isSelected = selectedChecker == Pair(row, column)
val checkerImage = when {
isWhitePiece -> R.drawable.white_checker
isBlackPiece -> R.drawable.black_checker
else -> 0
}
if (checkerImage != 0) {
Image(
painter = painterResource(id = checkerImage),
contentDescription = null,
modifier = Modifier
.size(40.dp)
.align(Alignment.Center)
.then(
if (isSelected) {
Modifier.border(2.dp, Color.Red)
} else {
Modifier
}
)
)
}
}
}
}
}
}
}
}
}
fun isValidMove(
fromRow: Int,
fromColumn: Int,
toRow: Int,
toColumn: Int,
board: Array<Array<Piece>>
): Boolean {
val piece = board[fromRow][fromColumn]
val targetPiece = board[toRow][toColumn]
Log.d("pizda", "fromColumn $fromColumn")
Log.d("pizda", "fromRow $fromRow")
Log.d("pizda", "toRow $toRow")
Log.d("pizda", "toColumn $toColumn")
val rowDiff = kotlin.math.abs(fromRow - toRow)
val colDiff = kotlin.math.abs(fromColumn - toColumn)
if (rowDiff != 1 || colDiff != 1) {
Log.d("pizda", "here")
return false
}
if (targetPiece != Piece.EMPTY) {
Log.d("pizda", "here1")
return false
}
if (piece == Piece.BLACK && toRow <= fromRow) {
Log.d("pizda", "here2")
return false
}
if (piece == Piece.WHITE && toRow >= fromRow) {
Log.d("pizda", "here3")
return false
}
val rowDirection = if (toRow > fromRow) 1 else -1
val colDirection = if (toColumn > fromColumn) 1 else -1
val intermediateRow = fromRow + rowDirection
val intermediateColumn = fromColumn + colDirection
if (kotlin.math.abs(toRow - fromRow) == 2 && kotlin.math.abs(toColumn - fromColumn) == 2) {
val middlePiece = board[intermediateRow][intermediateColumn]
if (middlePiece == Piece.EMPTY || middlePiece == piece) {
Log.d("pizda", "here4")
return false
}
Log.d("pizda", "here5")
return true
}
Log.d("pizda", "here6")
return false
}
1条答案
按热度按时间iq3niunx1#
所以你的问题很大一部分是你混合了状态和UI。别这样您的UI和@Composable函数不应写入任何状态。它应该是阅读它,执行很少或没有基于它的逻辑(它所做的所有逻辑都应该是严格的显示逻辑),并且写入应该由于您的状态中的回调而发生。通过将这两者结合起来,您会在技术上(您的初始化代码运行每个绘制,因此每个绘制都会重置状态)和逻辑级别上(您根本没有将业务逻辑与UI分离,这将使您的代码变得难以调试)造成问题。
这种形式的UI的全部要点是完全基于状态绘制每个帧,并将UI与任何状态操作分离开来。在这样做的时候,你隔离了代码库的两个部分,所以它们是独立可测试的。您可以通过生成适当的状态来测试UI,也可以通过生成适当的回调函数来测试业务逻辑。这种混合违反了这一切。