Creating a highscore list in c# - c#

I need to use arrays/lists for my assignment and thought of using one for my highscore list for my game in windows form.
Right now I'm using a regular int for my Score and I'm wondering how I can get this into an array for a highscore list on my highscore.cs
Current code for score in game.cs
int Score = 0;
Scorelabel.Text ="score:" + score;
if (Picturebox.Left < -180)
{
Picturebox.Left = 800;
Score++;*
Things I've tried:
namespace Game
{
public partial class Highscore : Form
{
public Highscore()
{
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
int[] Highscore = new int[10];
for (int Score = 0; Score < 10; Score++)
{
textBox1.Text = new System.Windows.Forms.TextBox();
}
}
}
I tried to make the initial score int an array. I would end up getting the error:"Operator ++ cannot be applied to operand of type 'int[]'
Also tried to get my int into an array but would get the error that I can't convert ints to arrays.
What I want
I want my scores from the game.cs to show in a listbox on my highscore.cs that shows the top 10 scores descending from highest to lowest.

Let's imagine you've got 20 players and each one got some score.
As you decided to create an array of ints to store all scores, so do I:
int[] scores = new int[20];
For example, I fill that array with random unique scores from 10 to 100. You fill in your way:
int[] scores = new int[20];
Random rnd = new Random();
for (int i = 0; i < scores.Length; i++)
{
int score = 0;
// This loop used to generate new random int until it wouldn't be unique (wouldn't exist in array)
while (score == 0 || scores.Contains(score))
score = rnd.Next(10, 100);
scores[i] = score;
lblAllScores.Text += "Player #" + (i + 1) + " score: " + scores[i] + "\n";
}
I append each score and Player # (as number of iteration + 1) to some Label on Form to show all players and their scores. Something like this:
Now you (and I) want take top 10 scores (obviously in descending order, from highest to lowest). Here the keywords are Take and Descending order. In C# through System.Linq namespace provided such pretty extension methods like Take and OrderByDescending. And seems they can give us desired result if we use it properly.
I (and you) creating a new array of ints to store only Top 10 Scores. Then a take initial array scores and use OrderByDescending method to sort values in it from highest to lowest. (x => x) provided as selector to determine key by which method should order values - in our case by value itself. And then I use Take(10) method to take first 10 scored from that sorted array - this is our Top 10 Scores:
int[] top10Scores = scores.OrderByDescending(x => x).Take(10).ToArray();
And all I need to do - put this into Form, which I can do by simple iteration on top10Scores array with for loop. But I (and probably you) want to know what Player has that score. Upper we use (index of array + 1) as Player Number. And we know that scores are unique for each Player. Than now we can take the score value from top10Scores array and try to find its index in source scores array with Array.FindIndex method:
for (int i = 0; i < top10Scores.Length; i++)
{
int playerNumber = Array.FindIndex(scores, score => score == top10Scores[i]) + 1;
lblTop10Scores.Text += "Player #" + playerNumber + " score: " + top10Scores[i] + "\n";
}
And at our Form we have this:
Complete code:
private void ScorePlayers()
{
int[] scores = new int[20];
Random rnd = new Random();
for (int i = 0; i < scores.Length; i++)
{
int score = 0;
while (score == 0 || scores.Contains(score))
score = rnd.Next(10, 100);
scores[i] = score;
lblAllScores.Text += "Player #" + (i + 1) + " score: " + scores[i] + "\n";
}
int[] top10Scores = scores.OrderByDescending(x => x).Take(10).ToArray();
for (int i = 0; i < top10Scores.Length; i++)
{
int playerNumber = Array.FindIndex(scores, score => score == top10Scores[i]) + 1;
lblTop10Scores.Text += "Player #" + playerNumber + " score: " + top10Scores[i] + "\n";
}
}
Please note, that this is only a sketch and example to demonstrate how to use OrderByDescending and Take extension methods to get first 10 elements of sorted from highest to lowest value collection. In real application you probably will have at least simple Dictionary<string, int>, where would be stored player name (as string) and his score (as int). Or, more likely, it would be a model class called Player with Name and Score properties and each Player would be stored in some List<Player>:
public class Player
{
public string Name { get; set; }
public int Score { get; set; }
}
Hope you can find your solution and this example would be helpful for you.

Related

How to assign a value from a "for loop" to an array [duplicate]

This question already has answers here:
What is the default value of a member in an array?
(4 answers)
Closed 2 years ago.
I'm trying to figure out how to assign values to an array while a for loop is happening. I've tried displaying one of the elements in the array but it always ends up with 0
using System;
namespace Assignment4
{
class Program
{
static void Main(string[] args)
{
int[] numArray = new int[48]; // 48 elements
int total = 1; // trying to get odd numbers to fill for the elements
int index;
for (index = 0; index <= numArray.Length; index++) // for loop to assign array
{
total = total + 2;
Console.WriteLine("#{0} current number is {1} ", index + 1, total); // double checking the index thing
}
Console.WriteLine(numArray[34]); // checking if the specified array will display the number in the list
}
}
}
index < numArray.Length // 1st change else it will throw an exception at numArray[48] = total if it was <=
numArray[index] = total // 2nd change Assign it to the array
int[] numArray = new int[48]; // 48 elements
int total = 1; // trying to get odd numbers to fill for the elements
int index;
// Changed <= to <
for (index = 0; index < numArray.Length; index++) // for loop to assign array
{
total = total + 2;
numArray[index] = total; // This is where you assign the values.
Console.WriteLine("#{0} current number is {1} ", index + 1, total); // double checking the index thing
}
Console.WriteLine(numArray[34]); // checking if the specified array will display the number in the list
the way to go is using the assign operator:
numArray[i] = y;
this asigns the value y to the cell i of the array numArray
You are missing assignment to an array. Let's see the below code. Here we are looping inside for for finding odd numbers from 0 to 100, and if found, storing in declared array, index wise.
using System;
namespace Assignment4
{
public class Program
{
public static void Main(string[] args)
{
int upperLimit=100;//adding this to loop upto
int[] numArray = new int[48]; // 48 elements
int total = 1; // trying to get odd numbers to fill for the elements
int index,i=0;
for(index = 0; index <= upperLimit; index++) // for loop to assign array, we will go upto 100 numbers
{
total = total + 2;
Console.WriteLine("#{0} current number is {1} ", index+1, index+1); // double checking the index thing
if(index%2==1){//checking if that one is an odd number
Console.WriteLine("{0} is odd number",index);
numArray[i]=index;
i++;
}
}
Console.WriteLine(numArray[34]); // checking if the specified array will display the number in the list
}
}
}

For loop for calculating score, how to combine two methods

In my method public static int PointsCalculator() I seem to be unable to use my values from my two other methods in order to compare the values in the two array and give points.
I'm not really sure how to call or initialize the values to begin but tried to do a quick mockup.
My goal is to add one point for every user value in the GetUserGuesses method that is the same as the random values in the RandomBingoNumbers method.
class UserBingo // Creates a class to store all user related
{
static int[] RandomNrs;
static int[] userGuesses;
static int num = 0;
public static int[] GetUserGuess() // A method for collecting user guesses and displaying them (SPLIT THEM UP)
{
userGuesses = new int[10]; // Creates the array to store 10 user inputs
for (int i = 0; i < userGuesses.Length; i++) // For loop itterates until 10 user values are put into the array
{
try
{
int input = Convert.ToInt32(Console.ReadLine());
if (input < 1 || input > 25) // Only values between 1-25
{
Console.WriteLine("Only enter a number between 1-25");
i--;
}
else if (userGuesses.Contains(input)) // Checks for repeated values
{
Console.WriteLine("You have already entered {0}", input);
i--;
}
else
{
userGuesses[i] = input; //When they do meet the correct values
Console.WriteLine("Thanks for entering the number " + input);
}
}
catch (Exception)
{
Console.WriteLine("Only numbers can be entered, ");
i--;
}
}
for (int i = 0; i < userGuesses.Length; i++) // Loop to display all the input values in the array
{
Console.Write(userGuesses[i]);
}
return userGuesses;
}
public static int[] RandomBingoNumbers() // Method for creating 10 random integers
{
RandomNrs = new int[10]; // Creates an array to store 10 integer
Random rnd = new Random();
for (int i = 0; i < RandomNrs.Length; i++)
{
num = rnd.Next(1, 25);
if (RandomNrs.Contains(num))
i--;
else
RandomNrs[i] = num;
}
return RandomNrs;
}
public static int PointsCalculator() //Method for calculating score
{
int points = 0; // Integer to hold the amount of correct guesses
for (int i = 0; i < 10; i++)
{
if (RandomNrs[i] == userGuesses[i]) // Check if the 10 user inputs is the same as the 10 randomized numbers
{
points++;
}
}
Console.WriteLine("Your Numbers: \n [{0}]", string.Join(", ", userGuesses)); // Display user inputed numbers
Console.WriteLine("Bingo Numbers: \n [{0}]", string.Join(", ", RandomNrs)); // Display the random bingo numbers
Console.WriteLine("You got: " + points + "poäng"); // Display the amount of correct guesses
return points;
}
}
}
Add a using System.Linq;
Lot of mistakes.
if (GetUserGuess == RandomBingoNumbers
) // Check if the 10 user inputs is the same as the 10 randomized numbers
{
points++;
}
should be
if (GetUserGuess().SequenceEqual(RandomBingoNumbers())
// Check if the 10 user inputs is the same as the 10 randomized numbers
{
points++;
}
And so many other mistakes, like the RandomNrs must be a static int[] declared outside the function. etc. etc..
This assignment is wrong RandomNrs[i] = new UserBingoNrs;. I'd suggest you to go over the entire syntax and usage of functions.
UPDATE 1
Instead of this
int[] RandomNrs = new int[10]; // Creates an array to store 10 integer
int[] userGuesses = new int[10]; // Creates the array to store 10 user inputs
you should use
RandomNrs = new int[10]; // Creates an array to store 10 integer
userGuesses = new int[10]; // Creates the array to store 10 user inputs
because RandomNrs and userGuesses is already defined globally.
and instead of
RandomNrs == userGuesses and RandomNrs != userGuesses
you must use
RandomNrs[i] == userGuesses[i]) and RandomNrs[i]!=userGuesses[i]
else if (RandomNrs[i] != userGuesses[i]) // If user guesses are not equal to array points
i--;
This will probably cause an infinite loop, instead of i--, do points--;
UPDATE 2
As simple as this
int num= rnd.Next(1, 25);
while(RandomNrs.Contains(num))
num = rnd.Next(1,25);
UPDATE 3
Change your PointsCalculator for loop to this
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
if (RandomNrs[i] == userGuesses[j]) // Check if the 10 user inputs is the same as the 10 randomized numbers
{
points++;
}
}

