Using an String array element as a variable name? - java

I'm trying to import many pictures into a visible grid line to appear as a bar (of health, to be exact) that will decrease (adds a white image in place of bar's placement) when damage is taken. So I decide instead of writing out chucks of code for each of the 10 possible health point (not to mention there are other player stats that will be done in the same format), I decided upon scraping together a "for" loop with two if-else statements to attempt a loop to fill each grid element as long as the health value is greater than the "for" loop's "i". There is a slightly different image if the player happens to max their health at 10, hence the second "if-else" loop needed.<p>
My main question concerns the name of my loop, for I used an array to act as a kind of holder for string names that I wished to become the ImageIcon names, yet I've failed to either arrange the code properly or find a source explaining how one would go about using an array string name as the name for an ImageIcon.
Here is the loops and data:<p>
String[] array1 ={"hOne","hTwo","hThree","hFour","hFive","hSix","hSeven","hEight","hNine","hTen"};
String tempY = " ", tempN = " ", tempF = " ", tempNF = " ";
//row 1, health
statsPanel.add(stat1);
for (int i=0; i<=9; i++){
if ((i+1)<heal){
tempY=array1[i];
ImageIcon tempY = new ImageIcon("C:\\Users\\Kunkle\\hea.png");
ColorPanel tempYz = new ColorPanel(Color.black, tempY);
statsPanel.add(tempYz);
}
else {
tempN=array1[i];
ImageIcon tempN = new ImageIcon("C:\\Users\\Kunkle\\non.png");
ColorPanel tempNz = new ColorPanel(Color.black, tempN);
statsPanel.add(tempNz);
}
if (i==8 && heal==10){
tempF=array1[i];
ImageIcon tempF = new ImageIcon("C:\\Users\\Kunkle\\shea.png");
ColorPanel tempFz = new ColorPanel(Color.black, tempF);
statsPanel.add(tempFz);
}
else {
tempNF=array1[i];
ImageIcon tempNF = new ImageIcon("C:\\Users\\Kunkle\\shea.png");
ColorPanel tempNFz = new ColorPanel(Color.black, tempNF);
statsPanel.add(tempNFz);
}
}
Everything has been properly declared variable and import-wise, and the only 3 errors I get is the four lines where the array element is is stated after the first "ImageIcon" in each declaration of a new image. Does there happen to be a way to keep code short with a "for" loop (or several) but still bring in an image under a new name for every pass?

You cannot do what you are attempting to do. Java is not a dynamic language that can substitute variable values for names, a la Perl where $x="a"; $$x=3; results in variable $a having the value 3.
The closest thing you can do is use a Map<String,ImageIcon> to associate strings with objects. If you want to associate both an ImageIcon and ColorPanel with a name you would need a wrapper object to hold references to both, and you have a Map<String,MyWrapper> instead.
I would provide a code sample but that would require seeing the code of statsPanel, which you haven't provided. My guess is statsPanel would be (or contain) the Map<> I mentioned above.

Related

JAVA seperate class method not incrementing a variable in my main class method

