I am very new to java and I set a goal for myself to make a dice rolling program (keeping it small). The end goal is to be able to roll a user-selected amount of dice and be able to have each die have a different amount of side if need be and I have it get the number of dice and how many sides each has. This is the code I made for it (Might be really bad, sorry if it is) :
public class Roller {
public final Random rando;
public final int faces;
public Roller(int faces) {
this.rando = new Random();
this.faces = faces;
}
public int roll() {
return 1 + rando.nextInt(faces);
}
//above code is not mine I built off what my friend wrote cause i didnt know if i still need it
public static void main(String[] args) {
Random rand = new Random();
Scanner scan = new Scanner(System.in);
System.out.print("How many dice do you want to roll?\n");
int D6 = scan.nextInt();
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < D6; i++) {
System.out.print("How many sides does die " + (i + 1) + " have?\n");
Roller dice = new Roller(scan.nextInt());
list.add(dice.roll());
}
}
}
Now I'm at the point where I want to display the ArrayList but I want to display it as
"Dice 1 rolled #
Dice 2 rolled #"
etc. and I'm lost on how to do that especially with the varying number of dice. Any help is very appreciated.
Let's assume you ran this and now have a List of values, [1, 3, 5, 2, 4] and you want to display them as you described.
In your main method, you have the list, so you could do some looping and string formatting to get your desired output. (edited to use printf() rather than String.format())
// in main...
// after list has all it's values
for (int i = 0; i < list.size(); i++) {
System.out.printf("Dice #%d rolled %d", i+1, list.get(i));
}
Note that the below statements are still valid, and can still be applied to printf(...)
To walk through it, String formatting is just a fancy way to format your strings (funny how that works out). The first %d corresponds to the first value given to format(), which is i+1. It's i+1 as opposed to plain i because otherwise you'd see "Dice #0 rolled ..." first, since you start indexing arrays and lists at 0. With the second %d in the format() call, you pass in list.get(i) which is the value in the list at the given index. This should correspond nicely to the order of the rolls.
This didn't have to be done with String formatting. I find it tends to be better and easier to read personally, but it is easily substituted with String concatenation.
//replace the print statement with this if you want
System.out.println("Dice #" + (i+1) + " rolled " + list.get(i));
It seems sloppier to me IMO, and needing to remember to leave spaces, or omit spaces between concatenated parts can be annoying.
Related
This question already has answers here:
Elegantly Insert Spaces During Loop Between Values Without Trailing Space
(3 answers)
Java: join array of primitives with separator
(9 answers)
Closed 6 months ago.
I'm trying to get the console to output 100 random numbers between 0 and 50, all on the same line with a space between each. I have everything but the formatting for the space. I know I need to use the printf function, but am completely lost on how to properly impliment it. This is what I have so far, but the output formatting is incorrect.
public static void main(String[] args) {
Random rand = new Random();
for (int count = 0; count <=100; count++)
{
int randomNum = rand.nextInt(51);
System.out.printf("%1d %1d", randomNum, randomNum);
}
}
Here's a version neither using a condition or a separate first print but avoiding any leading or trailing space.
public static void main(String[] args) {
Random rand = new Random();
String delim="";
for (int count = 0; count <100; count++)//fixed as per comments elsewhere.
{
int randomNum = rand.nextInt(51);
System.out.printf("%s%1d", delim,randomNum);
delim=" ";// Change this to delim="," to see the action!
}
}
It's a classic faff to print out n items with n-1 internal separators.
PS: printf feels like overkill on this. System.out.print(delim+randomNum); works just fine.
[1] Your code actually prints 101 numbers. Embrace the logic computers (and java) applies to loops and 'the fences' (the start and end): The first number is inclusive, the second is exclusive. By doing it that way, you just subtract the two to know how many items there are. so, for (int count = 0; count < 100; count++) - that loops 100 times. Using <= would loop 101 times.
[2] You're making this way too complicated by focusing on the notion of 'there must be a space in between 2', as if the 2 is important. What you really want is just 'after every random number, print a space'. The only downside is that this prints an extra space at the end, which probably doesn't matter:
for (int count = 0; i < 100; count++) {
System.out.print(randomNum + " ");
}
is all you actually needed. No need to involve printf:
I know I need to use the printf function
No, you don't. No idea why you concluded this. It's overkill here.
If you don't want the extra space.. simply don't print it for the last number:
for (int count = 0; i < 100; count++) {
System.out.print(randomNum);
if (count < 99) System.out.print(" ");
}
[3] You mention that the code shuold print it all 'on one line', which perhaps suggests the line also needs to actually be a line. Add, at the very end, after the loop, System.out.println() to also go to a newline before you end.
So I'm working on a program which is supposed to randomly put people in 6 rooms (final input is the list of rooms with who is in each room). So I figured out how to do all that.
//this is the main sorting sequence:
for (int srtM = 0; srtM < Guys.length; srtM++) {
done = false;
People newMove = Guys[srtM]; //Guys is an array of People
while (!done) {
newMove.rndRoom(); //sets random number from 4 to 6
if (newMove.getRoom() == 4 && !room4.isFull()) {
room4.add(newMove); //adds person into the room4 object rList
done = true;
} else if (newMove.getRoom() == 5 && !room5.isFull()) {
room5.add(newMove);
done = true;
} else if (newMove.getRoom() == 6 && !room6.isFull()) {
room6.add(newMove);
done = true;
}
}
The problem now is that the code for reasons I don't completely understand (something with the way I wrote it here) is hardly random. It seems the same people are put into the same rooms almost every time I run the program. For example me, I'm almost always put by this program into room 6 together with another one friend (interestingly, we're both at the end of the Guys array). So how can I make it "truly" random? Or a lot more random than it is now?
Thanks in advance!
Forgot to mention that "rndRoom()" does indeed use the standard Random method (for 4-6) in the background:
public int rndRoom() {
if (this.gender == 'M') {
this.room = (rnd.nextInt((6 - 4) + 1)) + 4;
}
if (this.gender == 'F') {
this.room = (rnd.nextInt(((3 - 1) + 1))) + 1;
}
return this.room;
}
if you want it to be more random try doing something with the Random method, do something like this:
Random random = new Random();
for (int i = 0; i < 6; i++)
{
int roomChoice = random.nextInt(5) + 1;
roomChoice += 1;
}
of course this is not exactly the code you will want to use, this is just an example of how to use the Random method, change it to how you want to use it.
Also, the reason I did random.nextInt(5) + 1; is because if random.nextInt(5) + 1; gets you a random number from 0 to 5, so if you want a number from 1 to 6 you have to add 1, pretty self explanatory.
On another note, to get "truly" random is not as easy as it seems, when you generate a "random" number it will use something called Pseudo random number generation, this, is basically these programs produce endless strings of single-digit numbers, usually in base 10, known as the decimal system. When large samples of pseudo-random numbers are taken, each of the 10 digits in the set {0,1,2,3,4,5,6,7,8,9} occurs with equal frequency, even though they are not evenly distributed in the sequence.
There might be something wrong with code you didn't post.
I've build a working example with what your classes might be, and it is distributing pretty randomly:
http://pastebin.com/u8sZRxi6
OK so I figured out why the results don't seem very random. So the room sorter works based on an alphabetical people list of 18 guys. There are only 3 guy rooms (rooms 4, 5 and 6) So each guy has a 1 in 3 chance to be put in say, room 6. But each person could only possibly be in 2 of the 6 spots in each room (depending on where they are in the list).
The first two people for example, could each only be in either the first or second spot of each room. By "spot" I mean their place in the room list which is printed in the end. Me on the other hand am second last on the list, so at that point I could only be in either the last or second last spot of each room.
Sorry if it's confusing but I figured out this is the reason the generated room lists don't appear very random - it's because only the same few people could be put in each room spot every time. The lists are random though, it's just the order in which people appear in each list which is not random.
So in order to make the lists look more random I had to make people's positions in the room random too. So the way I solved this is by adding a shuffler action which mixes the Person arrays:
public static void shuffle(Person[] arr) {
Random rgen = new Random();
for (int i = 0; i < arr.length; i++) {
int randPos = rgen.nextInt(arr.length);
Person tmp = arr[i];
arr[i] = arr[randPos];
arr[randPos] = tmp;
}
}
TL;DR the generated room lists were random - but since the order of the people that got put into the rooms wasn't random the results didn't look very random. In order to solve this I shuffled the Person arrays.
I'm in the process of writing a very simple quiz-style boardgame that moves players around the board based on if they answer the question correctly and what they roll on the dice. I'm attempting to create and pass an array mehtod that stores the scores of player 1 and player 2, but the array doesn't seem to actually keep track of the score. For example, a fragment of some of the code is as follows:
public static int[] scorearray
{
int scoreplayer1 = 0;
int scoreplayer2 = 0;
return new int[] = {scoreplayer1, scoreplayer2};
}
public static int questions(int diceroll, int[] score)
{
String textinput = input("What's 9+10?");
int ans = Integer.parseInt(textinput);
if (ans == 19)
{
output("Fantastic answer, that's correct!");
diceroll = dicethrow(diceroll); // rolls the dice
output("Move forward " + diceroll + " squares. You are on square " + score[0]);
//I need the output above to print position 0 in the above array
score[0] = score[0] + diceroll; //array stores the cumulative score
}
else
{
output("Sorry, the answer was 19. Next player's turn.")
//This is where I need the loop to switch between players
}
In addition, I need to come up with a way of switching between player 1 and 2 while also switching to the position 1 in the above array, that is, I need to add to player two's score instead of player one's. I've been combing through this code for ages now trying to figure out how to do this but I can only come up with the idea of using a for/while loop. Other than that I'm truly stumped.
Thanks.
EDIT: It appears that my array apparently still does not store the score when being used in the method questions.
Also I have now realised I can control whose turn it is by creating another method, for example public static void activePlayer() but I'm still not sure how to use a loop (or anything else for that matter) to switch between the two. Also my concern is where I use score[0] = score[0] + diceroll; in my questions method only keeps the score (or at least attempts to; see above problem) for player one. How would I switch it to keep score for score[1]? Please.
your options here seem to be either have your questions function output the score or change your score object to be a static object instead of a static function.
public static int[] scorearray = [0,0];
or
public static int[] questions(int diceroll, int[] score)
So here is the code I have right now.
public static void main(String[] args) {
Scanner keyboard = new Scanner (System.in);
int set[] = new int[5];
set[0] = (int)(Math.random()*6)+1;
set[1] = (int)(Math.random()*6)+1;
set[2] = (int)(Math.random()*6)+1;
set[3] = (int)(Math.random()*6)+1;
set[4] = (int)(Math.random()*6)+1;
System.out.println("Your current dice: " + set[0] + " " + set[1] + " " + set[2] + " " + set[3] + " " +set[4] );
System.out.println("Select a die to re-roll (-1 to keep remaining dice):");
int ask = keyboard.nextInt();
After this if the user types in let's say 1 then set[1] should change to the number zero and so it becomes x0xxx and if the user also wants the 3rd number to change then it should be x0x0x.
The x's are just the generated random numbers by the way.
How do I keep doing this? It has to be a total of utmost 5 times.
Here are the basic steps you should follow to accomplish what you want/need.
Read user input (using Scanner or something else).
Validate if the user input is a valid index for the array (this is, the input is a number with a value between 0 and 5). You can store this in a variable int x.
Change the value of the element of the array inside the index user entered to 0 (or the value you want/need). This would traduce into something like set[x] = ... (change the ... by the proper value).
The way you do one thing many times is in a loop. The key is in learning which kind of loop to use.
For things that get applied to every element, use a for-each loop. For things that need done until some condition use a while loop. For things that need done until some condition becomes false, use a do-until loop.
The thing you do is the same, that goes into the block of the loop. The thing you are "working on" changes, that is a variable which the loop will set each time it "goes through" the loop's block.
In your case
for (Die die : dice) {
die.roll();
}
where class Die looks like
public class Die {
private int value;
public Die() {
roll();
}
public void roll() {
value = (int)(Math.random()*6)+1;
}
public int getValue() {
return value;
}
}
Then, since you need "order" (first, second, third, etc...) use a data structure that can contain Objects (like your Die)
List<Die> dice = new ArrayList<>();
Arrays are nice, and you do need to know how to use them; however, there are far better ways of solving most problems by not using them.
When you really can't get around using them, use a for loop to walk each array index.
Im working on a CS assignment and Im having a little trouble understanding how to output an array of doubles that represent the amt of money in a bank account at increments of time given a user specified growth rate. I have a main method that asks the user for initialAmount of $, a growthRate and the number of time intervals (denoted iA, gR and nP for inital Amount, growth Rate and number of Periods). this method then calls another method which is of return type double[]. My issue is with the code inside my for-loop, it compiles fine but outputs gibberish. heres the code:
import java.util.Scanner;
public class Benford {
public static double[] generateBenfordNumbers (double iA, double gR, int nP) {
double[] bankStatement = new double[nP];
for (int i = 0; i<nP; i++) {
bankStatement[i] = (iA*(Math.pow((1+(gR)), (i++))));
}
return bankStatement;
}
public static void main (String[] args) {
Scanner scan = new Scanner(System.in);
double iA;
double gR;
int nP;
System.out.print("What is the initial amount of money that you are starting with? : ");
iA = scan.nextDouble();
System.out.println();
System.out.print("What is the amount of growth per time period? : ");
gR = scan.nextDouble();
System.out.println();
System.out.print("How many time periods would you like to use? : ");
nP = scan.nextInt();
System.out.println();
generateBenfordNumbers(iA, gR, nP);
System.out.print(generateBenfordNumbers(iA, gR, nP));
}
}
In the line
bankStatement[i] = (iA*(Math.pow((1+(gR)), (i++))));
i++ increments i a second time. You probably want:
bankStatement[i] = (iA*(Math.pow((1+(gR)), i + 1)));
or, if we clean it up,
bankStatement[i] = iA * Math.pow(1 + gR, i + 1);
i + 1 returns a value 1 greater than that of i, but does not actually increment the variable itself.
Also, do you really have to use Math.pow each time? Can't you just manually set the first element of your array to iA and subsequently use bankStatement[i-1] to compute bankStatement[i]? Doing something like this will probably improve your program.
i is incremented twice : at loop level and into the body
The gibberish output looks like this:
[D#1b67f74
which is s double array text representation. You could use:
System.out.print(Arrays.toString(generateBenfordNumbers(iA, gR, nP)));
You should not be incrementing i inside your call to Math.pow. This is because you already increment it in your for loop. The result is that elements of your array are getting skipped and not set. This is probably where the gibberish-ness is coming from.
You probably want to change:
bankStatement[i] = (iA*(Math.pow((1+(gR)), (i++))));
To:
bankStatement[i] = iA*Math.pow(1+gR, i);
Also, as an aside, you generally shouldn't use so many parenthesis because it makes it hard to read. If you're not sure what the order of operations is, look it up.
What the others said, you're incrementing i twice so I'm not going to repeat that. I just want to add that brackets are good to organize formulas and to ensure correct execution order of calculations, but if you overuse them, they can obfuscate the intention of your program and they may make the problem you're looking for harder to spot. Compare
bankStatement[i] = iA * Math.pow(1.0 + gR, i+1);
with
bankStatement[i] = (iA*(Math.pow((1+(gR)), (i))));
See what I mean?
EDIT - following ARS very valid remark about the initial value of i, I changed the cleaned up statement.