I am a beginner at C# and I have a homework assignment where I have to write a dice roll simulator.
The user can chose a maximum of 5 die and then as they roll each one the sum is added up with the one rolled previously. At the end the number of rolls and the the total sum is presented.
However, if the user rolls a 6 then this result is not added to the sum but the die is rolled twice more and then the sum is added.
I have a few points where I have gotten stuck and/or would like to know a better way of writing it. I have included a snippet below.
Below I have stated my Random class every time the dice rolls but is it possible for me to do this only once and then use throughout my code?
Is there a simple way to write the part with what happens if you roll a 6? I mean I guess I could write another if statement every time the die rolls but seems that this would very long?
if (intnumberofdie == 1)
{
Random rnd1 = new Random();
int dice1 = rnd1.Next(1, 7);
Console.WriteLine("You have rolled " + dice1);
else if (intnumberofdie == 2)
{
Random rnd1 = new Random();
int dice1 = rnd1.Next(1, 7);
Console.WriteLine("The first die rolled " + dice1);
Console.ReadKey();
Random rnd2 = new Random();
int dice2 = rnd2.Next(1, 7);
Console.WriteLine("The second die has rolled " + (dice2));
Console.ReadKey();
Console.WriteLine("The total sum so far is " + (dice1 + dice2));
}
Give this one a go:
var rnd1 = new Random();
var rollsRemaining = 6;
var sum = 0;
while (rollsRemaining > 0)
{
int dice1 = rnd1.Next(1, 7);
Console.WriteLine("You have rolled " + dice1);
if (dice1 == 6)
{
rollsRemaining += 2;
}
else
{
sum += dice1;
rollsRemaining -= 1;
}
}
Console.WriteLine("The sum is " + sum);
Since you are a beginner I'll try to explain a few things first.
If you have a number of times you have to do the same thing, you should never handle each case yourself. This means you shouldn't use the if else if else.. but instead use a loop like for or while.
I have written a short function which should do what you want.
private int GetNumber(int amountDie) {
if (amountDie <= 0 || amountDie > 5) return 0;
int total = 0;
for (int i = 0; i < amountDie; i++)
{
int roll = rnd.Next(1, 7);
if (roll == 6)
{
int specialRoll1 = rnd.Next(1, 7);
int specialRoll2 = rnd.Next(1, 7);
total += specialRoll1;
total += specialRoll2;
}
else {
total += roll;
}
}
return total;
}
Now some more explaining:
Since you said that you can't have more than 5 die, we will first check if the value given was valid, otherwise we'll just return 0 (there are better things to do in this case but for simplicity we'll just say they get back 0).
After that we declare a total to keep track of how many points we have to return.
Then we start the loop. For each dice, we roll once (first line in the for-construct).
Since we need to check if the user rolled a 6, we have this if there. Inside it we roll two die and add both results to the total. Note, that for these two rolls 6 is just like any other number and not handled differently (if you need that, it would be a bit more complicating).
If the user didn't roll a 6, we just add whatever they rolled to the total.
After we've done that for all die we simply return the total we got.
You'll see that if you just copy paste this code, it will not compile. The reason for that is that you are missing a Random-object. In your code you always created a new one everytime you rolled. This is a problem since the Random class isn't as random as you might think and you should always create just one for many random numbers.
Thats why I added this at the top of my class:
private static readonly Random rnd = new Random();
This random-object is only created once and then used for every die. This gives you a lot more randomness and prevents that every user always rolls the same value.
I hope this shows you how you can create a method like this. Of course you can add the console-output etc like you did in your code.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
ok so im pretty new to programming and am trying to make a game where i roll random ints for the dice inside of a loop and i want to be able to subtract the results of the dice roll from a value for the enemy's Hp and have that value carry over throughout the loop until the hp value equals zero then break the loop and end the game. I have tried declaring an int for the value, but i cant figure out how to save the damage dealt from the previous dice roll loop. Can anyone point me in the right direction to do this?
Edit:
forgot to add the code whoops.
This is my crappy code
class Program
{
static void Main(string[] args)
{
Program.hit();
}
static void hit()
{
bool enemyAlive = true;
while (enemyAlive)
{
Random rnd = new Random();
int roll20 = rnd.Next(1, 21);
int roll6 = rnd.Next(1, 7);
int rollCrt = rnd.Next(1, 7);
int critDmg = roll6 + rollCrt + 4;
if (roll20 == 20)
{
WriteLine($"\nyou rolled. { roll20} CRIT!!");
WriteLine($"you deal. {roll6} + {rollCrt} + 4 = {critDmg} damage.");
//currentEhp = enemyHp - critDmg;
// WriteLine(currentEhp);
}
else if (roll20 <= 14)
{
WriteLine($"\nyou rolled. {roll20} you miss");
}
else if (roll20 >= 15)
{
WriteLine($"\nyou rolled. {roll20} you hit");
WriteLine($"you deal. {roll6} damage");
//currentEhp = enemyHp - roll6;
// WriteLine(currentEhp);
}
ReadLine();
}
}
}
Declare the int variable outside of the loop and subtract from within the loop.
For example:
int hp = 100;
// I'm guessing this is the dice roll loop
for (int i = 0; i < NumOfTimes; i++)
{
if (hp <= 0)
break;
DiceRoll();
hp -= ValueOfDiceRoll;
}
I am trying to make a program for a game of pig where there user enters a point total to play for and then takes turns with a computer player until one player reaches the point total. For the human turn the player rolls and if they roll 2-6 then they can use r to roll again or h to hold. when hold is selected it adds up the total points and goes to the next turn. If 1 is rolled then they get 0 points for the round and it goes to the computers turn. For some reason when I select h to hold it just keeps going and when it does end the points don't get added up. Not sure how to fix this
any help would be appericated
static int pigRoll()
{
Random random = new Random();
int die1 = 0;
die1 = random.Next(1, 6);
Console.WriteLine($"You rolled {die1}");
return die1;
}
static double humanTurn()
{
double pointTotal = 0;
string gameSelect = null;
var pigDiceRoll = 0;
Console.WriteLine("It's your turn");
do
{
pigDiceRoll = pigRoll();
if (pigDiceRoll != 1)
{
Console.WriteLine("r to roll or h to hold (r/h)");
gameSelect = Console.ReadLine();
pointTotal = pointTotal + pigDiceRoll;
}
else if(pigDiceRoll ==1)
{
pointTotal = 0;
}
} while (gameSelect != "r" || pigDiceRoll != 1);
Console.WriteLine($"Your turn point total is {pointTotal}");
return pointTotal;
}
The while statement should read:
while (gameSelect == "r" && pigDiceRoll != 1)
This translates to keep looping while the user wants to roll again and they didn't roll a 1.
Alternatively you could use:
while (!(gameSelect != "r" || pigDiceRoll == 1))
Both are logically the same, but the first is probably easier to read.
Im new to programming and Im currently attempting to make a dice program, where the user can input how many throws they would like to do and then a list will display how many throws it took to get a specific number, in this case that number is 6 (later on I'd like to make it for all numbers 1-6) How should I go about doing this?
Im currently trying to use an if-statement to recognize when a specific number is rolled, currently I want the program to recognize the number 6, but im a bit unsure how to display the amount of rolls it took to get that number, in a list, and also keeping the loop going until all rolls have been executed.
private void Btnkast_Click(object sender, EventArgs e)
{
bool throws;
int numberofthrows = 0;
int dice;
Random dicethrow = new Random();
throws = int.TryParse(rtbantal.Text, out numberofthrows);
int[] list = new int[numberofthrows];
for (int i = 0; i <= numberofthrows; i++)
{
dice = dicethrow.Next(1, 7);
if (dice == 6)
{...}
}
}
Also, the only reason I use tryparse is to prevent crashes when having to handle with string-values.
I have written this for you using a C# Console Application, but I'm sure you will be able to edit it to fit your requirements for Windows Forms.
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
Random rnd = new Random(); // create Random object
Console.WriteLine("Enter a number between 1 and 6: "); // prompt user to enter a number between 1 and 6
int chosenNumberInt;
var chosenNumber = int.TryParse(Console.ReadLine(), out chosenNumberInt); // check to see if user actually entered a number. If so, put that number into the chosenNumberInt variable
Console.WriteLine("How many rolls would you like?"); // prompt user to enter how many rolls they would like to have
int chosenRollsInt;
var chosenRolls = int.TryParse(Console.ReadLine(), out chosenRollsInt);
Console.WriteLine(); // to create space
Console.WriteLine(); // to create space
Console.WriteLine("Chosen Number = " + chosenNumberInt + " --- Chosen Rolls = " + chosenRollsInt); // show user what they entered
Console.WriteLine("------------");
int count = 0;
int numberRolled = 0;
var lstRolls = new List<int>(); // create list object
for(int i = 1; i <= chosenRollsInt; i++)
{
count++;
int dice = rnd.Next(1, 7);
numberRolled = dice;
lstRolls.Add(numberRolled); // add each roll to the list
Console.WriteLine("Roll " + i + " = " + numberRolled); // show each roll
}
var attempts = lstRolls.Count; // how many rolls did you do
var firstIndexOfChosenNumber = lstRolls.FindIndex(x => x == chosenNumberInt) + 1; // have to add 1 because finding the index is 0-based
Console.WriteLine("-------------");
if(firstIndexOfChosenNumber == 0)
Console.WriteLine("The chosen number was " + chosenNumberInt + " and that number was NEVER rolled with " + chosenRollsInt + " rolls.");
else
Console.WriteLine("The chosen number was " + chosenNumberInt + " and the number of rolls it took to hit that number was " + firstIndexOfChosenNumber);
}
}
Something that I didn't add would be the validation to ensure that the user does indeed enter a number between 1 and 6, but you can do that I'm sure.
I have created a DotNetFiddle that proves this code does work and even shows you each roll.
Let me know if this helps or if you need any more assistance.
UPDATE
Based on your comment on my original post, I have edited my code to allow the user to enter the number they want, along with how many rolls. Then, once all of the rolls have been completed, I find the index of the first occurrence of the number they selected in the beginning.
Let me know if this is what you want.
Read the comments I added in the code
private void Btnkast_Click(object sender, EventArgs e)
{
bool throws;
int numberofthrows = 0;
int dice;
Random dicethrow = new Random();
throws = int.TryParse(rtbantal.Text, out numberofthrows);
List<int> list = new List<int>(); //I changed this to a list
for (int i = 0; i < numberofthrows; i++)
{
dice = dicethrow.Next(1, 7);
list.Add(dice); //add every roll to the array to check later the values if you want
if (dice == 6)
{
//Print that you found 6 at the roll number list.Count
Console.WriteLine("Found 6 at roll number: " + list.Count);
break; //probably break the loop so you won't continue doing useless computation
}
}
}
Im trying to make random number generator and want it to include max value in array of numbers, what i did was use math.abs and i dont know if i even achieved what i wanted... so here is my code:
using System;
namespace _7
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello this is random number generator!");
Console.WriteLine("Enter min number:");
int pirmas = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("enter max number:");
int antras = Convert.ToInt32(Console.ReadLine());
antras = Math.Abs(antras + 1);
Random generator = new Random();
Console.WriteLine("Generated number is:");
int end = generator.Next(pirmas, antras);
Console.WriteLine(end);
Console.ReadKey();
}
}
}
The Math.Abs() call is unnecessary and makes the code not work as expected for negative max numbers. Otherwise, what you are doing should work exactly as expected. Just increment antras by one.
antras += 1;
EDIT:
As Haukinger suggested, it would probably be better to not modify the max value (antras) and instead only modify the call to Random.Next().
int end = generator.Next(pirmas, antras + 1);
after reading some C# tutorials I decided to make a minigame of Heads/Tails. It generates a random number, 0 or 1, and writes out the result. Using a loop I repeat this a thousand times. The problem is that it would only write "heads" or "tails" depending on whether 0 or 1 gets generated more. For example if there are 535 "0s" and 465 "1s" it would only write down "Heads". Here is my code:
//variables
int count = 0;
int tails = 0;
int heads = 0;
while(count < 1000)
{
Random rnd = new Random();
int result = rnd.Next(0,2);
if(result == 1)
{
Console.WriteLine("Tails!");
tails = tails + 1;
count = count + 1;
}
else if(result == 0)
{
Console.WriteLine("Heads!");
heads = heads + 1;
count = count + 1;
}
}
Console.WriteLine("Heads = " + heads + "Tails = " + tails + " Counts = " + count);
Console.ReadLine();
Try moving Random rnd = new Random(); outside of the while loop:
Random rnd = new Random();
while (count < 1000)
//...
The problem is that there are no true random numbers in computers; they all work off of a list of previously-generated random numbers. Since you are instantiating Random every loop, you're essentially picking the same start seed every time. By using just one instance of Random, created outside of the loop, then your application will truly behave as if the numbers are being generated randomly.
EDIT: To echo what Solal Pirelli said in the comments, the instance of Random is actually being seeded using the current computer system's time (if you don't give it any seed value in the constructor); however, since the loop iterations are happening so quickly, each instance created for each loop iteration has the same seed.
EDIT #2: As CalebB pointed out, it's also a good practice to provide your own seed to your Random instance via its other constructor. I would suggest using the hash value from a GUID:
Random rnd = new Random(Guid.NewGuid().GetHashCode());
This essentially guarantees that each of your instances of Random will always be seeded differently, even if you create new instances in quick succession. I say essientially because, while statistically very VERY low in probability, there is some chance that two GUID values could be the same.
Fixed! :
using System;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
public static void Main(string[] args)
{
Random rand = new Random();
Console.WriteLine(String.Join("\n",Enumerable.Repeat(0, 1000).Select(i => rand.Next(0,2) == 1 ? "Tails" : "Heads").GroupBy(i=>i).Select(g=> g.Key + " " + g.Count())));
Console.ReadLine();
}
}
}