so this is the main code for my text-based game.
import java.util.Scanner;
public class D_M_RPG {
public static void main(String[] args) {
//Creating the class to call on my toolbox
D_M_RPGtoolbox toolbox = new D_M_RPGtoolbox();
//Creating the scanner class for user input
Scanner input = new Scanner(System.in);
//Initiating variables and final variables aswell as arrays
//token variable to validate open spots in an array
int slotCounter = 0;
int inventoryExpander = 11;
//First initiated will be the character creation variables
String hairColor = "";
String eyeColor = "";
String skinColor = "";
String gender = "";
//Initiating the arrays for character inventory slots
String[] weaponSlots = new String[10];
//initiating the arrays for the character creation
String[] hairColorARR = {"black","Green","Yellow","Brown","Blue","Blonde","Grey","White"};
String[] eyeColorARR = {"Green","Brown","Blue","Grey",};
String[] skinColorARR = {"White","brown","Black",};
String[] genderARR = {"Male","Female"};
//Creating the introduction title and introduction
System.out.println("Welcome to, COLD OMEN.");
System.out.println("\nNOVEMBER 12th, 2150: ONTARIO, CANADA");
System.out.println("\nYou hear loud shouts and gun fire all around you but can't pinpoint the location of anything, you feel a bit dazed until someone grabs you and you open your eyes and snap out of it.");
System.out.println("\nUnknown: 'Get up, its time to move out. Take this.'");
System.out.println("\nUnknown hands you a 'M4-A4 RIFLE'");
System.out.println("\nyou manage to catch a small glimpse of him before you get up.");
//Character creation screen
System.out.println();
//ONLY WORKS ONCE WONT INCREMEMENT THE SLOTCOUNTER
toolbox.insert(weaponSlots, slotCounter, inventoryExpander, "M4-A4 RIFLE");
System.out.println("\n" + weaponSlots[0]);
toolbox.insert(weaponSlots, slotCounter, inventoryExpander, "ak47");
System.out.println(weaponSlots[0]);
}
}
so I have this method I made to basically add an "item" to the weaponSlots array (the inventory) but whenever I run it it will add to the first element in the array [0] but it wont incremement the slotcounter which should go up by one every time the method is used so that I dont replace any items in the array It should just add items until its full which is checked using the inventoryExpander variable. at the moment I have it printing the element at 0 and 0 for the array but i have checked 1 aswell and 1 is just null no item added it only just replaces the element at 0. heres the code for the method to increment etc:
public class D_M_RPGtoolbox {
//method for random number generating to be used for crit hits, turns, loot generation etc
public int randomGen(){
int x = (int) (Math.random()*((20-0)+1)+0);
return x;
}
//method for inserting into an array ONLY WORKS ONCE WONT INCREMEMENT THE SLOTCOUNTER FIX
public void insert(String[] a, int b, int d , String c) {
if(b < d) {
a[b] = c;
b++;
}//end of if statement
}//end of method
}
What you are actually performing the ++ operation on in b is a copy of the value in slotCounter.
The variable slotCounter is passed into insert "by-value".
This unlike what you probably imagine, that it is passed "by-reference".
One solution would be to do the slotCounter++ from the call row instead; and another would be to let the toolbox own the slotCounter variable completely.
This question uses the image of passing a copy of document content (by value) where changes to the document would not be seen by the sender; or as a link to a shared document (by reference), where changes could be made to the same page that the sender sees.
Its always going to be zero since you are passing zero and incrementing the local variable b.
Try calling the method as below with post increment ++ to slotCounter and see if it works for you,
toolbox.insert(weaponSlots, slotCounter++, inventoryExpander, "M4-A4 RIFLE");

Using HashMaps in creating a game of 15 puzzle?

