开发一个Android App: 打牌计分器

package com.example.myapplication
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.tooling.preview.Preview
import com.example.myapplication.ui.theme.MyApplicationTheme
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApplicationTheme {
                Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
                    ScoreCounterApp()
                }
            }
        }
    }
}
// 数据类:表示一个玩家
data class Player(
    val id: Int,
    var name: String,
    var totalScore: Int = 0
)
// 数据类:表示一轮得分
data class RoundScore(
    val roundNumber: Int,
    val scores: Map<Int, Int> // 玩家ID -> 得分
)

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ScoreCounterApp() {
    var players by remember { mutableStateOf(listOf<Player>()) }
    var currentRound by remember { mutableStateOf(1) }
    var currentTotal by remember { mutableStateOf(0) }
    var currentRoundScores by remember { mutableStateOf(mapOf<Int, String>()) }
    var scoreHistory by remember { mutableStateOf(listOf<RoundScore>()) }
    var newPlayerName by remember { mutableStateOf("") }
    var showHistory by remember { mutableStateOf(false) }
    var showAddPlayerDialog by remember { mutableStateOf(false) }
    Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
        if (players.isEmpty()) {
            Card(modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.secondaryContainer)) {
                Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) {
                    Text(text = "添加玩家", style = MaterialTheme.typography.headlineSmall, modifier = Modifier.padding(bottom = 8.dp))
                    OutlinedTextField(value = newPlayerName, onValueChange = { newPlayerName = it }, label = { Text("玩家姓名") }, modifier = Modifier.fillMaxWidth(), singleLine = true)
                    Spacer(modifier = Modifier.height(8.dp))
                    Button(
                        onClick = {
                            if (newPlayerName.isNotBlank()) {
                                val newPlayer = Player(id = players.size + 1, name = newPlayerName)
                                players = players + newPlayer
                                newPlayerName = ""
                            }
                        }, modifier = Modifier.fillMaxWidth()
                    ) { Text("添加玩家") }
                }
            }
        } else {
            Card(modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.primaryContainer)) {
                Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) {
                    Text(text = "当前总分 (第${currentRound}轮)", style = MaterialTheme.typography.headlineSmall, modifier = Modifier.padding(bottom = 8.dp))
                    LazyColumn {
                        items(players.sortedBy { it.id }) { player ->
                            Row(modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp), horizontalArrangement = Arrangement.SpaceBetween) {
                                Text(text = player.name, style = MaterialTheme.typography.bodyLarge)
                                Text(text = "${player.totalScore} 分", style = MaterialTheme.typography.bodyLarge, color = if (player.totalScore >= 0) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.error)
                            }
                        }
                    }
                }
            }
            Spacer(modifier = Modifier.height(16.dp))
            Column(modifier = Modifier.fillMaxWidth().weight(1f).padding(top = 8.dp)) {
                Card(modifier = Modifier.fillMaxSize(), elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)) {
                    Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
                        Text(text = "第${currentRound}轮得分", style = MaterialTheme.typography.headlineSmall, modifier = Modifier.padding(bottom = 16.dp))
                        LazyColumn(modifier = Modifier.fillMaxWidth().weight(1f), verticalArrangement = Arrangement.spacedBy(12.dp)) {
                            items(players.sortedBy { it.id }) { player ->
                                Column(modifier = Modifier.padding(vertical = 4.dp)) {
                                    Text(text = player.name, style = MaterialTheme.typography.bodyMedium, modifier = Modifier.padding(bottom = 4.dp))
                                    OutlinedTextField(
                                        value = currentRoundScores[player.id] ?: "",
                                        onValueChange = { newValue -> if (newValue.matches(Regex("-?\\d*"))) { currentRoundScores = currentRoundScores.toMutableMap().apply { put(player.id, newValue) } } },
                                        label = { Text("得分") }, modifier = Modifier.fillMaxWidth(), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), singleLine = true
                                    )
                                }
                            }
                        }
                        // 计算当前轮次总分
                        val currentTotal = currentRoundScores.values.sumOf { it.toIntOrNull() ?: 0 }
                        Column(modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
                            Text(text = "当前轮次总分: $currentTotal", style = MaterialTheme.typography.bodyLarge, color = if (currentTotal == 0) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.error, modifier = Modifier.padding(vertical = 12.dp))
                            Row(horizontalArrangement = Arrangement.spacedBy(12.dp), modifier = Modifier.fillMaxWidth()) {
                                Button(
                                    onClick = {
                                        if (currentTotal != 0) {
                                            // 可以在这里显示错误提示
                                            return@Button
                                        }
                                        players = players.map { player ->
                                            val roundScore = currentRoundScores[player.id]?.toIntOrNull() ?: 0
                                            player.copy(totalScore = player.totalScore + roundScore)
                                        }
                                        val scoresMap = currentRoundScores.mapValues { it.value.toIntOrNull() ?: 0 }
                                        val newRoundScore = RoundScore(currentRound, scoresMap)
                                        scoreHistory = scoreHistory + newRoundScore
                                        currentRound++
                                        currentRoundScores = players.associate { it.id to "" }
                                    },
                                    modifier = Modifier.weight(1f),
                                    enabled = currentTotal == 0
                                ) { Text("确认本轮得分") }
                                OutlinedButton(onClick = { currentRoundScores = players.associate { it.id to "" } }, modifier = Modifier.weight(1f)) { Text("重置输入") }
                            }
                        }
                    }
                }
            }

            Column(modifier = Modifier.fillMaxWidth().padding(top = 16.dp)) {
                Row(horizontalArrangement = Arrangement.spacedBy(12.dp), modifier = Modifier.fillMaxWidth()) {
                    Button(onClick = { showHistory = !showHistory }, modifier = Modifier.weight(1f)) { Text(if (showHistory) "隐藏历史" else "查看历史") }
                    OutlinedButton(onClick = { showAddPlayerDialog = true }, modifier = Modifier.weight(1f)) { Text("添加玩家") }
                    OutlinedButton(
                        onClick = {
                            players = emptyList()
                            currentRound = 1
                            currentRoundScores = emptyMap()
                            scoreHistory = emptyList()
                        },
                        modifier = Modifier.weight(1f), colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error)
                    ) { Text("重置游戏") }
                }
                // 历史记录
                if (showHistory && scoreHistory.isNotEmpty()) {
                    Spacer(modifier = Modifier.height(16.dp))
                    Card(modifier = Modifier.fillMaxWidth()) {
                        Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) {
                            Text(text = "历史得分记录", style = MaterialTheme.typography.headlineSmall, modifier = Modifier.padding(bottom = 8.dp))
                            LazyColumn {
                                items(scoreHistory.reversed()) { round ->
                                    Card(modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant)) {
                                        Column(modifier = Modifier.fillMaxWidth().padding(12.dp)) {
                                            Text(text = "第${round.roundNumber}轮", style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(bottom = 4.dp))
                                            round.scores.forEach { (playerId, score) ->
                                                val player = players.find { it.id == playerId }
                                                Row(modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp), horizontalArrangement = Arrangement.SpaceBetween) {
                                                    Text(text = player?.name ?: "玩家$playerId")
                                                    Text(text = "$score 分", color = if (score >= 0) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.error)
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    // 添加玩家对话框
    if (showAddPlayerDialog) {
        AlertDialog(
            onDismissRequest = { showAddPlayerDialog = false },
            title = { Text("添加新玩家") },
            text = { Column { OutlinedTextField(value = newPlayerName, onValueChange = { newPlayerName = it }, label = { Text("玩家姓名") }, modifier = Modifier.fillMaxWidth(), singleLine = true) } },
            confirmButton = {
                Button(
                    onClick = {
                        if (newPlayerName.isNotBlank()) {
                            val newPlayer = Player(id = players.size + 1, name = newPlayerName)
                            players = players + newPlayer
                            currentRoundScores = currentRoundScores.toMutableMap().apply { put(newPlayer.id, "") }
                            newPlayerName = ""
                        }
                        showAddPlayerDialog = false
                    }
                ) { Text("添加") }
            },
            dismissButton = { TextButton(onClick = { showAddPlayerDialog = false }) { Text("取消") } }
        )
    }
}
@Preview(showBackground = true)
@Composable
fun ScoreCounterAppPreview() {
    MyApplicationTheme {
        ScoreCounterApp()
    }
}
posted @ 2026-02-01 22:24  肉肉的男朋友  阅读(7)  评论(0)    收藏  举报