I'm trying to create a leaderboard system by using a merge sort algorithm that sorts the scores in ascending order and then sorts the usernames by their score. I then use a for loop that displays the scores in descending order. The code in the image works perfectly fine when each user has a unique score and duplicate scores do not exist. However, I am having a problem when more than one user has the same score (i.e. there are duplicate scores).
For example, if two users have the same score (in this case 5), the wrong username is displayed. I believe this is because it only looks at the first occurrence of the sorted score. Hence, it's overwriting the original name. Is there any way I can skip the first occurrence of the duplicate number after it has been visited?
I need to keep the merge sort algorithm!
string[] UsernameAndScoresArray = System.IO.File.ReadAllLines(@"UsernamesAndScores.txt");
string[] UnsortedUsernamesArray = new string[UsernameAndScoresArray.Length];
int[] UnsortedScoresArray = new int[UsernameAndScoresArray.Length];
string UsernameAndScore = "";
string Username = "";
int Score = 0;
int position = 0;
for (int i = 0; i < UsernameAndScoresArray.Length; i )
{
//Locates the username and scores and stores them in an 'unsorted array'
UsernameAndScore = UsernameAndScoresArray[i];
position = UsernameAndScore.IndexOf(':');
Username = UsernameAndScore.Substring(0, position);
UnsortedUsernamesArray[i] = Username;
position = UsernameAndScore.IndexOf(':');
Score = int.Parse(UsernameAndScore.Remove(0, position 1));
UnsortedScoresArray[i] = Score;
}
//Sorts the Scores in ascending order using the merge sort algorithm
SortedArray = MergeSort(UnsortedScoresArray);
SortedUsernames = new string[SortedArray.Length];
for (int i = 0; i < UnsortedScoresArray.Length; i )
{
for (int a = 0; a < SortedArray.Length; a )
{
if (UnsortedScoresArray[i] == SortedArray[a])
{
//The usernames are sorted based on the scores
SortedUsernames[a] = UnsortedUsernamesArray[i];
}
}
}
int place = 0;
for (int i = SortedArray.Length - 1; i >= 0; i--)
{
//The place, username and number of points are displayed in descending order
place ;
Username = SortedUsernames[i];
Score = SortedArray[i];
ListBoxLeaderBoardPlaceAndUser.Items.Add(place ": " Username);
ListBoxLeaderboardScore.Items.Add(Score);
}
//This is an example of the error
UnsortedScoresArray[] = {46, 7, 5, 10, 5}
UnsortedUsernamesArray[] = {User1, User2, User3, User4, User5}
SortedScoresArray[] = {5, 5, 7, 10, 46}
SortedUsernamesArray[] = {User5, User5, User2, User4, User1}
It should say SortedUsernamesArray[] = {User3, User5, User2, User4, User1}
CodePudding user response:
You can also sort user by score
:
int[] UnsortedScoresArray = { 46, 7, 5, 10, 5 };
string[] UnsortedUsernamesArray = { "User1", "User2", "User3", "User4", "User5" };
int[] sortedScoresArray=new int[UnsortedScoresArray.Length];
string[] sortedUsernamesArray = new string[UnsortedUsernamesArray.Length];
for (int i = 0; i < UnsortedScoresArray.Length; i )
{
for (int j = i; j < UnsortedScoresArray.Length; j )
{
if (UnsortedScoresArray[i] > UnsortedScoresArray[j])
{
int temp;
temp = UnsortedScoresArray[i];
UnsortedScoresArray[i] = UnsortedScoresArray[j];
UnsortedScoresArray[j] = temp;
string temp2 = UnsortedUsernamesArray[i];
temp2 = UnsortedUsernamesArray[i];
UnsortedUsernamesArray[i] = UnsortedUsernamesArray[j];
UnsortedUsernamesArray[j] = temp2;
}
}
}
sortedScoresArray = UnsortedScoresArray;
sortedUsernamesArray = UnsortedUsernamesArray;
result:
CodePudding user response:
For this kind of problem, I would use a dictionary. I know it is a bother to get an answer that suggests a completely different data structure but eventually, you will get benefitted from its use.
I like this approach:
var dict = Enumerable.Range(0, keys.Length).ToDictionary(i => keys[i], i => values[I]);
CodePudding user response:
The idiomatic way to solve such an issue in C# would be to
store both user name and score in the same data structure
public class UserAndScore { public string User { get; } public int Score { get; } public UserAndScore(string user, int score) { User = user; Score = score; } }
and then use the built-in sort functionality of .NET to do the work for you:
UserAndScore[] unsorted = new[] { new UserAndScore("User1", 46), new UserAndScore("User2", 7), // ... }; // No need to re-invent the wheel... let .NET do the sorting! UserAndScore[] sorted = unsorted.OrderBy(u => u.Score).ToArray();