Sort C# ListBox Items

I'm using C# Adapter method, I add elements to a list and after that I call that list to fill a listbox, here is my button for do that:
private void button1_Click(object sender, EventArgs e) {
listCustomers.Items.Clear();
List < Customer > customers = CustomerList.GetCustomers();
List < CustomerSaldo > customersSaldo = CustomerListSaldo.GetCustomers();
int total = 0;
int totalCustomer = 0;
foreach(Customer customer in customers)
total++;
listCustomers.Items.Clear();
totalCustomer = total;
int x = totalCustomer;
foreach(CustomerSaldo customer2 in customersSaldo) {
if (x >= 1) {
listCustomers.Items.Add("Costumer ID # " + x + " is: " + customer2.Saldo);
x--;
}
}
}
This is what I get, it's ok but I want to know if exists a way to do this like this example:
Costumer #1 Saldo...
Costumer #2 Saldo...
Costumer #3 Saldo...
If you see my code I have a variable x, this variable is the total number of costumers, so I think that my sort has to start with this variable, but I don't know exactly how to do it, what can I do?
Reverse the list and start counting untill you reach the end:
//Reverse the list
customersSaldo.Reverse();
//Add new items
for(int i = 0; i < customers.Count; i++)
listCustomers.Items.Add(string.Format("Costumer ID # {0} is: {1}", (i+1).ToString(), customersSaldo[i].Saldo);
you can probably reverse (Using the Reverse method) your list "customersSaldo" before adding it, and then use the variable 'x' in increment order.
https://msdn.microsoft.com/en-us/library/b0axc2h2(v=vs.110).aspx

remaining values from HashSet into secondary out

We've been asked to create a program which takes 2 input (which I have parsed) for seats and passengers in a plane and randomly place passengers on seats in a plane in one output as well as placing the remaining seats in a secondary output.
I was wondering if there is a simple way to replace the remaining values in HashSet, into the listBoxLedige.
As it works now, the seats are being distributing but the values in the secondary output arent related the the first output.
if(passengers > seats)
{
MessageBox.Show("For mange passagerer");
}
else
{
HashSet<int> check = new HashSet<int>();
for(int i = 0; i <= passengers - 1; i++)
{
int resultat = rnd.Next(1, seats + 1);
while(check.Contains(resultat))
{
resultat = rnd.Next(1, seats + 1);
}
check.Add(resultat);
int[] passagerer01 = new int[passengers];
passagerer01[i] = i+1;
listBoxFulde.Items.Add("Passager #" + passagerer01[i] + "på sæde #" + resultat);
}
HashSet<int> ledige01 = new HashSet<int>();
for(int i = 0; i <= (seats - passengers - 1); i++)
{
int tilbage = rnd.Next(1, seats + 1);
while(ledige01.Contains(tilbage))
{
ledige01.Add(tilbage);
}
listBoxLedige.Items.Add("Sæde #" + tilbage);
I'm not exactly sure I understand your problem, but have you taken a look at the Except LINQ extension method? Judging by your wording ("remaining values"), it might be the right method for you.
Edit Here's how it's done:
IEnumerable<int> empty = allSeats.Except(check);
Note how empty is now a deferred enumerator (unless you do a .ToArray(), .ToList() or similar on it).
Here's what I'd do (see Range and ExceptWith):
HashSet<int> ledige01 = new HashSet<int>(
Enumerable.Range(1, seats));
ledige01.ExceptWith(taken);
Note in generating the seeds you can remove the trial and error by simply shuffling the seats and taking the first N:
var taken = HashSet<int>(Enumerable.Range(1,seats).Shuffle().Take(passengers));
For hints on how to do shuffle, see e.g. Optimal LINQ query to get a random sub collection - Shuffle
As an aside:
int[] passagerer01 = new int[passengers];
passagerer01[i] = i+1;
listBoxFulde.Items.Add("Passager #" + passagerer01[i] + "på sæde #" + resultat);
looks to be something other than you need :) But I'm assuming it's unfinished and you're likely aware of that
A 'fully' edited take:
if(passengers > seats)
{
MessageBox.Show("For mange passagerer");
}
else
{
HashSet<int> taken = new HashSet<int>();
for(int i = 0; i <= passengers - 1; i++)
{
int resultat;
do {
resultat = rnd.Next(1, seats + 1);
} while(taken.Contains(resultat));
taken.Add(resultat);
listBoxFulde.Items.Add("Passager #" + (i+1) + "på sæde #" + resultat);
}
HashSet<int> ledige01 = new HashSet<int>(
Enumerable.Range(1, seats));
ledige01.ExceptWith(taken);
if(passengers > seats)
{
MessageBox.Show("For mange passagerer");
}
else
{
HashSet<int> taken = new HashSet<int>();
for(int i = 0; i <= passengers - 1; i++)
{
int resultat;
do {
resultat = rnd.Next(1, seats + 1);
} while(taken.Contains(resultat));
taken.Add(resultat);
listBoxFulde.Items.Add("Passager #" + (i+1) + "på sæde #" + resultat);
}
HashSet<int> ledige01 = new HashSet<int>(Enumerable.Range(1, seats));
ledige01.ExceptWith(taken);
foreach(var tilbage in ledige01)
listBoxLedige.Items.Add("Sæde #" + tilbage);
Not a hundred percent sure I understand your problem or solution, but are you aware that you declare and initialize passagerer01 once for each passenger, then deterministically (not randomly) assign seat i+1 to passenger i and afterwards throw away that array? If you wanted to keep the information, you'd have to declare the array outside the for loop.
Also, it doesn't really seem like you're doing anything meaningful in that second part of your code. To determine the empty seats, it would make sense to go through numbers 1 to passengers, check if they are in the set check and, if not, add them to set ledige01. Or, of course, to do something equivalent using a library method as suggested by sehe.
As a last note, in computer science you usually start counting from zero. Thus, you would usually have seat numbers 0 to seats-1 and choose seats randomly like so: rnd.Next(0, seats). And you would usually loop like this: for(int i = 0; i < passengers; i++) instead of for(int i = 0; i <= passengers - 1; i++).

c#, using .length method

I have a method that needs to do a calculation based upon the length of an array. I am using the .length method for the calculation, but the method is doing arithmetic with the max length of the array (which I have declared as 10). This is the loop I am using to get data from the user. I know it isn't the ideal way to sort array data, but this is for a homework assignment, and it revolves around using the .Split method correctly (which isn't the problem I'm having).
for (int i = 0; i < MAX; i++)
{
Console.Write("Enter a name and a score for player #{0}: ", (i + 1));
string input = Console.ReadLine();
if (input == "")
{
// If nothing is entered, it will break the loop.
break;
}
// Splits the user data into 2 arrays (integer and string).
string[] separateInput = input.Split();
name [i] = separateInput[0];
score [i] = int.Parse(separateInput[1]);
}
Here is the method I am using to calculate the average score:
static void CalculateScores(int[] score)
{
int sum = 0;
int average = 0;
for (int i = 0; i < score.Length; i++)
{
sum += score[i];
average = sum / score.Length;
}
Console.WriteLine("The average score was {0}", average);
I am calling the method like this:
CalculateScores(score);
Edit: My arrays are declared:
int[] score = new int[MAX]; //MAX == 10.
string[] name = new string[MAX];
The CalculateScores method is doing the math as though score.Length is always 10, no matter how many different combinations of scores I input to the console. I can't figure out if it's because my loop to gather input has been done incorrectly, or my CalculateScores method is flawed. Thanks in advance.
Edit: to clarify, I am just confused at why I can't get the correct value out of CalculateScores.
Length always represents the size of the array, which if you've instantiated as 10, then it will always be 10, regardless of how many items you've filled.
There are lots of ways of solving your problem, but I'd go with the simple one of not using length in your calculation, but rather just storing the number of items in a separate variable:
int numItems = 0;
for(int i=0;i<MAX;i++)
{
Console.Write("Enter a name and a score for player #{0}: ", (i + 1));
string input = Console.ReadLine();
if (input == "")
{
break; // if nothing is entered, it will break the loop
}
numItems++;
...
}
static void CalculateScores(int[] score, int numItems)
{
// don't use Length at all, use numItems instead
}
Arrays are generally used for fixed sized data, so the Length property reflects how many items the array can hold rather than the amount of elements in the array. The simplest fix would be to use a List(T), which is used for variadic data, instead.
// A nice abstraction to hold the scores instead of two separate arrays.
public class ScoreKeeper
{
public string Name { get; set; }
public int Score { get; set; }
}
var scores = new List<ScoreKeeper>();
for (int i = 0; i < MAX; i++)
{
Console.Write("Enter a name and a score for player #{0}: ", (i + 1));
string input = Console.ReadLine();
if (input == "")
{
// If nothing is entered, it will break the loop.
break;
}
// Splits the user data into 2 arrays (integer and string).
string[] separateInput = input.Split();
scores.Add(new ScoreKeeper { Name = separateInput[0], Score = int.Parse(separateInput[1]) });
}
static void CalculateScores(ICollection<ScoreKeeper> scores)
{
// We take advantage of Linq here by gathering all the
// scores and taking their average.
var average = scores.Select(s => s.Score).Average();
Console.WriteLine("The average score was {0}", average);
}
checking maually:
int sum = 0;
int average = 0;
int length;
for (int i = 0; i < MAX; i++) {
if(name[i]!=string.empty) {
sum += score[i];
length=i+1;
}
}
average = sum / length;
Console.WriteLine("The average score was {0}", average);

Categories