Create a list from a number entered by user - c#

I've entered a number between 1 and 10, I now want to create a list to that size entered and store new integers to each element from more input.
so I enter 5 into the console, I now want to create a list of size 5, so that I can store 5 new integers into each element, here is my code so far -
I'm not looking for code to solve this, but a point in the right direction of what I need to learn to be able to do this,
thanks
using System;
using System.Collections.Generic;
namespace Monsters1
{
class Program
{
static void Main(string[] args)
{
int totalOfMonsters = numberOfMonsters();
Console.WriteLine("Total Number of Monsters = " + totalOfMonsters);
Console.WriteLine();
int numberOfHitPoints = HitPoints();//store this number into list - monstersInput?
List<int> monstersInput = new List<int>(totalOfMonsters) ;
}
public static int numberOfMonsters()
{
string monsterNumbers;
int min = 1;
int max = 10;
int result;
do
{
Console.WriteLine("Enter a number between 1 and 10 for Number of Monsters.");
monsterNumbers = Console.ReadLine();
result = int.Parse(monsterNumbers);
if (result < min || result > max) ;
else
break;
} while (true);
return result;
}
public static int HitPoints()
{
// enter a number of hit points and store to list monsters
int hitPoints;
int min = 1;
int max = 100;
string hit;
do
{
Console.WriteLine("Enter a Hit Number between 1 and 100 : ");
hit = Console.ReadLine();
hitPoints = int.Parse(hit);
if (hitPoints < min || hitPoints > max) ;
else
break;
} while (true);
return hitPoints;
}
//public static string Total()
//{
// //final output to console with element list and hit points
// do
// {
// Console.WriteLine("Monster no.? has number of hit points");
// } while (true);
//}
}
}

Since you do know about loops, the best approach I can think of is:
Ask for an integer from 1 to 10 and store it in a variable (totalOfMonsters)
Create a list with size equal to totalOfMonsters (monstersInput)
Create a loop that repeats itself "totalOfMonsters" times.
3.a Inside the loop ask on each iteration for the number of hitPoints and add it to the list.
You are already doing step 1 and 2:
static void Main(string[] args)
{
int totalOfMonsters = numberOfMonsters();
Console.WriteLine("Total Number of Monsters = " + totalOfMonsters);
Console.WriteLine();
int numberOfHitPoints = HitPoints();//store this number into list - monstersInput?
List<int> monstersInput = new List<int>(totalOfMonsters);
}
But for step 3 you have to create a loop, you had the right idea with the line:
int numberOfHitPoints = HitPoints();
The only thing missing is the loop and saving each new element on the list. Since you don't want code solutions, let me give at least and outline on how you can do this:
//Creating loop to fill the hitPoints of every monsters
int someCounter = 1;
do
{
//ask for the hitpoints
//save the hitpoints in the list
//increase the value of the counter
}
while(someCounter <= sizeOfYourList);

Related

Method does not return random number from another method

