4

EDIT: I'm so sorry, I need to expand. I'm using LibGDx, so my code is actually more complex.

Rock1 = new TextureRegion(texture, 5, 10);
Rock2 = new TextureRegion(texture, 6, 11);
Rock3 = new TextureRegion(texture, 7, 12);

int rannum = ran.nextInt (3)+1;

I want it to be that the rock that shows up is random.

I have a random integer called 'rannum' that is set between the bounds of 1 and 3. So I want to figure out how I can get a method that makes it so that I can combine "Rock" and "rannum" so that it can randomly return either Rock1, Rock2, or Rock3.

I'm not referring to concatenating two strings - but specifically object names.

How can I do this? Does it require using an array?

Erick Adam
  • 399
  • 6
  • 13
  • Use an array instead of numbered variables. – Filburt Aug 20 '17 at 14:54
  • 2
    `Rock[] rocks = new Rock[3]; /*...*/ Rock randomRock = rocks[ran.nextInt(rocks.length)];` – Gil Vegliach Aug 20 '17 at 14:56
  • You appear to put a lot of importance on variable names, and they're actually a lot less important than you think. Much more important is *object reference* and how to get a handle on this, and the ways include use of a variable, or a collection... – DontKnowMuchBut Getting Better Aug 20 '17 at 15:02
  • 2
    You _could_ actually make use of reflection, but I neither see the need nor would I recommend it. – Marvin Aug 20 '17 at 15:05
  • @Marvin: I'm not so sure. I'm not a reflection pro, but I thought that while it can be used to find and call methods and constructors, and to gain references to fields, I don't think that it can be used to create new variable names that didn't exist before. The original poster is essentially asking how to create dynamic variable names, and this is something that can't be done in standard Java, even with reflection. – DontKnowMuchBut Getting Better Aug 20 '17 at 15:17
  • @DontKnowMuchButGettingBetter: Added an answer that shows how to do it with reflection. – Gil Vegliach Aug 20 '17 at 15:28
  • @DontKnowMuchButGettingBetter: That is true, but I'm not reading anything about creating new variables in the question. And none of the current answers covers that point specifically. – Marvin Aug 20 '17 at 15:33
  • @SotiriosDelimanolis is that you who down-vote all the answers, if yes can i know the reason? ;) – Youcef LAIDANI Aug 20 '17 at 16:41
  • @SotiriosDelimanolis: why do you assume there is the need to add or remove a rock? Plus, the question is: "How can I do this? Does it require an array?". It doesn't ask for optimal solutions or best practices. – Gil Vegliach Aug 20 '17 at 16:54
  • @SotiriosDelimanolis: I haven't assumed that the variables were fields, I analyzed the situation and gave an answer both if they are and aren't. I don't see the point of many of your downvotes if you remove your assumption. Anyway, that is your opinion, so I respect that. – Gil Vegliach Aug 20 '17 at 17:02
  • 2
    For the records, SotiriosDelimanolis's point was that most of the approaches were not flexible when adding or removing rocks. – Gil Vegliach Aug 20 '17 at 17:55

5 Answers5

5

You can use an array or List like this :

TypeRock[] rocks = new TyprRock[]{Rock1, Rock2, Rock3};

or :

List<TypeRock> rocks = Arrays.asList(Rock1, Rock2, Rock3);

...then you can use Random like this :

Random ran = new Random();
TypeRock selectedRock = rocks[ran.nextInt(rocks.length)];

or :

TypeRock selectedRock = rocks[ran.nextInt(rocks.size())];

Or like @davidxxx mention in comment, you can use Collections.shuffle(list) without Random like this :

List<TypeRock> rocks = Arrays.asList(Rock1, Rock2, Rock3);
Collections.shuffle(rocks);

