C# 创建高分文本文件并对结果重新排序
本文关键字:新排序 排序 结果 创建 文本 文件 | 更新日期: 2023-09-27 18:37:28
我正在尝试创建一个包含玩家刽子手游戏分数的文本文件。文本文件的结构应遵循顺序:编号。姓名分数(例如 1.海伦2500)。我试图拆分行,以便我可以将数据引入名称和分数的特定数组中,以便我可以比较结果并重新排序它们(数字保持不变:1、2、3 等),但它不起作用。我没有收到错误,但由于数组 v[] 的使用不正确,构建在此函数处停止。你建议我怎么做才能让它工作?
[代码]
private void New_Score(int score)
{
int k=0, i;
char[] sep = new char[] { ' ', ''n', '.' };
string line, aux1, aux2;
string n=null, s=null;
n = textBox1.Text;
s = Convert.ToString(score);
string[] part=null, nr=null, name=null, result=null;
file_path = @"D:'Visual Studio 2005'Projects'WindowsApplication2'WindowsApplication2'Resources'HighScore.txt";
StreamReader f = new StreamReader(file_path);
while ((line = f.ReadLine()) != null)
{
part = null;
v = null;
part = line.Split(sep);
i=0;
foreach(string c in part)
{
v[i]= c;
i++;
}
nr[k] = v[0];
name[k] = v[1];
result[k] = v[2];
}
for (i = 0; i < k; i++)
if (string.CompareOrdinal(s,result[i]) == 1)
{
aux1 = s;
s = result[i];
result[i] = aux1;
aux2 = n;
n = name[i];
name[i] = aux2;
}
for (i = 0; i < k; i++)
{
line = nr[i] + ". " + name[i] + " " + result[i] + "'n";
File.WriteAllText(file_path, line);
}
}
[/代码]
我个人会进一步抽象代码,但如果您不想添加更多类或真正在方法之外执行任何操作,我会这样做:
- 将高分解析为
List<Tuple<int, string, int>>
- 添加新分数
- 使用
list.Sort()
或 LINQ 对列表进行排序 - 将列表写出到文件中。
它比你在问题中的内容更干净,更具可读性。
尽管这完全违背了我强烈支持的关于钓鱼和吃饭的说法,但我还是冒昧地通过完全重写您的代码进行了一些改进。
首先,我摆脱了在文本文件中存储播放器位置的功能。这效率不高,因为当您添加得分最高的玩家(渲染他 #1)时,您必须重新编号此时文件中存在的其他人。
因此,生成的文件如下所示:
Foo 123
Qux 714
Bar 456
Baz 999
main()
方法如下所示:
var scores = ReadScoresFromFile("Highscores.txt");
scores.ForEach(s => Console.WriteLine(s));
Console.ReadKey();
然后是Highscore
类:
class Highscore
{
public String Name { get; set; }
public int Position { get; set; }
public int Score { get; set; }
public Highscore(String data)
{
var d = data.Split(' ');
if (String.IsNullOrEmpty(data) || d.Length < 2)
throw new ArgumentException("Invalid high score string", "data");
this.Name = d[0];
int num;
if (int.TryParse(d[1], out num))
{
this.Score = num;
}
else
{
throw new ArgumentException("Invalid score", "data");
}
}
public override string ToString()
{
return String.Format("{0}. {1}: {2}", this.Position, this.Name, this.Score);
}
}
您会看到 Highscore 根据它输入的高分数文件中的行填充自身。我使用此方法填充分数列表:
static List<Highscore> ReadScoresFromFile(String path)
{
var scores = new List<Highscore>();
using (StreamReader reader = new StreamReader(path))
{
String line;
while (!reader.EndOfStream)
{
line = reader.ReadLine();
try
{
scores.Add(new Highscore(line));
}
catch (ArgumentException ex)
{
Console.WriteLine("Invalid score at line '"{0}'": {1}", line, ex);
}
}
}
return SortAndPositionHighscores(scores);
}
最后是一些排序和位置同理:
static List<Highscore> SortAndPositionHighscores(List<Highscore> scores)
{
scores = scores.OrderByDescending(s => s.Score).ToList();
int pos = 1;
scores.ForEach(s => s.Position = pos++);
return scores.ToList();
}
结果是:
1. Baz: 999
2. Qux: 714
3. Bar: 456
4. Foo: 123
没有理由存储数字,行位置可以达到这个目的。更好的是将带有分数对象的 List 序列化为例如 XML(如果要保留人类可读的分数文件),以避免行解析。但是如果你想存储到纯文本,这里有一个简单的例子:
private void New_Score(int score, string name)
{
string filename = "scores.txt";
List<string> scoreList;
if (File.Exists(filename))
scoreList = File.ReadAllLines(filename).ToList();
else
scoreList = new List<string>();
scoreList.Add(name + " " + score.ToString());
var sortedScoreList = scoreList.OrderByDescending(ss => int.Parse(ss.Substring(ss.LastIndexOf(" ") + 1)));
File.WriteAllLines(filename, sortedScoreList.ToArray());
}
稍后在显示结果时,在前面添加订单号,如下所示:
int xx = 1;
List<string> scoreList = File.ReadAllLines(filename).ToList();
foreach (string oneScore in scoreList)
{
Console.WriteLine(xx.ToString() + ". " + oneScore);
xx++;
}
似乎是一种存储简单高分列表的复杂方法。您为什么不尝试以下方法。
定义一个简单的对象来保存玩家的分数。
[Serializable]
public class HighScore
{
public string PlayerName { get; set; }
public int Score { get; set; }
}
请确保使用 [可序列化] 属性对其进行标记。
让我们快速为几个玩家创建一个高分列表。
var highScores = new List<HighScore>()
{
new HighScore { PlayerName = "Helen", Score = 1000 },
new HighScore { PlayerName = "Christophe", Score = 2000 },
new HighScore { PlayerName = "Ruben", Score = 3000 },
new HighScore { PlayerName = "John", Score = 4000 },
new HighScore { PlayerName = "The Last Starfighter", Score = 5000 }
};
现在,您可以使用二进制格式化程序序列化乐谱并将其保存到本地文件。
using (var fileStream = new FileStream(@"C:'temp'scores.dat", FileMode.Create, FileAccess.Write))
{
var formatter = new BinaryFormatter();
formatter.Serialize(fileStream, highScores);
}
稍后,您可以以类似的方式从此文件中加载高分。
using (var fileStream = new FileStream(@"C:'temp'scores.dat", FileMode.Open, FileAccess.Read))
{
var formatter = new BinaryFormatter();
highScores = (List<HighScore>) formatter.Deserialize(fileStream);
}
如果要对它们进行排序,可以在 HighScore 类型上实现 IComparable 接口。
[Serializable]
public class HighScore : IComparable
{
//...
public int CompareTo(object obj)
{
var otherScore = (HighScore) obj;
if (Score == otherScore.Score)
return 0;
if (Score < otherScore.Score)
return 1;
return -1;
}
}
现在,您只需在泛型列表集合上调用 Sort(...)。
highScores.Sort();
瞧,分数按降序排序。
foreach(var score in highScores)
{
Console.WriteLine(String.Format("{0}: {1} points", score.PlayerName, score.Score));
}
或者更简单,只需使用 LINQ 对高分进行排序。
var sortedScores = highScores.OrderByDescending(s => s.Score).ToList();