Array correlation issues - c#

I am trying to create an application that prompts a user for 5 names, then display each name and allow the user to enter a score for that particular name. So if in the first array, the value for index [0] is a string "Bob", then in the other array for scores index [0] should be the score for bob.
I am having a hard time understand how to pass the nameArray[] to the PopulateScore() method so that it can display the name for the user to enter a corresponding score.
I also have to search the Array by name and return the score.
Thanks for any help.
public class InitArraya
{
public static string[] arrayName = new string[5];
public static int[] arrayScore = new int[5];
public static void PopulateNameArray()
{
// Prompt user for names and assign values to the elements of the array
for (int intCounter = 1; intCounter < arrayName.Length; intCounter++)
{
Console.Write("Enter name {0}: ", intCounter);
arrayName[intCounter] = Console.ReadLine();
}
}
public static void PopulateScoreArray(string[] array)
{
// Prompt user for names and assign values to the elements of the array
for (int intCounter = 1; intCounter < 5; intCounter++)
{
Console.Write("Enter score for {0}: ", arrayName[0]);
arrayScore[intCounter] = Convert.ToInt32(Console.ReadLine());
}
}
public static void Main( string[] args )
{
Console.WriteLine("Enter 5 names:"); // headings
PopulateNameArray();
PopulateScoreArray(arrayName);
Console.ReadLine();
}
}

