Reputation:
I am working on a simple program in Java swing that randomly selects a word from an array when you click a button. The issue is that I do not want to have the same thing generated after clicking the button again. For example, You click the button and it generates the word ‘donut’ from the array, you click again, and it generates donut again. I want to avoid generating the same thing directly after.
Here is the code:
import javax.swing.*;
import java.awt.*;
import java.util.Random;
import java.awt.event.*;
class Main implements ActionListener{
JFrame f = new JFrame("ℂ𝕙𝕒𝕣𝕒𝕔𝕥𝕖𝕣 𝔾𝕖𝕟𝕖𝕣𝕒𝕥𝕠𝕣");
Random r = new Random();
JButton generate = new JButton("Generate");
JButton clear = new JButton("Clear");
JLabel characterClass = new JLabel("Style", JLabel.CENTER);
JLabel characterClass2 = new JLabel("Race", JLabel.CENTER);
JLabel characterClass3 = new JLabel("Weapon", JLabel.CENTER);
JLabel newGenerate = new JLabel("?", JLabel.CENTER);
JLabel newGenerate2 = new JLabel("?", JLabel.CENTER);
JLabel newGenerate3 = new JLabel("?", JLabel.CENTER);
Color custBlue = new Color(10, 63, 250);
Color custOrange = new Color(251,167,88);
Color saturatedCustOrange = new Color(254, 127, 46);
ImageIcon wheel = new ImageIcon("images/loading_wheel.gif");
JLabel img = new JLabel(wheel);
ImageIcon back_image = new ImageIcon("images/back_ground.png");
JLabel img2 = new JLabel(back_image);
String[] style = {"<html><p align='center'>Steampunk</p></html>", "<html><p align='center'>Sci-Fi</p></html>", "<html><p align='center'>Medieval</p></html>", "<html><p align='center'>Imprisoned</p></html>", "<html><p align='center'>Superpowered</p></html>", "<html><p align='center'>Villainous</p></html>", "<html><p align='center'>Primal</p></html>", "<html><p align='center'>Musical</p></html>", "<html><p align='center'>Aquatic</p></html>", "<html><p align='center'>Undead</p></html>"};
String[] race = {"<html><p align='center'>Sorcerer</p></html>", "<html><p align='center'>Alien</p></html>", "<html><p align='center'>Knight</p></html>", "<html><p align='center'>Orc</p></html>", "<html><p align='center'>Elf</p></html>", "<html><p align='center'>Bear</p></html>", "<html><p align='center'>Human</p></html>", "<html><p align='center'>Vampire</p></html>", "<html><p align='center'>Werewolf</p></html>", "<html><p align='center'>Dwarf</p></html>"};
String[] weapon = {"<html><p align='center'>Bow<br />And Arrow</p></html>", "<html><p align='center'>Blade</p></html>", "<html><p align='center'>Gun</p></html>", "<html><p align='center'>Nunchucks</p></html>", "<html><p align='center'>Shield</p></html>", "<html><p align='center'>Bomb</p></html>", "<html><p align='center'>Claws</p></html>", "<html><p align='center'>Mace</p></html>", "<html><p align='center'>Axe</p></html>", "<html><p align='center'>Staff</p></html>"};
public static void main(String[] args) {
Main o = new Main();
o.gui();
}
public void gui(){
f.setSize(500, 400);
this.newGenerate.setBounds(132,107, 180, 40);
newGenerate.setFont(new Font("Arial", Font.BOLD, 20));
this.newGenerate.setForeground(saturatedCustOrange);
f.add(this.newGenerate);
this.newGenerate2.setBounds(304,107, 180, 40);
newGenerate2.setFont(new Font("Arial", Font.BOLD, 20));
this.newGenerate2.setForeground(saturatedCustOrange);
f.add(this.newGenerate2);
this.newGenerate3.setBounds(218,250, 180, 40);
newGenerate3.setFont(new Font("Arial", Font.BOLD, 20));
this.newGenerate3.setForeground(saturatedCustOrange);
f.add(this.newGenerate3);
characterClass.setBounds(132,50, 180, 40);
characterClass.setFont(new Font("Arial", Font.BOLD, 20));
this.characterClass.setForeground(saturatedCustOrange);
f.add(this.characterClass);
characterClass2.setBounds(304,50, 180, 40);
characterClass2.setFont(new Font("Arial", Font.BOLD, 20));
this.characterClass2.setForeground(saturatedCustOrange);
f.add(this.characterClass2);
characterClass3.setBounds(218,192, 180, 40);
characterClass3.setFont(new Font("Arial", Font.BOLD, 20));
this.characterClass3.setForeground(saturatedCustOrange);
f.add(this.characterClass3);
this.generate.setBounds(50, 240, 120, 40);
generate.setFont(new Font("Arial", Font.BOLD, 16));
this.generate.setForeground(custOrange);
this.generate.setBackground(custBlue);
this.generate.addActionListener(this);
f.add(this.generate);
this.clear.setBounds(50, 290, 120, 40);
clear.setFont(new Font("Arial", Font.BOLD, 16));
this.clear.setForeground(custOrange);
this.clear.setBackground(custBlue);
this.clear.addActionListener(this);
f.add(this.clear);
img.setBounds(0, -10,500,400);
f.add(img);
img2.setBounds(0, -10,500,400);
f.add(img2);
f.setLayout(null);
f.setVisible(true);
}
public void actionPerformed(ActionEvent e){
if(e.getSource() == this.clear){
img.setVisible(true);
this.newGenerate.setText("?");
this.newGenerate2.setText("?");
this.newGenerate3.setText("?");
}
else{
this.newGenerate.setText(this.returnStyle());
this.newGenerate2.setText(this.returnRace());
this.newGenerate3.setText(this.returnWeapon());
img.setVisible(false);
}
}
public String returnStyle() {
int ranNum = r.nextInt(this.style.length);
return this.style[ranNum];
}
public String returnRace() {
int ranNum = r.nextInt(this.race.length);
return this.race[ranNum];
}
public String returnWeapon() {
int ranNum = r.nextInt(this.weapon.length);
return this.weapon[ranNum];
}
}
If it is confusing, the program generates a character. It randomly mixes the style of character (like medieval or sci-fi), a race (like human or vampire), and a weapon (like a blade or axe).
I specifically need help with this portion, and I preferably need to do it with a loop, since it is the only way I could think to work a loop into this (it is required for my final project.)
public String returnStyle() {
int ranNum = r.nextInt(this.style.length);
return this.style[ranNum];
}
Upvotes: 1
Views: 65
Reputation: 347234
For a, "different" approach, you could make use of Collections#shuffle
to randomise a List
of values
First, you will need...
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
Next, you will need define a series of "random" List
s. This allows us a simpler method for getting the next random value while maintaining a reference to the "original" values, for example...
private String[] masterStyles = {"<html><p align='center'>Steampunk</p></html>", "<html><p align='center'>Sci-Fi</p></html>", "<html><p align='center'>Medieval</p></html>", "<html><p align='center'>Imprisoned</p></html>", "<html><p align='center'>Superpowered</p></html>", "<html><p align='center'>Villainous</p></html>", "<html><p align='center'>Primal</p></html>", "<html><p align='center'>Musical</p></html>", "<html><p align='center'>Aquatic</p></html>", "<html><p align='center'>Undead</p></html>"};
private String[] masterRaces = {"<html><p align='center'>Sorcerer</p></html>", "<html><p align='center'>Alien</p></html>", "<html><p align='center'>Knight</p></html>", "<html><p align='center'>Orc</p></html>", "<html><p align='center'>Elf</p></html>", "<html><p align='center'>Bear</p></html>", "<html><p align='center'>Human</p></html>", "<html><p align='center'>Vampire</p></html>", "<html><p align='center'>Werewolf</p></html>", "<html><p align='center'>Dwarf</p></html>"};
private String[] masterWeapons = {"<html><p align='center'>Bow<br />And Arrow</p></html>", "<html><p align='center'>Blade</p></html>", "<html><p align='center'>Gun</p></html>", "<html><p align='center'>Nunchucks</p></html>", "<html><p align='center'>Shield</p></html>", "<html><p align='center'>Bomb</p></html>", "<html><p align='center'>Claws</p></html>", "<html><p align='center'>Mace</p></html>", "<html><p align='center'>Axe</p></html>", "<html><p align='center'>Staff</p></html>"};
private List<String> randomStyles = new ArrayList<>(8);
private List<String> randomRaces = new ArrayList<>(8);
private List<String> randomWeapons = new ArrayList<>(8);
Then, you would modify your returnXxx
methods to return the next random value, except, if the random List
isEmpty
, you fill it with the original values and then shuffle
it, for example...
public String returnStyle() {
if (randomStyles.isEmpty()) {
randomStyles.addAll(Arrays.asList(masterStyles));
Collections.shuffle(randomStyles);
}
return randomStyles.remove(0);
}
public String returnRace() {
if (randomRaces.isEmpty()) {
randomRaces.addAll(Arrays.asList(masterRaces));
Collections.shuffle(randomRaces);
}
return randomRaces.remove(0);
}
public String returnWeapon() {
if (randomWeapons.isEmpty()) {
randomWeapons.addAll(Arrays.asList(masterWeapons));
Collections.shuffle(randomWeapons);
}
return randomWeapons.remove(0);
}
This guarantees that values from the List
will only begin to repeat once you have used ALL the values from the original List
We could then encapsulate the concept into a class to make it easier, for example...
public class RandomList<Value> {
private List<Value> masterValues;
private List<Value> randomValues;
public RandomList(Value[] masterValues) {
this(Arrays.asList(masterValues));
}
public RandomList(List<Value> masterValues) {
this.masterValues = masterValues;
randomValues = new ArrayList<>(masterValues);
Collections.shuffle(randomValues);
}
public Value next() {
if (randomValues.isEmpty()) {
randomValues.addAll(masterValues);
Collections.shuffle(randomValues);
}
return randomValues.remove(0);
}
public Value nextOrNull() {
if (randomValues.isEmpty()) {
return null;
}
return randomValues.remove(0);
}
}
Which would change your code to something like...
private RandomList<String> randomStyles = new RandomList<>(new String [] {"<html><p align='center'>Steampunk</p></html>", "<html><p align='center'>Sci-Fi</p></html>", "<html><p align='center'>Medieval</p></html>", "<html><p align='center'>Imprisoned</p></html>", "<html><p align='center'>Superpowered</p></html>", "<html><p align='center'>Villainous</p></html>", "<html><p align='center'>Primal</p></html>", "<html><p align='center'>Musical</p></html>", "<html><p align='center'>Aquatic</p></html>", "<html><p align='center'>Undead</p></html>"});
private RandomList<String> randomRaces = new RandomList<>(new String [] {"<html><p align='center'>Sorcerer</p></html>", "<html><p align='center'>Alien</p></html>", "<html><p align='center'>Knight</p></html>", "<html><p align='center'>Orc</p></html>", "<html><p align='center'>Elf</p></html>", "<html><p align='center'>Bear</p></html>", "<html><p align='center'>Human</p></html>", "<html><p align='center'>Vampire</p></html>", "<html><p align='center'>Werewolf</p></html>", "<html><p align='center'>Dwarf</p></html>"});
private RandomList<String> randomWeapons = new RandomList<>(new String [] {"<html><p align='center'>Bow<br />And Arrow</p></html>", "<html><p align='center'>Blade</p></html>", "<html><p align='center'>Gun</p></html>", "<html><p align='center'>Nunchucks</p></html>", "<html><p align='center'>Shield</p></html>", "<html><p align='center'>Bomb</p></html>", "<html><p align='center'>Claws</p></html>", "<html><p align='center'>Mace</p></html>", "<html><p align='center'>Axe</p></html>", "<html><p align='center'>Staff</p></html>"});
and your returnXxx
methods to something like...
public String returnStyle() {
return randomStyles.next();
}
public String returnRace() {
return randomRaces.next();
}
public String returnWeapon() {
return randomWeapons.next();
}
which is much simpler and cleaner and removes all the duplicate code ... but, this might be a bit more "advanced" then you are right now, but something to keep in mind 😉
Upvotes: 1
Reputation: 2256
If you want it to be able to repeat results, just not the last one it produced, you can store the last result it produced and check if the new is the same. If it is, generate another one. Taking the example from ATP's answer and modifying it to accomplish this, it would look as follows:
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class RandomGenerator
{
public static void main (String[] args) throws java.lang.Exception
{
ArrayList<String> fruits = new ArrayList<>(Arrays.asList("banana", "apple", "orange","grape","watermelon"));
Random r = new Random();
int previousRandom = -1;
int random = r.nextInt(fruits.size());
System.out.println("double size: " + 2 * fruits.size());
for (int i = 0; i < 2 * fruits.size(); i++) {
if (random == previousRandom) {
random = r.nextInt(fruits.size());
i = i -1;
} else {
System.out.println(fruits.get(random));
previousRandom = random;
}
}
}
}
If you don't want it to ever repeat any result, and generate only as many results as possible values you have, then ATP's answer will do the trick.
Upvotes: 0
Reputation: 3249
Basically you can do something like this:
ArrayList<String> fruits = new ArrayList<>(Arrays.asList("banana", "apple", "orange","grape","watermelon"));
Random r = new Random();
while(fruits.size()>0) {
int random = r.nextInt(fruits.size());
System.out.println(fruits.get(randomInt));
fruits.remove(randomInt);
}
create a list.
generate a random index, pop the element in this index, repeat.
Upvotes: 0