// 导入必要的包 package view; // 引入颜色类,字体类,绘图类,随机数生成器,Swing的面板类,边界类,以及模型层的Block和Box类 import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.util.Random; import javax.swing.JPanel; import javax.swing.border.EtchedBorder; import model.Block; import model.Box; // 定义GameCanvas类,继承自JPanel public class GameCanvas extends JPanel { // 定义成员变量,包括背景色、前景色、行数、列数、游戏分数、分数更新阈值、游戏结束标记、暂停标记、方格数组、方格宽高 private Color backColor = Color.GRAY, frontColor = Color.orange; private int rows, cols, score = 0, scoreForLevelUpdate = 0; private Box[][] boxes; private int boxWidth = 25, boxHeight = 25; private boolean gameOver = false; public boolean pau = false; // 构造函数,初始化画布的行数和列数 public GameCanvas(int rows, int cols) { // 初始化成员变量 this.rows = rows; this.cols = cols; this.setOpaque(false); // 创建方格数组 boxes = new Box[rows][cols]; // 循环遍历方格数组,初始化每个方格为无色 for (int i = 0; i < boxes.length; i++) { for (int j = 0; j < boxes[i].length; j++) { boxes[i][j] = new Box(false); } } // 设置画布的位置和尺寸,以及边框样式 setBounds(0, 0, 300, 500); setBorder(new EtchedBorder(EtchedBorder.RAISED, Color.white, new Color(148, 145, 140))); } // 构造函数,允许传入背景色和前景色 public GameCanvas(int rows, int cols, Color backColor, Color frontColor) { // 调用另一个构造函数初始化行数和列数 this(rows, cols); // 设置背景色和前景色 this.backColor = backColor; this.frontColor = frontColor; } // 设置背景色的方法 public void setBackgroundColor(Color backColor) { this.backColor = backColor; } // 获取背景色的方法 public Color getBackgroundColor() { return backColor; } // 设置前景色(方块颜色)的方法 public void setBlockColor(Color frontColor) { this.frontColor = frontColor; } // 获取前景色(方块颜色)的方法 public Color getBlockColor() { return frontColor; } // 获取画布的行数的方法 public int getRows() { return rows; } // 获取画布的列数的方法 public int getCols() { return cols; } // 获取游戏分数的方法 public int getScore() { return score; } // 获取分数更新阈值的方法 public int getScoreForLevelUpdate() { return scoreForLevelUpdate; } // 获取画布上指定位置的方格引用的方法 public Box getBox(int row, int col) { // 检查索引是否合法,否则返回null if (row < 0 || row > boxes.length - 1 || col < 0 || col > boxes[0].length - 1) return null; // 返回指定位置的方格引用 return boxes[row][col]; } // 消行方法,当一行被填满时调用,将该行上方的行下移覆盖已消去的行 public void delete(int row) { // 从待消去的行开始向上遍历,直到第一行 for (int i = row; i > 0; i--) { // 将当前行复制为上一行的状态 for (int j = 0; j < 12; j++) boxes[i][j] = new Box(boxes[i - 1][j].isColorBox()); } // 重新绘制画布 repaint(); } // 自动上涨方法,在游戏过程中调用,模拟方格从下方升起 public void addRow() { // 遍历画布的行,除了最后一行 for (int i = 0; i < 19; i++) { // 将当前行复制为下一行的状态 for (int j = 0; j < 12; j++) { boxes[i][j] = new Box(boxes[i + 1][j].isColorBox()); } } // 随机填充最后一行的状态 for (int i = 0; i < 12; i++) { int a = (int) (Math.random() * 2); if (a == 1) boxes[19][i] = new Box(true); else boxes[19][i] = new Box(false); } // 重新绘制画布 repaint(); } // 重写paint方法,用于绘制游戏界面 public void paint(Graphics g) { // 调用父类的paint方法 super.paint(g); // 如果游戏结束,绘制游戏结束的信息 if (gameOver) { paintGame(g); g.setColor(Color.RED); g.setFont(new Font("黑体", Font.BOLD, 80)); g.drawString("GAME", 50, 220); g.drawString("OVER", 50, 310); } else if (pau == true) { // 如果游戏暂停,绘制游戏暂停的信息 paintGame(g); g.setColor(Color.BLUE); g.setFont(new Font("华文行楷", Font.BOLD, 40)); g.drawString("暂停", 100, 200); g.drawString("按C继续!", 60, 310); } else { // 如果游戏进行中,绘制游戏界面 paintGame(g); } } // 绘制游戏界面的方法 public void paintGame(Graphics g) { // 设置画布颜色 g.setColor(Color.BLUE); // 绘制画布边框 g.draw3DRect(0, 0, 298, 498, true); // 设置方块颜色 g.setColor(frontColor); // 遍历画布上的所有方格 for (int i = 0; i < boxes.length; i++) { for (int j = 0; j < boxes[i].length; j++) { // 如果方格有颜色,则绘制方格 if (boxes[i][j].isColorBox() == true) { g.setColor(frontColor); g.fill3DRect(j * boxWidth, i * boxHeight, boxWidth, boxHeight, true); } } } } // 设置游戏结束标记的方法 public boolean setGameOver(boolean go) { gameOver = go; return gameOver; } // 重置画布的方法,将所有方格设置为无色 public void reset() { for (int i = 0; i < boxes.length; i++) { for (int j = 0; j < boxes[i].length; j++) boxes[i][j].setColor(false); } // 重新绘制画布 repaint(); } }