Question

I am trying to develop a checkerboard given a template of classes and some code for school. I got the board to appear but the right amount of checkers are not being drawn. There are supposed to be 7 red and 9 black checkers but each time I run the program a different amount of each is drawn.

import java.applet.Applet;
import java.awt.*;
import java.util.Random;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class Checkers extends JApplet
{
private final int MAX_SIZE = 8; 
private final int APP_WIDTH = 400;
private final int APP_HEIGHT = 400;
private final int MAXSIZE = 8;

Square[][] sq;

public void paint(Graphics page)
    {
   setBackground(Color.white);
   fillBoard(page); // draws the method that will draw the checkers         
   placeCheckers(page, 7, Color.red);   //method to place the red checkers
   placeCheckers(page, 9, Color.black); //method to draw  black checkers
   CheckJumps(page);    //check if checkers can jump    
   setSize (APP_WIDTH,APP_HEIGHT);

   }

 public void fillBoard(Graphics page)
 {  
    sq = new Square[8][8];

    int x,y;
    Color rb;

    for (int row = 0; row < MAXSIZE; row++)
      for (int col = 0; col < MAXSIZE; col++)
      {
         x = row * (APP_WIDTH/MAXSIZE);
         y = col * (APP_HEIGHT/MAXSIZE);
         if ( (row % 2) == (col % 2) )
            rb = Color.red;
         else
            rb = Color.black;
         sq[row][col] = new Square (x, y, rb);  
      }

     for (int row = 0; row < 8; row++)
       for (int col = 0; col < 8; col++)
          sq[row][col].draw(page);
}

public void placeCheckers (Graphics page, int num_checkers, Color ncolor)
    {
    int count, row, col;
    int x, y;
    Circle c;

   Random rand = new Random();

   for (count = 0; count < num_checkers; count++)
   {
      do
      {
         row = rand.nextInt(8);
         col = rand.nextInt(8);
      } while (sq[row][col].getOccupy() || ncolor == sq[row][col].getColor());

      x = row * (APP_WIDTH/MAXSIZE);
      y = col * (APP_HEIGHT/MAXSIZE);

      c = new Circle (x, y, 50, ncolor);

      c.draw(page);

      sq[row][col].setOccupy(true);
   }    
    }

class Square 
{

 private int x, y = 0;  
 private Color c;
 private boolean occupied;

 public Square (int x, int y, Color c)
 {
   this.x = x;
   this.y = y;
   this.c = c;
 }

 public void setX (int x)
 {
   x = this.x;
 }

 public int getX ()
 {
   return x;
 }

 public void setY (int y)
 {
   y= this.y;
 }

 public int getY ()
 {
   return y;
 }

 public void setColor (Color c)
 {
   c = this.c;
 }

 public Color getColor ()
 {
   return c;
 }

 public void setOccupy (boolean occupied)
 {
   occupied = this.occupied;
 }

 public boolean getOccupy ()
 {
   return occupied;
 }

 public String toString()
 {
   return ("X coordinate: " + x + "\nY coordinate:" + y + "\nSquare color: " + c);
 }

public void draw (Graphics page)
    {
      page.setColor(c);
      page.fillRect(x, y, 50, 50);    
    } 
}

class Circle
{


   private int x,y;
   private int diameter;
   private Color c;

   public Circle (int x, int y, int diameter, Color c)
   {
      this.x = x;
      this.y = y;
      this.diameter = diameter;
      this.c = c;
   }


   public void setX (int x)
   {
      x = this.x;
   }

    public int getX ()
    {
      return x;
    }

    public void setY (int y)
    {
      y= this.y;
    }

    public int getY ()
    {
      return y;
    }

    public void setColor (Color c)
    {
      c = this.c;
    }

    public Color getColor ()
    {
      return c;
    }

    public void setDiameter (int x)
    {
      diameter = x;
    }


public void draw (Graphics page)
{
   page.setColor(c);
   page.fillOval(x, y, diameter, diameter);
}
}
Was it helpful?

Solution

If, you have followed some of the advice from your previous question you may have avoided this issue.

As near as I can tell, your problem is you're not calling super.paint, which is responsible for (amongst a lot of other things) preparing the Graphics context for painting. It does this, by clearing what ever was painted on it previously.

Instead of overriding paint of JApplet, which will cause flicker when the applet is updated, you should start with something like a JPanel and override it's paintComponent method. JPanel is double buffered, which will prevent any flicker from occuring. Don't forget to call super.paintComponent.

You shouldn't be calling fillBorder every time paint is called, this is wasteful on a number of levels, instead, you should only call it when you need to. With a little bit more clever design, you could actually get away with calling it from the constructor, but I don't have the time to re-code your entire program.

The size the applet is defined by the HTML page which contains it, not the applet itself, relying on magic numbers (like APP_WIDTH and APP_HEIGHT) is a bad idea. You should, instead, rely on known values, like getWidth and getHeight. This of course assumes you'd like to be able to resize the playable area and avoid possible issues with people deploying your applet with the wrong size ;)

While, I'm guessing that placeCheckers is a test method, you should know, paint can be called any number of times for any number of reasons, many of which you don't control, this means that the checkers will be randomized each time paint is called.

Instead, you should consider creating a virtual board which contains the information about the state of the game and update this as required. You would then simply use the painting process to reflect this model.

An example of how I might "start"...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JApplet;
import javax.swing.JPanel;

public class Checkers extends JApplet {

    @Override
    public void init() {
        add(new Board());
    }

    public class Board extends JPanel {

        private final int APP_WIDTH = 400;
        private final int APP_HEIGHT = 400;
        private final int MAXSIZE = 8;

        Square[][] sq;

        @Override
        public void invalidate() {
            fillBoard();
            super.invalidate(); 
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
            for (int row = 0; row < 8; row++) {
                for (int col = 0; col < 8; col++) {
                    sq[row][col].draw(g);
                }
            }
            setBackground(Color.white);
            placeCheckers(g, 7, Color.red);   //method to place the red checkers
            placeCheckers(g, 9, Color.black); //method to draw  black checkers
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(APP_WIDTH, APP_HEIGHT);
        }

        public void fillBoard() {
            sq = new Square[8][8];

            int x, y;
            Color rb;

            int gridSize = Math.min(getWidth(), getHeight());
            int size = gridSize / MAXSIZE;

            for (int row = 0; row < MAXSIZE; row++) {
                for (int col = 0; col < MAXSIZE; col++) {
                    x = row * (gridSize / MAXSIZE);
                    y = col * (gridSize / MAXSIZE);
                    if ((row % 2) == (col % 2)) {
                        rb = Color.red;
                    } else {
                        rb = Color.black;
                    }
                    sq[row][col] = new Square(x, y, rb, size);
                }
            }

        }

        public void placeCheckers(Graphics page, int num_checkers, Color ncolor) {
            int count, row, col;
            int x, y;
            Circle c;

            int gridSize = Math.min(getWidth(), getHeight());
            int size = gridSize / MAXSIZE;

            Random rand = new Random();

            for (count = 0; count < num_checkers; count++) {
                do {
                    row = rand.nextInt(8);
                    col = rand.nextInt(8);
                } while (sq[row][col].getOccupy() || ncolor == sq[row][col].getColor());

                x = row * (gridSize / MAXSIZE);
                y = col * (gridSize / MAXSIZE);

                c = new Circle(x, y, size, ncolor);

                c.draw(page);

                sq[row][col].setOccupy(true);
            }
        }

    }

    class Square {

        private int x, y = 0;
        private Color c;
        private boolean occupied;
        private int size;

        public Square(int x, int y, Color c, int size) {
            this.x = x;
            this.y = y;
            this.c = c;
            this.size = size;
        }

        public void setX(int x) {
            x = this.x;
        }

        public int getX() {
            return x;
        }

        public void setY(int y) {
            y = this.y;
        }

        public int getY() {
            return y;
        }

        public void setColor(Color c) {
            c = this.c;
        }

        public Color getColor() {
            return c;
        }

        public void setOccupy(boolean occupied) {
            occupied = this.occupied;
        }

        public boolean getOccupy() {
            return occupied;
        }

        public String toString() {
            return ("X coordinate: " + x + "\nY coordinate:" + y + "\nSquare color: " + c);
        }

        public void draw(Graphics page) {
            page.setColor(c);
            page.fillRect(x, y, size, size);
        }
    }

    class Circle {

        private int x, y;
        private int diameter;
        private Color c;

        public Circle(int x, int y, int diameter, Color c) {
            this.x = x;
            this.y = y;
            this.diameter = diameter;
            this.c = c;
        }

        public void setX(int x) {
            x = this.x;
        }

        public int getX() {
            return x;
        }

        public void setY(int y) {
            y = this.y;
        }

        public int getY() {
            return y;
        }

        public void setColor(Color c) {
            c = this.c;
        }

        public Color getColor() {
            return c;
        }

        public void setDiameter(int x) {
            diameter = x;
        }

        public void draw(Graphics page) {
            page.setColor(c);
            page.fillOval(x, y, diameter, diameter);
        }

    }
}

Updated

This ones had me scratching me head for a while. Basically, after some additional checking I discovered that the checkers where being allowed to occupy space that was suppose to be already taken. After bashing me head against the do-while loop, I check the setOccupy method and found...

public void setOccupy(boolean occupied) {
    occupied = this.occupied;
}

You're assiging the Square's occupied state back to the value you are passing, which has no effect on anything

Instead, it should look more like...

public void setOccupy(boolean occupied) {
    this.occupied = occupied;
}

You may also like to have a read through Why CS teachers should stop teaching Java applets

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top