It was hard to find right title for this problem. I had little problem earlier with this dice game and I solved it, thanks for the guys in here Stackoverflow.
My game is 99% ready now, but somehow main program cannot return the dice numbers. This game is meant to break when player have three wins and that makes him a winner. That why there is round.
Console should look like this:
Name of player 1:
Name of player 2:
Round 1
"Player 1 name": 5 + 4 = 9
"Player 2 name": 1 + 2 = 3
Round 2 et cetera
And when player get three wins it is winner. I have also two other class but problem is with Dice so I do not attach the others here.
Class game
using System;
using System.Collections.Generic;
using System.Text;
using static System.Console;
namespace Dicegame
{
static class Game
{
static int winline = 3;
static int round = 1;
public static void Aja()
{
Player p1 = new Player
(
Helpers.Syote.Merkkijono("Name of player 1: ")
);
Player p2 = new Player
(
Helpers.Syote.Merkkijono("Name of player 2: ")
);
Dice dice1 = new Dice();
Dice dice2 = new Dice();
for (int i = 1; p1.Points < winline | p1.Points < winline; i++)
{
int p1throw1 = dice1.Throw(), p1throw2 = dice2.Throw(), p1total = p1throw1 + p1throw2,
p2throw1 = dice1.Throw(), p2throw2 = dice2.Throw(), p2total = p2throw1 + p2throw2;
round++;
}
}
}
}
Class Dice
using System;
using System.Collections.Generic;
using System.Text;
using static System.Random;
namespace Dicegame
{
class Dice
{
static Random randomnumber = new Random();
public int Count { get; set; }
public int ThrowCount { get; set; }
public Dice()
{
ThrowCount = 0;
}
public int Throw()
{
int Count = randomnumber.Next(1, 7);
ThrowCount++;
return Count;
}
}
}
You simply never actualise the points of P1 or P2.
Also you use a for loop where a simple while loop would work way better:
while(p1.Points < winline || p2.Points < winline)
{
p1.AddPoints(dice1.Throw() + dice2.Throw());
p2.AddPoints(dice1.Throw() + dice2.Throw());
round++;
}
I post my solution of this I hope it helps someone in future. Commented all so it is easy to understand for beginners also.
do
{
if (p1.Points == WINLINE || p2.Points == WINLINE)
{
break; // Break this loop when either one reach WINLINE points (3)
}
else
{
// Get random numbers for each throw between 1-6 and sum them together
int p1throw1 = dice1.Throw(), p1throw2 = dice2.Throw(), p1total = p1throw1 + p1throw2,
// Get random numbers for each throw between 1-6 and sum them together
p2throw1 = dice1.Throw(), p2throw2 = dice2.Throw(), p2total = p2throw1 + p2throw2;
// Write round number which is how many times dice is thrown. Split with 2, because same dice is throwed two times in one round
WriteLine($"Round {dice1.ThrowCount / 2}");
// Write given player names and points of each throw and after all sum of those points
WriteLine($"{p1.Name}: {p1throw1} + {p1throw2} = {p1total}");
WriteLine($"{p2.Name}: {p2throw1} + {p2throw2} = {p2total}");
// If player 1 get more points than player 2, add one point for player 1 and reset player 2 points
if (p1total > p2total)
{
p1.Points++;
p2.Points = 0;
}
// If player 2 get more points than player 1, add one point for player 2 and reset player 1 points
else if (p1total < p2total)
{
p2.Points++;
p1.Points = 0;
}
else // If something else (same points for both) do nothing
{
}
}
}
while (true);
// When do loop broke print results of the game
if (p1.Points == WINLINE) // Print this if player 1 wins
{
WriteLine($"Winner of the game is {p1.Name} and total rounds: {dice1.ThrowCount / 2}.");
}
else if (p2.Points == WINLINE) // Print this if player 2 wins
{
WriteLine($"Winner of the game is {p2.Name} and total rounds: {dice1.ThrowCount / 2}");
}

C# exclude numbers from a list in random generation

