i have a problem with a grid i created. the buttons of this smallerGrid will not appear until i hover over them with the mouse.
each smallerGrid consists of a 3x3 grid which fits into a biggerGrid also 3x3 grid that conatins the smaller grids.
that is a brief explanation of how i am constructing the sudoku grid.
You will find the code below.
Thank you in advance.
import java.awt.*;
import javax.swing.*;
public class MyGridLayout {
private int filledFields = 0;
private JFrame mainFrame;
private JPanel panelForSolvingButton;
private JPanel smallerGridPanel;
private boolean solvingButtonAppeared = false;
SudokuCell[][] biggerGrid = new SudokuCell[10][10];
MyGridLayout() {
mainFrame = new JFrame("sudoku-solver");
mainFrame.setLayout(new BorderLayout());
smallerGridPanel = new JPanel(new GridLayout(3, 3));
mainFrame.add(smallerGridPanel, BorderLayout.CENTER);
panelForSolvingButton = new JPanel();
panelForSolvingButton.setLayout(new FlowLayout(FlowLayout.RIGHT));
mainFrame.add(panelForSolvingButton, BorderLayout.SOUTH);
mainFrame.pack();
mainFrame.setSize(600,600);
mainFrame.setLocationRelativeTo(null);
mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainFrame.setResizable(false);
addRegularButtons();
}
void addRegularButtons() {
int currentCol = 0;
int currentRow = 0;
int smallerGridFirstCol = 0;
int firstRowOfLayer = 0;
for (int layerOfGrids = 0; layerOfGrids < 3; ++layerOfGrids) {
for (int gridOfLayer = 0; gridOfLayer < 3; ++gridOfLayer) {
JComponent smallerGrid = new JPanel(new GridLayout(3, 3));
smallerGrid.setBorder(BorderFactory.createLineBorder(Color.BLACK));
smallerGridPanel.add(smallerGrid);
for (int j = 0; j < 3; ++j) {
for (int k = 0; k < 3; ++k) {
var cell = new SudokuCell(currentRow, currentCol);
smallerGrid.add(cell);
biggerGrid[currentRow][currentCol++] = cell;
cell.addActionListener(new CellActionListener(this));
}
currentRow++;
currentCol = smallerGridFirstCol;
}
smallerGridPanel.revalidate();
currentRow = firstRowOfLayer;
smallerGridFirstCol += 3;
currentCol = smallerGridFirstCol;
}
firstRowOfLayer += 3;
currentRow = firstRowOfLayer;
smallerGridFirstCol = currentCol = 0;
}
mainFrame.revalidate();
mainFrame.setVisible(true);
}
// checking if the solving process can begin
// (filled fields must at least reach 17)
void makeSolveButtonAppear() {
JButton solveButton = new JButton();
solveButton.setBackground(Color.white);
solveButton.setFont(new Font("Arial", Font.PLAIN, 20));
solveButton.setOpaque(false);
solveButton.setText("Solve ?");
panelForSolvingButton.add(solveButton);
}
public boolean isSolvingButtonAppeared() {
return solvingButtonAppeared;
}
public void setSolvingButtonAppeared(boolean solvingButtonAppeared) {
this.solvingButtonAppeared = solvingButtonAppeared;
}
public int getFilledFields() {
return filledFields;
}
public void setFilledFields(int filledFields) {
this.filledFields = filledFields;
}
public JPanel getPanelForSolvingButton() {
return panelForSolvingButton;
}
public static void main(String[] args) {
var gridLayout = new MyGridLayout();
}
}
package mainFrame;
import java.awt.*;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;
public class SudokuCell extends JButton {
private int x;
private int y;
public SudokuCell(int x, int y) {
this.x = x;
this.y = y;
setBackground(Color.white);
setOpaque(true);
setFont(new Font("Arial", Font.PLAIN, 20));
}
#Override
public int getX() {
return x;
}
#Override
public int getY() {
return y;
}
}
package mainFrame;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class CellActionListener implements ActionListener {
private int clicked = 0;
MyGridLayout currentGrid;
CellActionListener(MyGridLayout currentGrid) {
this.currentGrid = currentGrid;
}
#Override
public void actionPerformed(ActionEvent e) {
if(clicked ==0) currentGrid.setFilledFields(currentGrid.getFilledFields()+1);
//clicked (number of clicks) must remain between 0 and 9
clicked = (clicked % 9) + 1;
((JButton) e.getSource()).setText(Integer.toString(clicked));
//first click on the button means an entry has been made
//which means one less needed filledField out of 17
if(!currentGrid.isSolvingButtonAppeared() && currentGrid.getFilledFields() >= 17) {
currentGrid.makeSolveButtonAppear();
currentGrid.setSolvingButtonAppeared(true);
}
}
}```
Related
im trying to make a Sudoku game and I want to change the background color of the same box, same column and same row when I click on a JTextField. I'm trying to add multiple Mouse Listener, one for each JTextField but It doesnt work. I'm now testing changing the background color of just the JTextField that I click on.
The main problem is in here.
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Panel extends JPanel {
public static final int ROWS = 3;
public static final int COLUMNS = 3;
public static JTextField[][] fields = new JTextField[ROWS * COLUMNS][ROWS * COLUMNS];
for (int i = 0; i < ROWS*COLUMNS; i++) {
for (int j = 0; j < ROWS*COLUMNS; j++) {
fields[i][j] = new JTextField();
int finalI = i;
int finalJ = j;
fields[i][j].addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
fields[finalI][finalJ].setBackground(Color.BLUE);
}
});
}
}
}
I have also try with this but it doesn't work.
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Panel extends JPanel {
public static final int ROWS = 3;
public static final int COLUMNS = 3;
public static JTextField[][] fields = new JTextField[ROWS * COLUMNS][ROWS * COLUMNS];
for (int i = 0; i < ROWS*COLUMNS; i++) {
for (int j = 0; j < ROWS*COLUMNS; j++) {
fields[i][j] = new JTextField();
addMouseActions(i, j);
}
}
private void addMouseActions(int row, int col){
fields[row][col].addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
fields[row][col].setBackground(Color.BLUE);
}
});
}
}
Here it's the full code that I have for the Panel class.
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Panel extends JPanel {
static String[] levels = {"Easy", "Medium", "Hard"};
public static final JComboBox<String> levelsBox = new JComboBox<>(levels);
private final JButton playButton = new JButton("Play");
private final JButton checkButton = new JButton("Check");
private final JButton hintButton = new JButton("Hint");
private final JButton solveButton = new JButton("Solve");
private final JButton exitButton = new JButton("Exit");
public static final int ROWS = 3;
public static final int COLUMNS = 3;
public static JTextField[][] fields = new JTextField[ROWS * COLUMNS][ROWS * COLUMNS];
public Panel(JFrame frame) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(600, 200);
frame.setLayout(new BorderLayout());
frame.add(new SudokuBoard());
frame.add(new MenuPane(), BorderLayout.AFTER_LINE_ENDS);
frame.pack();
frame.setVisible(true);
}
});
}
public class MenuPane extends JPanel {
public MenuPane() {
setBorder(new EmptyBorder(4, 4, 4, 4));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.weightx = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
JLabel diff = new JLabel("Select the difficulty: ");
diff.setFont(new Font("SansSerif",Font.BOLD,18));
add(diff, gbc);
gbc.gridx++;
levelsBox.setFont(new Font("SansSerif",Font.BOLD,16));
add(levelsBox,gbc);
gbc.gridy++;
playButton.setActionCommand("Play");
add(playButton, gbc);
gbc.gridy++;
checkButton.setActionCommand("Check");
checkButton.setEnabled(false);
add(checkButton, gbc);
gbc.gridy++;
hintButton.setActionCommand("Hint");
hintButton.setEnabled(false);
add(hintButton, gbc);
gbc.gridy++;
solveButton.setActionCommand("Solve");
solveButton.setEnabled(false);
add(solveButton, gbc);
gbc.gridy++;
exitButton.setActionCommand("Exit");
add(exitButton, gbc);
}
}
public static class SudokuBoard extends JPanel {
private SubBoard[] subBoards;
public SudokuBoard() {
setBorder(new EmptyBorder(30, 30, 30, 10));
subBoards = new SubBoard[ROWS * COLUMNS];
setLayout(new GridLayout(ROWS, COLUMNS));
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
int bigIndex = (row * COLUMNS) + col;
int index = (row * ROWS) + col;
SubBoard board = new SubBoard(bigIndex);
board.setBorder(new LineBorder(Color.GRAY, 3));
subBoards[index] = board;
add(board);
}
}
}
}
public static class SubBoard extends JPanel {
public SubBoard(int bigIndex) {
setLayout(new GridLayout(ROWS, COLUMNS));
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
int index = (row * COLUMNS) + col;
JTextField field = new JTextField();
field.setPreferredSize(new Dimension(60, 60));
field.setHorizontalAlignment(JTextField.CENTER);
field.setFont(new Font("SansSerif", Font.BOLD, 25));
field.setDocument(new JTextFieldLimit(1));
//field.setEditable(false);
fields[bigIndex][index] = field;
add(field);
}
}
}
}
public void addListeners(Controller controller) {
playButton.addActionListener(controller);
checkButton.addActionListener(controller);
hintButton.addActionListener(controller);
solveButton.addActionListener(controller);
exitButton.addActionListener(controller);
for (int i = 0; i < ROWS*COLUMNS; i++) {
for (int j = 0; j < ROWS*COLUMNS; j++) {
fields[i][j] = new JTextField();
int finalI = i;
int finalJ = j;
fields[i][j].addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
fields[finalI][finalJ].setBackground(Color.BLUE);
}
});
}
}
}
public void enableButtons(boolean enabled){
checkButton.setEnabled(enabled);
hintButton.setEnabled(enabled);
solveButton.setEnabled(enabled);
}
}
And this is the Controller Class that I'm using for Actions Events.
import pkgClient.MyClient;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Objects;
public class Controller implements ActionListener {
Panel panel;
JFrame frame;
public Controller(Panel panel, JFrame frame) {
this.frame = frame;
this.panel = panel;
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equalsIgnoreCase("Play")){
String level = Panel.levelsBox.getItemAt(Panel.levelsBox.getSelectedIndex());
if(Objects.equals(level, "Easy")){
MyClient.out.println("easyMode");
}else if(Objects.equals(level, "Medium")){
MyClient.out.println("mediumMode");
}else if (Objects.equals(level, "Hard")){
MyClient.out.println("hardMode");
}
panel.enableButtons(true);
Panel.fields[0][0].setBackground(Color.WHITE);
} else if(e.getActionCommand().equalsIgnoreCase("Check")){
System.out.println("Comprobar");
MyClient.out.println("check");
panel.enableButtons(false);
}else if(e.getActionCommand().equalsIgnoreCase("Hint")){
System.out.println("Pista");
MyClient.out.println("hint");
} else if(e.getActionCommand().equalsIgnoreCase("Solve")){
System.out.println("Resolver");
MyClient.out.println("solve");
panel.enableButtons(false);
} else if(e.getActionCommand().equalsIgnoreCase("Exit")) {
frame.dispose();
MyClient.out.println("exit");
}else if(e.getActionCommand().equalsIgnoreCase("Text")) {
System.out.println("hola");
Panel.fields[0][0].setBackground(Color.BLACK);
}else{
System.err.println("Error: unexpected event");
}
}
}
Is there any way to set an unique Mouse Event to every single JTextField like I do with buttons and Actions in the Controller Class? Or how do I have to do it?
Thank you.
I finally could solve the problem, I just needed to use a FocusListener instead of a MouseListener. I can change the background color of a field int the FocusGained(FocusEvent event) method and each JTextField has an independent event. I can know which JTextField is being clicked with event.getComponent() inside of the FocusGained method.
I'm making a Battleship game using one board. The picture below shows how the board GUI should look. My current code sets up a board without the 'menu-layer'. (see picture)
I tried doing this using Swing GUI designer in Intellij and got the following form (see picture), but can't find a way to insert these buttons inside the panel. Currently, I have got the following code.
package BattleshipGUI;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class BoardFrame extends JFrame {
//variables
Ships ship = new Ships();
static final Color colorHit = Color.red;
static final Color colorNormal = Color.gray;
static final Color colorWater = Color.blue;
static final Color colorCarrier = Color.yellow;
static final Color colorBattleship = Color.BLACK;
static final Color colorSubmarine = Color.magenta;
static final Color colorDestroyer = Color.white;
int[][] map;
private Container contents;
int cols;
int rows;
boolean equalPoints;
Player p1 = new Player();
Player p2 = new Player();
private JPanel mainPanel; // I tried using the GUI swing designer, but I cant manage to create
//a menu-layer on top of the buttons
private JButton buttonHighScores;
private JButton quitGame;
private JLabel player1Points;
private JLabel player2Points;
private JLabel playerTurn;
JButton[][] tiles = new JButton[100][100]; // I create 100*100 buttons, but only assign the right
// number to them
public void setMap(int[][] map) {
this.map = map;
}
public void SetFrame(int r, int c) {
this.rows = r;
this.cols = c;
}
public BoardFrame(int r, int c) {
super("Battleship");
setSize(400,450); // I create a frame
this.setLayout(new GridLayout(r, c)); // I set the layout depending on the number of rows and
//columns
AttackHandler attackHandler = new AttackHandler(); // action event class
p1.turn = true; // player 1's turn is true, he commences
p2.turn= false; //player 2's turn is false
for (int i =0; i<r; i++) {
for (int j =0; j <c; j++) {
tiles[i][j] = new JButton(); // this is where all the buttons are declared
tiles[i][j].setBackground(colorNormal);
add(tiles[i][j]);
tiles[i][j].addActionListener(attackHandler);
}
}
setResizable(true);
setLocationRelativeTo(null);
setVisible(true);
setDefaultCloseOperation(this.DISPOSE_ON_CLOSE);
setSize(400,450); //the size of my frame
}
public class AttackHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (source == tiles[i][j]) {
isHit(i, j);
return;
}
}
}
}
}
public void isHit(int row, int col) {
// the map consists of an 2D array
//where 0's represent the water, 1's represent the tiles that are
//already hit, and the other represent the ships
if (AllHit()) {
JOptionPane.showMessageDialog(null, "All Ships Destructed!");
setWinner();
String winner =DecideWinner();
JOptionPane.showMessageDialog(null, winner+" has won!", "Winner",
JOptionPane.PLAIN_MESSAGE);
int again = JOptionPane.showConfirmDialog(null, "Play Again", "Play
Again",JOptionPane.YES_NO_OPTION);
if (again==0){
Main.main(null);
}
dispose();
}
else if (map[row][col] == 5) {
AddPoint(p1.turn, 5); // this should add points to the player that
//has the turn
tiles[row][col].setBackground(colorCarrier);
map[row][col] = 1;
} else if (map[row][col] == 4) {
AddPoint(p1.turn, 4);
tiles[row][col].setBackground(colorBattleship);
map[row][col] = 1;
} else if (map[row][col] == 3) {
AddPoint(p1.turn, 3);
tiles[row][col].setBackground(colorSubmarine);
map[row][col] = 1;
} else if (map[row][col] == 2) {
AddPoint(p1.turn, 2);
tiles[row][col].setBackground(colorDestroyer);
map[row][col] = 1;
} else if (map[row][col] == 1) {
System.out.println("Already Hit!");
} else if (map[row][col] == 0 || map[row][col] == 9) {
tiles[row][col].setBackground(colorWater);
map[row][col] = 1;
}
p1.changeTurn(p1.turn); // every click, the turn of each player should
//switch from true to false, p1 starts with value
//true, and p2 with false
p2.changeTurn(p2.turn);
System.out.println("Points Player 1: "+p1.points);
System.out.println("Points Player 2: "+p2.points);
}
public boolean AllHit() { // if all ships are hit, a message pops up
boolean allHit = true;
for (int i = 0; i<rows;i++) {
for (int j = 0; j < cols; j++) {
if (map[i][j] != 1 && map[i][j] != 0) {
allHit = false;
break;
}
}
}
return allHit;
}
public void AddRandomShips(int rows, int cols) {
int[][] map = ship.setRandomShips(rows, cols);
setMap(map);
}
public void AddShipsNotRandom(int size, int[][] coordinates){
int[][] map = ship.PlaceShips(size, coordinates);
setMap(map);
}
public void ScoreMethod(boolean scoreMethod){
if(scoreMethod){
equalPoints = true;
}
else if(!scoreMethod){ // the second method adjusts the score
//for the second player because the first player
//is more likely to hit a ship
equalPoints = false;
}
}
public void AddPoint(boolean turn,int amount){
if (turn){
p1.points = p1.points+ amount;
}
else p2.points = p2.points+amount;
}
public void setWinner(){
if(p1.points>p2.points){
p1.setWon();
}
else p2.setWon();
}
public String DecideWinner(){
if (p1.won == true){
return "Player 1";
}
else return "Player 2";
}
}
This is how the GUI should look like:
This is what my code generates:
this is the for that I designed using Intellij's Swing Designer (the panel with 'buttons' should be filled with the JButtons I created in the code):
UPDATE :
Thanks to mr. Kroukamp, I was able to add a menu-overlay. The code looks like this:
package BattleshipGUI;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import java.awt.Dimension;
public class BoardFrame extends JFrame {
//variables
Ships ship = new Ships();
static final Color colorNormal = Color.gray;
static final Color colorWater = Color.blue;
static final Color colorCarrier = Color.yellow;
static final Color colorBattleship = Color.BLACK;
static final Color colorSubmarine = Color.magenta;
static final Color colorDestroyer = Color.white;
int[][] map;
int cols;
int rows;
boolean equalPoints;
Player p1 = new Player();
Player p2 = new Player();
JButton[][] tiles = new JButton[100][100];
public void setMap(int[][] map) {
this.map = map;
}
public void SetFrame(int r, int c) {
this.rows = r;
this.cols = c;
}
JButton highScoresButton = new JButton("High Scores");
JLabel player1ScoreTitleLabel = new JLabel(String.valueOf(p1.points));
JLabel turnTitleLabel = new JLabel(Turn());
JLabel player2ScoreTitleLabel = new JLabel(String.valueOf(p1.points));
JButton quitGameButton = new JButton("Quite Game");
JFrame frame = new JFrame("Battleship");
public BoardFrame(int r, int c) {
super("Battleship");
AttackHandler attackHandler = new AttackHandler(); // action event class
p1.turn = true; // player 1's turn is true, he commences
p2.turn= false; //player 2's turn is false
JFrame frame = new JFrame("Battleship");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// panel 1 (yellow border)
JPanel panel1 = new JPanel(new GridBagLayout());
JButton highScoresButton = new JButton("High Scores");
JLabel player1ScoreTitleLabel = new JLabel(String.valueOf(p1.points));
JLabel turnTitleLabel = new JLabel(Turn());
JLabel player2ScoreTitleLabel = new JLabel(String.valueOf(p1.points));
JButton quitGameButton = new JButton("Quite Game");
GridBagConstraints s = new GridBagConstraints();
s.weightx = 1;
s.gridx = 0;
s.gridy = 0;
panel1.add(highScoresButton, s);
s.weightx = 1;
s.gridx = 1;
s.gridy = 0;
panel1.add(player1ScoreTitleLabel, s);
s.weightx = 1;
s.gridx = 2;
s.gridy = 0;
panel1.add(turnTitleLabel);
s.weightx = 1;
s.gridx = 3;
s.gridy = 0;
panel1.add(player2ScoreTitleLabel, s);
s.weightx = 1;
s.gridx = 4;
s.gridy = 0;
panel1.add(quitGameButton, s);
// panel 2 (red border)
JPanel panel2 = new JPanel();
GridLayout layout = new GridLayout(r, c);
layout.setHgap(0);
layout.setVgap(0);
panel2.setLayout(layout);
panel2.setBorder(new LineBorder(Color.blue, 4));
for (int i =0; i<r; i++) {
for (int j =0; j < c; j++) {
tiles[i][j] = new JButton(){
#Override
public Dimension getPreferredSize() {
return new Dimension(100,100);
}
};
tiles[i][j].setBackground(colorNormal);
panel2.add(tiles[i][j]);
tiles[i][j].addActionListener(attackHandler);
}
}
frame.add(panel1, BorderLayout.NORTH);
frame.add(panel2, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public class AttackHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (source == tiles[i][j]) {
isHit(i, j);
return;
}
}
}
}
}
public void isHit(int row, int col) {
if (AllHit()) {
JOptionPane.showMessageDialog(null, "All Ships Destructed!");
setWinner();
String winner =DecideWinner();
if(p1.won){
p1.checkHighScore();
}
else if (p2.won){
p2.checkHighScore();
}
JOptionPane.showMessageDialog(null, winner, "Winner",
JOptionPane.PLAIN_MESSAGE);
int again = JOptionPane.showConfirmDialog(null, "Play Again", "Play
Again",JOptionPane.YES_NO_OPTION);
if (again==0){
Main.main(null);
}
frame.dispose();
}
else if (map[row][col] == 5) {
AddPoint(p1.turn, 5);
tiles[row][col].setBackground(colorCarrier);
map[row][col] = 1;
} else if (map[row][col] == 4) {
AddPoint(p1.turn, 4);
tiles[row][col].setBackground(colorBattleship);
map[row][col] = 1;
} else if (map[row][col] == 3) {
AddPoint(p1.turn, 3);
tiles[row][col].setBackground(colorSubmarine);
map[row][col] = 1;
} else if (map[row][col] == 2) {
AddPoint(p1.turn, 2);
tiles[row][col].setBackground(colorDestroyer);
map[row][col] = 1;
} else if (map[row][col] == 1) {
System.out.println("Already Hit!");
} else if (map[row][col] == 0 || map[row][col] == 9) {
tiles[row][col].setBackground(colorWater);
map[row][col] = 1;
}
p1.changeTurn(p1.turn);
p2.changeTurn(p2.turn);
// I cannot find a way to change the labels....
player1ScoreTitleLabel.setText(String.valueOf(p1.points));
player2ScoreTitleLabel.setText(String.valueOf(p2.points));
turnTitleLabel.setText(Turn());
System.out.println("Points Player 1: "+p1.points);
System.out.println("Points Player 2: "+p2.points);
}
public boolean AllHit() {
boolean allHit = true;
for (int i = 0; i<rows;i++) {
for (int j = 0; j < cols; j++) {
if (map[i][j] != 1 && map[i][j] != 0) {
allHit = false;
break;
}
}
}
return allHit;
}
public void AddRandomShips(int rows, int cols) {
int[][] map = ship.setRandomShips(rows, cols);
setMap(map);
}
public void AddShipsNotRandom(int size, int[][] coordinates){
int[][] map = ship.PlaceShips(size, coordinates);
setMap(map);
}
public void ScoreMethod(boolean scoreMethod){
if(scoreMethod){
equalPoints = true;
}
else {
equalPoints = false;
}
}
public void AddPoint(boolean turn,int amount){
if (turn){
p1.points = p1.points+ amount;
}
else p2.points = p2.points+amount;
}
public void setWinner(){
if(p1.points>p2.points){
p1.setWon();
}
else if (p2.points>p1.points){
p2.setWon();
}
}
public String DecideWinner(){
if (p1.won){
return "Player 1 won the game!";
}
else if (p2.won){
return "Player 2 won the game!";
}
else return "It's a tie!";
}
public String Turn(){
if (p1.turn){
return "Player 1";
}else return "Player 2";
}
This generates the following GUI:
However, I am still struggling finding a way to change the values of the text of the score JLabels, the following code did not work for me:
player1ScoreTitleLabel.setText(String.valueOf(p1.points));
player2ScoreTitleLabel.setText(String.valueOf(p2.points));
turnTitleLabel.setText(Turn())
Adding to my comment here is a small example to help get you started without the burden of an IDE for building your UI incorporating as much of Swing best practices as possible:
I opted to use JLabels as it just makes more sense
The yellow border represents panel1 which makes use of a GridBagLayout.
The red panel represents panel2 which makes use of a GridLayout.
Finally the 2 JPanels are added to a JFrame which by default uses BorderLayout.
TestApp.java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
public class TestApp {
public TestApp() {
createAndShowGui();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(TestApp::new);
}
private void createAndShowGui() {
JFrame frame = new JFrame("TestApp");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// panel 1 (yellow border)
JPanel panel1 = new JPanel(new GridBagLayout());
JButton highScoresButton = new JButton("High Scores");
JLabel player1ScoreLabel = new JLabel("<html>Player 1 Score:<br><h2>950</h2>");
JLabel turnLabel = new JLabel("<html>Turn:<br><h1>Player 1</h1>");
JLabel player2ScoreLabel = new JLabel("<html>Player 2 Score:<br><h2>925</h2>");
JButton quitGameButton = new JButton("Quit Game");
GridBagConstraints c = new GridBagConstraints();
c.weightx = 1;
c.gridx = 0;
c.gridy = 0;
panel1.add(highScoresButton, c);
c.weightx = 1;
c.gridx = 1;
c.gridy = 0;
panel1.add(player1ScoreLabel, c);
c.weightx = 1;
c.gridx = 2;
c.gridy = 0;
panel1.add(turnLabel);
c.weightx = 1;
c.gridx = 3;
c.gridy = 0;
panel1.add(player2ScoreLabel, c);
c.weightx = 1;
c.gridx = 4;
c.gridy = 0;
panel1.add(quitGameButton, c);
panel1.setBorder(new LineBorder(Color.YELLOW, 4)); // just for visual purposes of the answer
// panel 2 (red border)
JPanel panel2 = new JPanel();
GridLayout layout = new GridLayout(8, 8);
layout.setHgap(5);
layout.setVgap(5);
panel2.setLayout(layout);
panel2.setBorder(new LineBorder(Color.RED, 4)); // just for visual purposes of the answer
for (int i = 0; i < 64; i++) {
JLabel label = new JLabel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
};
label.setOpaque(true);
label.setBackground(Color.DARK_GRAY);
panel2.add(label);
}
frame.add(panel1, BorderLayout.NORTH);
frame.add(panel2, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
I have a matrix of colorful buttons and I need to compare their colors and their values after clicking them. All my code does is removing every button without searching their values or colors.Also i need to add the jlabel without rearranging jbuttons. How can i fix the problem?
public class Legos2 extends JFrame implements ActionListener{
private static final long serialVersionUID = 1L;
public JPanel jp = (JPanel)this.getContentPane();
public JButton[][] jb = new JButton[12][24];//my matrix
public static JLabel jl = new JLabel("score",SwingConstants.CENTER);//a jlabel to count the scores every time two buttons are removed
public Legos2() {
super();
this.setSize(2000,2000);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
jp.setLayout(new GridLayout(12, 24));//size of my jpanel
Random rnd = new Random();
Color[] c = {Color.lightGray, Color.gray, Color.white, Color.cyan};//colored jbuttons
final int MAXCOLOR = c.length;
JButton jb1;
for(int i = 0;i <jb.length;i++) {
for(int j = 0; j<jb[i].length; j++) {
int k = (int) (Math.random()*9+1);//k is a random integer from 1 to 9
jb1 = new JButton(Integer.toString(k));
add(jb1);
jb[i][j]=jb1;
jb[i][j].addActionListener(this);
}
}
for(int i=0; i<jb.length; i++){
for(int j = 0; j<jb[i].length; j++) {
jb[i][j].setBackground(c[rnd.nextInt(MAXCOLOR)]);//i add colors in here
}
}
for (int row = 0; row < jb.length; row++) {
for (int column = 0; column < jb[row].length; column++) {
jb[row][column].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
String buttonText = button.getText();
// now iterate over all the jbuttons you have
for(int i=0;i<jb.length;i++){
for(int j=0;j<jb[0].length;j++){
JButton b = jb[i][j];
String bText = b.getText();
if(e.getSource()==b)
if(buttonText.equals(bText)){
b.setEnabled(false);
jl.setText(Integer.toString(i));
}
}
}
}
}
);
jp.add(jb[row][column]);
}
}
}
}
The following is mcve of the required functionality. Please review and ask for clarifications as needed:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class Legos2 extends JFrame{
private static final long serialVersionUID = 1L;
private static final int ROWS = 12, COLS =24;
public JButton[][] jb = new JButton[ROWS][COLS];
private int score = 0;
public static JLabel jl;
public Legos2() {
super();
this.setSize(2000,2000);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel jp= new JPanel();
jp.setLayout(new GridLayout(ROWS, COLS));
Random rnd = new Random();
Color[] c = {Color.lightGray, Color.gray, Color.white, Color.cyan};
final int MAXCOLOR = c.length;
//all can be done in one loop
for(int i = 0;i <jb.length;i++) {
for(int j = 0; j<jb[i].length; j++) {
int k = (int) (Math.random()*9+1);//k is a random integer from 1 to 9
JButton button = new JButton(Integer.toString(k));
button.setBackground(c[rnd.nextInt(MAXCOLOR)]);
button.addActionListener(e -> {
disableTwoMatchingButtons(button);
});
jb[i][j]=button;
jp.add(button);
}
}
add(jp); //add panel at content pane center
jl= new JLabel("",SwingConstants.CENTER);
updateScore(0);
add(jl, BorderLayout.PAGE_END); //add label at content pane bottom
pack();
setVisible(true);
}
private void disableTwoMatchingButtons(JButton button) {
for(int i=0;i<jb.length;i++){
for(int j=0;j<jb[0].length;j++){
JButton b = jb[i][j];
if(b.isEnabled() && button.getText().equals(b.getText()) &&
button.getBackground().equals(b.getBackground())){
b.setEnabled(false);
button.setEnabled(false);
updateScore(2* Integer.valueOf(b.getText()));
return;
}
}
}
}
private void updateScore(int value) {
score += value;
jl.setText("Score: "+ score );
}
public static void main(String[] args) {
new Legos2();
}
}
If you need to disable all matching button, and not just two, use :
private void disableAllMatchingButtons(JButton button) {
for(int i=0;i<jb.length;i++){
for(int j=0;j<jb[0].length;j++){
JButton b = jb[i][j];
if(b.isEnabled() && button.getText().equals(b.getText())
&& button.getBackground().equals(b.getBackground())){
b.setEnabled(false);
updateScore(Integer.valueOf(b.getText()));
}
}
}
}
(instead of disableTwoMatchingButtons)
For future post always consider posting an mcve, and stick to one question per post.
UPDATE: I just coded each button manually. Thanks Anyways.
I am trying to make a Memory Game written in Java. For some reason Java renders all the images as the same. It appears to render the latest image to all buttons when clicked.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import java.util.ArrayList;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
/**
* #author Steven
*
*/
public class Memory extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final int GRIDSIZE = 4;
private PicButton[][] liteBut = new PicButton[GRIDSIZE][GRIDSIZE];
private Random rand = new Random();
private ClassLoader cl = this.getClass().getClassLoader();
private String[] imagelist = {"images/image01.jpg", "images/image02.jpg", "images/image03.jpg", "images/image04.jpg"};
private ArrayList<String> images = new ArrayList<String>();
private volatile String icon = "";
public Memory() {
initGUI();
setTitle("Memory");
setResizable(false);
pack();
setLocationRelativeTo(null);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void initGUI() {
assignimages();
TitleLabel framedTitle = new TitleLabel("Memory");
add(framedTitle, BorderLayout.PAGE_START);
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new GridLayout(GRIDSIZE, GRIDSIZE));
add(centerPanel, BorderLayout.CENTER);
for (int row = 0; row < GRIDSIZE; row++) {
for (int col = 0; col < GRIDSIZE; col++) {
liteBut[row][col] = new PicButton(row, col);
if (row == 0) {
if (col == 0) {
icon = images.get(0);
System.out.println(icon);
} else if (col == 1) {
icon = images.get(1);
System.out.println(icon);
} else if (col == 2) {
icon = images.get(2);
System.out.println(icon);
} else if (col == 3) {
icon = images.get(3);
System.out.println(icon);
}
} else if (row == 1) {
if (col == 0) {
icon = images.get(0);
System.out.println(icon);
} else if (col == 1) {
icon = images.get(1);
System.out.println(icon);
} else if (col == 2) {
icon = images.get(2);
System.out.println(icon);
} else if (col == 3) {
icon = images.get(3);
System.out.println(icon);
}
}
liteBut[row][col].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
PicButton button = (PicButton) e.getSource();
int row = button.getRow();
int col = button.getCol();
String id = button.getID();
System.out.println("Hi from " + id);
liteBut[row][col].setIcon(new ImageIcon(cl.getResource(icon)));
}
});
centerPanel.add(liteBut[row][col]);
}
}
}
private void assignimages() {
for (int x = 0; x < 4; x++) {
int i = rand.nextInt(GRIDSIZE);
images.add(imagelist[i]);
}
for (int x = 0; x < images.size(); x++) {
System.out.println(images.get(x));
}
}
public static void main(String[] args) {
try {
String className = UIManager.getCrossPlatformLookAndFeelClassName();
UIManager.setLookAndFeel(className);
} catch (Exception e) {
}
EventQueue.invokeLater(new Runnable() {
public void run() {
new Memory();
}
});
}
public class PicButton extends JButton {
private static final long serialVersionUID = 1L;
private static final int MAXSIZE = 150;
private int row = 0;
private int col = 0;
private String id = "";
//private Boolean hasPic;
public PicButton(int row, int col) {
this.row = row;
this.col = col;
id = Integer.toString(row) + Integer.toString(col);
System.out.println(id);
setBackground(Color.BLACK);
Dimension size = new Dimension(MAXSIZE, MAXSIZE);
setPreferredSize(size);
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
public String getID() {
return id;
}
public void setImage() {
setBackground(Color.RED);
//hasPic = true;
}
public void clearImage() {
setBackground(Color.BLACK);
//hasPic = false;
}
}
public class TitleLabel extends JLabel {
private static final long serialVersionUID = 1L;
public TitleLabel(String title) {
Font titleFont = new Font(Font.SERIF, Font.BOLD, 32);
setFont(titleFont);
setHorizontalAlignment(JLabel.CENTER);
setText(title);
setBackground(Color.BLACK);
setForeground(Color.WHITE);
setOpaque(true);
}
}
}
liteBut[row][col].setIcon(new ImageIcon(cl.getResource(icon)));
is assigning the last known value of icon as the image to the button (this is an instance field, so it remembers), this is not the "value" assigned to the button, but the last value assigned to icon by the for-loop in which you create the buttons, so basically, ALL the buttons will get the last icon, instead, supply the icon value the PictureButton itself so you can "update" the button when it's clicked.
This functionality could be self contained to the button itself, further making it easier to manage
I have problem with the Play Again button, which is to reset the panel to initial state.
The Play Again button should reset the panel, it does reshuffle the gameList, but not reset the panel, which means all the buttons remain and lost the ActionListener function.
Here is my program :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import static java.util.Collections.*;
public class MemoryGame extends JFrame
{
private JButton exitButton, replayButton;
private JButton[] gameButton = new JButton[16];
private ArrayList<Integer> gameList = new ArrayList<Integer>();
private int counter = 0;
private int[] buttonID = new int[2];
private int[] buttonValue = new int[2];
public static Point getCenterPosition(int frameWidth, int frameHeight)
{
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension dimension = toolkit.getScreenSize();
int x = (dimension.width - frameWidth)/2;
int y = (dimension.height - frameHeight)/2;
return (new Point(x,y));
}
public MemoryGame(String title)
{
super(title);
initial();
}
public void initial()
{
for (int i = 0; i < gameButton.length; i++)
{
gameButton[i] = new JButton();
gameButton[i].setFont(new Font("Serif", Font.BOLD, 28));
gameButton[i].addActionListener(new ButtonListener());
}
exitButton = new JButton("Exit");
replayButton = new JButton("Play Again");
exitButton.addActionListener(new ButtonListener());
replayButton.addActionListener(new ButtonListener());
Panel gamePanel = new Panel();
gamePanel.setLayout(new GridLayout(4, 4));
for (int i = 0; i < gameButton.length; i++)
{
gamePanel.add(gameButton[i]);
}
Panel buttonPanel = new Panel();
buttonPanel.add(replayButton);
buttonPanel.add(exitButton);
buttonPanel.setLayout(new GridLayout(1, 0));
add(gamePanel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
for (int i = 0; i < 2; i++)
{
for (int j = 1; j < (gameButton.length / 2) + 1; j++)
{
gameList.add(j);
}
}
shuffle(gameList);
int newLine = 0;
for (int a = 0; a < gameList.size(); a++)
{
newLine++;
System.out.print(" " + gameList.get(a));
if (newLine == 4)
{
System.out.println();
newLine = 0;
}
}
}
public boolean sameValues()
{
if (buttonValue[0] == buttonValue[1])
{
return true;
}
return false;
}
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (exitButton == e.getSource())
{
System.exit(0);
}
else if (replayButton == e.getSource())
{
initial();
}
for (int i = 0; i < gameButton.length; i++)
{
if (gameButton[i] == e.getSource())
{
gameButton[i].setText("" + gameList.get(i));
gameButton[i].setEnabled(false);
counter++;
if (counter == 3)
{
if (sameValues())
{
gameButton[buttonID[0]].setEnabled(false);
gameButton[buttonID[1]].setEnabled(false);
}
else
{
gameButton[buttonID[0]].setEnabled(true);
gameButton[buttonID[0]].setText("");
gameButton[buttonID[1]].setEnabled(true);
gameButton[buttonID[1]].setText("");
}
counter = 1;
}
if (counter == 1)
{
buttonID[0] = i;
buttonValue[0] = gameList.get(i);
}
if (counter == 2)
{
buttonID[1] = i;
buttonValue[1] = gameList.get(i);
}
}
}
}
}
public static void main(String[] args)
{
int x, y;
int width = 500;
int height = 500;
Point position = getCenterPosition(width, height);
x = position.x;
y = position.y;
JFrame frame = new MemoryGame("Memory Game");
frame.setBounds(x, y, width, height);
frame.setVisible(true);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
How can I solve this problem?
EDIT :
Another problem is after reset(), all buttons seem like become sameValue(). I have insert some audio to the buttons, and it's happen in the condition of the ButtonListener. Here is the part :
if (counter == 3)
{
if (sameValues())
{
gameButton[buttonID[0]].setEnabled(false);
gameButton[buttonID[1]].setEnabled(false);
}
Seems like it's satisfy the condition sameValue(), but why?
LATEST UPDATE :
Problem Solved. Latest code is not uploaded.
In the initial() method the code is creating a new GUI. It would be preferable to retain handles to the original controls, and reset them to a 'begin game' state and the correct values (for number).
Alternatives with your current method are to remove() and add() new for every component (not recommended) or to use a CardLayout (not necessary - see first suggestion).
Ok, I've fixed your code.
Be sure to check out my comment to your question and let me know if it works (I did a quick test and it went fine)
package varie;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import static java.util.Collections.shuffle;
import javax.swing.JButton;
import javax.swing.JFrame;
public class MemoryGame extends JFrame {
private JButton exitButton, replayButton;
private JButton[] gameButton = new JButton[16];
private ArrayList<Integer> gameList = new ArrayList<>();
private int counter = 0;
private int[] buttonID = new int[2];
private int[] buttonValue = new int[2];
public static Point getCenterPosition(int frameWidth, int frameHeight) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension dimension = toolkit.getScreenSize();
int x = (dimension.width - frameWidth) / 2;
int y = (dimension.height - frameHeight) / 2;
return (new Point(x, y));
}
public MemoryGame(String title) {
super(title);
initial();
}
public void initial() {
for (int i = 0; i < gameButton.length; i++) {
gameButton[i] = new JButton();
gameButton[i].setFont(new Font("Serif", Font.BOLD, 28));
gameButton[i].addActionListener(new ButtonListener());
}
exitButton = new JButton("Exit");
replayButton = new JButton("Play Again");
exitButton.addActionListener(new ButtonListener());
replayButton.addActionListener(new ButtonListener());
Panel gamePanel = new Panel();
gamePanel.setLayout(new GridLayout(4, 4));
for (int i = 0; i < gameButton.length; i++) {
gamePanel.add(gameButton[i]);
}
Panel buttonPanel = new Panel();
buttonPanel.add(replayButton);
buttonPanel.add(exitButton);
buttonPanel.setLayout(new GridLayout(1, 0));
add(gamePanel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
for (int i = 0; i < 2; i++) {
for (int j = 1; j < (gameButton.length / 2) + 1; j++) {
gameList.add(j);
}
}
shuffle(gameList);
int newLine = 0;
for (int a = 0; a < gameList.size(); a++) {
newLine++;
System.out.print(" " + gameList.get(a));
if (newLine == 4) {
System.out.println();
newLine = 0;
}
}
}
public boolean sameValues() {
if (buttonValue[0] == buttonValue[1]) {
return true;
}
return false;
}
public void reset() {
for(int i = 0; i< gameButton.length; i++){
gameButton[i].setEnabled(true);
gameButton[i].setText("");
for(ActionListener al : gameButton[i].getActionListeners()){
gameButton[i].removeActionListener(al);
}
gameButton[i].addActionListener(new ButtonListener());
}
buttonID = new int[2];
buttonValue = new int[2];
counter = 0;
shuffle(gameList);
int newLine = 0;
for (int a = 0; a < gameList.size(); a++) {
newLine++;
System.out.print(" " + gameList.get(a));
if (newLine == 4) {
System.out.println();
newLine = 0;
}
}
}
private class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (exitButton.equals(e.getSource())) {
System.exit(0);
} else if (replayButton.equals(e.getSource())) {
reset();
} else {
for (int i = 0; i < gameButton.length; i++) {
if (gameButton[i].equals(e.getSource())) {
gameButton[i].setText("" + gameList.get(i));
gameButton[i].setEnabled(false);
counter++;
if (counter == 3) {
if (sameValues()) {
gameButton[buttonID[0]].setEnabled(false);
gameButton[buttonID[1]].setEnabled(false);
} else {
gameButton[buttonID[0]].setEnabled(true);
gameButton[buttonID[0]].setText("");
gameButton[buttonID[1]].setEnabled(true);
gameButton[buttonID[1]].setText("");
}
counter = 1;
}
if (counter == 1) {
buttonID[0] = i;
buttonValue[0] = gameList.get(i);
}
if (counter == 2) {
buttonID[1] = i;
buttonValue[1] = gameList.get(i);
}
}
}
}
}
}
public static void main(String[] args) {
int x, y;
int width = 500;
int height = 500;
Point position = getCenterPosition(width, height);
x = position.x;
y = position.y;
JFrame frame = new MemoryGame("Memory Game");
frame.setBounds(x, y, width, height);
frame.setVisible(true);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}