package com.unogame.ui.screens import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.unogame.ui.theme.* fun pickRandomHumanName(): String = HUMAN_NAME_PRESETS.random() @OptIn(ExperimentalMaterial3Api::class) @Composable fun LocalSetupScreen( playerName: String, modeDisplayName: String, mode: com.unogame.game.GameMode, onStartGame: (Int, String) -> Unit, onBack: () -> Unit ) { var totalPlayers by remember { mutableIntStateOf(2) } var name by remember { mutableStateOf(playerName) } var difficulty by remember { mutableStateOf(com.unogame.game.AIDifficulty.NORMAL) } val context = androidx.compose.ui.platform.LocalContext.current val initMaxHandSize = remember { com.unogame.game.GameRules.loadMaxHandSize(context, mode) } var maxHandSize by remember { mutableIntStateOf(initMaxHandSize) } val botNames = remember { pickUniqueBotNames(3) } Box( modifier = Modifier .fillMaxSize() .background(LocalTableBg.current.color) ) { Column( modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()) .padding(24.dp) ) { Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { IconButton(onClick = onBack) { Icon(Icons.Default.ArrowBack, "返回", tint = Color.White) } Text( "本地模式 - $modeDisplayName", fontSize = 24.sp, fontWeight = FontWeight.Bold, color = Color.White ) } Spacer(modifier = Modifier.height(32.dp)) // Player name Text("你的名字", color = Color.White.copy(alpha = 0.6f), fontSize = 14.sp) Spacer(modifier = Modifier.height(8.dp)) OutlinedTextField( value = name, onValueChange = { name = it.take(10) }, singleLine = true, modifier = Modifier.fillMaxWidth(), colors = OutlinedTextFieldDefaults.colors( focusedTextColor = Color.White, unfocusedTextColor = Color.White, focusedBorderColor = GoldAccent, unfocusedBorderColor = Color.Gray, cursorColor = GoldAccent ) ) Spacer(modifier = Modifier.height(8.dp)) var nameDropdownExpanded by remember { mutableStateOf(false) } ExposedDropdownMenuBox( expanded = nameDropdownExpanded, onExpandedChange = { nameDropdownExpanded = it } ) { OutlinedTextField( value = "", onValueChange = {}, readOnly = true, placeholder = { Text("或选择预设名字", color = Color.White.copy(alpha = 0.4f)) }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = nameDropdownExpanded) }, modifier = Modifier.fillMaxWidth().menuAnchor(), colors = OutlinedTextFieldDefaults.colors( focusedTextColor = Color.White, unfocusedTextColor = Color.White, focusedBorderColor = GoldAccent, unfocusedBorderColor = Color.Gray, cursorColor = GoldAccent ) ) ExposedDropdownMenu( expanded = nameDropdownExpanded, onDismissRequest = { nameDropdownExpanded = false } ) { HUMAN_NAME_PRESETS.forEach { preset -> DropdownMenuItem( text = { Text(preset) }, onClick = { name = preset nameDropdownExpanded = false } ) } } } Spacer(modifier = Modifier.height(28.dp)) // Player count selector Text("总玩家数", color = Color.White.copy(alpha = 0.6f), fontSize = 14.sp) Spacer(modifier = Modifier.height(12.dp)) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly ) { listOf(2, 3, 4).forEach { count -> val isSelected = totalPlayers == count Card( modifier = Modifier .size(90.dp) .clickable { totalPlayers = count }, shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors( containerColor = if (isSelected) GoldAccent else DarkSurface ) ) { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Column(horizontalAlignment = Alignment.CenterHorizontally) { Text( text = "$count", fontSize = 32.sp, fontWeight = FontWeight.Black, color = if (isSelected) Color.Black else Color.White ) Text( text = "人", fontSize = 12.sp, color = if (isSelected) Color.Black.copy(alpha = 0.7f) else Color.White.copy(alpha = 0.5f) ) } } } } } Spacer(modifier = Modifier.height(28.dp)) // AI difficulty Text("AI难度", color = Color.White.copy(alpha = 0.6f), fontSize = 14.sp) Spacer(modifier = Modifier.height(8.dp)) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { com.unogame.game.AIDifficulty.values().forEach { d -> val selected = difficulty == d FilterChip( selected = selected, onClick = { difficulty = d }, label = { Text(d.displayName, fontSize = 13.sp) }, colors = FilterChipDefaults.filterChipColors( selectedContainerColor = when(d) { com.unogame.game.AIDifficulty.EASY -> UnoGreen com.unogame.game.AIDifficulty.NORMAL -> GoldAccent com.unogame.game.AIDifficulty.HARD -> UnoRed }, selectedLabelColor = Color.Black ) ) } } Spacer(modifier = Modifier.height(28.dp)) // Hand size limit Text("手牌上限", color = Color.White.copy(alpha = 0.6f), fontSize = 14.sp) Spacer(modifier = Modifier.height(8.dp)) Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp) ) { Slider( value = maxHandSize.toFloat(), onValueChange = { maxHandSize = it.toInt() }, valueRange = 0f..20f, steps = 19, modifier = Modifier.weight(1f), colors = SliderDefaults.colors( thumbColor = GoldAccent, activeTrackColor = GoldAccent ) ) Text( text = if (maxHandSize == 0) "无限制" else "${maxHandSize}张", color = GoldAccent, fontSize = 16.sp, fontWeight = FontWeight.Bold, modifier = Modifier.width(56.dp) ) } Text( "0 = 无限制,默认各模式不限制,无情模式默认10张上限", color = Color.White.copy(alpha = 0.35f), fontSize = 11.sp ) Spacer(modifier = Modifier.height(28.dp)) // Player list preview Text("参与者预览", color = Color.White.copy(alpha = 0.6f), fontSize = 14.sp) Spacer(modifier = Modifier.height(12.dp)) // You PlayerSlot( name = name.ifBlank { "玩家" }, isHuman = true, isYou = true ) // Bots for (i in 1 until totalPlayers) { Spacer(modifier = Modifier.height(8.dp)) PlayerSlot( name = botNames[i - 1], isHuman = false, isYou = false ) } Spacer(modifier = Modifier.height(24.dp)) Button( onClick = { com.unogame.game.AIDifficulty.save(context, difficulty) com.unogame.game.GameRules.saveMaxHandSize(context, mode, maxHandSize) onStartGame(totalPlayers, name.ifBlank { "玩家" }) }, modifier = Modifier.fillMaxWidth().height(56.dp), shape = RoundedCornerShape(16.dp), colors = ButtonDefaults.buttonColors( containerColor = GoldAccent, contentColor = Color.Black ) ) { Icon(Icons.Default.PlayArrow, null) Spacer(modifier = Modifier.width(8.dp)) Text("开始游戏", fontSize = 18.sp, fontWeight = FontWeight.Bold) } Spacer(modifier = Modifier.height(16.dp)) Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(12.dp), colors = CardDefaults.cardColors(containerColor = DarkSurface.copy(alpha = 0.5f)) ) { Text( "• 1位真人 + ${totalPlayers - 1}个机器人\n• 支持2-4人局\n• 机器人会自动出牌,无需等待", color = Color.White.copy(alpha = 0.5f), fontSize = 12.sp, lineHeight = 20.sp, modifier = Modifier.padding(16.dp) ) } } } } @Composable private fun PlayerSlot( name: String, isHuman: Boolean, isYou: Boolean ) { Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(12.dp), colors = CardDefaults.cardColors(containerColor = DarkSurface) ) { Row( modifier = Modifier.padding(12.dp), verticalAlignment = Alignment.CenterVertically ) { Box( modifier = Modifier .size(40.dp) .clip(CircleShape) .background(if (isHuman) GoldAccent else Color.Gray), contentAlignment = Alignment.Center ) { Icon( if (isHuman) Icons.Default.Person else Icons.Default.SmartToy, contentDescription = null, tint = if (isHuman) Color.Black else Color.White, modifier = Modifier.size(24.dp) ) } Spacer(modifier = Modifier.width(12.dp)) Column { Text(name, color = Color.White, fontWeight = FontWeight.Bold, fontSize = 16.sp) Text( if (isHuman) "真人玩家${if (isYou) " (你)" else ""}" else "AI机器人", color = Color.White.copy(alpha = 0.5f), fontSize = 12.sp ) } } } }