I am trying to create a 2dimesional JTabbedPane. I found a small example at coderanch to create the JTabbedPane in 2 dimensions. What I would like to do now is add a figure to each tab from an external class after creation of the table. Meaning, I create this table, then place the figures I want inside the table (maybe user does not know needed order beforehand, just knows number of figures to use). But I cannot seem to get the tab to update. I was hoping someone could show me what I am doing incorrectly. Here is a MWE for adding text (instead of a figure).
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
public class DCTabbed2DPane {
private Dimension screensize;
private JFrame frame;
private JTabbedPane topTabbedPane;
private JTabbedPane[] leftTabbedPane;
private int rows;
private int cols;
private String frameName;
public DCTabbed2DPane(String frameName, int rows, int cols) {
this.frameName = frameName;
this.rows = rows;
this.cols = cols;
init();
}
private void setScreenSize() {
screensize = Toolkit.getDefaultToolkit().getScreenSize();
}
private void setJFrame() {
frame = new JFrame(frameName);
frame.setSize((int) (screensize.getHeight() * .75 * 1.618), (int) (screensize.getHeight() * .75));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void setJTabbedPane() {
topTabbedPane = new JTabbedPane(JTabbedPane.TOP);
leftTabbedPane = new JTabbedPane[cols];
}
private void setTabs() {
for (int i = 0; i < cols; i++) {
leftTabbedPane[i] = new JTabbedPane(JTabbedPane.LEFT);
for (int j = 0; j < rows; j++) {
leftTabbedPane[i].addTab("Super Layer " + (j + 1), new JLabel("Sector " + (i + 1) + " - " + (j + 1)));
}
topTabbedPane.addTab("Sector " + (i + 1), leftTabbedPane[i]);
}
frame.add(topTabbedPane);
topTabbedPane.setSelectedIndex(-1);
}
private void init() {
setScreenSize();
setJFrame();
setJTabbedPane();
setTabs();
}
public void addCanvasToPane(Integer row, String str) {
leftTabbedPane[row].addTab("", new JLabel(str));
frame.add(topTabbedPane);
frame.revalidate();
frame.repaint();
}
public void showFrame() {
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
int rows = 6;
int cols = 6;
DCTabbed2DPane test = new DCTabbed2DPane("PooperDooper", rows, cols);
for (int j = 0; j < cols; j++) {
test.addCanvasToPane(j, "Name " + j);
}
test.showFrame();
}
}
It's either you want the figure on the tab's navigation, like
leftTabbedPane[i] = new JTabbedPane(JTabbedPane.LEFT);
for (int j = 0; j < rows; j++) {
leftTabbedPane[i].addTab("Super Layer " + (j + 1),new ImageIcon(getClass().getResource("Images/map.png")), new JLabel("Sector " + (i + 1) + " - " + (j + 1)));
}
Or like this one
leftTabbedPane[i] = new JTabbedPane(JTabbedPane.LEFT);
for (int j = 0; j < rows; j++) {
leftTabbedPane[i].addTab("Super Layer " + (j + 1), new MyLabel("Images/Horse.png","").getLabel());
}
where MyLabel is
public class MyLabel {
JLabel label;
String path;
String text;
public MyLabel(String path, String text) {
this.label = new JLabel();
this.path = path;
this.text = text;
}
public void setUpImage(String path) {
this.label.setIcon(new ImageIcon(getClass().getResource(path)));
}
public JLabel getLabel() {
setUpImage(this.path);
return this.label;
}
}
Related
public class ChutesAndLadders2d {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] numbersOnBoard = new int [6][6];
boardSetUpA (numbersOnBoard);
printTwoD(numbersOnBoard);
}
public static void boardSetUpA (int[][]twoD) {
//Square with even size
//even rows
for (int row = 0;row<twoD.length; row ++) {
if (row %2 ==0) {
int num = twoD.length*(twoD.length-row);
for (int col = 0; col<twoD[row].length; col ++ ) {
twoD[row][col] = num;
num--;
}
}//
else {
int num = twoD.length*(twoD.length-(row + 1))+ 1;
for (int col = 0; col<twoD[row].length; col ++ ) {
twoD[row][col] = num;
num++;
}
}
}//for row
}//
public static void printTwoD(int [][] array){
for (int row = 0; row < array.length; row++){
for (int column = 0; column < array[row].length; column++){
System.out.print(array[row][column] + "\t");
}
System.out.println();
}
}
public static void boardDetails(String[][]board) {
for (int row = 0;row<board.length; row++){
for (int col = 0;col<board[row].length; col++){
if( col+2 == row||col+1 == row*2 ){
board[row][col] = "Lad"; // Append value
}
else if (col*2 == row|| row*2 == col){
board[row][col] = "Cht";// Append value
}
else {
board[row][col] = " ";
}
}
board[board.length-1][0] = "Start";
if (board.length%2 ==0) {
board[0][0] = "End";}
else {
board[0][board.length-1]="End";
}
}
}
public static void printBoard (int[][]twoD, String[][]strTwoD) {
//Printing
for (int row = 0;row<twoD.length;row++) {
for (int col = 0;col<twoD[row].length;col++) {
System.out.print(twoD[row][col] + " "+strTwoD[row][col]+"\t\t");
}
System.out.println("\n");
}
}
}
This is the starter code I have for setting up the snakes and ladders game. I also tried to set the chutes/snakes and ladders on the board but it is not printing. How should I fix it and how do I develop this code to have three methods: update the moves of a player once he reaches a snake, a ladder, and once he rolls his die, from one place to another?
Is it possible to implement a Shutes & Ladders game using a 2D Array? For sure! Does that make sense in an object-oriented language such as Java? I dont know ....
What do you need for that?
A square board with e.g. 36 playing fields.
Connections between two playing fields. (shutes and ladders)
Pawns and a dice.
A renderer that outputs the playing field (as text or graphics).
A program that allows input and connects everything to a functioning game.
Here is an example that works with a List instead of an Array. That can certainly be changed if it is necessary for your purposes.
I hope this is of some help to you.
P.S .: After the start, the board is displayed with field numbers. Shutes are shown as red lines. Ladders as green lines. Keys 1-6 on the keyboard simulate rolling the dice..
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.*;
public class ChutesAndLadders2d {
public static void main(String[] args) {
JFrame frame = new JFrame("Chutes and Ladders 2D");
Game game = new ChutesAndLadders2d().new Game();
game.setPreferredSize(new Dimension(400, 400));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setContentPane(game);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#SuppressWarnings("serial")
class Game extends JPanel{
private final Font defaultFont = new Font("Arial", Font.PLAIN, 16);
private final BasicStroke stroke = new BasicStroke(4f);
private static final int SCALE = 64;
// board and pawns
private final Board board = new Board(6);
private final List<Pawn> pawns = new ArrayList<>();
public Game(){
setFocusable(true); // receive Keyboard-Events
addKeyListener(new KeyAdapter(){
#Override
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
if(c >= '1' && c <= '6'){
int steps = Integer.parseInt(Character.toString(c));
Pawn pawn = pawns.get(0);
pawn.move(steps);
Field field = board.get(pawn.fieldIndex);
if(field.targetKind() != Kind.NONE){
pawn.move(field.getTarget().index - field.index);
}
repaint();
}
}
});
board.connect(5, 12); // Ladder 5 -> 12
board.connect(8, 4); // Shute 8 -> 4
board.connect(15, 32); // Ladder 15 -> 32
board.connect(35, 17); // Shute 35 -> 17
board.connect(23, 30); // Ladder 23 -> 30
pawns.add(new Pawn(Color.BLUE, board.size() - 1));
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
setFont(defaultFont);
for(Field field : board){
Point p = field.getLocation();
g2d.drawRect(p.x * SCALE, p.y * SCALE, SCALE, SCALE);
g2d.drawString(field.text, p.x * SCALE + 24, p.y * SCALE + 40);
}
for(Field field : board){
if(field.targetKind() != Kind.NONE){
g2d.setColor(field.targetKind() == Kind.LADDER ? Color.GREEN : Color.RED);
g2d.setStroke(stroke);
Point source = field.getLocation();
Point target = field.getTarget().getLocation();
g2d.drawLine(source.x * SCALE + 40, source.y * SCALE + 24, target.x * SCALE + 40, target.y * SCALE + 24);
}
}
for(Pawn pawn : pawns){
Point loc = board.get(pawn.fieldIndex).getLocation();
g2d.setColor(pawn.color);
g2d.fillOval(loc.x * SCALE + 32, loc.y * SCALE + 32, 16, 16);
}
}
}
class Board implements Iterable<Field>{
private final List<Field> fields = new ArrayList<>();
public Board(int size){
for(int index = 0; index < size * size; index++)
fields.add(new Field(index, size));
}
public Field get(int index){
return fields.get(index);
}
public void connect(int startFieldnumber, int targetFieldnumber){
get(startFieldnumber - 1).setTarget(get(targetFieldnumber - 1));
}
#Override
public Iterator<Field> iterator() {
return fields.iterator();
}
public int size(){
return fields.size();
}
}
class Field{
final int index;
final String text;
final int size;
private Field target;
public Field(int index, int size){
this.index = index;
this.size = size;
text = "" + (index + 1);
}
public void setTarget(Field target){
if(target == this) return;
this.target = target;
}
public Field getTarget(){
return target;
}
public Kind targetKind(){
if(target == null) return Kind.NONE;
return index < target.index ? Kind.LADDER : Kind.SHUTE;
}
public Point getLocation(){
int x = index % size;
int y = index / size;
if(y % 2 != 0) x = size - x - 1;
return new Point(x, size - y - 1);
}
}
class Pawn{
int fieldIndex = 0;
int maxIndex;
Color color;
public Pawn(Color color, int maxIndex){
this.color = color;
this.maxIndex = maxIndex;
}
public void move(int steps){
fieldIndex += steps;
if(fieldIndex < 0) fieldIndex = 0;
if(fieldIndex > maxIndex) fieldIndex = maxIndex;
}
}
enum Kind{
NONE, SHUTE, LADDER
}
}
spacebattle
so far i was able to make a board composed of tiles using jlabels. the next step of the game is for players Red and Blue, to take turns selecting a planet (by clicking on a planet tile) they initially control. once a player clicks on a planet, a meeple counter should be placed on top of that tile planet.
the array data for the planets should also be updated so the owner of the planet be known. right now, i have no idea how to link my jlabel tiles with my variables.
if you can point me to the right direction, it will be much appreciated. thanks.
package SpaceBattle;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
//import javax.smartcardio.Card;
import javax.swing.*;
public class spacebattle2 extends JFrame {
JLabel[] tilelabel = new JLabel[31];
JLabel[] hexlabel = new JLabel[31];
ImageIcon tileicon, hexicon;
int rownum, colnum;
int c, r, xloc, yloc, hexctr, tilectr;
int energy, ore, capacity;
String labelname;
String type;
int numtiles = 31;
int deckctr = 26;
String[] tiledeck = new String[numtiles];
int[] tilexloc = new int[numtiles];
int[] tileyloc = new int[numtiles];
int tileenergy[] = new int[numtiles];
int tileore[] = new int[numtiles];
int tilecapacity[] = new int[numtiles];
String tiletype[] = new String[numtiles];
String tilename[] = new String[numtiles];
int tilemeeple[] = new int[numtiles];
String[] hexnum = new String[numtiles];
int[] hexxloc = new int[numtiles];
int[] hexyloc = new int[numtiles];
String[] hexempty = new String[numtiles];
int hexenergy[] = new int[numtiles];
int hexore[] = new int[numtiles];
int hexcapacity[] = new int[numtiles];
String hextype[] = new String[numtiles];
String hexname[] = new String[numtiles];
String hexplayer[] = new String[numtiles];
String[] players = new String[6];
String playerturn;
int startingplanets = 2;
int bluemaxplanet = startingplanets;
int redmaxplanet = startingplanets;
int numplanets = 7;
int numspace = 24;
int nonplayertiles = numplanets + numspace;
String planetCode;
String planetselected = "none";
//selectPlanet
String player = "Red";
int i;
public spacebattle2() {
setLayout(null);
createDeck();
shuffleDeck();
drawBoard();
//selectPlanet();
}
private void selectPlanet() {
// TODO Auto-generated method stub
for(i = 0; i < numtiles; i++) {
tilelabel[i].addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e) {
System.out.println(i);
}
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
});
}
}
private void shuffleDeck() {
// TODO Auto-generated method stub
System.out.println("shuffling deck...");
Random r = new Random();
int swapIndex;
String temp;
for(int startIndex = 0; startIndex < numtiles; startIndex++) {
System.out.println(startIndex + " startIndex " + tiledeck[startIndex]);
swapIndex = r.nextInt(numtiles);
System.out.println(swapIndex + " swapIndex " + tiledeck[swapIndex]);
if(swapIndex != startIndex) {
temp = tiledeck[swapIndex];
tiledeck[swapIndex] = tiledeck[startIndex];
System.out.println("Moving " + startIndex + " " + tiledeck[startIndex] + " startIndex to " + swapIndex + " swapIndex");
tiledeck[startIndex] = temp;
System.out.println("Moving " + temp + " temp to " + startIndex + " startIndex");
}
}
}
private void createDeck() {
// TODO Auto-generated method stub
int s, p, xloc = 667, yloc = 10;
/*******************************
*
* Create Space tiles
*
******************************/
System.out.println("creating space tiles...");
tilectr = 0;
for(s= 0; s < numspace; s++) {
tiledeck[tilectr] = "000";
System.out.println(tilectr + " " + tiledeck[tilectr]);
tilectr++;
}
/**************************
*
* Create Planet tiles
*
*************************/
System.out.println("creating planet tiles...");
for(p = 0; p < numplanets; p++) {
energy = (int) (Math.random()*3 + 1);
ore = (int) (Math.random()*3 +1);
capacity = (int) (Math.random()*3 +1);
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("");
stringBuffer.append(energy);
stringBuffer.append(ore);
stringBuffer.append(capacity);
String planetCode = stringBuffer.toString();
tiledeck[tilectr] = planetCode;
System.out.println(tilectr + " " + tiledeck[tilectr]);
tilectr++;
}
}
private void drawBoard() {
// TODO Auto-generated method stub
int xloc = 10;
int yloc = 61;
int hexctr = 0;
int colnum = 7;
int rownum = 4;
xloc = 10;
yloc = 61;
hexctr = 0;
colnum = 7;
rownum = 4;
int row = 0, col = 0, numtiles = 31;
for(int c = 0; c < numtiles; c ++) {
if(tiledeck[c] == "000") {
System.out.println(c + " " + tiledeck[c] + " tile is space");
tileenergy[c] = 0;
tileore[c] = 0;
tilecapacity[c] = 0;
tiletype[c] = "space";
tilename[c] = "space";
tileicon = new ImageIcon(getClass().getResource("/000.png"));
tilelabel[c] = new JLabel();
tilelabel[c].setIcon(tileicon);
tilelabel[c].setBounds(xloc, yloc, 115, 100);
add(tilelabel[c]);
yloc = yloc + 102;
row++;
if(row == rownum) {
xloc = xloc + 88;
row = 0;
col++;
if(col % 2 == 0) {
yloc = 61;
rownum = rownum - 1;
}
else {
yloc = 10;
rownum = rownum + 1;
}
}
}
else {
System.out.println(c + " " + tiledeck[c] + " tile is planet");
tileenergy[c] = Integer.parseInt(tiledeck[c].substring(0, 1));
tileore[c] = Integer.parseInt(tiledeck[c].substring(1, 2));
tilecapacity[c] = Integer.parseInt(tiledeck[c].substring(2, 3));
tiletype[c] = "planet";
tilemeeple[c] = 0;
tileicon = new ImageIcon(getClass().getResource("/" + tiledeck[c] + ".png"));
tilelabel[c] = new JLabel();
tilelabel[c].setIcon(tileicon);
tilelabel[c].setBounds(xloc, yloc, 115, 100);
add(tilelabel[c]);
yloc = yloc + 102;
row++;
if(row == rownum) {
xloc = xloc + 88;
row = 0;
col++;
if(col % 2 == 0) {
yloc = 61;
rownum = rownum - 1;
}
else {
yloc = 10;
rownum = rownum + 1;
}
}
}
}
}
private Object i(int numtiles2, int i) {
// TODO Auto-generated method stub
return null;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
spacebattle2 board = new spacebattle2();
board.setSize(900, 600);
board.setResizable(false);
board.setTitle("Space Battle");
board.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
board.setVisible(true);
}//End void main
}
I suggest restructuring the program to use a "tile" class to hold all the information related to a given tile. It can also be helpful to have a "tile manager" class that knows about the collection of tiles and how they relate to one another.
Here is what a tile class might look like for your program. I have tried not to change any functionality, only to reorganize things. You should be able to match everything up with your original program.
class TileInfo {
TileManager manager;
public JLabel label = new JLabel();
public JLabel hexlabel = new JLabel();
int xloc;
int yloc;
int energy;
int ore;
int capacity;
String type;
String name;
int meeple;
String hexnum;
int hexxloc;
int hexyloc;
String hexempty;
// etc...
public TileInfo(Icon tileicon, int x, int y, TileManager manager) {
this.manager = manager;
label.setIcon(tileicon);
label.setBounds(x, y, 115, 100);
label.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
manager.clickedTile(TileInfo.this);
};
});
}
};
You can then extend this base class for "space" and "planet" tiles:
class SpaceTile extends TileInfo {
public SpaceTile(Icon icon, int x, int y, TileManager manager) {
super(icon, x, y, manager);
energy = 0;
ore = 0;
capacity = 0;
type = "space";
name = "space";
}
};
class PlanetTile extends TileInfo {
public PlanetTile(Icon icon, int x, int y,
int energy, int ore, int capacity, TileManager manager) {
super(icon, x, y, manager);
this.energy = energy;
this.ore = ore;
this.capacity = capacity;
type = "planet";
meeple = 0;
}
};
The subclasses are not strictly necessary in your example, but tile construction is slightly different in each case and this helps keep them straight.
Each TileInfo creates its own mouse listener, but passes the events up to the tile manager. The tile manager acts like a container and holds the array:
class TileManager {
public int numtiles;
public TileInfo[] tile;
public String tiledeck[];
public TileManager(int numtiles) {
this.numtiles = numtiles;
this.tile = new TileInfo[numtiles];
this.tiledeck = new String[numtiles];
System.out.printf("TileManager(%d): tile[%d]\n", numtiles, numtiles);
}
public void clickedTile(TileInfo tile) {
if (tile instanceof SpaceTile) {
System.out.println("clicked space tile " + tile.label.getBounds());
} else if (tile instanceof PlanetTile) {
System.out.println("clicked planet tile " + tile.label.getBounds());
}
}
};
Notice now you only need a single array. TileManager could override ArrayList if you like that better; I wanted to stick as closely as possible to your original program. The clickedTile() method handles mouse clicks on tiles, but since it is in the tile manager it can see all the tiles instead of just one. If, for example, you want to de-select tile A when you click on tile B, you need to be able to see both tiles.
Having a separate tile manager is not strictly necessary; you could leave this functionality in the spacebattle2 class. I like to have a manager class to separate the functionality of creating, manipulating, and drawing groups of tiles, separate from gameplay. It acts sort of like a "tile library".
Finally, how this all fits into your main class. Lots of code omitted for clarity.
public class spacebattle2 extends JFrame {
TileManager tiles = new TileManager(31);
// didn't change anything except tiledeck[] now lives inside tiles
// this method could be moved into the TileManager
private void shuffleDeck() {
for(int startIndex = 0; startIndex < tiles.numtiles; startIndex++) {
swapIndex = r.nextInt(tiles.numtiles);
if(swapIndex != startIndex) {
temp = tiles.tiledeck[swapIndex];
tiles.tiledeck[swapIndex] = tiles.tiledeck[startIndex];
tiles.tiledeck[startIndex] = temp;
}
}
}
void createTile(String deck, int xloc, int yloc) {
tileicon = new ImageIcon(getClass().getResource("/" + deck + ".png"));
if (deck.equals("000")) {
tiles.tile[c] = new SpaceTile(tileicon, xloc, yloc, tiles);
} else {
int energy = Integer.parseInt(deck.substring(0, 1));
int ore = Integer.parseInt(deck.substring(1, 2));
int capacity = Integer.parseInt(deck.substring(2, 3));
tiles.tile[c] = new PlanetTile(tileicon, xloc, yloc, 0, 0, 0, tiles);
}
add(tiles.tile[c].label);
}
private void drawBoard() {
/* ... */
for(int c = 0; c < tiles.numtiles; c ++) {
createTile(tiles.tiledeck[c], xloc, yloc);
yloc = yloc + 102;
row++;
if(row == rownum) {
xloc = xloc + 88;
row = 0;
col++;
if(col % 2 == 0) {
yloc = 61;
rownum = rownum - 1;
} else {
yloc = 10;
rownum = rownum + 1;
}
}
}
}
}
The loop in drawBoard() is simplified; it had a lot of duplicate code, so I factored that out and added a createTile() method to create the two types of tile.
Thare are still improvements that could be made. I would not consider a public array with public TileInfo variables to be ideal as a way to accessing your data, but did not want to change it so much that it is unrecognizable.
This is not meant to be a final design, but to suggest a way to organize the code in a way that will make it easier to work with, and also answer your question about how to associate data with tiles.
Here is my code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ChessBoardGUI extends JFrame {
private Container contents;
private JButton[][] squares = new JButton[8][8];
private Color colorBlack = Color.BLACK;
private int row = 7;
private int col = 1;
private ImageIcon knight = new ImageIcon("knight.jpg");
public ChessBoardGUI() {
super("GUI GridLayout Manager - (click a valid square to move knight)");
contents = getContentPane();
contents.setLayout(new GridLayout(8,8));
ButtonHandler buttonHandler = new ButtonHandler();
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
squares[i][j] = new JButton();
if ((i + j) % 2 != 0) {
squares[i][j].setBackground(colorBlack);
}
contents.add(squares[i][j]);
squares[i][j].addActionListener(buttonHandler);
}
}
squares[row][col].setIcon(knight);
setSize(500, 500);
setResizable(false);
setLocationRelativeTo(null);
setVisible(true);
}
private boolean isValidMove(int i, int j) {
int rowDelta = Math.abs(i - row);
int colDelta = Math.abs(j - col);
if ((rowDelta == 1) && (colDelta == 2)) {
return true;
}
if ((colDelta == 1) && (rowDelta == 2)) {
return true;
}
return false;
}
private void processClick(int i, int j) {
if (isValidMove(i, j) == false) {
return;
}
squares[row][col].setIcon(null);
squares[i][j].setIcon(knight);
row = i;
col = j;
}
private class ButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (source == squares[i][j]) {
processClick(i, j);
return;
}
}
}
}
}
public static void main(String args[]) {
ChessBoardGUI gui = new ChessBoardGUI();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I have a program that creates a chess board GUI, but when I runs my code, the buttons are all white instead of black and white buttons (Just like chess board). Could anyone please tell me where am I doing wrong? Any help is appreciated!
When I runs my program, all I see is a window with white buttons, but there is no black color button.
In my code I added the setOpaque() method but the black color was only at border, so I added this line of code:
squares[i][j].setBorder(null);
Here is the code:
if ((i + j) % 2 != 0) {
squares[i][j].setBackground(colorBlack);
squares[i][j].setBorder(null);
squares[i][j].setOpaque(true);
}
I am trying to find a way to either SWITCH the buttons or SWAP the button icons in a 2D array of buttons. I am attempting to create a board game and move pieces around.
I'm not sure if my logic is just completely off here but my though process is.. Create a Gamepiece class that extends JButton. Pass those buttons into a 2d array and add that button to the GridLayout.
Now, I feel like swapping the icons on the buttons is simpler but I cant seem to figure out how to do it correctly.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Board implements ActionListener {
private int p1;
private int p2;
private int fromRow;
private int fromCol;
private int toRow;
private int toCol;
private JPanel grid = new JPanel(new GridLayout(8,8));
private JFrame jf = new JFrame();
GamePieces gp;
private boolean isFirstClick = true;
Icon eagles = new ImageIcon("eagles.png");
Icon cowboys = new ImageIcon("cowboys.png");
GamePieces boardGame [][] = new GamePieces [8][8];
int board [][] = new int [][]{{1,1,1,1,0,0,0,0},
{1,1,1,0,0,0,0,0},
{1,1,0,0,0,0,0,0},
{1,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,2},
{0,0,0,0,0,0,2,2},
{0,0,0,0,0,2,2,2},
{0,0,0,0,2,2,2,2}};
///////////////////////////////////////////////////////////////////
public Board(){
jf.setTitle("Board Game");
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setSize(640,640);
JMenuBar menuBar = new JMenuBar();
jf.setJMenuBar(menuBar);
JMenu file = new JMenu("File");
JMenu about = new JMenu("About");
menuBar.add(file);
menuBar.add(about);
createBoard();
jf.setVisible(true);
}// end constructor
////////////////////////////////////////////////////////////////////
public void movePiece(){
for(int row = 0; row < boardGame.length; row++){
for(int col = 0; col < boardGame.length; col++){
boardGame[toRow][toCol] = boardGame[fromRow][fromCol];
gp = new GamePieces(fromRow,fromCol);
gp.setIcon(eagles);
boardGame[toRow][toCol] = gp;
jf.repaint();
}
}
}
/////////////////////////////////////////////////////////
public void actionPerformed(ActionEvent ae){
for(int row = 0; row < boardGame.length; row++){
for(int col = 0; col < boardGame.length; col++){
if(ae.getSource() == boardGame[row][col]){
if(isFirstClick){
fromRow = boardGame[row][col].getRow();
fromCol = boardGame[row][col].getCol();
isFirstClick = false;
System.out.println("First Row " + boardGame[row][col].getRow() + " Col " + boardGame[row][col].getCol());
}
else {
toRow = boardGame[row][col].getRow();
toCol = boardGame[row][col].getCol();
System.out.println("Second Row " + boardGame[row][col].getRow() + " Col " + boardGame[row][col].getCol());
this.movePiece();
}
}
}
}
}
///////////////////////////////////////////////////////
public void createBoard(){
for(int row = 0; row < board.length; row++){
for(int col = 0; col < board.length; col++){
if (board[row][col] == 1){
gp = new GamePieces(row,col);
gp.setIcon(eagles);
boardGame[row][col] = gp;
grid.add(boardGame[row][col]);
boardGame[row][col].addActionListener(this);
}
else if (board[row][col] == 0){
gp = new GamePieces(row,col);
boardGame[row][col] = gp;
grid.add(boardGame[row][col]);
boardGame[row][col].addActionListener(this);
}
else if(board[row][col] == 2){
gp = new GamePieces(row,col);
gp.setIcon(cowboys);
boardGame[row][col] = gp;
grid.add(boardGame[row][col]);
boardGame[row][col].addActionListener(this);
}
}
}
jf.add(grid);
}
class GamePieces extends JButton {
private int row;
private int col;
private String player;
public GamePieces(int row, int col){
this.row = row;
this.col = col;
}
public int getRow(){
return row;
}
public int getCol(){
return col;
}
public String getPlayer(){
return player;
}
}
public static void main(String [] args){
Board Halmas = new Board();
}
}
No, don't swap buttons as there's no need, and no benefit to doing this. Instead use an MVC or Model-View-Control program structure and swap Icons held by JButtons or JLabels (my preference) as dictated by changes in the model's state.
Regardless of what overall technique you use, swap your icons, not your buttons.
The idea here is to create a grid of boxes. underneath the black grid is another grid of multi-colored boxes. when you click a box it's mask disappears showing the colored box beneath. You then click a second box if the colors match hurray, if not then the game continues. Here is the code for GuessingGame.java
import java.applet.Applet;
import java.awt.Button;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GuessingGame extends Applet{
/**
*
*/
private static final long serialVersionUID = 1L;
private final int START_X = 20;
private final int START_Y = 40;
private final int ROWS = 4;
private final int COLS = 4;
private final int BOX_WIDTH = 20;
private final int BOX_HEIGHT = 20;
//this is used to keep track of boxes that have been matched.
private boolean matchedBoxes[][];
//this is used to keep track of two boxes that have been clicked.
private MaskableBox chosenBoxes[];
private MaskableBox boxes[][];
private Color boxColors[][];
private Button resetButton;
public void init() {
boxes = new MaskableBox[ROWS][COLS];
boxColors = new Color[ROWS][COLS];
resetButton = new Button("Reset Colors");
resetButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
randomizeColors();
buildBoxes();
repaint();
}
});
add(resetButton);
//separate building colors so we can add a button later
//to re-randomize them.
randomizeColors();
buildBoxes();
}
public void paint(Graphics g) {
for (int row =0; row < boxes.length; row ++) {
for (int col = 0; col < boxes[row].length; col++) {
if(boxes[row][col].isClicked()) {
//boxes[row][col].setMaskColor(Color.black);
//boxes[row][col].setMask(!boxes[row][col].isMask());
//boxes[row][col].setClicked(false);
//}
if (!matchedBoxes[row][col]) {
gameLogic(boxes[row][col]);
//boxes[row][col].draw(g);
}
}
}
}
//loop through the boxes and draw them.
for (int row = 0; row < boxes.length; row++) {
for (int col = 0; col < boxes[row].length; col++) {
boxes[row][col].draw(g);
}
}
}
public void gameLogic(MaskableBox box) {
if ((chosenBoxes[0] != null)&&(chosenBoxes[1] != null)) {
chosenBoxes = new MaskableBox[2];
if(chosenBoxes[0].getBackColor() == chosenBoxes[1].getBackColor()) {
for (int i=0; 0 < 2; ++i ) {
for(int row = 0; row < boxes.length; row++) {
for(int col = 0; col < boxes[row].length; col++) {
if( boxes[row][col] == chosenBoxes[i] ) {
System.out.println("boxes [row][col] == chosenBoxes[] at index: " + i );
matchedBoxes[row][col] = true;
break;
}
}
}
}
}else {
chosenBoxes[0].setMask(true);
chosenBoxes[1].setMask(true);
}
}else {
if (chosenBoxes[0] == null) {
chosenBoxes[0] = box;
chosenBoxes[0].setMask(false);
return;
}else{
if (chosenBoxes[1] == null) {
chosenBoxes[1] = box;
chosenBoxes[1].setMask(false);
}
}
}
}
private void removeMouseListeners() {
for(int row = 0; row < boxes.length; row ++) {
for(int col = 0; col < boxes[row].length; col++) {
removeMouseListener(boxes[row][col]);
}
}
}
private void buildBoxes() {
// need to clear any chosen boxes when building new array.
chosenBoxes = new MaskableBox[2];
// create a new matchedBoxes array
matchedBoxes = new boolean [ROWS][COLS];
removeMouseListeners();
for(int row = 0; row < boxes.length; row++) {
for(int col = 0; col < boxes[row].length; col++) {
boxes[row][col] =
new MaskableBox(START_X + col * BOX_WIDTH,
START_Y + row * BOX_HEIGHT,
BOX_WIDTH,
BOX_HEIGHT,
Color.gray,
boxColors[row][col],
true,
true,
this);
addMouseListener(boxes[row][col]);
}
}
}
private void randomizeColors() {
int[] chosenColors = {0,0,0,0,0,0,0,0};
Color[] availableColors = {Color.red, Color.blue, Color.green,
Color.yellow, Color.cyan, Color.magenta, Color.pink, Color.orange };
for(int row = 0; row < boxes.length; row++) {
for (int col = 0; col < boxes[row].length; col++) {
for (;;) {
int rnd = (int) (Math.random() * 8);
if (chosenColors[rnd]< 2) {
chosenColors[rnd]++;
boxColors[row][col] = availableColors[rnd];
break;
}
}
}
}
}
}
here is the second batch of code containing maskablebox
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
public class MaskableBox extends ClickableBox {
private boolean mask;
private Color maskColor;
Container parent;
public MaskableBox(int x, int y, int width, int height, Color borderColor,
Color backColor, boolean drawBorder, boolean mask, Container parent ) {
super(x, y, width, height, borderColor, backColor, drawBorder, parent);
this.parent = parent;
this.mask = mask;
}
public void draw(Graphics g) {
if(mask=false) {
super.draw(g);
// setOldColor(g.getColor());
// g.setColor(maskColor);
// g.fillRect(getX(),getY(),getWidth(), getHeight());
// if(isDrawBorder()) {
// g.setColor(getBorderColor());
// g.drawRect(getX(),getY(),getWidth(),getHeight());
// }
// g.setColor(getOldColor());
}else {
if(mask=true) {
//super.draw(g);
setOldColor(g.getColor());
g.setColor(maskColor);
g.fillRect(getX(),getY(),getWidth(), getHeight());
if(isDrawBorder()) {
g.setColor(getBorderColor());
g.drawRect(getX(),getY(),getWidth(),getHeight());
}
g.setColor(getOldColor());
}
}
}
public boolean isMask() {
return mask;
}
public void setMask(boolean mask) {
this.mask = mask;
}
public Color getMaskColor() {
return maskColor;
}
public void setMaskColor(Color maskColor) {
this.maskColor = maskColor;
}
}
I now get these error messages.
Exception in thread "AWT-EventQueue-1" java.lang.NullPointerException
at GuessingGame.gameLogic(GuessingGame.java:74)
at GuessingGame.paint(GuessingGame.java:55)
at java.awt.Container.update(Container.java:1801)
at sun.awt.RepaintArea.updateComponent(RepaintArea.java:239)
at sun.awt.RepaintArea.paint(RepaintArea.java:216)
at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:306)
at java.awt.Component.dispatchEventImpl(Component.java:4706)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
You are getting a NullPointerException on line 74 of GuessingGame.java in method gameLogic, which corresponds to this line :
if(chosenBoxes[0].getBackColor() == chosenBoxes[1].getBackColor()) {
and the reason you're getting a NullPointerException there is because in the line before it you do:
chosenBoxes = new MaskableBox[2];
which initailizes an array of MaskableBox with 2 references, but the actual MaskableBox objects neeed to be instantiated as well - does that make sense?
Basically the lesson is this: Creating an array of Objects is not the same as creating an array of objects and initializing each one of the elements in the array.
Because at line 73 you do:
chosenBoxes = new MaskableBox[2];
i.e. you create a new MaskableBox array (each element in the new array will be null). The next line you do is:
chosenBoxes[0].getBackColor() == chosenBoxes[1].getBackColor()
chosenBoxes[0] and chosenBoxes[1] are both null since you just created chosenBoxes on the previous line. Remove the call to create a new MaskableBox array and you won't get the NullPointerException.