I am making a tic tac toe game and I am making it to be unbeatable
but first I have to let the computer know the rules.
I'm stuck in a step that is => when it's the computer's turn and we have just started the game so no win case so it's up to the computer to generate a random number that will be the computer's choice ( the block where he mark X or O )
so I need it to generate a number from 1 to 9 but by excluding the already used blocks ( numbers ).
I tried doing that by making a list and adding a number every time the human player used a block but I can't find a way to use those numbers from the list as exclusion for the random choice of the computer.
Here is what I tried and thnx in advance:
//random
List<int> cas = new List<int>();
if (c1 == true)
{
cas.Add(1);
}
if (c2 == true)
{
cas.Add(2);
}
if (c3 == true)
{
cas.Add(3);
}
if (c4 == true)
{
cas.Add(4);
}
if (c5 == true)
{
cas.Add(5);
}
if (c6 == true)
{
cas.Add(6);
}
if (c7 == true)
{
cas.Add(7);
}
if (c8 == true)
{
cas.Add(8);
}
if (c9 == true)
{
cas.Add(9);
}
for (int i = 0; i < cas.Count; i++)
{
random_except_list(cas[]);
}
public static int random_except_list(int[] x)
{
Random r = new Random();
int result = r.Next(1, 9 - );
for (int i = 0; i < x.Length; i++)
{
if (result < x[i])
return result;
result++;
}
return result;
}
Lets have possible places to use:
List<int> possible = Enumerable.Range(1,9).ToList(); // create a list and add 1-9
and used places:
List<int> used = new List<int>();
Random rnd = new Random();
Now everytime we generate a random number in the range of possible list count as index and remove it from there and move it to used:
int index = rnd.Next(0, possible.Count);
used.Add(possible[index]);
possible.RemoveAt(index);
for user its just enough to check if it exists in the used so the acceptable number should be:
!used.Any(x=> x== NumberUserHaveChosen)
So the first time the random number can be 0-8 (as possible.Count==9) and take from it at random index.
the second time the random number can be 0-7 (as possible.Count==8) and take from it at random index.
and so on... while the possible.Count != 0
in this case there is no need to generate random numbers several times that finally it won't exist in our used List.
Several years ago I was working on a Sudoku algorithm, and what I was trying to achieve was to generate a valid solved sudoku table in minimum time possible, i get to the conclusion that I should replace the algorithm that each time I generate a number I have to check some lists to make sure the number was not generated before, as count of numbers were increasing these comparisons would become more and more. for example when only the number 4 is remaining, I should generate random numbers till I get 4. so I used this approach and the result was amazing.
I think you should do something like this:
public static int random_except_list(List<int> x)
{
Random r = new Random();
int result = 0;
while (true)
{
result = r.Next(1, 10);
if (!x.Contains(result))
return result;
}
}
Just trying to use what you have written (more or less), but changing the method to take a List<int> which is what you are building, I would write the method using LINQ like this (except I would create a static Random variable and keep it between calls):
public static int random_except_list(List<int> x) => Enumerable.Range(1, 9).Where(n => !x.Contains(n)).ToList()[new Random().Next(0, 9 - x.Count)];
However, you can implement the same idea in a more explicit way using procedural code:
public static int random_except_list_explicit(List<int> x) {
// First, generate a list of possible answers by skipping the except positions in x
var possibles = new List<int>();
for (int i = 1; i <= 9; i++)
if (!x.Contains(i))
possibles.Add(i);
// now pick a random member of the possible answers and return it
return possibles[new Random().Next(0, possibles.Count)];
}
I believe it is better to work with positions left. So user or computer select from all open positions:
using System;
using System.Collections.Generic;
class app
{
public static int random_except_list(List<int> openPositions)
{
Random r = new Random();
int index = r.Next(openPositions.Count - 1);
int result = openPositions[index];
openPositions.RemoveAt(index);
return result;
}
static void Main()
{
List<int> openPositions = new List<int>();
for (int i = 1; i < 10; i++)
{
openPositions.Add(i);
}
bool turn = false;
while (openPositions.Count > 0)
{
foreach (int value in openPositions)
{
Console.Write(value + " ");
}
Console.WriteLine();
if (!turn)
{
while (true)
{
Console.WriteLine("Choose your Position");
ConsoleKeyInfo key = Console.ReadKey();
int num = (int)key.KeyChar - 48;
if (openPositions.Contains(num))
{
openPositions.Remove(num);
Console.WriteLine();
break;
}
else Console.Write(" is not Valid: ");
}
}
else
{
int compPos = random_except_list(openPositions);
Console.WriteLine("Computer choose: " + compPos);
}
turn = !turn;
}
Console.WriteLine("No positions left");
Console.ReadKey();
}
}

