我必须制作这个程序,对游戏的高分进行排序,然后用用户名USING LISTS显示它们从大到小。到目前为止我写道:
Public highscore As New List(Of HighScores)
highscore.Add(New HighScores("Jeremias", 6))
highscore.Add(New HighScores("Tom", 1))
highscore.Add(New HighScores("sdf", 5))
highscore.Add(New HighScores("asfd", 1))
highscore.Sort()
highscore.Reverse()
Console.WriteLine("------High Scores-----")
For Each scores In highscore
Console.WriteLine(scores)
Next
Console.WriteLine("----------------------")
HighScores类:
Public Class HighScores
Public name As String
Public score As Integer
Public Sub New(ByVal name As String, ByVal score As Integer)
Me.name = name
Me.score = score
End Sub
Public Overrides Function ToString() As String
Return String.Format("{0}, {1}", Me.name, Me.score)
End Function
End Class
通常我会使用.Sort()和.Reverse()来对列表进行排序,但在这种情况下我不认为我能做到这一点。我有什么想法可以重写这个/只是轻松地对列表进行排序吗?
答案 0 :(得分:3)
您可以指定如何以各种方式对List(Of T)
进行排序。最简单的就是这样:
highscore.Sort(Function(x, y) y.score.CompareTo(x.score))
使用Sort
的重载,它接受Comparison(Of T)
委托,并为该委托使用Lambda表达式。请注意,Lambda参数为x
和y
,并且正文在CompareTo
score
上调用y
。这很关键,因为这是使排序按降序排列的原因,并且无需调用Reverse
。
请注意,您可以使用命名方法而不是Lambda。这样的方法看起来像这样:
Private Function CompareHighScoresByScoreDescending(x As HighScores, y As HighScores) As Integer
Return y.score.CompareTo(x.score)
End Function
要排序的代码如下所示:
highscore.Sort(AddressOf CompareHighScoresByScoreDescending)
在比较对象以进行排序时,惯例是使用-1,0和1来表示相对位置。这就是CompareTo
的作用,因此这就是我们的比较方法在这里所做的。如果您在CompareTo
上调用的对象在概念上较少传递的对象,则结果为-1。 1表示第一个对象大于第二个对象,0表示它们相等。该方法可以像这样重写:
Private Function CompareHighScoresByScoreDescending(x As HighScores, y As HighScores) As Integer
If y.score < x.score Then
Return -1
ElseIf y.score > x.score Then
Return 1
Else
Return 0
End If
End Function
使用IComparable
类型的现有Integer
实现显然更为简洁,即CompareTo
方法。
顺便说一句,您的代码可以在其他方面使用一些改进。首先,HighScores
不是该类的合适名称。它代表一个单一的东西,所以名称不应该是复数,它实际上并不代表自己的高分。更合适的名称是PlayerScore
,因为它更准确地描述了它所代表的内容。
其次,您的List
变量实际上代表多个对象,即包含多个项目的列表,因此它的名称应该是复数。它实际上也代表高分,因此它应该被命名为highScores
。
最后,公开公开成员变量几乎是普遍的坏习惯。你应该绝对使用该类中的属性:
作为奖励,如果你使用VS 2015或更高版本,那么你也可以用字符串插值替换String.Format
。
Public Class PlayerScore
Public Property Name As String
Public Property Score As Integer
Public Sub New(name As String, score As Integer)
Me.Name = name
Me.Score = score
End Sub
Public Overrides Function ToString() As String
Return $"{Name}, {Score}"
End Function
End Class