Minesweeper, how can i work on cells - java

I would like to create a minesweeper game. Firstly, this will work on buttons. I think I will work on two dimensional array, and there will be like boolean array that will present where are bombs, for example if booleanArray[0][4] is true, there is a bomb.
Now, how can I implement this in my buttons? I can set Names on these buttons, and then if I click some button, then I will get the name from this div. For example when i click first button, i will get "00" name, then i will get first letter "0" and second letter "0" and parse it to int. And this will be the indexes from my previous booleanArray, in this case it will be booleanArray[0][0].
So, can I do this another, better way, instead of that?
This is the way I will be creating the buttons:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
JButton button = new JButton("");
button.setPreferredSize(new Dimension(50, 50));
button.setName(Integer.toString(i) + Integer.toString(j));
}
}
EDIT
I will have a two dimensional Array, that will reflect my buttons:
and now, how can I check if I hit the bomb after I click for example in the first button?

Just hold a two dimensional array of buttons,
JButton[][] myButtons = new JButton[10][10];
which you use to draw them and they all call the same method with their value
for (int x=0; x<10; x++){
for (int y=0; y<10; y++){
myButtons[x][y] = new JButton("0");
//add to page, or do it elsewhere
myButtons[x][y].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
selectionButtonPressed(x,y);
}
});
}
}
Then a call to yout method selectionButtonPressed() will tell you what button has been pressed, you can take action and even make changes to the button with myButtons[x][y].whatever()

That is one way but you should create the String of the name by using something like:
button.setName(i + ":" j);
This will make it easier to parse out the two values as you can just use the String.split(...) method.
Another option might be to create a HashTable with the JButton as the key and then use a Point object (representing the row/column) as the value Object of the HashTable. Then you just use the get(...) method of the HashMap to retrieve the Point for the clicked button.
Another option is to extend JButton and add two parameters (row, column) when creating the button. Then you also add getRow() and getColumn() methods.
Either of this approaches will keep the logic simple and you only need to create a single ActionListener to be used by all the buttons.

Related

How do I modify 100 objects without having to write 100 lines of code? (Java)

I have a lot of JButton objects which have the names a, b, c, d, ...
I want to set all of their states according to a boolean array I have. For example, if the boolean array is [true, false, true], I want to set a's state to true, b's state to false, and c's state to true. (using JButton.setEnabled(boolean))
The problem is that I have too many objects and if I have to change their states one by one, the code is going to get long and redundant.
How do I do this in a simple way?
I'm programming in Netbeans, Java with Ant, JFrame Form.
Edit) Netbeans won't let you change the code that creates the objects.
So "private javax.swing.JButton a" this part is unchangeable.
Having that many individual JButtons seems like something you should try to avoid at all costs, especially if you have scenarios when you need to address them all, but if you are stuck with that you could do this:
JButton a = new JButton();
JButton b = new JButton();
//Etc for all the buttons you make
JButton[] list = {a,b}; //Manually insert the JButtons into an array
for(int i=0; i < list.length; i++) //For loop through all of the buttons in the list
{
list[i].addNotify(); //Then just use list[i] and that will be whatever JButton is at index i in the list (so in my example, i=0 is button a, i=1 is button b)
}
In the code above you insert all of your buttons into an array and then do the same function like I showed, where I called the .addNotify() function on every button in the list.
If you do have the opportunity to start from scratch and this would make things easier, I suggest putting all of the buttons into an array to begin with, such as the code below:
JButton[] list = new JButton[10]; //Manually insert the JButtons into an array
for(int i=0; i < list.length; i++) //For loop through all of the buttons in the list
{
list[i] = new JButton();
list[i].addNotify(); //Then just use list[i] and that will be whatever JButton is at index i in the list (so in my example, i=0 is button a, i=1 is button b)
}
Arrays are especially useful for these scenarios where you have a lot of objects of the same type and have the same operations done to them, so based on your description it might be a good application

How to give each JButton in a 10 x 10 grid button layout a unique ID/name

I am trying to give each JButton from a 10 x 10 button layout (so 100 buttons) each unique name or ID or number so I can call them later. I made an ArrayList because that's what some other person did.
public ArrayList<JButton> myList;
//Some other code
for(int row = 0; row < 10; row++)
{
for(int col = 0; col < 10; col++)
{
button = new JButton();
button.addActionListener( al );
myList.add(button);
for(JButton button : myList)
button.setText("");
panel_1.add(button);
}
}
The program compiles but it doesn't run. It's showing error at
myList.add(button);
It's a null pointer exception apparently.
but I don't know why. Is it not adding the buttons to the ArrayList? Also how do I give each button a unique name or string?
The program compiles but it doesn't run. It's showing error at
The ArrayList is null because you didn't create an ArrayList object.
The code should be:
private ArrayList<JButton> myList = new ArrayList<JButton>();
Also how do I give each button a unique name or string?
There is no need to give the button a unique name. Its unique name is the "index" used to access the JButton in the ArrayList.
You probably don't even need the ArrayList.
Normally you add an ActionListener to the button. Then you can just use the getSource() method of the ActionEvent to get the reference to the button.

Deep copies of 2d object array

