C# WinForms排行榜开发:实现分数排序且排除名称干扰
解决Windows Forms排行榜添加玩家名称后排序混乱的问题
你遇到的核心问题是把分数和玩家名称拼接成字符串后,排序逻辑变成了按字符串字典序比较,而非分数的数值大小,导致排序结果不符合预期。比如分数100和名称"Bob"拼接成"100Bob",分数99和名称"Alice"拼接成"99Alice",字符串比较时"100Bob"会被判定为小于"99Alice"(因为首字符'1'<'9'),从而出现排序混乱。
正确的实现思路
应该将玩家名称和分数作为一个整体(实体对象)存储,排序时只针对分数字段进行比较,最后再统一格式化显示内容。
1. 创建玩家分数实体类
定义一个类来封装玩家名称和分数,同时重写ToString()方法方便在ListBox中显示:
public class PlayerScore { public string Name { get; set; } public int Score { get; set; } // 自定义显示格式 public override string ToString() { return $"{Name}: {Score}"; } }
2. 修改添加与排序逻辑
使用泛型List<T>替代非类型安全的ArrayList,可以直接对PlayerScore对象按分数降序排序:
方式一:使用LINQ排序(简洁直观)
// 添加新的玩家记录 var newPlayerScore = new PlayerScore { Name = txtName.Text.Trim(), Score = int.Parse(txtScore.Text) }; lstleaderboard.Items.Add(newPlayerScore); // 按分数降序排序 var sortedScores = lstleaderboard.Items.Cast<PlayerScore>() .OrderByDescending(ps => ps.Score) .ToList(); // 更新ListBox内容 lstleaderboard.Items.Clear(); foreach (var score in sortedScores) { lstleaderboard.Items.Add(score); } // 限制排行榜最多10条记录 if (lstleaderboard.Items.Count > 10) { lstleaderboard.Items.RemoveAt(lstleaderboard.Items.Count - 1); }
方式二:自定义比较器(适合理解排序原理)
如果你想使用自定义比较器替代LINQ,可以实现IComparer<PlayerScore>:
public class PlayerScoreDescComparer : IComparer<PlayerScore> { public int Compare(PlayerScore x, PlayerScore y) { // 按分数降序排列:y的分数减x的分数,返回正数则y排在x前面 return y.Score.CompareTo(x.Score); } }
然后修改排序代码:
// 添加新记录逻辑同上... // 转换为泛型列表并排序 List<PlayerScore> sortingList = lstleaderboard.Items.Cast<PlayerScore>().ToList(); sortingList.Sort(new PlayerScoreDescComparer()); // 更新ListBox内容 lstleaderboard.Items.Clear(); foreach (var score in sortingList) { lstleaderboard.Items.Add(score); } // 限制记录数量逻辑同上...
为什么原代码会出错
原修改后的代码中,你将分数(int类型)与玩家名称拼接成字符串后存储,排序时ArrayList.Sort()会按字符串的字典序进行比较,而不是分数的数值大小。这种比较逻辑和你需要的"按分数从高到低排序"完全不符,因此出现了排序混乱的问题。
内容的提问来源于stack exchange,提问作者EmilBJ8888
相关产品推荐
相关产品推荐