Getting User Input and Adding it to an array at C#

I am trying to get input from user 5 times and add those values to marks array;
Then, it will calculate the average and print positive or negative accordingly. However, I can not take input from the user it just prints "Enter 5 elements". After getting input from user how can I add them to marks array? Any tips would be helpful.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
double average =0;
int [] marks = new int[] { };
for (int a = 0; a < 5; a++){
Console.WriteLine("Enter 5 elements:");
string line = Console.ReadLine();
Console.WriteLine(line);
}
for (int i = 0; i < marks.Length; i++){
average = marks.Average();
}
if(average>0){
Console.WriteLine("Positive");
}else{
Console.WriteLine("Negative");
}
}
}
I would use a while loop combined with int.TryParse to check if the user input is a number. Also it doesn't make any sense to put average = marks.Average(); inside a for loop, because LINQ Average calculates the average of a collection (in your case the marks array).
static void Main()
{
int[] marks = new int[5];
int a = 0;
Console.WriteLine("Enter 5 elements:");
while (a < 5)
{
if (int.TryParse(Console.ReadLine(), out marks[a]))
a++;
else
Console.WriteLine("You didn't enter a number! Please enter again!");
}
double average = marks.Average();
if (average > 0)
Console.WriteLine("Positive");
else
Console.WriteLine("Negative");
}
DEMO HERE
Edited my answer to illustrate solving your problem without a for loop.
class Program
{
const int numberOfMarks = 5;
static void Main()
{
List<int> marks = new List<int>();
Enumerable.Range(1, numberOfMarks)
.ForEach((i) => {
Console.Write($"Enter element {i}:");
marks.Add(int.TryParse(Console.ReadLine(), out var valueRead) ? valueRead : 0);
Console.WriteLine($" {valueRead}");
});
Console.WriteLine(marks.Average() >= 0 ? "Positive" : "Negative");
}
}
This will help you, just copy and paste it.
There are some explanation with comments.
class Program
{
static void Main()
{
const int numberOfMarks = 5;
int[] marks = new int[numberOfMarks];
Console.WriteLine("Enter 5 elements:");
for (int a = 0; a < numberOfMarks; a++)
{
// If entered character not a number, give a chance to try again till number not entered
while(!int.TryParse(Console.ReadLine(), out marks[a]))
{
Console.WriteLine("Entered not a character");
}
Console.WriteLine("You entered : " + marks[a]);
}
// Have to call Average only once.
var avg = marks.Average();
Console.WriteLine(avg > 0 ? "Positive average" : "Negative average");
Console.ReadLine();
}
}
Follow Stackoverflow Answer
since integer array is being used, and as input from the console is a string value, you need to convert it using Parse() Method. For e.g.
string words = "83";
int number = int.Parse(words);
Edit: using string variable in parsing.

How to let the user enter any amount of variable from Console