I am creating a simple game of 15 puzzle (Please see here: https://en.wikipedia.org/wiki/15_puzzle). I have an array of 4 by 4 buttons and want to know the best way to handle a user clicking on a button and moving around the numbers.
I have started off by creating a JavaFX gridpane to display the buttons as well as a HashMap (suggested by multiple people) to store a mapping between the displayed number (1-15) and the button at that location.
I populate the map with class objects "Btn"
public class Btn {
private int ID;
private int x;
private int y;
public Button button;
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 4; j++) {
Btn btn = new Btn(count, j, i, new Button("" + count));
map.put(count, btn);
btn.button.setMinSize(100, 100);
btn.button.setOnAction(e -> {
if (isMoveLegal(btn) == true) {
move(btn);
}
});
count++;
grid.add(btn.button, j, i);
}
}
So far it has worked quite well. In the isMoveLegal() method I check if the empty field is above, left, right, or below the clicked button. Which gets quite complicated because of the HashMaps nature of not preserving any order. But my real problem lies in the move() method. Since there is no order, I can't just switch 2 map nodes or can I?
if (MoveDir.equals("Right")) {
map.get((btn.getYs()+1)*4 - (4-btn.getXs())).button.setText("" + map.get(btn.getID()).getID());
map.get(btn.getID()).button.setText("" + map.get((btn.getYs()+1)*4 - (4-btn.getXs())).getID());
int tempID = map.get(btn.getID()).getID();
map.get(btn.getID()).setID(16);
map.get((btn.getYs()+1)*4 - (4-btn.getXs())).setID(tempID);
// System.out.println(map.get(btn.getID()).getID());
// System.out.println(map.get((btn.getYs()+1)* 4 - (4-btn.getXs())).getID());
map.get(btn.getID()).setYs(map.get(btn.getID()).getYs()+1);
map.get((btn.getYs()+1)* 4 - (4-btn.getXs())).setYs(map.get((btn.getYs()+1)* 4 - (4-btn.getXs())).getYs()-1);
This is what I have come up with so far, which extremely complicated and tedious. To quickly sum it up, I first switch the labels of the buttons, then I change the ID variables of the 2 buttons, and then I change the cord variables (x & y) to indicate their new location in map/grid.
I'm pretty sure I have gone way too far with this and there is a simpler solution to all of this but I am just unsure what that would be. Should I ditch the HashMap entirely and just use an object array of Btns?
Thanks for the help.
The problem you're facing is that your UI and your data structure are too tightly coupled. You need to separate them, give them their own responsibilities, and use communication (method calls) between them to make things happen.
For example, the UI should only be responsible for displaying the numbers and allowing the user to click a number to perform a move. Using a gridpane of buttons seems reasonable for this. Each button only needs to know it's x,y coordinate.
The data model should be a 2-dimensional array that contains the number at that location. For example:
+-+-+-+
|4|1|8|
+-+-+-+
|2|3|7|
+-+-+-+
| |5|6|
+-+-+-+
(You can figure out how to represent the empty space. Maybe a null, or the number '0' or '-1')
The data model can be wrapped in a data object that handles questions about and manipulations to the data model. For example, one method it might contain is getTheNumberAtLocation(x,y) which the buttons will call, and will return the number at that location. The buttons will use this to determine what number they should show.
Another method it might contain is isThereASpaceNextToLocation(x,y). This would return whether or not a space exists next to the location given by the x,y. The button will call this method to determine whether or not it can be clicked.
Finally, you could have a moveLocationToEmptySpace(x,y) which will manipulate the data to put the number at the current location into the empty space. After that, all the buttons should call getTheNumberAtLocation(x,y) to update the number they are showing.
By arranging your code like this you've nicely separated the concern of the UI (show text, handle button clicks) from the concern of maintaining the game state (checking if a move is valid, performing a move, determining the state of the board). Now when you write code it will be easier to write because each method will be responsible for a small, manageable piece of logic.
To summarise:
Gridpane (4x4)
-> Button
-> label [calls GameData.getTheNumberAtLocation]
-> click [calls GameData.isThereASpaceNextToLocation, moveLocationToEmptySpace]
GameData
-> Array (4x4) (private)
-> Integer (1-15)
-> getTheNumberAtLocation(x,y)
-> isThereASpaceNextToLocation(x,y)
-> moveLocationToEmptySpace(x,y)

Is it possible to randomize a single word within a String attribute within an object from an array of possible options?

I'm very new to java and coding in general, so I apologize if this is a simple thing. I want to know if it's possible to add a variable within a string that will be randomized when the item itself is chosen from the ArrayList of options.
I've already created the objects, put them in an ArrayList, and have a method that randomly calls indices from the ArrayList and prints their attributes. However, some (not all) I would like to randomize a part of the "name" attribute from another separate Array. Is there a way to do this? If possible, I'd like it to be randomized each time its called, so in the case that I call that particular object twice from the ArrayList, its "name" attribute would not be identical (unless by chance the same suffix is called from the random name Array twice).
//Doesn't need randomization
Item r1 = new Item("Static Name", 1000);
// (X) needs to be either "Title", "Callsign", or "Identifier"
Item r2 = new Item("Random (X)", 500);
UPDATE:
I followed DevilsHnd's suggestion, but it doesn't seem to replace anything.
//declared in class
String[] suffix = {"Title","Callsign","Nickname"};
//as part of toString()
if (name.contains("(X)")) {
name.replace("(X)", [new Random().nextInt(((suffix.length - 1) - 0) + 1) + 0]);
My toString still prints out "Random (X)" instead of a desired "Random Title".
I am able to get it to work if I remove the if function and use a static value for the replacement, like name = name.replace("(X)","Title");, but I still can't figure out how to get it to replace it with a value from the suffix array.
I'm not sure if I get what you mean but you may get an idea from the following:
String[] attributes = {"Title", "Callsign", "Identifier"};
String itemString = "Random (X)";
if (itemString.contains("(X)")) {
itemString = itemString.replace(
"(X)",
attributes[new Random().nextInt(((attributes.length - 1) - 0) + 1) + 0]
);
}
System.out.println(itemString);
Item r2 = new Item(itemString, 500);

Adding a several random numbers to graphics context above images

I am creating a old school game where the user has to collect the falling objects. Currently I have an image that is printed to the GraphicsContext several times accross the pane and is added and removed from an arrayList() when it disappears off of the screen. I can create a random number and I can print this to the same position as the falling image. However the random number is always the same and I want the number to be different on each of the objects. My code in my start method is as follows:
int i;
for(i=0;i<800; i+=90)
arrayList.add(new Object(ImageView, noOnImage, i,-10));
I then also have an update method where the objects are continously redrawn:
int newObject = 0;
Iterator<Object> objectIterator = object.iterator();
while(objectIterator.hasNext())
{
Object ob = objectIterator.next();
if(ob.move())
{
objectIterator.remove();
newObject++;
}
gc.drawImage(ob.objectImage,ob.r.getX(), ob.r.getY(), ob.r.getWidth(),
ob.r.getHeight());
gc.fillText(String.valueOf(noOnImage), ob.r.getX()+8, ob.r.getY()+22);
}
noOneImage is just a randomly generated number that I declared at the top. I would like each object to contain a different random value, currently they are all the same though, even though it is random.
When you create the object, pass in the random number within your loop.
Random rand = new Random()
arrayList.add(new Object(ImageView, noOnImage, i,-10, rand.nextInt(0, 10)));
That rand will give you a number between 0 and 10. You can put whatever int you want in there.
And make sure the object you create has the field and you are able to retrieve this number (e.g. for a score tally, etc.).

Java update jLabel.setText via for loop

I basically checked out a book from the Library and started learning Java. I'm trying to code a little score calculator for my golf league and this site has been a lof of help! So thanks for even being here!
Now to the question:
I have a 9 labels, created with NetBeans GUI, with names like jLabel_Hole1, jLabel_Hole2, ...
If a user selects the radio option to play the front nine those labels have number 1 - 9 and if they change it to the "Back Nine" then they should display 10 - 18. I can manually set each label to the new value on a selection change but I wanted to know if there was a more elegant way and if so if one of you could be kind enough to explain how it works.
Here is the code that I want to try and truncate:
TGL.jLbl_Hole1.setText("10");
TGL.jLbl_Hole2.setText("11");
TGL.jLbl_Hole3.setText("12");
TGL.jLbl_Hole4.setText("13");
TGL.jLbl_Hole5.setText("14");
TGL.jLbl_Hole6.setText("15");
TGL.jLbl_Hole7.setText("16");
TGL.jLbl_Hole8.setText("17");
TGL.jLbl_Hole9.setText("18");
I've read some things about String being immutable and maybe it's just a limitation but I would think there has to be way and I just can't imagine it.
Thanks.
Basically, rather then creating a individual label for each hole, you should create an array of labels, where each element in the array represents a individual hole.
So instead of...
TGL.jLbl_Hole1.setText("10");
TGL.jLbl_Hole2.setText("11");
TGL.jLbl_Hole3.setText("12");
TGL.jLbl_Hole4.setText("13");
TGL.jLbl_Hole5.setText("14");
TGL.jLbl_Hole6.setText("15");
TGL.jLbl_Hole7.setText("16");
TGL.jLbl_Hole8.setText("17");
TGL.jLbl_Hole9.setText("18");
You would have...
for (JLabel label : TGL.holeLables) {
lable.setText(...);
}
A better solution would be to hide the labels from the developer and simply provide a setter...
TGL.setHoleText(hole, text); // hole is int and text is String
Internally to your TGL class, you have two choices...
If you've used the form editor in Netbeans, you're going to have to place the components that Netbeans creates into your own array...
private JLabel[] holes;
//...//
// Some where after initComponents is called...
holes = new JLabel[9];
holes[0] = jLbl_Hole1;
// There other 8 holes...
Then you would simply provide a setter and getter methods that can update or return the value...
public void setHole(int hole, String text) {
if (hole >= 0 && hole < holes.length) {
holes[hole].setText(text);
}
}
public String getHole() {
String text = null;
if (hole >= 0 && hole < holes.length) {
text = holes[hole].getText();
}
return text;
}
Take a closer look at the Arrays tutorial for more details...
I've never found a Java GUI-generator to provide code that's any good. I may be wrong--there may be a good one, but I always prefer to position and name them myself. So,
/**
* The JLabels for the holes on the golf course.
* <p>
* holeLabels[0][i] are for the outward holes, 1-9.
* holeLabels[1][i] are for the inward holes, 10-18.
*/
private JLabel[][] holeLabels;
/**
* The starts of the outward and inward ranges of holes.
*/
private static final int[] holeStart = {1, 10};
// Later
holeLabels = new JLabel[2][9];
for(final int i = 0; i < holeLabels.length; i++) {
for (final int j = 0; j < holeLabels[i].length; j++) {
holeLabel[i][j] = new JLabel();
holeLabel[i][j].setText(Integer.toString(holeStart[i] + j));
}
}
Interestingly, holeLabels.length is 2. holeLabels is an array of 2 arrays of 9 ints. i goes from 0 to 1, and j goes from 0 to 8, so the text computation works. The reason I did things this way is so you can easily place the labels in an appropriate GridLayout later.

Categories