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( "" );
}
}
}
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
}
}
I am writing the code for connect four game.
I am using color as indicators for winners; however, "tie game" continously appears and no winners are identified even if there is a winner.
I am still learning java so I am not entirely confident with the language. Here is my code mainly.
public static class MultiDraw extends JPanel implements MouseListener {
int startX = 10;
int startY = 10;
int cellWidth = 40;
int turn = 2;
int rows = 6;
int cols = 7;
boolean Go = true;
Object winner;
String playerOne = playernames(1);
String playerTwo=playernames(2);
Color c1 = new Color(255,0,0);
Color c2 = new Color(0,255,0);
Color[][] grid = new Color[rows][cols];
Color winner_color;
public MultiDraw(Dimension dimension) {
setSize(dimension);
setPreferredSize(dimension);
addMouseListener(this);
int x = 0;
for (int row = 0; row < grid.length; row++) {
for (int col = 0; col < grid[0].length; col++) {
grid[row][col] = new Color (255, 255, 255);
}
}
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
Dimension d = getSize();
g2.setColor(new Color(0, 0, 0));
g2.fillRect(0,0,d.width,d.height);
startX = 0;
startY = 0;
for (int row = 0; row < grid.length; row++) {
for (int col = 0; col < grid[0].length; col++) {
g2.setColor(grid[row][col]);
g2.fillOval(startX, startY, cellWidth, cellWidth);
startX = startX + cellWidth;
}
startX = 0;
startY = startY +cellWidth;
}
g2.setColor(new Color(255, 255, 255));
if (turn%2==0){
g2.drawString(playerOne,400,20);
}else{
g2.drawString(playerTwo, 400, 20);
}
}
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
int xSpot = x/cellWidth;
int ySpot = y/cellWidth;
//play a turn
//while (turn <= 42){
ySpot= testForOpenSpot(xSpot);
if(ySpot<0){
System.out.println("Not a valid entry");
}else{
grid[ySpot][xSpot]= c2;
if (turn%2==0){
grid[ySpot][xSpot]= c1;
checkWinner(c1, grid);
checkWinner(c2, grid);
}else{
grid[ySpot][xSpot]= c2;
checkWinner(c1, grid);
checkWinner(c2, grid);
}
turn++;
}
repaint();
print_player(winner_color, c1, c2);
}
public String playernames(int i){
Scanner scan = new Scanner(System.in);
System.out.println("Enter the name of the" + i + " player:");
String playerOne = scan.nextLine();
return playerOne;
}
public Color checkWinner(Color c, Color[][] grid){
//check right and left
for(int row = 0; row<grid.length; row++){
for (int col = 0;col < grid[0].length - 3;col++){
if (grid[row][col].equals(c) &&
grid[row][col+1].equals(c)&&
grid[row][col+2].equals(c)&&
grid[row][col+3].equals(c)){
return c ;
}
}
}
//check for 4 up and down
for(int row = 0; row < grid.length - 3; row++){
for(int col = 0; col < grid[0].length; col++){
if (grid[row][col] == c &&
grid[row][col+1] == c &&
grid[row][col+2] == c &&
grid[row][col+3] == c){
return c;
}
}
}
//check upward diagonal
for(int row = 3; row < grid.length; row++){
for(int col = 0; col < grid[0].length - 3; col++){
if (grid[row][col] == c &&
grid[row-1][col+1] == c &&
grid[row-2][col+2] == c &&
grid[row-3][col+3] == c){
return c;
}
}
}
//check downward diagonal
for(int row = 0; row < grid.length - 3; row++){
for(int col = 0; col < grid[0].length - 3; col++){
if (grid[row][col].equals(c) &&
grid[row+1][col+1].equals(c) &&
grid[row+2][col+2].equals(c) &&
grid[row+3][col+3].equals(c)){
return c;
}
}
}
return new Color(255,255,255);
}
public void print_player(Color winner_color, Color c1, Color c2){
//determine if winner is color1(first player):
winner_color = checkWinner(c1,grid);
//determine if winner is color2 (2nd player):
winner_color = checkWinner(c2,grid);
if (winner_color == c1){
System.out.println("Winner is first player");}
else if (winner_color == c2){
System.out.println("Winner is 2nd player");}
else{
System.out.println("Tie game");
}
}
public int testForOpenSpot(int xSpot){
int ySpot = rows-1;
while (!(grid[ySpot][xSpot].equals(new Color(255,255,255))|| ySpot<0)){
ySpot--;
}
return ySpot;
}
I keep on getting this error while running the code:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 6
One of the loops for your array is going out of bounds. Step through your code and see where it is stepping out of bounds. This error can easily be fixed by stepping through your code and seeing when it happens.
I would first like to say that I have extensively looked into this over the past day and I haven't found anything that fits this particular case. I'm in the midst of trying to create a simply Conway's Game of Life Application, and I seem to be having trouble with drawing to a JavaFX Canvas. Everything seems to be configurerd correctly (Canvas added to a layout container, said container added to a scene, and the stage is started) but even after trying different ways of encapsultating the code the Canvas remains to be empty
Here is my code:
public class Life extends Application implements Runnable {
private Grid grid;
private boolean running;
private boolean paused;
private int stepsPerMinute;
#Override
public void start(Stage stage) {
this.grid = new Grid(60, 40);
this.running = true;
this.paused = false;
this.stepsPerMinute = 60;
StackPane root = new StackPane();
root.getChildren().add(grid);
Scene scene = new Scene(root, 1080, 720);
stage.setTitle("Conway's Game of Life");
stage.setScene(scene);
stage.setResizable(false);
stage.setOnCloseRequest(e -> stop());
stage.show();
}
public void run() {
while (running) {
if (!paused) {
try {
Thread.sleep(1000 / stepsPerMinute);
} catch (InterruptedException e) { e.printStackTrace(); }
grid.step();
grid.draw();
}
}
}
#Override
public void stop() {
this.running = false;
// TODO: Dump Stats at end
System.exit(0);
}
public static void main(String[] args) { launch(args); }
public class Grid extends Canvas {
private final int WIDTH = 1080, HEIGHT = 720;
private boolean[][] cellStates;
private int rows, cols;
private int stepNum;
public Grid(int rows, int cols) {
this.rows = rows;
this.cols = cols;
this.stepNum = 0;
randomize();
minWidth(WIDTH);
maxWidth(WIDTH);
prefWidth(WIDTH);
minHeight(HEIGHT);
maxHeight(HEIGHT);
prefHeight(HEIGHT);
}
public Grid(boolean[][] cellStates) {
this.cellStates = cellStates;
this.rows = cellStates.length;
this.cols = cellStates[0].length;
this.stepNum = 0;
}
public void step() {
boolean[][] updatedStates = new boolean[rows][cols];
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++) {
int aliveNeighbors = countAliveNeighbors(i, j);
if (cellStates[i][j]) {
if (aliveNeighbors == 2 || aliveNeighbors == 3)
updatedStates[i][j] = true;
}
else if (aliveNeighbors == 3)
updatedStates[i][j] = true;
}
this.cellStates = updatedStates;
stepNum++;
}
private int countAliveNeighbors(int r, int c) {
int result = 0;
for (int i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++) {
if (cellStates[ (rows + r + i) % rows ][ (cols + c + j) % cols ])
result++;
}
return result;
}
public void randomize() {
boolean[][] updatedStates = new boolean[rows][cols];
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++) {
if (Math.random() < 0.08)
updatedStates[i][j] = true;
}
this.cellStates = updatedStates;
}
public void glider(){
this.cellStates = new boolean[rows][cols];
this.cellStates[1][2] = true;
this.cellStates[2][3] = true;
this.cellStates[3][1] = true;
this.cellStates[3][2] = true;
this.cellStates[3][3] = true;
}
public void draw() {
GraphicsContext g = this.getGraphicsContext2D();
int cellWidth = WIDTH / cols, cellHeight = HEIGHT / rows;
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++) {
if (cellStates[i][j])
g.setFill(Color.color(0.0078, 0, 1));
else
g.setFill(Color.color(0.9961, 1, 0.8431));
g.fillRect(j * cellWidth, i * cellHeight, cellWidth, cellHeight);
g.strokeLine(j * cellWidth, 0, j * cellWidth, HEIGHT);
g.strokeLine(0, i * cellHeight, WIDTH, i * cellHeight);
}
}
}
}
I left the imports out of the code for sake of brevity.
Thank you!
How would I go about modifying my current code for a checker board so that the checker pieces recursively alternate in color? Just to be clear, I don't want each piece to be a solid color - I want them to have levels that alternate in color in on itself. So for example, the currently yellow pieces would change to being yellow and blue pieces, having an outer level of yellow, followed by a level of blue, then yellow, etc. I hope that makes sense? I don't believe I can highlight code, but the checker pieces start after the first nested for statement in the checkerBoard method. There are 2 cases, the first being the top 2 rows, and the second being the bottom two.
import java.awt.*;
import java.applet.*;
public class Checkerboard extends Applet
{
private final int DIST = 100;
private final int SIZE = 1000;
public void checkerBoard(int row, int col, int x, int y, boolean b, Graphics g)
{
for ( row = 0; row < 8; row++ )
{
for ( col = 0; col < 8; col++)
{
x = col * 100;
y = row * 100;
if ( (row % 2) == (col % 2) )
g.setColor(Color.black);
else
g.setColor(Color.red);
g.fillRect(x, y, 100, 100);
}
}
for ( row = 0; row < 2; row++ )
{
for ( col = 0; col < 8; col++)
{
x = col * 100;
y = row * 100;
g.setColor(Color.yellow);
g.fillOval(x, y, 100, 100);
}
}
for ( row = 7; row > 5; row-- )
{
for ( col = 0; col < 8; col++)
{
x = col * 100;
y = row * 100;
g.setColor(Color.green);
g.fillOval(x, y, 100, 100);
}
}
}
public void paint(Graphics g)
{
checkerBoard(0, 0, 0, 0, true, g);
}
}
is this what you want
for ( row = 0; row < 2; row++ )
{
for ( col = 0; col < 8; col++)
{
for ( int ring = 0; ring < 5; ring++) {
x = col * 100 + (ring * 10);
y = row * 100 + (ring * 10);
if((ring & 1) == 0){
g.setColor(Color.yellow);
}else{
g.setColor(Color.blue);
}
g.fillOval(x, y, 100-(ring*20), 100-(ring*20));
}
}
}
recursive method would be like,
private void drawCircle(int x, int y, int circleSize, int ringSize, Color primary, Color alternate, Graphics g){
if(circleSize > 0){
g.setColor(primary);
g.fillOval(x, y, circleSize,circleSize);
drawCircle(x+ringSize/2,y+ringSize/2,circleSize-ringSize,ringSize,alternate,primary, g);
}
}
for ( row = 0; row < 2; row++ )
{
for ( col = 0; col < 4; col++)
{
int y = row * 100;
int x = ((col * 2) + (col & 1)) * 100; // want to alternate squares
drawCircle(x, y, 100, 20, Color.Yellow, Color.Blue,g);
}
}
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.