java - 棋盘未绘制正确数量的棋子

标签 java object paint

我正在尝试开发一个棋盘格,给定类(class)模板和一些学校代码。我让棋盘出现,但没有绘制适量的棋子。应该有 7 个红色和 9 个黑色棋子,但每次我运行程序时,都会绘制不同数量的棋子。

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);
}
}

最佳答案

如果您已遵循 previous question 中的一些建议您可能已经避免了这个问题。

据我所知,您的问题是您没有调用 super.paint,它负责(以及许多其他事情)准备图形 > 绘画的背景。它通过清除之前绘制的内容来实现此目的。

您应该从 JPanel 之类的东西开始,而不是覆盖 JAppletpaint(这会在小程序更新时导致闪烁)重写它的 paintComponent 方法。 JPanel 是双缓冲的,这将防止发生任何闪烁。不要忘记调用 super.paintComponent

您不应该在每次调用 paint 时都调用 fillBorder,这在很多层面上都是浪费,相反,您应该仅在需要时调用它。通过更巧妙的设计,您实际上可以从构造函数中调用它,但我没有时间重新编码整个程序。

小程序的大小是由包含它的 HTML 页面定义的,而不是小程序本身,依赖魔数(Magic Number)(例如 APP_WIDTHAPP_HEIGHT)是一个坏主意。相反,您应该依赖已知值,例如 getWidthgetHeight。当然,这是假设您希望能够调整可玩区域的大小,并避免人们以错误的大小部署您的小程序时可能出现的问题;)

虽然,我猜测 placeCheckers 是一种测试方法,但您应该知道,paint 可以出于多种原因被调用任意多次,其中许多原因是您无法控制的,这意味着每次调用 paint 时,跳棋都会被随机化。

相反,您应该考虑创建一个虚拟板,其中包含有关游戏状态的信息并根据需要进行更新。然后,您只需使用绘画过程来反射(reflect)该模型。

我如何“开始”的一个例子......

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);
        }

    }
}

已更新

这个让我挠头一阵子。基本上,经过一些额外的检查,我发现跳棋被允许占据原本应该被占用的空间。在对 do-while 循环进行猛烈攻击后,我检查了 setOccupy 方法并发现...

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

您正在将Square占用状态分配回您传递的值,这对任何事情都没有影响

相反,它应该看起来更像......

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

您可能还想阅读Why CS teachers should stop teaching Java applets

关于java - 棋盘未绘制正确数量的棋子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21355769/

相关文章:

python - 绘制图像到 gtk.DrawingArea?

java - 有没有人在巴克明斯特有真实的经验?

java - Unity 4.3 + Android - 我需要在 1080 x 1920 下至少以 30 FPS 更新 Texture2D 或 RenderTexture

java - 如何迭代一次会更改几次的对象数组,但同时确保迭代所有项目?

java - ArrayList中的对象正在改变

java - 在 Java 类之间传递数据

Java并发实践: BoundedExecutor implementation

r - 在 R 中通配数据框或其他对象

object - SWF 对象参数 - scale 或 scaleMode

delphi - 在 TFrame 表面上绘画最安全、最正确的方法是什么?