Make array of objects which contains the name and score, this will make your solution much more usefull and readable.
public class NameScore{
public string Name { get; set; }
public int Score { get; set; }
}
public class InitArraya{
public NameScore[] arrayScore = new NameScore[5];
...

public static void PopulateScoreArray(string[] array)
{
// Prompt user for names and assign values to the elements of the array
for (int intCounter = 0; intCounter < array.Length; intCounter++)
{
Console.Write("Enter score for {0}: ", array[intCounter]);
arrayScore[intCounter] = Convert.ToInt32(Console.ReadLine());
}
}
Assuming that there are always 5 names in arrayName. Extra checks should be made otherwise.
Oh, and start intCounter at 0 in PopulateNameArray too.

in
public static void PopulateScoreArray(string[] array)
change
Console.Write("Enter score for {0}: ", arrayName[0]);
to
Console.Write("Enter score for {0}: ", array[intCounter]);
To use input array. Also in all for(-) change the start for counter to 0
for (int intCounter = 0; intCounter < 5; intCounter++)

Related

Returning array of objects from static function

I am making a basic Visual Studio project.
Easiest way to explain is to show the code.
using System;
using System.Collections.Generic;
namespace testing
{
class Program
{
static void Main(string[] args)
{
int amountOfCars = getAmountOfCars();
Car[] myCars = createCars(amountOfCars);
}
public static int getAmountOfCars (){
Console.WriteLine("Amount of Cars to enter");
int amountOfCars = Convert.ToInt32(Console.ReadLine());
return amountOfCars;
}
public static Car createCars(int amountOfCars)
{
Car[] myCars = new Car[amountOfCars];
for (int i = 0; i < amountOfCars; i++)
{
Console.WriteLine("Enter brand");
string brand = Convert.ToString(Console.ReadLine());
Console.WriteLine("Enter amount of wheels");
int amountOfWheels = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter amount of seats");
int amountOfSeats = Convert.ToInt32(Console.ReadLine());
myCars[i] = new Car(brand, amountOfWheels, amountOfSeats);
}
return myCars[amountOfCars];
}
}
}
This line
Car[] myCars = createCars(amountOfCars);
Throws the following error:
Cannot implicitly convert type testing.Car to testing.Car[]
So, I then tried this to convert over
Car[] myCars = (Car[]) createCars(amountOfCars);
But it still throws the error.
Essentially I am just trying to return the array of objects from createcar function, so that it can be used within the rest of the code.
What is the best practice to solve this?
You need to return an array from createCars():
public static Car[] createCars(int amountOfCars)
{
Car[] myCars = new Car[amountOfCars];
for (int i = 0; i < amountOfCars; i++)
{
Console.WriteLine("Enter brand");
string brand = Convert.ToString(Console.ReadLine());
Console.WriteLine("Enter amount of wheels");
int amountOfWheels = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter amount of seats");
int amountOfSeats = Convert.ToInt32(Console.ReadLine());
myCars[i] = new Car(brand, amountOfWheels, amountOfSeats);
}
return myCars;
}
The signature of the function is
public static Car createCars(int amountOfCars)
instead of
public static Car[] createCars(int amountOfCars)
Also return just the array
return myCars;
instead of
return myCars[amountOfCars]; // This returns only one object at the amountOfCars index in the myCars array.
Also, this will trigger the ArrayIndexOutOfBoundsException as the myCars is allocated for amountOfCars and array spans from myCars[0] to myCars[amountOfCars-1]
funcion
public static int[] addFirst(int value, int count, int[] test)
{
test = test.Where(val => val != value).ToArray();
Array.Resize(ref test, test.Length + 1);
for (int i = count-1; i > 0; i--)
{
test[i] = test[i-1];
}
test[0] = value;
return test;
}
declaracion
array= addFirst(value, array.Length, array);

How to loop through array to find all occurrences of an element C#

I'm pretty new to programming,
I have two arrays that correspond with eachother.
The First displays student names the other displays the students grade.
My goal is to loop through the arrays and print out all of the students who have the grade
87 for example.
As of right now I am able to print the first person with that grade, however the loop ends once it finds the first grade.
I'm having trouble figuring out how to find ALL of the people with that grade. Any help would be appreciated. Thanks
public static void OptionTwo()
{
LoadArray();
Console.WriteLine("Enter a student grade to see all students with that grade");
int userInput = Convert.ToInt32(Console.ReadLine());
int subscript;
subscript = Search(studentGrade, userInput, ref counter);
ShowResults(userInput, subscript, counter);
}
public static int Search(int[] studentGrade, int userInput, ref int counter)
{
counter = 0;
for (int s = 0; s < studentGrade.Length; s++)
{
counter++;
if (studentGrade[s] == userInput)
return s;
}
return -1;
}
public static void ShowResults(int userInput, int subscript, int counter)
{
//LOOP THROUGH ARRAY
Console.WriteLine();
Console.WriteLine("The following students have that grade: ");
Console.WriteLine();
if (subscript == -1)
Console.WriteLine("{0} is NOT in array, # of comparisons is {1}",
userInput, counter);
else
Console.WriteLine("{0} {1}", studentName[subscript].PadRight(20), studentGrade[subscript].ToString().PadRight(5));
}
Good programming is the art of reducing cognitive load. In your architecture, you - the programmer - know that both arrays are related to each other. If you create a Student class as such:
public class Student
{
public string Name;
public int Grade;
}
Now you can create a
var students = new List<Student>();
At this point, the compiler knows to associate student names and their grades, and you don't have to remember which arrays are correlated.
You can now return your filtered list using System.Linq as such:
return students.Where(x => x.Grade == 87);
You have reduced cognitive load. This may seem trivial for your example, but it becomes central to good programming in a large organization where you will spend most of your time maintaining someone else's code.
First, let's state the problem. We have two arrays:
string[] studentName = new string[] {
"Amy", "Bob", "Charly", "Dimitry", "Eva",
};
int[] studentGrade = new int[] {
80, 70, 80, 95, 68,
};
And you want to get all the students with the given grade. E.g. "Amy" and "Charly" for 80.
If it's your case you have to scan both arrays:
private static List<string> Search(string[] studentName, int[] studentGrade, int grade) {
List<string> result = new List<string>();
// Let's use good old for loop instead of Linq
for (int i = 0; i < studentGrade.Length; ++i)
if (studentGrade[i] == grade)
result.Add(studentName[i]);
return result;
}
public static void ShowResults(int userInput) {
Console.WriteLine();
Console.WriteLine("The following students have that grade: ");
Console.WriteLine();
List<string> list = Search(studentGrade, studentName, userInput);
if (list.Count <= 0)
Console.WriteLine("{0} is NOT in array", userInput);
else
Console.WriteLine("{0} {1}", string.Join(", ", list), userInput);
}
Linq is perfect for it:
var choosenGrades = studentGrade.Where(x=>x == userInput).ToList();
Remember to add import System.Linq
The reason your loop is ending after one is because you are returning the first instance of the subscript and the function ends there.
you should create a list of subscripts to return.
so you search function should be changed to something like this
public static List<int> Search(int[] studentGrade, int userInput, ref int counter)
{
var listOfSubscripts = new List<int>();
counter = 0;
for (int s = 0; s < studentGrade.Length; s++)
{
counter++;
if (studentGrade[s] == userInput)
listOfSubscripts.Add(s);
}
return listOfSubscripts;
}
And then your show results function should be like
public static void ShowResults(int userInput, List<int> subscripts, int counter)
{
//LOOP THROUGH ARRAY
Console.WriteLine();
Console.WriteLine("The following students have that grade: ");
Console.WriteLine();
if (subscript == -1)
Console.WriteLine("{0} is NOT in array, # of comparisons is {1}",
userInput, counter);
else
{
foreach(var subscript in subscripts)
{
Console.WriteLine("{0} {1}", studentName[subscript].PadRight(20), studentGrade[subscript].ToString().PadRight(5));
}
}
}

C# Dice Roll - Assigning scores to values

Currently working on a project and need some help. Still relatively new to c#. I have created a dice rolling game in which 5 dice are rolled at once in turns between 2 players. What I am stuck on is checking through these values for a three of a kind and assigning points .For example, A player presses enter and one appears three times then the player should receive three points or if four appears three times then the player receives the points. I have tried lots of different methods using if statements and for loops but cant seem to get it working. My code is provided below.Any help would be appreciated.
Thanks
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dice_v4
{
class Game
{
static void Main(string[] args)
{
Random RandomNum = new Random();
Player[] player1 = new Player[5];
Die[] myDie = new Die[5];
for (int i = 0; i < 5; i++)
{
myDie[i] = new Dice_v4.Die(RandomNum);
player1[i] = new Dice_v4.Player();
}
for (int i = 0; i < 2; i++) // Number of players
{
Console.Write("Enter Name for Player {0}:", i + 1);
string NewName = Console.ReadLine();
player1[i].SetName(NewName);
}
Console.WriteLine();
for (int j = 1; j < 20; j++)
{
for (int i = 0; i < 2; i++)
{
myDie[i].roll();
Console.WriteLine("{0} Rolled:{1} on the first dice", player1[i].GetName(), myDie[i].GetTopNumber());
Console.WriteLine("{0} Rolled:{1} on the second dice", player1[i].GetName(), myDie[i].GetTopNumber1());
Console.WriteLine("{0} Rolled:{1} on the third dice", player1[i].GetName(), myDie[i].GetTopNumber2());
Console.WriteLine("{0} Rolled:{1} on the fourth dice", player1[i].GetName(), myDie[i].GetTopNumber3());
Console.WriteLine("{0} Rolled:{1} on the fifth dice", player1[i].GetName(), myDie[i].GetTopNumber4());
Console.WriteLine("Total Throws:{0}", j);
Console.ReadLine(); }
}
}
}
class Die
{
private int NumberTop1; //attributes
private int NumberTop2;
private int NumberTop3;
private int NumberTop4;
private int NumberTop5;
int threepoints = 0;
private Random RandomNumGenerator;
public Die(Random RandomGenerator) // constructor
{
RandomNumGenerator = RandomGenerator; // initialises random number
}
public void roll()
{
NumberTop1 = RandomNumGenerator.Next(1, 6);
NumberTop2 = RandomNumGenerator.Next(1, 6);
NumberTop3 = RandomNumGenerator.Next(1, 6);
NumberTop4 = RandomNumGenerator.Next(1, 6);
NumberTop5 = RandomNumGenerator.Next(1, 6);
// generates random number / / Number of dice to be rolled
Console.WriteLine("\tTotal score = {0}", threepoints);
}
public int GetTopNumber()
{
return NumberTop1; // Returns number on top which equals dice roll
}
public int GetTopNumber1()
{
return NumberTop2;
}
public int GetTopNumber2()
{
return NumberTop3;
}
public int GetTopNumber3()
{
return NumberTop4;
}
public int GetTopNumber4()
{
return NumberTop5;
}
}
class Player
{
private string Name;
public void SetName(string NewName) // constructor
{
Name = NewName; // initalises name
}
public string GetName()
{
return Name; // Returns name when called
}
}
}
Advice:
Whenever you have variables or properties called something1, something2, ... - you're probably doing something wrong, and you probably want to use a list, array, hashmap...
My idea here would be to add all numbers to a list and then perhaps iterate to make a dictionary where key is the dice value and value is the count. Or you can do something else, depending which format you need for later operations.
List<int> diceValues = new List<int>();
diceValues.Add(die.GetTopNumber());
diceValues.Add(die.GetTopNumber1());
diceValues.Add(die.GetTopNumber2());
diceValues.Add(die.GetTopNumber3());
diceValues.Add(die.GetTopNumber4());
Now that you have them in a list, you can do something like:
var values = new Dictionary<int, int>();
foreach(var item in diceValues) {
if(values.Keys.Contain(item)) {
values[item]++;
} else {
values[item] = 1;
}
}
After this loop you will have a list of Dictionary items where a key will be the dice value, and the value the number of dice with that value.
E.g. if someone threw two threes, and two deuces and one four, the dictionary would look:
Key: 2, Value: 2
Key: 3, Value: 2
Key: 4, Value: 1
By iterating through these you can later make a scoring system...
I would remove these properties all along and use a list or array instead.
You declare a list:
public List<int> Roles { get; private set; }
And your roll method can become:
public void roll()
{
this.Roles = Enumerable.Range(1, 5)
.Select(i => RandomNumGenerator.Next(1, 6))
.ToList();
// Check for three of a kind:
bool threeOfAKind = this.Roles.GroupBy(i => i).Any(g => g.Count() >= 3);
// rest of your logic
Console.WriteLine("\tTotal score = {0}", threepoints);
}
Later you can access each individual roll by this.Roles[numOfRoll]

Sum the values of the array with a method

So I'm trying to get 10 inputs from a user via Console, store in them in an array, calculate in a method what the sum is and return it. I'm still in the process, so this isn't mean to be completed code, but I'm confused at this point why my error list says Main should be closed after the while statement?
class Program
{//Start class
//We need to declare the size of our array
const int ARRAYSIZE = 10;
static void Main()
{//Start main
//We need to create a counter for how many entries we currently have
int entries = 0;
int sumScore = 0;
//We need to create the array
int[] myArray = new int[ARRAYSIZE];
//Start a loop to ask for input
do
{//Start loop
Console.Write("Please enter the score of each test: ");
int entry = int.Parse(Console.ReadLine());
myArray[entries] = entry;
entries++;
}
while (entries < ARRAYSIZE);//End loop
static void PrintArray(int[ ] myArray)
{
foreach(int value in myArray)
{
Console.WriteLine(value);
Console.ReadLine();
}
}
}//End main
}//End class
At the position of static void PrintArray(int[ ] myArray), you are declaring a new function. You need the }//End main before you declare a new function:
do
{//Start loop
Console.Write("Please enter the score of each test: ");
int entry = int.Parse(Console.ReadLine());
myArray[entries] = entry;
entries++;
}
while (entries < ARRAYSIZE);//End loop
}//End main
static void PrintArray(int[ ] myArray)
{
foreach(int value in myArray)
{
Console.WriteLine(value);
Console.ReadLine();
}
}
You have misplaced the closing bracket of your Main method. You may also want to call your PrintArray method after while (entries < ARRAYSIZE);//End loopand also compute your sum inside that method. But I guess it is because, as you said, it is a work in progress. Here is what it looks like
class Program
{
const int ARRAYSIZE = 10;
static void Main()
{//Start main
//We need to create a counter for how many entries we currently have
int entries = 0;
int sumScore = 0;
//We need to create the array
int[] myArray = new int[ARRAYSIZE];
//Start a loop to ask for input
do
{//Start loop
Console.Write("Please enter the score of each test: ");
int entry = int.Parse(Console.ReadLine());
myArray[entries] = entry;
entries++;
}
while (entries < ARRAYSIZE);//End loop
PrintArray(myArray);
}//End main
static void PrintArray(int[ ] myArray)
{
int sum = 0;
foreach(int value in myArray)
{
sum += value;
Console.WriteLine(value);
Console.ReadLine();
}
Console.WriteLine(sum);
}
}
This isn't a direct answer to your question, but I thought it might be interesting for you.
If you'd like to do this in a slightly easier way, then try this:
static void Main()
{
var sum =
Enumerable
.Range(0, ARRAYSIZE)
.Select(n =>
{
Console.WriteLine("Please enter the score of each test:");
return int.Parse(Console.ReadLine());
})
.Sum();
Console.WriteLine();
Console.WriteLine("The sum is:");
Console.WriteLine(sum);
}