This is the code that I have made that rolls two dice until a pair appear.
My question is, is there a way for the user to enter any amount of dice he/she wants?
I don't want to create 50 int dice. If I use an array or List I would have the same problem. I'd have to assign each array section to numbergen 50 or more times. Maybe there is something I am missing?
static void Main(string[] args)
{
Random numbergen = new Random();
int dice1=0;
int dice2=1;
for (int counter = 0; counter <= 1; counter++)
{
while (dice1 != dice2)
{
dice1 = numbergen.Next(1, 7);
dice2 = numbergen.Next(1, 7);
if (dice1 == dice2)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(dice1 + "\t" + dice2);
counter++;
dice1 = 0;
dice2 = 1;
}
else if (dice1 != dice2)
{
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine(dice1 + "\t" + dice2);
}
if (counter ==1 )
{
break;
}
}
}
Console.ReadLine();
}
Here's a version where all die must match.
using System;
namespace Dicey
{
class Program
{
static void Main(string[] args)
{
int numberOfDice;
// check for and retrieve the number of dice the user wants.
if (args.Length != 1 || !int.TryParse(args[0], out numberOfDice))
{
Console.WriteLine("Please provide the number of dice.");
return; // exit because arg not provided
}
// Must have at least one and set some arbitrary upper limit
if (numberOfDice < 1 || numberOfDice > 50)
{
Console.WriteLine("Please provide a number of dice between 1 and 50");
return; // exist because not in valid range
}
var dice = new int[numberOfDice]; // create array of die (ints)
var rand = new Random();
var match = false; // start with false (match not found yet)
while (!match) // loop until match becomes true
{
var message = string.Empty;
match = true; // assume match until something doesn't match
for (var i = 0; i < numberOfDice; i++)
{
// initialize dice at index i with the random number
dice[i] = rand.Next(1, 7);
// build the message line to write to the console
message += dice[i]; // first add the die's number
if (i < numberOfDice - 1)
message += "\t"; // if not at the end, add a tab
// check if the previous die (except for the first of course) has a different number
if (i > 0 && dice[i - 1] != dice[i])
match = false; // uh oh, not all match. we have to keep going
}
// print out the message
Console.ForegroundColor = match ? ConsoleColor.Yellow : ConsoleColor.White;
Console.WriteLine(message);
}
Console.ReadLine();
}
}
}
If you want to store a number of integers specified by the user, then the easiest way to do that would be using an array like int x[z] where z is the number specified by the user, or, even better, make a list of ints in the form List<int> where you can add ints depending on the number the user entered.
You wouldn't have the same problem as if you had many different variables when doing numbergen, because you could just have a for loop go through your list or array, giving them a value assigned by numbergen.
Try this,
Ask user to enter a number of dice store it in a variable then create an array of that size.

dice rolling in C# console application giving incorrect totals

