Minesweeper Java Inheritance - java

I have 5 classes for this project, Button Minefield GUI MenuBar Game.
Button is an individual mine cell.
Minefield contains a 2d array of buttons, and operations that concern all of the buttons.
GUI is the portion above the MineField grid, displaying the reset button, time lapsed and how many flags remain,
Game puts all of the other classes in Panels and places them in the applet. No game logic here.
Here is a screenshot of my applet
I'm having problems when it comes to using inheritance. If I can solve this issue, I can do the other problems too. It has to do with invoking a method in the super class.
One of my problems:
When a Button mine cell is right-clicked, the mouse listener picks it up and changes the text of the JButton to "F" for flag. However, I want to update the counter of how many flags are available, which is a variable in the Minefield class. Finally, I want the GUI class to listen for changes to that variable and update the JLabel.
In the MouseListener for Button:
if (e.getButton() == MouseEvent.BUTTON3)
{
advanceCurrentState();
if (currentState == "FLAG")
super.setNumFlagsRemaining(-1); //update the Minefields variable
}
Back in Minefield:
public void setNumFlagsRemaining(int delta)
{
numFlagsRemaining += delta;
}
But this doesn't work. When I am debugging, super.setNumFlagsRemaining(-1) is creating a new instance of Minefield and I cannot update the variable inside the super class. I thought that it would update the existing object of Minefield, but I read that Java does not pass by reference, so I was confused as how to do it. If you need to see additional code please say so, I tried to not clutter this post with 5 whole classes and say, "fix it".

You do not provide enough code so I can only guess here.
I think you are confused with key word super
It actually mean to call method from the super class which you had inherited.
I doubt that JButton inherits anything from your class Minefield. Usually it is in opposite way.
Also count of the fields is stored and displayed in the JLabel. So you, actually, have to call method of the class which has this JLabel and takes care of total count.

Related

ActionListener and dynamic(?) GUI