How do I split an array into two different arrays?

I can't seem to figure out how to fix my code so that it works. I need the user to be able to input their first name then space then the what they scored. Then I need to split the array into two different arrays and pass them to the four different methods to display to the user what they scored, etc. Can anyone help me figure this problem out?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace proj09LEA
{
class Program
{
static void Main(string[] args)
{
// declare and array of integers
int[] array = new int[10];
Console.WriteLine("\nSaturday Coder's Bowling Team");
Console.WriteLine("Enter in a name and score for each person on the team.");
Console.WriteLine("For example, Mary 143. Just hit Enter when you are done.\n");
// fill an array with user input
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine("Enter in a name and score: ");
string userInput;
string[] parsedInput;
parsedInput = userInput.Split();
string name = parsedInput[0];
int score = int.Parse(parsedInput[1]);
}
Console.WriteLine("------------ Input Complete ------------\n");
Console.WriteLine("Here are the scores for this game:");
DisplayScore(array);
HighScore(array);
LowScore(array);
AverageScore(array);
Console.WriteLine("Press Enter to continue. . .");
Console.ReadLine();
}
static void DisplayScore(int[] array)
{
foreach (int n in array)
{
Console.WriteLine("{0}'s score was {0}.\n", array);
}
}
static void HighScore(int[] array)
{
int max = array.Max();
Console.WriteLine("Congratulations {0}, your score of {0} was the highest.", max);
}
static void LowScore(int[] array)
{
int min = array.Min();
Console.WriteLine("{0}, your score of {0} was the lowest. Better get some practice.", min);
}
static void AverageScore(int[] array)
{
int sum = array.Sum();
int average = sum / array.Length;
Console.WriteLine("The average score for this game was {0:d}.", average);
}
}
}
If you absolutely have to use simple primitive arrays, you would need two distinct arrays of the same size, to hold the names as strings and scores as ints:
class Program
{
const int MaxScores = 10; // .. Use a constant to ensure the sizes remain in sync
static void Main(string[] args)
{ ///
string[] names = new int[MaxScores];
int[] scores = new int[MaxScores];
// ... parse names into names[] and scores into scores[]
DisplayScore(names, scores);
You would then need to pass both arrays to the various methods:
static void DisplayScore(string[] names, int[] scores)
{
for(int i=0; i < MaxScores; i++)
{
Console.WriteLine("{0}'s score was {1}.\n", names[i], scores[i]);
}
}
// etc
However, there are better ways to do this, e.g. by defining a custom class for the tuple of Name, Score:
class PersonScore
{
public string Name {get; set;}
public int Score {get; set;}
}
You can then declare and pass the single array of PersonScore[] around.
PersonScore[] personScores = new PersonScore[MaxScores];
for (... prompting the user for data)
{
... parsing user input
personScores[i] = new PersonScore{Name = name, Score = score};
}
DisplayScore(personScores); // Pass around the single array
static void DisplayScore(IEnumerable personScores)
{
foreach(var personScore in personScores)
{
Console.WriteLine("{0}'s score was {1}.\n", personScore.Name, personScores.Score);
}
}
// etc - other methods
As others have mentioned, other collections are also possible alternatives to an array, most commonly List.
You can do like this. Just use Console.ReadLine() to get user input. This is what you do in your code. There are better ways to do this but following will solve your problem.Also you need to perform validation as well.
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine("Enter in a name and score: ");
string userInput = Console.ReadLine();
string[] parsedInput;
parsedInput = userInput.Split(' ');
string name = parsedInput[0];
int score = int.Parse(parsedInput[1]);
array[i] = score;
}
Why you need to split array in to two arrays on containing names and other containing score. Its better to create a structure having String field for name and integer field for score and write Comparator for sorting the Array containing elements of this Data structure type and sort them.
It will solve all your problems and that too efficiently.
Not many data integrity checks in the methods you are using, but here are the extensions I use to split arrays or any type of enumerable. I have not tested these all that much, so I cannot guarantee that they will work. I have removed all my input validation, but I suggest you add those back your own way.
public static List<List<T>> Split<T>(this IEnumerable<T> collection, Int32 groupSize)
{
var collectionList = collection.ToList();
if (groupSize > collectionList.Count)
groupSize = collectionList.Count;
var chunks = new List<List<T>>();
while (collectionList.Any())
{
var chunk = collectionList.Take(groupSize);
chunks.Add(chunk.ToList());
collectionList = collectionList.Skip(groupSize).ToList();
}
return chunks;
}
public static List<List<T>> Split<T>(this IEnumerable<T> collection, Func<T, Boolean> splitFunction)
{
var collectionList = collection.ToList();
if (collectionList.IsNullOrEmpty())
return new List<List<T>>();
var indices = collectionList.FindIndices(splitFunction); // Custom method that searches for the indices that satisfy the predicate and returns the index of each matching item in the list.
if (indices.IsNullOrEmpty()) // equivalent to indices == null || !indices.Any()
return new List<List<T>> { collectionList };
var chunks = new List<List<T>>();
var lastIndex = 0;
if (indices[0] > 0)
{
chunks.Add(collectionList.Take(indices[0]).ToList());
lastIndex = indices[0];
}
for (var i = 1; i < indices.Count; i++)
{
var chunkSize = indices[i] - lastIndex;
var chunk = collectionList.Skip(lastIndex).Take(chunkSize).ToList();
if (chunk.IsNullOrEmpty())
{
break;
}
chunks.Add(chunk);
lastIndex = indices[i];
}
if (collectionList.Count - lastIndex > 0)
{
var lastChunk = collectionList.Skip(lastIndex).ToList();
chunks.Add(lastChunk);
}
return chunks;
}

Categories

Resources