+ 1
Dice roller/nested for loop?
I want to make a dice roller. I've made them before using nested for loops, with each loop being a dice setting the dice, but I want to make a program that can use different amount of dice. I was wondering if there was a way I can generate a nested for loop without coding it, like if I input 3 it'll generate a nested for loop of 3 loops. If not, is there any other way I can generate this program? EDIT: If needed I can provide the example, just need to rewrite it.
18 Réponses
+ 1
@Dennis, I'm running into issues using your code. Heres the code I used:
#include <iostream>
#include <vector>
#include <cmath>
int validate (){
int given;
while (!(std::cin >> given)|| (given <= 0)){
std::cout << "Incorrect Value! Try again!! \n\n";
std::cin.clear();
std::cin.ignore(1000000000,'\n');
}
return given;
}
int main(){
int sides, diceNum, Wanted,TotalWanted = 0;
std::cout << "How many sides?" << std::endl;
sides = validate();
std::cout << "How many dice?" << std::endl;
diceNum = validate();
std::cout << "What number you wanting to find the probability of?" << std::endl;
Wanted = validate();
std::vector <int> AllDice(diceNum,1);
unsigned long long loops = pow(sides,diceNum);
for (unsigned long long looper; looper < loops; ++looper){
int last = AllDice.size() - 1, counter = 0;
for ( int counting = 0; counting < diceNum; counting++){
counter += AllDice[counting];
}
if(counter = Wanted){
TotalWanted+= 1;
}
if (++AllDice[last] > sides){
AllDice[last] = 1;
for (int Looping =last - 1; Looping >= 0; --Looping){
++AllDice[Looping];
if (AllDice[Looping] > sides){
AllDice[Looping] = 1;
}else {break;}
}
}
}
std::cout << "Probability of " << Wanted << " is " << TotalWanted << " out of " << loops;
return 0;
}
The problem I'm getting is that the TotalWanted is coming up zero when I run the program.
0
Hello again ^^.
I'm kinda having a hard time to understand the question.
An example would be nice indeed.
0
kk, give me a bit. I'll post my old one in visual Basic. it doesn't batter if you don't know it, it's pretty self explanatory code if you know code already
0
I think what you need is recursion, why you don't give it a try :)
0
Private Sub btnFind_Click(sender As Object, e As EventArgs) Handles btnFind.Click
Dim firstNum As Integer
Dim secNum As Integer
Dim thirNum As Integer
Dim forthNum As Integer
Dim options(-1) As Integer
Dim Number(3) As Integer
Dim sizeOfDice As Integer = 6
Const Total As Integer = 1296
lstOptions.Items.Clear()
For firstNum = 1 To sizeOfDice
For secNum = 1 To sizeOfDice
For thirNum = 1 To sizeOfDice
For forthNum = 1 To sizeOfDice
Number(0) = firstNum
Number(1) = secNum
Number(2) = thirNum
Number(3) = forthNum
Array.Sort(Number)
If Number(1) + Number(2) + Number(3) = cboProb.SelectedIndex + 3 Then
ReDim Preserve options(options.Length)
Dim count As Integer = options.Length - 1
options(count) = ((firstNum * 1000) + (secNum * 100) + (thirNum * 10) + (forthNum))
lstOptions.Items.Add(options(count))
End If
Next
Next
Next
Next
Dim counter As Integer
Dim Numerator As Decimal = options.Length
Dim Denominator As Decimal = Total
For counter = options.Length To 1 Step -1
If (Numerator % counter = 0) And (Denominator % counter = 0) Then
Numerator /= counter
Denominator /= counter
End If
Next
lblProbability.Text = options.Length & "/" & Total & " or " & Numerator & "/" & Denominator
End Sub
End Class
This is in VB, ask if you have any questions about the code, feel free to ask. The point of this is to find the probability of a dice roll for a said roll with 4 dice, keeping highest 3 rolls.
0
@Dennis
Got you your code you wanted. I'm looking at the nested for loop, to see if I can generate that without actually coding it. I'm going to try the recursion idea posted earlier.
0
#include <iostream>
#include <vector>
#include <cmath>
int main(){
const int SIDES = 6;
const int ROLLS = 4;
std::vector<int> v(ROLLS, 1);
unsigned long long loops = pow(SIDES, v.size());
for(unsigned long long j = 0; j < loops; ++j){
int last = v.size() - 1;
/*
Do whatever with the data here
*/
if(++v[last] > SIDES){
v[last] = 1;
for(int a = last - 1; a >= 0; --a){
++v[a];
if(v[a] > SIDES)
v[a] = 1;
else
break;
}
}
}
}
This generates all combinations if that's what you want, do keep in mind that it does get slow with alot of SIDES/ROLLS.
0
Okay, lets start breaking it down so I can understand and learn.
-What's the purpose of the vector <int> v (ROLLS, 1) // Im guessing an array?
-Why unassigned long long for the loop/j variable //Just checking, its power(base, exponent) right?
0
vector is indeed an array, <int> tells the vector which type are going to be in it. The first constructor parameter tells the vector how big our initial size is gonna be, and the second parameter tells it what the default data is gonna be.
Of course these 2 are optional, but it makes life easier sometimes.
Since pow can get pretty big I want to save as much as possible.
j is comparing to this 64 bit number.
If j would be an int, it would overflow at 2^31, thus causing annoying problems.
Making the j also 64 bit, it matches the type that it compares with.
Since I'm not expecting to get negative I also use unsigned just for the extra space.
Pow is indeed base, exponent
0
Is there a reason you use vector instead of just declaring an array via
int array[size] ?
You mind explaining what you mean by default data for the second parameter, or how they are optional, but preferred?
On a unrelated related note, why is C++ so obsessed with memory saving? I understand it doesn't allocate memory itself, but the fixation of data/memory saving confuses me still.
0
A vector is actually very flexible, you can add to it as long as you have available memory in your pc, you can delete from it. It is very useful in game making where you keep adding and erasing from it.
There are also many algorithms that work with it.
Most important is that it's size is not hardcoded, so you should prefer it over normal arrays. This is C++ after all and not C.
I don't have to use the first or second parameter, I could have done
for(int i = 0; i < ROLLS; ++i)
v.push_back(1); //Add 1 to it ROLLS times
and it would have done the same thing. But you have to agree that the other way was much shorter.
vector<int> v(4, 2) would have made an array of 4, all filled with the integer 2
C++'s library tries to keep memory management as far away from you as it can because it's really hard to manage correctly, especially when exceptions come into play.
Vector handles that stuff for you.
You can allocate memory yourself.
int* arr = new int[5];
But you always have to remember to call delete, or delete[]. Gotta choose the correct one.
delete[] arr; //In this case.
Calling delete again from this point would cause memory corruption.
But that's a different topic^^
0
Sorry for responding so late @Dennis, but how are you going through each combination in that code you sent. I now understand up to declaring the 'last' variable, but don't quite understand what you're doing with the statements below that would step through every possible dice roll.
0
I keep incrementing the last number, when it goes over the maximum number I increment the next number by 1 and reset everything before that number to 1.
1 1 1 1
1 1 1 2
...
1 1 1 6
1 1 1 7, it went over the max of 6 so it has to carry.
1 1 2 1
...
1 1 6 6
1 1 6 7 then becomes
1 1 7 1 but now the 3rd number is above 6 as well, so it has to carry as well
1 2 1 1
etc...
0
Probably because you're doing an assignment instead of a comparison:
if(counter = Wanted) -> if(counter == Wanted)
0
Nope, still not working right
0
And now give looper a starting value
for (unsigned long long looper = 0; looper < loops; ++looper)
0
It works for me
sides = 6
diceNum = 4
Wanted = 12
Output = Probability of 12 is 125 out of 1296
0
Did that, even put a cout inside the first loop, didnt get nearly enough output than I should. I used 4 6 sided dice, so 6^4 loops should play out
EDIT: nvm, its hitting them all. It's not adding to TotalWanted though. It should though, it has the proper scope, right?
EDIT: Don't know what I did, but it works now! I'll post the code on my codes.