I've read through a dozen or so actionlistener/loop related questions here, but I'm not sure I've found my answer. I started on my first large Java project, a text RPG that's spiraled into around 5K lines of logic and game features which was functioning as intended using just the console - when I decided I'd try to build a Java swing GUI for it instead. Here's my problem:
I use a Room object which handles the description of where the player is at and also has an array of options for the player to choose next which it creates dynamically based on what cell the room's id is in on a csv file and what is beside it. I stopped outputting this to the console and instead started creating JButtons based on the options array like so:
public void showNarrate(){
add(dd,gridConstraints);
optionCopy.clear();
int i = 0;
for(JButton j : optionButtons){
//adding and formatting buttons to gridBagConstraint I also set actionCommand for each button to the triggerValue (ID of the next room which the button should take the player to)
}
//I tried using a copy of my JButton array here so I could have something to iterate over in actionListener after clearing out the original
//(Since it needs to be cleared so the next Room's buttons can be built after the player chooses an option)
for(JButton j : optionButtons){
optionCopy.add(j);
}
optionButtons.clear();
//dd is a seperate drawingComponent I used for outputting room descriptions which may be totally unnecessary at this point :/
dd.repaint();
setVisible(true);
}
Over in actionlistener (Same class) this is how I tried to swing it:
for(JButton j : optionCopy){
if(e.getActionCommand().equals(j.getActionCommand())){
Main.saveRoom = Main.currentRoom;
Main.currentRoom = j.getActionCommand();
System.out.println(Main.currentRoom);
}
}}
Then in my main class I call:
narrator.narrate(currentRoom, saveRoom); which takes care of some other logic concerning locked doors, encounters, etc.
Also in Main loop are some other methods related to autosave and tracking which rooms the player has visited. I know from other q/a i'v read on here that this is all pretty bad design, and I'm sttarting to understand that now, but my issue is this:
The first room of the game loads up fine, when I click a button it outputs to console(Just for testing) the correct trigger value of the room the button should be calling, so I'm getting that far, but how can I call the same method over again now?
-If I call narrate from actionListener it will wind up calling itself again and complain about ConcurrentModification.
-If I try to keep a loop going in my Main class it will keep looping and won't allow for the player to actually choose a button.
I've never used threads before, which I wonder might be the answer,and the closest thing to a related answer I've found is this:
Java: Method wait for ActionListener in another class
but I don't think moving actionListener to Main class would resolve my problem which is actionListener winding up calling itself recursively. And as for the observer-observable pattern... I just can't understand it :(
I appreciate any and all help, I've learned a LOT trying to make this thing work without seeking help as much as possible but this has stumped me.
Your loop in actionPerformed only checks whether a JButton exists in your optionList with the given actionCommand. However this can be done before actually doing something:
boolean contained = false;
for (JButton j : optionButtons)
if (j.getActionCommand().equals(e.getActionCommand()))
contained = true;
if (contained) {
// change room
}
now you can call narrate because you have finished iterating over the collection beforehand and will not get a ConcurrentModificationException

Can't change/modify button background from another method - JAVA

I have a problem about modify button background. I am using netbeans gui builder for build form. I am trying change button background when the second frame is open and turn it back when second frame close.
public void update(boolean x){
if(x==true){
circleButton.setOpaque(true);
circleButton.setBackground(new java.awt.Color(0, 0, 0));
System.out.println("testoutput");
}
}
this is my update method from first class.
I added window listener to second frame.
private void formWindowOpened(java.awt.event.WindowEvent evt) {
isitopen = true;
//this is first class which includes button
homework hwork = new homework();
hwork.update(isitopen);
System.out.println("testoutput2");
}
I got 2 testoutput but color of the button didn't change.
What can i do to fix this issue ?
You're creating a new homework object in your formWindowOpened(...) method, one completely unrelated to the homework object that is displayed, and changing the state of the new object will have no effect on the displayed one.
A simple and WRONG solution is to use static fields or methods.
Instead one simple solution is to give the calss with your formWindowOpened(...) method a valid reference to the displayed homework object, something that can be done with a constructor parameter or a setHomework(...) method.
A much better and even simpler solution:
Make the 2nd window a modal JDialog, not a JFrame
This way homework will know when the window is open and can set its own button colors. When the 2nd window opens, program flow in the calling class is put on hold, and only resumes when the 2nd window closes -- just like using a JOptionPane.
For more on this, please see The Use of Multiple JFrames, Good/Bad Practice?
As an aside, you will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.

How to access local variables in anonymous inner actionListener class and actionPerformed method?

I am working on a project for a CS class, so I cannot post any code, but I will try my best to describe what setup I have. The program is supposed to have 3 separate JPanels, each with an image and buttons to rotate and reset the image. A Driver class was provided that sets up the JFrame, creates a single Project object to pass around to other classes (this Project class contains the methods for rotating and combining the images), and has the main method.
What I've done is create a class that extends JPanel to setup a JPanel with the image, file name, and rotate/reset buttons. I have the constructor for this class taking in the number of the panel (to keep up with writing the image number in the panel), the image file to display, and the Project object that was created in the Driver class (to be able to access the methods for manipulating the images). I immediately call super(); and then set up the file name and image (as a JLabel) and buttons as (JButtons).
This is where my problem comes in though. I'm trying to set up the Rotate button, so I created an anonymous inner class action listener and actionPerformed method. What I planned on doing was using the Project object reference to call the rotate method on the image object, having it return a BufferedImage into a modifiedImage BufferedImage. Then remove the JLabel with the original image, add the modifiedImage as a JLabel, revalidate, and repaint. However, I cannot use the this reference or the reference to the Project object within the inner actionPerformed class.
How do I gain access to these references within the actionperformed inner class? or is my setup completely awful? Please bear with me- it's my first time working with any kind of GUI.
Make your reference to Project object final. It will solve the problem and does not make any harm as you are not going to assign it again.

Java: Cannot Cast to Custom Class

I am creating a Tic-Tac-Toe game in which a square in the grid is represented by a class called Square which I created. It extends JButton, but I added a boolean field called pressable which states whether or not the button can be pressed in-game. If the button already has a letter, then it cannot be pressed. I want to implement code in my actionPerformed() method that will check the pressable variable, and if pressable is false, it will not change the letter of the square. I am using the getSource() method on my ActionEvent to give me a reference to the square pressed. Therefore, I need to cast the Object to type Square so that I can access its pressable field. But when I do this, I get the following error: java.lang.ClassCastException: javax.swing.JButton cannot be cast to tic.tac.toe.Square This makes no sense to me. Before I needed each square to have a pressable field, I used a JButton, which worked just fine. But since Square inherits JButton, I would think that it would work as well. How can I fix this?
The JVM is telling you the truth: the object returned by getSource() is in fact a JButton and is not a Square object, despite your statements above. So the fact is, you are adding your ActionListener to a JButton and not to a Square object. You will need to inspect your code to see why this is so. If you need more of our help, you'll need to show this code.
Edit
You state:
I looked into it and realized that my "Start" button was going through the same process, which is where the error came from.
Thank you for the update.
This suggests that you're using one ActionListener for all buttons, which you'll not want to do. Certainly all the tic-tac-toe buttons can use the same listener, but any others should use there own separate listener object, perhaps via an anonymous inner class.
You could disable the JButton the first time it is clicked with .setEnabled(false) which would get around this issue. But I agree with HovercraftFullOfEels.

Black Jack with GUI, add objects to main frame from ActionListener in another class

I made a Black Jack version with a gui. My problem is that to much of the implementation is in the same class that creates the window. The Class GameWindow both initilizes JFrame, adds visual objects like card icons, and text are stored to JLabels and then adds them to different JPanels.
Thats fine, but GameWindow (which implements ActionListener) also adds ActionListener to the buttons (which are simple JButtons not created classes), and implements the ActionPerformed.
I would like to create one class for each button, like "Class Deal implements ActionListener", and then let the class deal with the ActionPerformed(ActionEvent e). The problem is how can I add objects to GameWindow, from this other class?
And how do I send the Deck, Player(Score and Cards, stored in ArrayList) and Bank(Score and Cards), objects to the ActionPerformed in respective class (Deal, Stay and Hit)?
I didnĀ“t want to post the code cause its alot and since I tried different solutions is a bit of a mess right now, but if you would want me to post any part of the code or all of it just tell me.
edit, thought it was to little text ;)
The classes I use right now, are
CardDeck, has an ArrayList and methods like drawCard(), shuffle() etc.
Card, has an ImageIcon and an int that holds its value.
GameWindow extends JFrame implements ActionListener, initilizes the JFrame, and also deal with the ActionPerformed associated with JButtons Deal, Hit and Stay (this is what I want to change).
Player, holds the player cards that are drawn in an ArrayList, and the score as an int
Bank, same as player but for the ai.
Main, executes GameWindow.
Divide and conquer. You need a GameEngine class, which holds data and provides methods to manipulate it. You need a separate GameWindow which deals with displaying the game but relies on GameEngine to hold data and actually run the game. The ActionListners need a reference to the GameEngine, and that's all; everything else they can do by calling methods on that.
The GameEngine itself may internally work with other classes: Deck, Card, etc. Try to make each class represent one well defined concept. Keep code near the data it uses.

Categories