0

ハングマン ゲームのプレーヤーのスコアを含むテキスト ファイルを作成しようとしています。テキスト ファイルの構造は、次の順序に従う必要があります。番号。名前のスコア (例: 1. Helen 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);
            }
        }

[/コード]

4

4 に答える 4

4

私は個人的にコードをもう少し抽象化しますが、これ以上クラスを追加したくない場合、またはメソッドの外部で実際に何かをしたくない場合は、次のようにします。

  • ハイスコ​​アをList<Tuple<int, string, int>>
  • 新しいスコアを追加
  • list.Sort()または LINQ を使用してリストを並べ替えます
  • リストをファイルに書き出します。

質問にあるものよりもはるかにクリーンで読みやすいです。

于 2012-06-16T09:51:50.173 に答える
2

これは私が強く支持している釣りと食事についてのことわざに完全に反しているという事実にもかかわらず、私はあなたのコードを完全に書き直すことによっていくつかの改善をする自由を取りました。

まず、プレーヤーの位置をテキストファイルに保存することをやめました。これは効率的ではありません。最高のスコアを持つプレーヤーを追加する(そのプレーヤーを#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は、フィードされた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
于 2012-06-16T10:09:33.860 に答える
2

番号を保存する理由はありません。行の位置はその目的に役立ちます。さらに良いのは、行の解析を避けるために、スコアオブジェクトを含むリストをたとえば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++;
  }
于 2012-06-16T10:02:52.240 に答える
1

ハイスコ​​アの単純なリストを保存するための複雑な方法のようです。次のことを試してみませんか。

プレーヤーのスコアを保持するための単純なオブジェクトを定義します。

[Serializable]
public class HighScore
{
    public string PlayerName { get; set; }

    public int Score { get; set; }
}

必ず[Serializable]属性でマークしてください。

数人のプレーヤーのハイスコアのリストをすばやく作成しましょう。

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 }
};

これで、 BinaryFormatterを使用してスコアをシリアル化し、ローカルファイルに保存できます。

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();
于 2012-06-16T10:02:35.080 に答える