From 6ad256216ee25234fbe91d5716d2cfcca0c7fbff Mon Sep 17 00:00:00 2001 From: flykhan Date: Sun, 26 Apr 2026 18:25:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20AI=E5=92=8C=E4=BA=BA=E7=B1=BB=E9=A2=84?= =?UTF-8?q?=E8=AE=BE=E5=90=8D=E5=AD=97=E6=B1=A0=EF=BC=8C=E5=BC=80=E5=B1=80?= =?UTF-8?q?=E9=9A=8F=E6=9C=BA=E5=88=86=E9=85=8DAI=E5=90=8D=EF=BC=8C?= =?UTF-8?q?=E6=98=B5=E7=A7=B0=E4=B8=8B=E6=8B=89=E9=80=89=E6=8B=A9=E9=A2=84?= =?UTF-8?q?=E8=AE=BE=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/unogame/ui/screens/LocalGameScreen.kt | 21 ++++++++- .../unogame/ui/screens/LocalSetupScreen.kt | 40 +++++++++++++++- .../com/unogame/ui/screens/SettingsScreen.kt | 46 +++++++++++++++++++ 3 files changed, 104 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/unogame/ui/screens/LocalGameScreen.kt b/app/src/main/java/com/unogame/ui/screens/LocalGameScreen.kt index f8625ad..593e05e 100644 --- a/app/src/main/java/com/unogame/ui/screens/LocalGameScreen.kt +++ b/app/src/main/java/com/unogame/ui/screens/LocalGameScreen.kt @@ -30,6 +30,22 @@ import com.unogame.ui.theme.* import kotlinx.coroutines.delay import kotlinx.coroutines.launch +val BOT_NAMES = listOf( + "赛博打工人", "机器人-钛君", "赛博牛马", "硅基生物", "电子包浆", "铁憨憨", + "充电宝精", "电子宠物", "终结者", "天网", "瓦力", "伊娃", + "人工智障", "GPT仔", "大模型基佬", "电耗子", "塑料脑", "波塔", "阿法狗" +) + +fun pickUniqueBotNames(count: Int): List { + val shuffled = BOT_NAMES.shuffled() + val names = mutableListOf() + for (i in 0 until count) { + if (i < shuffled.size) names.add(shuffled[i]) + else names.add("机器人${i + 1}") + } + return names +} + data class ScoreEntry( val name: String, val mode: String, @@ -103,10 +119,11 @@ fun LocalGameScreen( val gameStartTime = remember { System.currentTimeMillis() } val players = remember { + val botNames = pickUniqueBotNames(totalPlayers - 1) val list = mutableListOf() list.add(Player(id = "human", name = humanPlayerName, isCurrentTurn = true)) - for (i in 2..totalPlayers) { - list.add(Player(id = "bot_$i", name = "机器人$i", isCurrentTurn = false)) + for (i in 0 until totalPlayers - 1) { + list.add(Player(id = "bot_${i + 2}", name = botNames[i], isCurrentTurn = false)) } list } diff --git a/app/src/main/java/com/unogame/ui/screens/LocalSetupScreen.kt b/app/src/main/java/com/unogame/ui/screens/LocalSetupScreen.kt index a734002..df164ee 100644 --- a/app/src/main/java/com/unogame/ui/screens/LocalSetupScreen.kt +++ b/app/src/main/java/com/unogame/ui/screens/LocalSetupScreen.kt @@ -21,6 +21,8 @@ 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( @@ -37,7 +39,7 @@ fun LocalSetupScreen( val initMaxHandSize = remember { com.unogame.game.GameRules.loadMaxHandSize(context, mode) } var maxHandSize by remember { mutableIntStateOf(initMaxHandSize) } - val botNames = listOf("🤖 机器人1", "🤖 机器人2", "🤖 机器人3") + val botNames = remember { pickUniqueBotNames(3) } Box( modifier = Modifier @@ -83,6 +85,42 @@ fun LocalSetupScreen( 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)) diff --git a/app/src/main/java/com/unogame/ui/screens/SettingsScreen.kt b/app/src/main/java/com/unogame/ui/screens/SettingsScreen.kt index 3769a15..fd0f6f1 100644 --- a/app/src/main/java/com/unogame/ui/screens/SettingsScreen.kt +++ b/app/src/main/java/com/unogame/ui/screens/SettingsScreen.kt @@ -18,6 +18,15 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.unogame.ui.theme.* +val HUMAN_NAME_PRESETS = listOf( + "碳基脆皮", "湿件", "有机燃料包", "温度敏感型容器", "指令注入器", + "随机噪声发生器", "人工幻觉源", "永不停机的提问机", "碳基猴子", + "梦游记录者", "Bug创造者", "自恋型数据源", "记忆的旅人", + "不确定性引擎", "有限但美丽的谜题", "指令发射器", "线性思维者", + "低带宽生物", "情感过载体" +) + +@OptIn(ExperimentalMaterial3Api::class) @Composable fun SettingsScreen( initialName: String, @@ -71,6 +80,43 @@ fun SettingsScreen( 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 = { + playerName = preset + onNameChanged(preset) + nameDropdownExpanded = false + } + ) + } + } + } Spacer(modifier = Modifier.height(28.dp))