数组排序效率......初学者需要建议

时间:2011-02-17 23:14:59

标签: c# arrays algorithm

我首先要说的是我是一名初学程序员,这本质上是我使用学习资料之外的第一个真正的项目。我一直在使用C#和XNA做一个'Simon Says'风格的游戏(你重复计算机生成的模式的游戏),实际的游戏是完整的并且工作正常但是在创建它时,我还想创建一个'排名前10的记分牌。记分牌将记录玩家姓名,等级(他们完成了多少'轮次)和组合(他们按下了多少按钮),记分板将按组合分数排序。这导致我第一次使用XML,最终我得到了一个记录前10个分数的XML文件。 XML文件在记分板类中管理,记分板类还负责添加新分数和排序分数。这让我明白了......我想对我对排序列表进行排序以及如何更好地完成它的方式提出一些反馈,我没有其他方法可以获得反馈=(。我知道。 NET功能Array.Sort()但我不太清楚如何使用它,因为它不仅仅是一个需要排序的单个数组。当需要在记分板中输入新的分数时,玩家名称和级别也是如此必须添加。这些存储在'数组数组'中(10 ='前10'分数)

scoreboardComboData = new int[10]; // Combo

scoreboardTextData = new string[2][];
scoreboardTextData[0] = new string[10]; // Name
scoreboardTextData[1] = new string[10]; // Level as string

记分牌课程的工作原理如下:

- 检查'scoreboard.xml'是否存在,如果不存在则创建它 - 在数组上方初始化,并从之前的运行中添加scoreboard.xml中的任何球员数据 - 当调用AddScore(名称,级别,组合)时,排序开始
- 还可以调用另一种方法,用上面的数组数据填充XML文件

排序检查新得分(组合)是否小于或等于scoreboardComboData数组中的任何记录得分(如果它大于得分,则移动到下一个要素)。如果是这样,它将所有分数移动到低于或低于或等于下一个元素的分数,基本上删除最后一个分数,然后将新分数放在低于或小于等于的分数之下的元素内。如果分数大于所有记录分数,则将所有分数向下移动一个并将新分数插入第一个元素中。如果它是唯一的分数,它只是将它添加到第一个元素。添加新分数后,名称和级别数据也会以相同的方式添加到其相关阵列中。什么是绕口令。下面是AddScore方法,我添加了评论,希望它能让事情更清晰O_o。您可以获取实际的源文件HERE。下面的方法是添加分数以使用调试器的最快方法的示例。

    public static void AddScore(string name, string level, int combo)
    {
        // If the scoreboard has not yet been filled, this adds another 'active'
        // array element each time a new score is added. The actual array size is
        // defined within PopulateScoreBoard() (set to 10 - for 'top 10'
        if (totalScores < scoreboardComboData.Length)
            totalScores++;

        // Does the scoreboard even need sorting?
        if (totalScores > 1)
        {
            for (int i = totalScores - 1; i > - 1; i--)
            {
                // Check to see if score (combo) is greater than score stored in 
                // array
                if (combo > scoreboardComboData[i] && i != 0)
                {
                    // If so continue to next element
                    continue;
                }

                // Check to see if score (combo) is less or equal to element 'i'
                // score && that the element is not the last in the
                // array, if so the score does not need to be added to the scoreboard
                else if (combo <= scoreboardComboData[i] && i != scoreboardComboData.Length - 1)
                {
                    // If the score is lower than element 'i' and greater than the last
                    // element within the array, it needs to be added to the scoreboard. This is achieved
                    // by moving each element under element 'i' down an element. The new score is then inserted
                    // into the array under element 'i'
                    for (int j = totalScores - 1; j > i; j--)
                    {
                        // Name and level data are moved down in their relevant arrays
                        scoreboardTextData[0][j] = scoreboardTextData[0][j - 1];
                        scoreboardTextData[1][j] = scoreboardTextData[1][j - 1];
                        // Score (combo) data is moved down in relevant array
                        scoreboardComboData[j] = scoreboardComboData[j - 1];
                    }

                    // The new Name, level and score (combo) data is inserted into the relevant array under element 'i'
                    scoreboardTextData[0][i + 1] = name;
                    scoreboardTextData[1][i + 1] = level;
                    scoreboardComboData[i + 1] = combo;
                    break;
                }

                // If the method gets the this point, it means that the score is greater than all scores within
                // the array and therefore cannot be added in the above way. As it is not less than any score within
                // the array.
                else if (i == 0)
                {
                    // All Names, levels and scores are moved down within their relevant arrays
                    for (int j = totalScores - 1; j != 0; j--)
                    {
                        scoreboardTextData[0][j] = scoreboardTextData[0][j - 1];
                        scoreboardTextData[1][j] = scoreboardTextData[1][j - 1];
                        scoreboardComboData[j] = scoreboardComboData[j - 1];
                    }

                    // The new number 1 top name, level and score, are added into the first element
                    // within each of their relevant arrays.
                    scoreboardTextData[0][0] = name;
                    scoreboardTextData[1][0] = level;
                    scoreboardComboData[0] = combo;

                    break;
                }

                // If the methods get to this point, the combo score is not high enough
                // to be on the top10 score list and therefore needs to break
                break;
            }
        }

        // As totalScores < 1, the current score is the first to be added. Therefore no checks need to be made
        // and the Name, Level and combo data can be entered directly into the first element of their relevant
        // array.
        else
        {
            scoreboardTextData[0][0] = name;
            scoreboardTextData[1][0] = level;
            scoreboardComboData[0] = combo;
        }


    }
}