how can I make on a button press a new deep copy of a 2 dimensional array?
Basically I created a game field with buttons. The game is called sokoban and it's a puzzle. The player is moving from one button to the other with arrow keys on a fixed map (8x8 buttons).
I want to implement an undo function. So I thought that I just create a deep copy of the JButton array before each move and save it into a stack. So when I press the undo button it calls the pop function of my stack. The problem is that I need to declare and initialize another JButton[][] where I can save the game field to before each move. Since I want infinite possible moves and also undos it seems impossible to me. I can't declare and initalize infite diffrent JButton[][] arrays. Any idea on how I can solve that?
That's how I copy a 2d object array:
JButton[][] tempArray = new JButton[jbArray.length][jbArray[0].length];
for (int i = 0; i < getJbArray().length; i++) {
for (int j=0;j<getJbArray()[0].length;j++) {
tempArray[i][j]=jbArray[i][j];
}
}
movesStack.push(tempArray);
Unfortunately you can't clone swing components in general, as they do not implement the Cloneable interface. As I see it you have two options:
Create a new JButton inside your double loop and copy whatever properties (like alignment, color etc.) you have set to the new JButton
Write your own class that extends JButton and implement the Cloneable interface
The first way is somewhat of a hack and not very robust or reusable. The second way is much better practice. In this case you'll have to define how the deep copy is supposed to happen, and ensure that all relevant properties are copied over.
You've got the right idea. You're not quite going deep enough.
public JButton[][] copy(JButton[][] jbArray) {
JButton[][] tempArray = new JButton[jbArray.length][jbArray[0].length];
for (int i = 0; i < jbArray.length; i++) {
for (int j = 0; j < jbArray[0].length; j++) {
tempArray[i][j] = new JButton(jbArray[i][j].getText());
}
}
return tempArray;
}
Rather than copying JButtons, you should have a model that you use to set the JButtons. Maybe a ModelClass[][] array?

How do I get input from buttons I created using a loop?

I'm trying to make a simple calculator in Java using Swing, and I've created my buttons the following way:
//Our number keypad
public static JPanel numbers(){
//our panel to return
JPanel panel = new JPanel();
//Create and add 3x4 grid layout to panel
GridLayout gl = new GridLayout(3, 4);
panel.setLayout(gl);
//For creating and adding buttons to panel
for(int i = 0; i < 10; i++){
//Create a new button where the name is the value of i
String name = "" + i + "";
JButton button = new JButton(name);
//add action listener
button.addActionListener(handler);
//Add button to panel
panel.add(button);
}
return panel;
}
My question is how do I reference each specific button in my event handler? I can't think of a way to do this without having to manually create each button rather than using a loop.
Thanks.
In your listener, call event.getSource(), and that will return the button which has been pressed. Get the text of the button, and you have its number.
Or create a different instance of your handler for every button, and pass the value of the button (i) to the constructor of the handler. This last solution is cleaner, IMO, because it doesn't depend on the text of the button. If you replaced the text by an image, for example, the first technique wouldn't work anymore.
You can distinguish created buttons by adding the following inside handler:
String buttonText = ((JButton) e.getSource()).getText();
if (<text1>.equals(buttonText)){
//do the stuff
} else if (<text2>.equals(buttonText)){
//do the stuff
} else {
//do the stuff
}
Method #1: go through the child components of the parent JPanel (quite tedious, has to be rebuilt every time you modify the contents of that JPanel). Make sure they're JButtons by using an if . . instanceof clause.
Method #2: as you create them in that loop, add them to a List (or even better, a Map). I prefer a Map personally as it lets me customise the key for that specific JComponent
i.e.
HashMap<String, JComponent> buttonList = new HashMap<String, JComponent>();
for(. .) {
buttonList.put("nameForEachButton", button);
}
I recommend generating the button name based off of the loop counter. Either use your existing name value, or just set it to "button" + i;
Declare your buttons using an array.
JButton[] button = new JButton[9]; //outside the for loop
for (int i = 0; i < 10; i++) {
//put your code
button[i] = new JButton(name);
//your code
}

Initialize reference variables for many objects?

I'm having a little trouble building the grids for a Battleship game for my Java class. So far, I can easily make a for loop to add JPanel or JButton objects to the JFrame. However, my issue is that I'll need to use those Panels or Buttons again when playing the game (such as clicking on a button to see if your opponent put a ship on that square, et cetera). Is there a simple way in Java to initialize reference variables for a LOT of objects? Or will I have to declare all of them individually?
You could try a multi dimensional array of JPanels (or any other object). Create an array with the same size as your grid. The line below initializes an array with 5 rows and 5 columns.
JPanel[][] battleField = new JPanel[5][5];
Use nested for loops to create the panels in the array.
for (int rowIndex = 0; rowIndex < battleField.length; rowIndex++)
{
for (int cellIndex = 0; cellIndex < battleField[rowIndex]; cellIndex++)
{
battleField[rowIndex][cellIndex] = new JPanel();
}
}
If you want to reference the battleField array later on you would just make it into a instance variable.
For a battleship game, you most likely want to retrieve the location of a button after is has been clicked. You can create a hashtable using your buttons as keys and the point it is located at as a value.
HashMap<JButton, Point> buttonMap = new HashMap<JButton, Point>();
for (int x = 0; x < COLUMNS; x++)
{
for (int y = 0; y < ROWS; y++)
{
JButton btn = new JButton();
btn.addActionListener(this);
buttonMap.put(btn, new Point(x, y));
//then add the button to your container
}
}
The in your actionPerformed method you can convert the button to the point it is located at like this.
JButton btn = (JButton)actionEvent.getSource();
Point p = buttonMake.get(btn);
Of course you will need to properly handle error conditions such as source not being a button or the button not being in the map...
You can always extend JButton to keep track of the info you need. A simple example:
class MyButton extends JButton{
private MyGameInfo mygameInfo;
private int buttonId;
//More fields....
//Getters/Setters
}
Then instead of creating and adding JButton objects to your layout, create MyButton objects(which is also a JButton so your layout will not be effected) and use its extra functionality for your game logic.
For reference, here is a related matching game that uses a grid of buttons. This related answer demonstrates the application of the Model–View–Controller pattern to a simple game.

Categories

Resources