0

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);
}
}
V B
  • 61
  • 2
  • 12
  • Don't call setSize from within any paint method... – MadProgrammer Jan 25 '14 at 20:27
  • I commented out setSize but the problem still persists. – V B Jan 25 '14 at 20:29
  • It won't solve the problem at hand, but will solve the problem of the prompt ramming consuming your CPU – MadProgrammer Jan 25 '14 at 20:39
  • Ok. Thanks for that advice. I'm not sure why my professor put that there if that is the case. I'm still having a hard time figuring out what the issue is. I think the paint method is being called twice and so it is going through placeCheckers four times in total but even then, I don't see why this wouldn't work. – V B Jan 25 '14 at 20:48
  • Remember, the size of a applet is defined by the HTML page, not the applet... – MadProgrammer Jan 25 '14 at 20:56

1 Answers1

2

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

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Again, thank you so much for your help between this question and the last one and for taking the time to show me what is good code. Unfortunately, I believe I am forced to stick with the current implementation of the code given. However, I have tried running your code and the same issue still persists, and I have tried debugging both but to no avail. If you have an other ideas on how to fix this, that would be most appreciated. I am guessing it has something to do with my logic in placeCheckers. – V B Jan 26 '14 at 04:01
  • What, you mean because your randomizing the position each time it's painted? – MadProgrammer Jan 26 '14 at 04:58
  • Well the project asks for the checkers to be put in random squares on the board, so that is why I put them randomly on the board. The problem is that most of the time only some of the required checkers will appear. 9 black and 7 red are to be drawn each time I run it but it will usually draw 1-2 less then the required for each. Sometimes it will draw the correct amount for one and not the other. Sometimes it will draw the correct amount for both, but there is no pattern to any of this. – V B Jan 26 '14 at 05:08
  • I feel pretty bad now. Thank you so much for all your help. I looked at the link you attached and while I don't know enough to be able to form an opinion, I always did think we should be focusing on other things in class. – V B Jan 26 '14 at 15:26