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.
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
}
}
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'm trying to make a Connect Four Game in Java by using user input and drawing panel. Two people switch off turns typing the column they want their piece to go in. I'm having trouble making it so discs already placed stay on the board the next turn (because the a new drawing panel pops up with the updated board each time)(we tried using GUI but failed). I am also having trouble switching off turns and making the color change each time. Thank you so much, here is what I have so far.
import java.util.*;
import java.awt.*;
public class ConnectFour{
public static void main(String[] args){
Scanner console = new Scanner(System.in);
char [][] board = new char [7][6];
for (int i = 0; i< 7; i++){
for (int j= 0; j< 6; j++){
board[i][j] = ' ';
}
}
boolean isBlack = true ; //black discs turn
boolean isRed = false ; //red discs turn
boolean playersTurn = true ;
while (playersTurn){
if (isBlack == true ){
System.out.println("Black's Turn");
}
else {
System.out.println("Red's Turn");
}
System.out.print("Choose a column to place your disk (1-7): ");
int column = console.nextInt()-1;
if (column < 0 || column > 7) { //while loop?
System.out.print( "Column needs to be within 1-7"); //try catch?
}
drawBoard(column, board, isBlack, isRed);
// connectedFour(board);
// playersTurn = !playersTurn;
}
// isBlack = !isBlack; INVERT WHOSE TURN IT IS!!! unreachable statement??
}
public static void drawBoard(int column, char [][] board, boolean isBlack, boolean isRed) {
DrawingPanel panel = new DrawingPanel(550,550);
int rowAvailable;
Graphics g = panel.getGraphics();
g.drawLine(0,0,0,500);
g.drawLine(0,0,500,0);
g.drawLine(500,0,500,427);
g.drawLine(0,427,500,427);
for (int i = 0; i< 6; i++){
for (int j= 0; j<= 6; j++){
g.setColor(Color.YELLOW);
g.fillRect(j*71,i*71,71,71);
g.setColor(Color.WHITE);
g.fillOval(j*71,i*71,71,71);
}
}
int x = 0;
int row = 5;
while (board[column][row-x] != ' '){
x++;
}
row = 5-x;
if (isBlack == true) {
g.setColor(Color.BLACK);
board[column][row-x] = 'b';
}
else {
g.setColor(Color.RED);
board[column][row-x] = 'r';
}
// I KNOW THIS FOR LOOP DOES NOT WORK SUCCESSFULLY
for (int i = 0; i< 6; i++){
for (int j= 0; j<= 6; j++){
if(board[i][j] != 'b'){
g.fillOval((i * 71),j*71, 71,71);
}
}
}
// g.fillOval((column * 71),row*71, 71,71); //number 142 is just a test
//board[i][j] = WHOSE TURN IT IS (to update array)
// if(isBlack){
// board[column][row] = 'b';
// }
// else{
// board[column][row] = 'r';
// }
}
//get whose turn it is as parameter?? a color string? boolean?
public static boolean connectedFour( char[][] board){
int verticalCount = 0;
for (int i = 0; i< 6; i++){ //goes down each column //EXCEPTION HERE BECAUSE 0
for( int j=0; j<=6; j++){
if (board[i][j]== board[i-1][j]){
verticalCount ++;
}
}
}
int horizontalCount = 0;
for (int i =0; i<=6; i++){
for (int j =0; j<6; j++){
if (board[i][j-1] == board[i][j]){
horizontalCount++;
}
}
}
int diagonalCount = 0;
//get diagonal here
if (verticalCount >= 4 || horizontalCount >= 4|| diagonalCount >=4){
return true ; //return who the winner is. String?
//
}
else {
return false ;
}
}
}
Don't mix console based input with GUI output, these are two different user paradigms which require different work flows and approaches to manage
Don't use getGraphics, this is not how painting works. Swing has a defined paint process which you should use to ensure you are been notified when an update needs to be performed. See Painting in AWT and Swing and Performing Custom Painting for more details.
The following is a very basic example of how you might work with the API, instead of against it.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.RoundRectangle2D;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class ConnectFour {
public static void main(String[] args) {
new ConnectFour();
}
public ConnectFour() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new GamePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public enum Player {
RED, BLUE, NONE;
}
public class GamePane extends JPanel {
private BoardPane boardPane;
private JLabel label;
private Player player = null;
public GamePane() {
setLayout(new BorderLayout());
boardPane = new BoardPane();
add(boardPane);
label = new JLabel("...");
label.setHorizontalAlignment(JLabel.CENTER);
label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setBorder(new EmptyBorder(10, 10, 10, 10));
add(label, BorderLayout.NORTH);
updatePlayer();
boardPane.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
updatePlayer();
}
});
}
protected void updatePlayer() {
String text = "...";
Color color = null;
if (player == null || player.equals(Player.BLUE)) {
player = Player.RED;
text = "Red";
color = Color.RED;
} else if (player.equals(Player.RED)) {
player = Player.BLUE;
text = "Blue";
color = Color.BLUE;
}
label.setText(text);
label.setBackground(color);
boardPane.setPlayer(player);
}
}
public class BoardPane extends JPanel {
private Player[][] board;
private Player player;
private int hoverColumn = -1;
public BoardPane() {
board = new Player[8][8];
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[row].length; col++) {
board[row][col] = Player.NONE;
}
}
MouseAdapter mouseHandler = new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
hoverColumn = getColumnAt(e.getPoint());
repaint();
}
#Override
public void mouseExited(MouseEvent e) {
hoverColumn = -1;
repaint();
}
#Override
public void mouseClicked(MouseEvent e) {
if (hoverColumn > -1) {
addPieceTo(hoverColumn);
repaint();
}
}
};
addMouseMotionListener(mouseHandler);
addMouseListener(mouseHandler);
}
public void addChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
public void removeChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
public void setPlayer(Player player) {
this.player = player;
}
protected void addPieceTo(int col) {
boolean added = false;
if (col >= 0 && col < board[0].length) {
for (int row = 0; row < board.length; row++) {
if (board[row][col] != Player.NONE) {
if (row >= 0) {
board[row - 1][col] = player;
added = true;
}
break;
}
}
}
if (!added) {
if (board[0][col] == Player.NONE) {
board[board.length - 1][col] = player;
added = true;
}
}
if (added) {
fireStateChanged();
}
repaint();
}
protected void fireStateChanged() {
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
if (listeners != null && listeners.length > 0) {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : listeners) {
listener.stateChanged(evt);
}
}
}
protected int getColumnAt(Point p) {
int size = Math.min(getWidth() - 1, getHeight() - 1);
int xOffset = (getWidth() - size) / 2;
int yOffset = (getHeight() - size) / 2;
int padding = getBoardPadding();
int diameter = (size - (padding * 2)) / 8;
int xPos = p.x - xOffset;
int column = xPos / diameter;
return Math.min(Math.max(0, column), board[0].length - 1);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected int getBoardPadding() {
return 10;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
int size = Math.min(getWidth() - 1, getHeight() - 1);
int xOffset = (getWidth() - size) / 2;
int yOffset = (getHeight() - size) / 2;
g2d.fill(new RoundRectangle2D.Double(xOffset, yOffset, size, size, 20, 20));
int padding = getBoardPadding();
int diameter = (size - (padding * 2)) / 8;
for (int row = 0; row < board.length; row++) {
int yPos = (yOffset + padding) + (diameter * row);
for (int col = 0; col < board[row].length; col++) {
int xPos = (xOffset + padding) + (diameter * col);
switch (board[row][col]) {
case RED:
g2d.setColor(Color.RED);
break;
case BLUE:
g2d.setColor(Color.BLUE);
break;
default:
g2d.setColor(getBackground());
break;
}
g2d.fill(new Ellipse2D.Double(xPos, yPos, diameter, diameter));
}
}
if (hoverColumn > -1) {
int yPos = (yOffset + padding) + (diameter * 0);
int xPos = (xOffset + padding) + (diameter * hoverColumn);
if (player != null) {
switch (player) {
case RED:
g2d.setColor(Color.RED);
break;
case BLUE:
g2d.setColor(Color.BLUE);
break;
default:
g2d.setColor(getBackground());
break;
}
g2d.fill(new Ellipse2D.Double(xPos, yPos, diameter, diameter));
}
}
g2d.dispose();
}
}
}
I'm am new to graphics in java and for some reason the graphics are not displaying on the jframe. I am confused of how to set up and instantiate the graphics. There could also be a stupid error in the code that im just not seeing. Thanks for any feedback!
Map Class
public class Map extends JPanel{
private static int WIDTH;
private static int HEIGHT;
private static int ROWS;
private static int COLS;
private static int TILE_SIZE;
private static int CLEAR = 0;
private static int BLOCKED = 1;
private static int[][] GRID;
public Map(int w, int h, int t){
WIDTH = w;
HEIGHT = h;
TILE_SIZE = t;
ROWS = HEIGHT/TILE_SIZE;
COLS = WIDTH/TILE_SIZE;
GRID = new int[ROWS][COLS];
for (int row = 0; row < ROWS; row++){
for (int col = 0; col < COLS; col++){
GRID[row][col] = BLOCKED;
}
}
randomMap();
}
public void randomMap(){
int row = 0;
int col = 0;
int turn;
Random rand = new Random();
GRID[row][col] = CLEAR;
do{
turn = rand.nextInt(2)+1;
if (turn == 1)
row++;
else
col++;
GRID[row][col] = CLEAR;
}while(row<ROWS-1 && col<COLS-1);
if (row == ROWS-1){
for (int i = col; i < COLS; i++){
GRID[row][i] = CLEAR;
}
}
else{
for (int i = row; i < ROWS; i++){
GRID[i][col] = CLEAR;
}
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (int row = 0; row < WIDTH; row++){
for (int col = 0; col < HEIGHT; col++){
if (GRID[row][col] == 1){
g2d.setColor(Color.BLACK);
g2d.fillRect(row*TILE_SIZE, col*TILE_SIZE, TILE_SIZE, TILE_SIZE);
}else{
g2d.setColor(Color.WHITE);
g2d.fillRect(row*TILE_SIZE, col*TILE_SIZE, TILE_SIZE, TILE_SIZE);
}
}
}
}
public void displayConsole(){
for (int row = 0; row < ROWS; row++){
for (int col = 0; col < COLS; col++){
System.out.print(GRID[row][col] + " ");
}
System.out.println("");
System.out.println("");
}
}
}
Game Class
public class Game extends JFrame{
private Map map;
public Game(){
setLayout(null);
setBounds(0,0,500,500);
setSize(500,500);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Map map = new Map(500,500,50);
map.displayConsole();
add(map);
repaint();
setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Game game = new Game();
}
}
It is likely the painted component is of size 0x0. A custom painted component should return the preferred size of the component.
After the component is added to a frame, pack the frame to ensure the frame is the exact size needed to display the component.
Of course, either use or set an appropriate layout/constraint in the frame. In this case, I would use the default layout of BorderLayout and the default constraint of CENTER.
Andrew is correct. I had to re-do the layout to get this to work. I added the code for perferredSize() and minimumSize(), and I added a call to pack() and removed the setLayout(null). Also, you have a problem calculating your HEIGHT and WIDTH, they don't line up to ROWS and COLS and will throw Index Out Of Bounds.
Corrected code below.
class Game extends JFrame
{
private Map map;
public Game()
{
// setLayout( null );
setBounds( 0, 0, 500, 500 );
setSize( 500, 500 );
setResizable( false );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
Map map = new Map( 500, 500, 50 );
map.displayConsole();
add( map );
pack();
repaint();
setVisible( true );
}
public static void main( String[] args )
{
// TODO Auto-generated method stub
Game game = new Game();
}
}
class Map extends JPanel
{
private static int WIDTH;
private static int HEIGHT;
private static int ROWS;
private static int COLS;
private static int TILE_SIZE;
private static int CLEAR = 0;
private static int BLOCKED = 1;
private static int[][] GRID;
public Map( int w, int h, int t )
{
WIDTH = w;
HEIGHT = h;
TILE_SIZE = t;
ROWS = HEIGHT / TILE_SIZE;
COLS = WIDTH / TILE_SIZE;
GRID = new int[ ROWS ][ COLS ];
for( int row = 0; row < ROWS; row++ )
for( int col = 0; col < COLS; col++ )
GRID[row][col] = BLOCKED;
randomMap();
}
public void randomMap()
{
int row = 0;
int col = 0;
int turn;
Random rand = new Random();
GRID[row][col] = CLEAR;
do {
turn = rand.nextInt( 2 ) + 1;
if( turn == 1 )
row++;
else
col++;
GRID[row][col] = CLEAR;
} while( row < ROWS - 1 && col < COLS - 1 );
if( row == ROWS - 1 )
for( int i = col; i < COLS; i++ )
GRID[row][i] = CLEAR;
else
for( int i = row; i < ROWS; i++ )
GRID[i][col] = CLEAR;
}
#Override
public Dimension preferredSize()
{
// return super.preferredSize(); //To change body of generated methods, choose Tools |
return new Dimension( WIDTH, HEIGHT );
}
#Override
public Dimension minimumSize()
{
return preferredSize();
}
public void paintComponent( Graphics g )
{
super.paintComponent( g );
Graphics2D g2d = (Graphics2D) g;
for( int row = 0; row < ROWS; row++ )
for( int col = 0; col < COLS; col++ )
if( GRID[row][col] == 1 ) {
g2d.setColor( Color.BLACK );
g2d.fillRect( row * TILE_SIZE, col * TILE_SIZE,
TILE_SIZE, TILE_SIZE );
} else {
g2d.setColor( Color.WHITE );
g2d.fillRect( row * TILE_SIZE, col * TILE_SIZE,
TILE_SIZE, TILE_SIZE );
}
}
public void displayConsole()
{
for( int row = 0; row < ROWS; row++ ) {
for( int col = 0; col < COLS; col++ )
System.out.print( GRID[row][col] + " " );
System.out.println( "" );
System.out.println( "" );
}
}
}
Sometimes the mousePressed event gets executed , but at other times it won't. It also seems to depend on the time you press it. How do I get it to ALWAYS work?
I'm not sure which part of the code is faulty, so here's the whole class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Board extends JPanel implements ActionListener {
Timer timer = new Timer(500, this);
private boolean[][] board;
private boolean isActive = false;
private int height;
private int width;
private int multiplier = 20;
private JButton btnRun;
private JButton btnRand;
private JButton btnClear;
public Board() {
this(new boolean[20][20]);
}
public Board(final boolean[][] board) {
this.board = board;
height = board.length;
width = board[0].length;
setBackground(Color.black);
btnRun = new JButton("Run");
add(btnRun);
btnRun.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
isActive = !isActive;
btnRun.setText(isActive ? "Pause" : "Run");
}
});
btnRand = new JButton("Random");
add(btnRand);
btnRand.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setBoard(randomBoard());
}
});
btnClear = new JButton("Clear");
add(btnClear);
btnClear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setBoard(clearBoard());
}
});
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
getBoard()[e.getY() / multiplier][e.getX() / multiplier] = !getBoard()[e.getY() / multiplier][e.getX() / multiplier];
}
});
timer.start();
}
public int getMultiplier() {
return multiplier;
}
public boolean[][] getBoard() {
return board;
}
public void setBoard(boolean[][] boardToSet) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
board[i][j] = boardToSet[i][j];
}
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
g.setColor(board[i][j] ? Color.green : Color.gray);
g.fillRect(j * multiplier, i * multiplier, multiplier - 1, multiplier - 1);
}
}
if (isActive) {
timer.start();
}
else {
timer.stop();
repaint();
}
}
public void actionPerformed(ActionEvent e) {
board = nextGeneration();
repaint();
}
public boolean[][] randomBoard() {
Random rand = new Random();
boolean[][] randBoard = new boolean[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
randBoard[i][j] = rand.nextBoolean();
}
}
return randBoard;
}
public boolean[][] clearBoard() {
boolean[][] emptyBoard = new boolean[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
emptyBoard[i][j] = false;
}
}
return emptyBoard;
}
public int countSurrounding(int a, int b) {
int count = 0;
int[][] surrounding = {{a - 1, b - 1},
{a - 1, b },
{a - 1, b + 1},
{a , b - 1},
{a , b + 1},
{a + 1, b - 1},
{a + 1, b },
{a + 1, b + 1}};
for (int[] i: surrounding) {
try {
if (board[i[0]][i[1]]) {
count++;
}
}
catch (ArrayIndexOutOfBoundsException e) {}
}
return count;
}
public boolean[][] nextGeneration() {
boolean[][] nextBoard = new boolean[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
nextBoard[i][j] = board[i][j];
}
}
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (board[i][j] && !(countSurrounding(i, j) == 2 || countSurrounding(i, j) == 3)) {
nextBoard[i][j] = false;
}
else if (!board[i][j] && countSurrounding(i, j) == 3) {
nextBoard[i][j] = true;
}
}
}
return nextBoard;
}
}
Add a System.out statement in mousePressed() and you will see that it is always called:
public void mousePressed(MouseEvent e) {
System.out.println("mousePressed");
getBoard()[e.getY() / multiplier][e.getX() / multiplier] = !getBoard()[e.getY() / multiplier][e.getX() / multiplier];
repaint();
}
Like others suggested in your other very similar question, the problem stems from your use of timers in your paint method.
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
g.setColor(board[i][j] ? Color.green : Color.gray);
g.fillRect(j * multiplier, i * multiplier, multiplier - 1, multiplier - 1);
}
}
//if (isActive) { // take this stuff out...
// timer.start();
//}
//else {
// timer.stop();
// repaint();
//}
}
The paintComponent() method should be used to draw your components only. Do not use it to start/stop timers, make additional calls to repaint(), or otherwise call any other kind of program logic. Rethink your design, especially in paintComponent().
In addition to what whiskeyspider said, if you click on a cell while it's running, you won't see the cell light up until the next generation, and only if that position is considered alive, after processing, in the next generation.