添加分数的示例:

    private static void Initialize()
    {
        scoreboardDoc = new XmlDocument();
        if (!File.Exists("Scoreboard.xml"))
            GenerateXML("Scoreboard.xml");

        PopulateScoreBoard("Scoreboard.xml");

        // ADD TEST SCORES HERE!
        AddScore("EXAMPLE", "10", 100);
        AddScore("EXAMPLE2", "24", 999);

        PopulateXML("Scoreboard.xml");
    }

在当前状态下,源文件仅用于测试,在main中调用initialize,PopulateScoreBoard处理大部分其他初始化,因此除了添加测试分数外,不需要任何其他内容。

我感谢你的时间!

3 个答案:

答案 0 :(得分:3)

作为一个编程提示,你应该用一个Score Objects数组替换3个不同的数组,每个对象都有你提到的所有3个属性(Name,Level和Score)。然后,您可以为它创建一个类似比较器的函数(基于得分属性),可以通过Arrays.Sort()方法对其进行排序。

如果你想保留当前的3个数组,那么你可以在这里查找排序算法:http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms并且只需要对3个数组进行任何更改而不是逐个进行(因为你保持它们中的数据由索引同步。

答案 1 :(得分:1)

您可以考虑将您的用户名,级别和分数放在从IComparable继承的单独类(我们称之为ScoreBoardEntry)中,然后编写比较器。这将允许您使用List的内置排序功能,并且将是一个更简洁的解决方案,而不仅仅是编写自己的。

您的代码应如下所示:

1)创建/加载列表&lt; ScoreBoardEntry&GT;以前所有的分数

2)将新分数推入其中

3)排序列表

4)仅打印前10个条目

答案 2 :(得分:0)

我为你写了一些代码。我一直在学习一些新的类型C#的东西,如linq,IEnumerable,以及yield和想要将它们放在一起的东西,所以希望它有所帮助。

您可能会喜欢我使用的代码段编辑器 - linqpad - 它有助于学习/试验

void Main()
{
    string [] playerNames = {"Aaron", "Rick", "Josie"};
    var sim = new GameSimulator(playerNames, 1000000, 5000);
    var scores = sim.GetScores(5);
    var sorted = scores.OrderBy(c=>c.Score).Reverse();
    var top = sorted.Take(2);
    // uncomment if using linq pad
    //scores.Dump("scores");
    //sorted.Dump("sorted");
    //top.Dump("top");
}
class GameSimulator
{
    public GameSimulator(string [] playerNames, int maxScore, int maxLevel)
    {
        this.playerNames = playerNames;
        this.maxScore = maxScore;
        this.maxLevel = maxLevel;
    }
    private string [] playerNames;
    private int maxScore;
    private int maxLevel;
    public IEnumerable<ScoreBoardEntry> GetScores(int numGames)
    {
        for (int i = 0; i < numGames; i++)
        {
            string randomName = playerNames[random.Next(0, playerNames.Length-1)];
            int randomScore = random.Next(1, maxScore);
            int randomLevel = random.Next(1, maxLevel);
            yield return new ScoreBoardEntry(randomName, randomLevel, randomScore);
        }
    }
    static private Random random = new Random();
}
class ScoreBoardEntry
{
    public ScoreBoardEntry(string playerName, int levenNumber, int score)
    {
        PlayerName = playerName;
        LevelNumber = levenNumber;
        Score = score;
    }
    public string PlayerName { set; get; }
    public int LevelNumber { set; get; }
    public int Score { set; get; }
}