Then you can use the first value for example rocks.get(0)

Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • 3
    @davidxx: just to point it out, with shuffle the complexity becomes `O(#rocks)` – Gil Vegliach Aug 20 '17 at 15:26
  • 1
    @Gil Vegliach You are right. But this stays very relative.1) For list with few elements, it is so few significant that it is not a problem. So in this case, we should favor the code concision/readability. 2) If you need to retrieve more than one value, it is not necessary a problem to increase a little the complexity as the shuffle is an investment for next retrievals. 3) `Random.nextInt()` may return multiple times the same value. It may not be desirable. – davidxxx Aug 20 '17 at 18:39
  • @davidxxx: yep, if #rocks is constant, for example 3, the complexity is O(1). I'm not sure what you mean with "next retrievals". If you shuffle the list once and return the list's elements in succession, this will make the picks much "less random". For example, the n-th pick will be always known if you know the previous n - 1 picks. Anyway, I think in this case (3 rocks, re-shuffle on each pick), your approach is fine. – Gil Vegliach Aug 20 '17 at 19:04
3

If it will always be a small number of possibilities (in your case there are three possible outcomes) I recommend a switch statement with your random number as the argument.

switch(rannum) {
  case 1:
    return Rock1;
    break;

etc ...

}
Amr
  • 411
  • 6
  • 21
2

Yes, easiest way to do so would be using an array. Beware that array indizes start with 0.

Dorian Gray
  • 2,913
  • 1
  • 9
  • 25
2

You can do that with an array like so:

TextureRegion[] textures = new TextureRegion[3];

textures [0] = new TextureRegion(texture, 5, 10);
textures [1] = new TextureRegion(texture, 6, 11);
textures [2] = new TextureRegion(texture, 7, 12);

int rannum = ran.nextInt (3)+1;

return textures [rannum-1];
vatbub
  • 2,713
  • 18
  • 41
1

How can I do this? Does it require using an array?

Many other answers, and my comment, provide a solution using arrays or collections. But is it required to use such structures?

It depends. If the rocks are local variables, their variables names are lost at run-time and you will end up using arrays, switch, or something similar. Instead, if the rocks are instance variables (i.e. fields), you can use reflection. I'd still recommend the array approach though.

Here comes a snippet that illustrates the idea. Recall that throwing just Exception is bad practice:

Rock rock1;
Rock rock2;
Rock rock3;

public Rock getRandomRock() throws Exception {
  String fieldName = "rock" + (1 + ran.nextInt(3));
  Field field = getClass().getDeclaredField(fieldName);
  return (Rock) field.get(this);
}
Gil Vegliach
  • 3,542
  • 2
  • 25
  • 37
  • I am not the downvoter, but I am not sure if using reflection for such a simple problem is not overcomplicated – vatbub Aug 20 '17 at 16:56
  • @vatbub: I agree with you that's why I said I'd recommend the array approach instead. Anyway, from the comments (now partially removed), the reason was that this approach, along with most of the others, was not flexible when rocks were added or removed. – Gil Vegliach Aug 20 '17 at 17:50
  • @vatbub: btw, just to clarify, my point is: "Does it require an array? Theoretically no, you can do it with reflection, but I don't recommend it". If you think it is not clear, let me know and I'll rephrase the answer. – Gil Vegliach Aug 20 '17 at 18:12
  • No problem, I get your point. But when adding textures later is a requirement, then why not use lists or sets? – vatbub Aug 21 '17 at 13:02
  • @vatbub You can use the List interface here but I'd only use ArrayList as its implementation. Other implementations like LinkedList have slow random access. What's your idea with Set? Anyway, I think guessing requirements, in general, makes the code more rigid, but it would be fine in this situation. – Gil Vegliach Aug 21 '17 at 13:32
  • I thought about sets, as they sometimes have a better performance than lists, but ArrayLists usually do the job, too. – vatbub Aug 21 '17 at 14:19
  • @vatub: testing for containment is faster in Sets. Here you want to get an element in a random position and Set doesn't have an API for that. Lists have `get(int)`. Perhaps there is some other solution but I don't see it (Iterator?). – Gil Vegliach Aug 21 '17 at 14:58
  • That's why I thought about both of them :) – vatbub Aug 21 '17 at 20:23