I am writing dice roller program in C# console. I am giving two input
Enter the size of the dice and
Enter how times you want to play.
Suppose dice size is 6 and 10 times i have played.
Output is coming:
1 was rolled 2 times
2 was rolled 7 times
3 was rolled 8 times
4 was rolled 7 times
5 was rolled 4 times
6 was rolled 5 times
Total: 33 (its not fixed for every execution this no will be changed)
But my requirement was this total always should be number of playing times. Here I am playing 10 times so the total should be 10 not 33. It should happen for every new numbers... If I play 100 times sum or total should be 100 only not any other number. rest all will be remain same, in my programing not getting the expected sum. Please somebody modify it. Here is my code:
Dice.cs:
public class Dice
{
Int32 _DiceSize;
public Int32 _NoOfDice;
public Dice(Int32 dicesize)
{
this._DiceSize = dicesize;
}
public string Roll()
{
if (_DiceSize<= 0)
{
throw new ApplicationException("Dice Size cant be less than 0 or 0");
}
if (_NoOfDice <= 0)
{
throw new ApplicationException("No of dice cant be less than 0 or 0");
}
Random rnd = new Random();
Int32[] roll = new Int32[_DiceSize];
for (Int32 i = 0; i < _DiceSize; i++)
{
roll[i] = rnd.Next(1,_NoOfDice);
}
StringBuilder result = new StringBuilder();
Int32 Total = 0;
Console.WriteLine("Rolling.......");
for (Int32 i = 0; i < roll.Length; i++)
{
Total += roll[i];
result.AppendFormat("{0}:\t was rolled\t{1}\t times\n", i + 1, roll[i]);
}
result.AppendFormat("\t\t\t......\n");
result.AppendFormat("TOTAL: {0}", Total);
return result.ToString();
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter no of dice size");
int dicesize = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("How many times want to play");
int noofplay=Convert.ToInt32(Console.ReadLine());
Dice obj = new Dice(dicesize);
obj._NoOfDice = noofplay;
obj.Roll();
Console.WriteLine(obj.Roll());
Console.WriteLine("Press enter to exit");
Console.ReadKey();
}
}
It looks to me like you're getting the math backwards... shouldn't it be:
// to capture just the counts
int[] roll = new int[_DiceSize];
for (int i = 0; i < _NoOfDice; i++)
{
roll[rnd.Next(roll.Length)]++;
}
Or if you want the actual rolls:
// to capture individual rolls
int[] roll = new int[_NoOfDice];
for (int i = 0; i < _NoOfDice; i++)
{
roll[i] = rnd.Next(_DiceSize) + 1; // note upper bound is exclusive, so +1
}
You are creating a new Random instance on each iteration. This is not a good thing as it will affect the uniform distribution of results. Keep the Random instance in a field instead of creating a new one every time.
public class Dice {
private Random rnd = new Random();
// ... don't create a new random in `Roll` method. Use `rnd` directly.
}
First of all, the following for-loop is wrong:
for (Int32 i = 0; i < _DiceSize; i++)
{
roll[i] = rnd.Next(1,_NoOfDice);
}
Obviously you switched _DiceSize and _NoOfDice. The correct loop would look like
for (Int32 i = 0; i < _NoOfDice; i++)
{
roll[i] = rnd.Next(1,_DiceSize);
}
Because of that, the line
Int32[] roll = new Int32[_DiceSize];
has to be changed to
Int32[] roll = new Int32[_NoOfDice];
Maybe you should think about renaming these variables, so it's more clearly, which means what.
If you modify your code that way, you will mention that your analisys won't work that way you implemented it. Actually, what you are showing is the result of each throw, which is not what you want, if I understood you right.
UPDATE:
Sorry, I misunderstood you. You do want to show the result for every roll. So, why don't you just move the StringBuilder.AppendFormat to your "rolling-for-loop"?
UPDATE #2:
For me, the following Die-class works exactly the way you want it:
public class Die
{
private int maxValue;
private int numberOfRolls;
private Random random;
public Die(int maxValue, int numberOfRolls)
{
this.maxValue = maxValue;
this.numberOfRolls = numberOfRolls;
this.random = new Random();
}
public string Roll()
{
StringBuilder resultString = new StringBuilder();
for (int i = 0; i < this.numberOfRolls; i++)
{
resultString.AppendFormat("Roll #{0} - Result: {1}" + Environment.NewLine, i + 1, this.random.Next(1, maxValue + 1));
}
return resultString.ToString();
}
}
Hope I could help you.
This is the full code you have to use, according to Mehrdad and Marc Gravell.
Have fun.
public class Dice
{
private Random rnd = new Random();
Int32 _DiceSize;
public Int32 _NoOfDice;
public Dice(Int32 dicesize)
{
if (dicesize <= 0)
{
throw new ApplicationException("Dice Size cant be less than 0 or 0");
}
this._DiceSize = dicesize;
}
public string Roll()
{
if (_NoOfDice <= 0)
{
throw new ApplicationException("No of dice cant be less than 0 or 0");
}
// to capture just the counts
int[] roll = new int[_DiceSize];
for (int i = 0; i < _NoOfDice; i++)
{
roll[rnd.Next(roll.Length)]++;
}
StringBuilder result = new StringBuilder();
Int32 Total = 0;
Console.WriteLine("Rolling.......");
for (Int32 i = 0; i < roll.Length; i++)
{
Total += roll[i];
result.AppendFormat("{0}:\t was rolled\t{1}\t times\n", i + 1, roll[i]);
}
result.AppendFormat("\t\t\t......\n");
result.AppendFormat("TOTAL: {0}", Total);
return result.ToString();
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter no of dice size");
int dicesize = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("How many times want to play");
int noofplay = Convert.ToInt32(Console.ReadLine());
Dice obj = new Dice(dicesize);
obj._NoOfDice = noofplay;
Console.WriteLine(obj.Roll());
Console.WriteLine("Press enter to exit");
Console.ReadKey();
}
}

Categories