-1

I'm trying to display numbers of a four sided die. The numbers are 2, 3, 5, and 7. I used a string variable as shown below to get the int values for the dice:

    System.out.println("###############");
    System.out.println("#   Welcome   #");
    System.out.println("###############");


    String vals = "2357";

    int od1 = vals.charAt((int)(Math.random() * 4) - '0');
    int od2 = vals.charAt((int)(Math.random() * 4) - '0');
    int od3 = vals.charAt((int)(Math.random() * 4) - '0')


    System.out.print("\n" + "Player" + "\n");
    System.out.println("-----------");
    System.out.print(od1 + " " + od2 + " " + od3);

I receive a "String index out of range" error.

How can I fix my code to print out the following, for example:

    Player
    -----------
    3 7 5
Ricta
  • 3
  • 1
  • 4

5 Answers5

1

First of all change your code in the following way, if you want it to work properly: select one of the char randomly from your initial vals String.

    System.out.println("###############");
    System.out.println("#   Welcome   #");
    System.out.println("###############");


    String vals = "2357";

    char od1 = vals.charAt((int)(Math.random() * 4));
    char od2 = vals.charAt((int)(Math.random() * 4));
    char od3 = vals.charAt((int)(Math.random() * 4));


    System.out.print("\n" + "Player" + "\n");
    System.out.println("-----------");
    System.out.print(od1 + " " + od2 + " " + od3);

However you can use directly Random.nextInt() instead of your current implementation:

public int nextInt(int bound)

Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive), drawn from this random number generator's sequence. The general contract of nextInt is that one int value in the specified range is pseudorandomly generated and returned. All bound possible int values are produced with (approximately) equal probability. The method nextInt(int bound) is implemented by class Random as if by:

 public int nextInt(int bound) {
   if (bound <= 0)
     throw new IllegalArgumentException("bound must be positive");

   if ((bound & -bound) == bound)  // i.e., bound is a power of 2
     return (int)((bound * (long)next(31)) >> 31);

   int bits, val;
   do {
       bits = next(31);
       val = bits % bound;
   } while (bits - val + (bound-1) < 0);
   return val;
 }

The hedge "approximately" is used in the foregoing description only because the next method is only approximately an unbiased source of independently chosen bits. If it were a perfect source of randomly chosen bits, then the algorithm shown would choose int values from the stated range with perfect uniformity.

The algorithm is slightly tricky. It rejects values that would result in an uneven distribution (due to the fact that 2^31 is not divisible by n). The probability of a value being rejected depends on n. The worst case is n=2^30+1, for which the probability of a reject is 1/2, and the expected number of iterations before the loop terminates is 2.

The algorithm treats the case where n is a power of two specially: it returns the correct number of high-order bits from the underlying pseudo-random number generator. In the absence of special treatment, the correct number of low-order bits would be returned. Linear congruential pseudo-random number generators such as the one implemented by this class are known to have short periods in the sequence of values of their low-order bits. Thus, this special case greatly increases the length of the sequence of values returned by successive calls to this method if n is a small power of two.

Parameters: bound - the upper bound (exclusive). Must be positive. Returns: the next pseudorandom, uniformly distributed int value between zero (inclusive) and bound (exclusive) from this random number generator's sequence Throws: IllegalArgumentException - if bound is not positive Since: 1.2

Allan
  • 12,117
  • 3
  • 27
  • 51
1

You can simply do it that way:

String vals = "2357";
Random random = new Random();
int index = random.nextInt(vals.length());
int od3 = vals.charAt(index);

Further reading on why to use Random.nextInt() instead of Math.random(): Stackoverflow: Math.random() versus Random.nextInt(int)

Ramy M. Mousa
  • 5,727
  • 3
  • 34
  • 45
0

As the other correct answers pointed out, there are better ways to write this. However, your method would have worked if you had written it correctly.

int od2 = vals.charAt((int)(Math.random() * 4) - '0');

It looks like you were trying to retrieve one of the characters from the string, which would be '2', '3', '5', or '7', and then subtract '0' from it to result in the integer 2, 3, 5, or 7. This is an OK way to do this conversion. (Character.digit() is a little better since there are other characters in Unicode that can be interpreted as digits, but it doesn't matter here. Also, if all you're doing is printing the output, then you don't need to do the conversion at all--just print the char. But that's up to you, since I don't know if you plan to use the integer value in some other place.)

Your mistake was that you put - '0' inside the charsAt call. Thus, you generate a random number from 0 to 3, subtract 48, and then use the result as an index to the string. That results in IndexOutOfBoundsException, of course. All you need to do is put the - '0' in the right place:

int od2 = vals.charAt((int)(Math.random() * 4)) - '0';
ajb
  • 31,309
  • 3
  • 58
  • 84
0

Subtract the char from '0', not the int. Try this:

  int od1 = vals.charAt((int)(Math.random() * 4)) - '0';
Rinkesh Golwala
  • 979
  • 1
  • 7
  • 17
-1

There's problem with '0'. You use it to subtract ASCII value of 0 from your number so that you don't need to know any ASCII numbers. But you are subtracting it from int number. Try this

int od1 = vals.charAt((int)(Math.random() * 4)) - '0'; 
Pang
  • 9,564
  • 146
  • 81
  • 122
Rinkesh Golwala
  • 979
  • 1
  • 7
  • 17
  • 3
    `Math.random()` cannot return 1. – ajb Nov 06 '17 at 02:21
  • According to the documentation, Math.random() "Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0." This means it can be zero however it is exclusive on the upper boundary (can never be 1). – Allan Nov 06 '17 at 02:30