fix : 修复积分榜问题
This commit is contained in:
parent
1a215a4b8f
commit
d201ae48eb
@ -21,8 +21,15 @@ import com.unogame.ui.theme.*
|
||||
fun GameOverScreen(
|
||||
winnerName: String,
|
||||
isYouWinner: Boolean,
|
||||
onBackToMenu: () -> Unit
|
||||
onBackToMenu: () -> Unit,
|
||||
points: Int = 0,
|
||||
difficulty: String = "",
|
||||
duration: Int = 0,
|
||||
turnNumber: Int = 0,
|
||||
playerCount: Int = 0
|
||||
) {
|
||||
val durationText = if (duration >= 60) "${duration / 60}分${duration % 60}秒" else "${duration}秒"
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
@ -61,6 +68,38 @@ fun GameOverScreen(
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
if (isYouWinner && points > 0) {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Text(
|
||||
text = "+$points 分",
|
||||
fontSize = 32.sp,
|
||||
fontWeight = FontWeight.Black,
|
||||
color = GoldAccent
|
||||
)
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceEvenly
|
||||
) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text("难度", color = Color.White.copy(alpha = 0.5f), fontSize = 12.sp)
|
||||
Text(difficulty, color = Color.White, fontSize = 14.sp, fontWeight = FontWeight.Bold)
|
||||
}
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text("时长", color = Color.White.copy(alpha = 0.5f), fontSize = 12.sp)
|
||||
Text(durationText, color = Color.White, fontSize = 14.sp, fontWeight = FontWeight.Bold)
|
||||
}
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text("人数", color = Color.White.copy(alpha = 0.5f), fontSize = 12.sp)
|
||||
Text("${playerCount}人", color = Color.White, fontSize = 14.sp, fontWeight = FontWeight.Bold)
|
||||
}
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text("轮次", color = Color.White.copy(alpha = 0.5f), fontSize = 12.sp)
|
||||
Text("$turnNumber 轮", color = Color.White, fontSize = 14.sp, fontWeight = FontWeight.Bold)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(48.dp))
|
||||
|
||||
Button(
|
||||
|
||||
@ -14,10 +14,19 @@ import com.unogame.model.*
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
data class ScoreEntry(val name: String, val wins: Int, val mode: String)
|
||||
data class ScoreEntry(
|
||||
val name: String,
|
||||
val mode: String,
|
||||
val points: Int,
|
||||
val difficulty: String,
|
||||
val duration: Int,
|
||||
val playerCount: Int,
|
||||
val turnNumber: Int,
|
||||
val date: Long
|
||||
)
|
||||
|
||||
object Scoreboard {
|
||||
private const val PREFS_KEY = "uno_scores"
|
||||
private const val PREFS_KEY = "uno_scoreboard"
|
||||
private val gson = Gson()
|
||||
|
||||
fun loadScores(context: Context): List<ScoreEntry> {
|
||||
@ -33,15 +42,30 @@ object Scoreboard {
|
||||
.edit().putString(PREFS_KEY, gson.toJson(scores)).apply()
|
||||
}
|
||||
|
||||
fun addWin(context: Context, name: String, mode: GameMode) {
|
||||
fun addEntry(
|
||||
context: Context,
|
||||
name: String,
|
||||
mode: String,
|
||||
points: Int,
|
||||
difficulty: String,
|
||||
duration: Int,
|
||||
playerCount: Int,
|
||||
turnNumber: Int
|
||||
) {
|
||||
val scores = loadScores(context).toMutableList()
|
||||
val existing = scores.indexOfFirst { it.name == name && it.mode == mode.displayName }
|
||||
if (existing >= 0) {
|
||||
scores[existing] = scores[existing].copy(wins = scores[existing].wins + 1)
|
||||
} else {
|
||||
scores.add(ScoreEntry(name, 1, mode.displayName))
|
||||
}
|
||||
saveScores(context, scores.sortedByDescending { it.wins }.take(20))
|
||||
scores.add(
|
||||
ScoreEntry(
|
||||
name = name,
|
||||
mode = mode,
|
||||
points = points,
|
||||
difficulty = difficulty,
|
||||
duration = duration,
|
||||
playerCount = playerCount,
|
||||
turnNumber = turnNumber,
|
||||
date = System.currentTimeMillis()
|
||||
)
|
||||
)
|
||||
saveScores(context, scores.sortedByDescending { it.points }.take(50))
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,6 +81,7 @@ fun LocalGameScreen(
|
||||
val rules = remember { GameRules.forMode(mode) }
|
||||
val engine = remember { GameEngine(rules) }
|
||||
val aiDiff = remember { AIDifficulty.load(context) }
|
||||
val gameStartTime = remember { System.currentTimeMillis() }
|
||||
|
||||
val players = remember {
|
||||
val list = mutableListOf<Player>()
|
||||
@ -75,6 +100,10 @@ fun LocalGameScreen(
|
||||
var winnerName by remember { mutableStateOf("") }
|
||||
var isYouWinner by remember { mutableStateOf(false) }
|
||||
var scoreSaved by remember { mutableStateOf(false) }
|
||||
var gamePoints by remember { mutableIntStateOf(0) }
|
||||
var gameDuration by remember { mutableIntStateOf(0) }
|
||||
var gameDifficulty by remember { mutableStateOf("") }
|
||||
var gameTurnNumber by remember { mutableIntStateOf(0) }
|
||||
|
||||
val myPlayerId = "human"
|
||||
val currentPlayer = gameState.currentPlayer
|
||||
@ -90,7 +119,25 @@ fun LocalGameScreen(
|
||||
isYouWinner = state.winner?.id == myPlayerId
|
||||
if (isYouWinner && !scoreSaved) {
|
||||
scoreSaved = true
|
||||
Scoreboard.addWin(context, humanPlayerName, mode)
|
||||
gameTurnNumber = state.turnNumber
|
||||
gameDuration = ((System.currentTimeMillis() - gameStartTime) / 1000).toInt()
|
||||
gameDifficulty = aiDiff.displayName
|
||||
gamePoints = state.players.filter { it.id != myPlayerId }.sumOf { player ->
|
||||
player.cards.sumOf { card ->
|
||||
val active = if (state.flipped && card.flipSide != null) card.flipSide else card
|
||||
active.score
|
||||
}
|
||||
}
|
||||
Scoreboard.addEntry(
|
||||
context = context,
|
||||
name = humanPlayerName,
|
||||
mode = mode.displayName,
|
||||
points = gamePoints,
|
||||
difficulty = gameDifficulty,
|
||||
duration = gameDuration,
|
||||
playerCount = totalPlayers,
|
||||
turnNumber = gameTurnNumber
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -145,7 +192,12 @@ fun LocalGameScreen(
|
||||
GameOverScreen(
|
||||
winnerName = winnerName,
|
||||
isYouWinner = isYouWinner,
|
||||
onBackToMenu = onBackToMenu
|
||||
onBackToMenu = onBackToMenu,
|
||||
points = gamePoints,
|
||||
difficulty = gameDifficulty,
|
||||
duration = gameDuration,
|
||||
turnNumber = gameTurnNumber,
|
||||
playerCount = totalPlayers
|
||||
)
|
||||
} else {
|
||||
GameScreen(
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
package com.unogame.ui.screens
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
@ -19,6 +21,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.unogame.game.GameMode
|
||||
import com.unogame.ui.theme.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@ -48,7 +52,9 @@ fun ScoreboardScreen(onBack: () -> Unit) {
|
||||
// Mode filter chips
|
||||
if (scores.isNotEmpty()) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.horizontalScroll(rememberScrollState()),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
modes.forEach { mode ->
|
||||
@ -95,41 +101,75 @@ fun ScoreboardScreen(onBack: () -> Unit) {
|
||||
2 -> Color(0xFFCD7F32)
|
||||
else -> Color.White.copy(alpha = 0.5f)
|
||||
}
|
||||
val dateFormat = remember { SimpleDateFormat("MM-dd HH:mm", Locale.getDefault()) }
|
||||
val durationText = if (entry.duration >= 60) "${entry.duration / 60}分${entry.duration % 60}秒"
|
||||
else "${entry.duration}秒"
|
||||
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = if (index < 3) DarkSurface else DarkCard)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.padding(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
// Rank
|
||||
Text(
|
||||
text = "#${index + 1}",
|
||||
color = rankColor,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Black,
|
||||
modifier = Modifier.width(44.dp)
|
||||
)
|
||||
// Name
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(entry.name, color = Color.White, fontWeight = FontWeight.Bold, fontSize = 15.sp)
|
||||
Text(
|
||||
entry.mode,
|
||||
color = Color.White.copy(alpha = 0.5f),
|
||||
fontSize = 12.sp
|
||||
)
|
||||
}
|
||||
// Wins
|
||||
Column(modifier = Modifier.padding(12.dp)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(Icons.Default.Star, null, tint = GoldAccent, modifier = Modifier.size(18.dp))
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
Text(
|
||||
"${entry.wins}胜",
|
||||
color = GoldAccent,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 16.sp
|
||||
text = "#${index + 1}",
|
||||
color = rankColor,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Black,
|
||||
modifier = Modifier.width(44.dp)
|
||||
)
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(entry.name, color = Color.White, fontWeight = FontWeight.Bold, fontSize = 15.sp)
|
||||
Text(
|
||||
entry.mode,
|
||||
color = GoldAccent,
|
||||
fontSize = 12.sp
|
||||
)
|
||||
}
|
||||
Column(horizontalAlignment = Alignment.End) {
|
||||
Text(
|
||||
"${entry.points}分",
|
||||
color = GoldAccent,
|
||||
fontWeight = FontWeight.Black,
|
||||
fontSize = 20.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(Icons.Default.SmartToy, null, tint = Color.White.copy(alpha = 0.5f), modifier = Modifier.size(14.dp))
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
Text(entry.difficulty, color = Color.White.copy(alpha = 0.5f), fontSize = 11.sp)
|
||||
}
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(Icons.Default.Timer, null, tint = Color.White.copy(alpha = 0.5f), modifier = Modifier.size(14.dp))
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
Text(durationText, color = Color.White.copy(alpha = 0.5f), fontSize = 11.sp)
|
||||
}
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(Icons.Default.Group, null, tint = Color.White.copy(alpha = 0.5f), modifier = Modifier.size(14.dp))
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
Text("${entry.playerCount}人", color = Color.White.copy(alpha = 0.5f), fontSize = 11.sp)
|
||||
}
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(Icons.Default.Loop, null, tint = Color.White.copy(alpha = 0.5f), modifier = Modifier.size(14.dp))
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
Text("${entry.turnNumber}轮", color = Color.White.copy(alpha = 0.5f), fontSize = 11.sp)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(Icons.Default.Schedule, null, tint = Color.White.copy(alpha = 0.3f), modifier = Modifier.size(12.dp))
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
Text(
|
||||
dateFormat.format(Date(entry.date)),
|
||||
color = Color.White.copy(alpha = 0.3f),
|
||||
fontSize = 10.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user