1

I've got an Array of 11 numbers, and an array of 11 names. I've also got the Average and the top 3 numbers. The numbers and names are user input'd separately which then go into two separate Arrays.

For example lets say I have:

playerName[0] = player1.Text;
playerName[1] = player2.Text;
playerName[2] = player3.Text;
playerName[3] = player4.Text;
playerName[4] = player5.Text;
playerName[5] = player6.Text;

playerScore[0] = int.Parse(score1.Text);
playerScore[1] = int.Parse(score2.Text);
playerScore[2] = int.Parse(score3.Text);
playerScore[3] = int.Parse(score4.Text);
playerScore[4] = int.Parse(score5.Text);
playerScore[5] = int.Parse(score6.Text);

int highestScore = playerScore.Max();
double averageScore = playerScore.Average();
int largest = int.MinValue;
int second = int.MinValue;
int third = int.MinValue;

foreach (int i in playerScore)
{              
    if (i > largest)
    {
        third = second;
        second = largest;
        largest = i;
    }
    else if (i > second && i != largest)
        second = i;

    else if (i > third && i != second)
        third = i;
}

Is there any easy way to list out something like this?

 textbox.Text = highest score is: " + highestScore + " by " -INSERT RELEVENT playerName HERE-

I Can think of some ways to do but chances are it would turn into a giant clump of if's and switches

Thanks

Daniel Kelley
  • 7,579
  • 6
  • 42
  • 50
CodingNub
  • 303
  • 1
  • 5
  • 17
  • Hint: Change your `foreach` to a `for` and find the index of the highest score in the array. – D Stanley Aug 19 '14 at 16:14
  • Just because you type "What's an easy way" doesn't make it valid. You still haven't shown an effort in solving this yourself. At the moment there's no problem here. If you are looking for reviewing your code, provide an answer, and head over to http://codereview.stackexchange.com/ – Patrick Aug 19 '14 at 16:16
  • Alternate option is to use a dictionary of the user name and high score. – Maurice Reeves Aug 19 '14 at 16:17
  • Or create a player class with name and score – sondergard Aug 19 '14 at 16:19
  • 2
    Why are these even in arrays? C# is object oriented - wouldn't it make more sense to have a `Player` class that contains properties `Name`, `Score`? Getting ordered scores would then be trivial: `var playersOrderedByScore = players.OrderByDescending(p => p.Score);` – Fred Aug 19 '14 at 16:23

4 Answers4

2

Create a class to represent a Player object, and another class that inherits from List to contain your players. Then you can do something like this:

public class Player
{
    public string Name { get; set; }

    public int Score { get; set; }

    public Player(string name)
    {
        Name = name;
    }
}

public class Players : List<Player>
{
    public void SortByScore()
    {
        Sort((a, b) => a.Score.CompareTo(b.Score));
    }

    public void SortByName()
    {
        Sort((a, b) => a.Name.CompareTo(b.Name));
    }
}
ForeverZer0
  • 2,379
  • 1
  • 24
  • 32
  • `List` http://stackoverflow.com/a/5376343/251983 is not meant to be inherited. In this case there's also no advantage- it's generic. Use composition over inheritence: `List` is enough. If you want to prove `SortByName`, etc., use extension methods. – Fred Aug 19 '14 at 16:55
  • I really don't understand, nor care about, the "do not inherit from List" guideline. As for using it in this case, it is not a bad bad thing, and allows for a lot of expansion on the class itself. Sure, you could keep it as a generic list and not it's own class, but the same could be said of nearly any custom collection. It just makes the code cleaner, and more viewable. – ForeverZer0 Aug 19 '14 at 17:03
1

Instead of having parallel arrays, group the score and name into a new class and have an array of those:

class Player
{
    public string Name { get; set; }
    public int Score { get; set; }
}


Player players[] = new Player[11];


players[0] = new Player(){ Name = player1.Text, Score = int.Parse( score1.Text ) };

Then you can loop through each player and save the player that has the highest score, not just the score:

Player highestScore = players[0];

foreach( Player p in players )
{
    if( highestScore.Score < p.Score )
    {
         highestScore = p; 
    }
}

textBox.Text = "Highest Score is: " + highestScore.Score + " by " + highestScore.Name;

Also note that you do no validation on the textbox data, so if the text is not an int, your program will throw an exception and probably crash.

clcto
  • 9,530
  • 20
  • 42
  • For highest score use linq, import System.Linq and use players.Max(p => p.Score); – csblo Aug 19 '14 at 16:26
  • @Niels yes, but I abbreviated the code. He wants the highest 3, not just the max. I'm sure this can be done with linq, but it is more complicated than just `Max`. – clcto Aug 19 '14 at 16:27
0

This should work for your current design:

int index = playerScore.ToList().IndexOf(playerScore.Max());
textbox.Text = string.Format("highest score is:{0} - by player: {1}",playerScore.Max(),playerName[index]);

But the best approach should be to create classes that provide that information and then create a list that has each element with the info you require like the name and score.

terrybozzio
  • 4,424
  • 1
  • 19
  • 25
0

DO: Encapsulate your logic into a class whose responsibility is to track Player information:

public class Player
{
    public string Name { get; set; }

    public int Score { get; set; }
}

DON'T: Inherit List<T>

Easiest way to encapsulate your sorting logic for scores is with an extension method:

public static class PlayerExtensions
{
    public static IEnumerable<Player> SortByScore(this IEnumerable<Player> players)
    {
        return players.OrderByDescending(p => p.Score);
    }
}

However, I see little value in abstracting this LINQ code. IMO, you'd be fine with a simple List<Player> and when you need scores, just execute players.OrderByDescending(p => p.Score);

Community
  • 1
  • 1
Fred
  • 1,292
  • 10
  • 24