0

The idea is that I can set the max value to 15 or 25 but if the die only has 20 sides it shouldn't roll higher than 20.

I am creating a die roller as a personal project. I created a Dice object that takes in the size of the die (how many sides) as well as the minimum and maximum values that can be rolled on the die. I was having a problem where the on a 20 sided die, if i set the maximum over 20 it would roll higher than 20. I fixed this issue by implementing a do while loop that runs until the random value produces is less than the size of the die.

This seems wildly inefficient to me as theoretically it could run for hours just getting incorrect values again and again. I am looking for a more efficient solution.

//Main.java
public class Main {

    public static void main(String[] args) {

        MinMaxDice d20 = new MinMaxDice(20, 10, 20);
        System.out.println("\nThere are " + d20.sides + " sides on this die.");
        System.out.println("The max is " + d20.max + " and the min is " + d20.min + ".");
        for (int i = 0; i < 20; i++) {
            System.out.println("It rolled a " + d20.rollDie() + ".");
        }
    }
}

//MinMaxDice.java
import java.util.concurrent.ThreadLocalRandom;

public class MinMaxDice extends Dice {
    int max;
    int min;

    MinMaxDice(int sides, int min, int max) {
        super(sides);
        this.max = max;
        this.min = min;
    }

    public int rollDie() {
        int result;
        do {
            result = this.min + ThreadLocalRandom.current().nextInt(this.max - (this.min - 1));
        } while (result > sides);
        return result;
    }
}
Abra
  • 19,142
  • 7
  • 29
  • 41
HermitIX
  • 1
  • 1
  • [How do I generate random integers within a specific range in Java?](https://stackoverflow.com/questions/363681/how-do-i-generate-random-integers-within-a-specific-range-in-java) – Abra May 31 '23 at 04:32
  • You can use the _[Random#nextInt](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/random/RandomGenerator.html#nextInt(int,int))_ method, which has a lower and upper bound as parameters. – Reilas May 31 '23 at 04:37
  • I don't see the point of having sides if you've defined the bounds, but it would seem that something like `return ThreadLocalRandom.current().nextInt(min, max - 1);` would do exactly what you're asking (Oh, and "die" is the singular, "dice" is the plural ... oh my, I'm giving grammar corrections, the world has truely come to and end ) - oh and is max/min inclusive or exclusive as that would change your bounds ranges – MadProgrammer May 31 '23 at 04:39
  • So if there was a 20 sided die, and min was 16 and max was 25, you'd want any of the int values 16 through 20 to be returned, each with a 20% chance? – M. Justin May 31 '23 at 04:46

2 Answers2

0

Assuming I'm interpreting your intentions correctly, as a concrete example, rollDie for a MinMaxDice with sides = 20, min = 16, and max = 25 should produce an int value between 16 and 20, each with an equal 20% chance.

In that case, we can use ThreadLocalRandom.nextInt(int origin, int bound) to generate a random number in the allowed range:

Returns a pseudorandomly chosen int value between the specified origin (inclusive) and the specified bound (exclusive).

public int rollDie() {
    return ThreadLocalRandom.current()
            .nextInt(this.min, 1 + Math.min(this.max, this.sides));
}
M. Justin
  • 14,487
  • 7
  • 91
  • 130
0

This question was not as unique as I thought, and the answer was super simple. I just replaced the do-while with an if statement that changed the max value to sides if it was higher than sides. Easy Peasy, I am embarrassed I even asked the question.

HermitIX
  • 1
  • 1
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 31 '23 at 06:48