从蓝杰做完总结,突然感觉生活平静了下来,但是要是学完了不去运用,慢慢地就全会忘记,所以大家在家也要加油哦!
上面这都是题外话,今天我们来做的是最近网上很火的手机游戏——POPSTAR。
游戏规则自然不用多说,只需点击两个或两个以上颜色相同的方块即可消除,没有时间限制。每次消除的砖块越多,所得到的分也越多。到最后如果剩下10个以下的砖块,还会有额外加分。
下面我们开始写程序:
首先我们建立一个常量接口来存储信息:
/** * 常量接口 * @author Administrator * */ public interface Config { int SIZE = 30;// 砖块大小 int X = 10;// 砖块横向的个数 int Y = 10;// 砖块纵向的个数 int[][] array = new int[X][Y];// 砖块数组 // 红1 -1 // 黄2 -2 // 蓝3 -3 // 绿4 -4 // 桃5 -5 // 无0 JLabel[][] jparray = new JLabel[X][Y];// 面板数组 JTextField jtfscore = new JTextField("0", 5);//分数文本框 JTextField jtmax = new JTextField("0", 5);//最高分文本框 }
然后我们建立主窗体:
/** * 主界面 * * @author Administrator * */ public class MainFrame extends JPanel implements Config { private Random r = new Random();// 实例化随机数对象 private GameRule gr = new GameRule();// 实例化游戏规则对象 public static void main(String[] args) { MainFrame mf = new MainFrame(); mf.initGUI(); } /** * 实例化窗体 */ public void initGUI() { final JFrame jf = new JFrame("POPSTAR");// 创建一个窗体 jf.setSize(new Dimension(400, 400));// 设置窗体大小 jf.setResizable(false);// 设置窗体不可调节 jf.setLocationRelativeTo(null);// 设置窗体位置居中 jf.setDefaultCloseOperation(3);// 设置窗体关闭按钮 jf.setIconImage(new ImageIcon("assets/icon36.png").getImage());// 设置窗体的图标 this.setLayout(null);// 设置面板布局为空 BrickListener bl = new BrickListener(this);// 实例化监听器 // 循环给面板添加标签 for (int i = 0; i < X; i++) { for (int j = 0; j < Y; j++) { jparray[i][j] = new JLabel() // 给标签设置重绘方法 { public void paint(Graphics g) { super.paint(g); drawbricks(g);// 画砖块的方法 } }; jparray[i][j].setBounds(i * SIZE, 72 + j * SIZE, SIZE, SIZE);// 给标签设置绝对位置 jparray[i][j].setOpaque(true);// 设置标签透明 jparray[i][j].addMouseListener(bl);// 给标签添加鼠标监听器 this.add(jparray[i][j]);// 将标签添加到面板上 } } this.setBackground(Color.black);// 设置面板背景为黑色 jf.add(this, BorderLayout.CENTER);// 将面板添加到窗体中部 JPanel jpeast = new JPanel();// 创建东边面板 jpeast.setLayout(new FlowLayout(FlowLayout.CENTER, 50, 20));// 设置布局为流式布局 jpeast.setBackground(Color.black);// 设置背景为黑色 jpeast.setPreferredSize(new Dimension(94, 0));// 设置东部面板的大小 JButton jbustart = new JButton("开始");// 实例化开始按钮 // 给西部面板添加监听器 jbustart.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jtfscore.setText("0");// 初始化分数 for (int i = 0; i < X; i++) { for (int j = 0; j < Y; j++) { array[i][j] = r.nextInt(4) + 1;// 随机给标签添加颜色 } jf.repaint();// 重回面板 } } }); JLabel jlscore = new JLabel("当前分数");// 实例化分数标签 jlscore.setFont(new Font("微软雅黑", Font.BOLD, 12));// 设置标签字体 jlscore.setForeground(Color.white);// 设置字体颜色 JLabel jlmax = new JLabel("最高分");// 实例化最高分标签 jlmax.setFont(new Font("微软雅黑", Font.BOLD, 12));// 设置字体属性 jlmax.setForeground(Color.white);// 设置字体颜色 jtfscore.setEditable(false);// 设置分数标签不可编辑 jtfscore.setHorizontalAlignment(JTextField.CENTER);// 设置水平居中 jtfscore.setOpaque(false);// 设置透明 jtfscore.setBorder(null);// 设置无边框 jtfscore.setForeground(Color.white);// 设置字体为白色 jtfscore.setFont(new Font("微软雅黑", Font.BOLD, 12));// 设置字体属性 jtmax.setEditable(false);// 设置分数标签不可编辑 jtmax.setOpaque(false);// 设置透明 jtmax.setBorder(null);// 设置无边框 jtmax.setHorizontalAlignment(JTextField.CENTER);// 设置水平居中 jtmax.setText(gr.getmaxscore() + "");// 设置内容 jtmax.setFont(new Font("微软雅黑", Font.BOLD, 12));// 设置字体属性 jtmax.setForeground(Color.white);// 设置字体为白色 // 将组件加到容器上 jpeast.add(jbustart); jpeast.add(jlscore); jpeast.add(jtfscore); jpeast.add(jlmax); jpeast.add(jtmax); jf.add(jpeast, BorderLayout.EAST);// 将东部面板添加到窗体上 jf.setVisible(true);// 设置窗体可见 } /** * 画砖块的方法 * * @param g */ private void drawbricks(Graphics g) { for (int i = 0; i < X; i++) { for (int j = 0; j < Y; j++) { if (array[i][j] != 0) { jparray[i][j].setIcon(new ImageIcon("image/" + array[i][j] + ".png")); } else if (array[i][j] == 0) { jparray[i][j].setIcon(null); jparray[i][j].setBackground(Color.black); } } } } }
下面我们给星星面板添加监听器:
/** * 星星面板监听器 * * @author Administrator * */ public class BrickListener extends MouseAdapter implements Config { private GameRule gr = new GameRule();// 实例化游戏规则对象 private MainFrame mf;// 声明窗体对象 private AudioClip audio;// 生命声音对象 /** * 构造方法 * * @param mf主面板 */ public BrickListener(MainFrame mf) { this.mf = mf; } /** * 鼠标按下监听器 */ public void mousePressed(MouseEvent e) { JLabel jl = (JLabel) e.getSource();// 实例化标签 int x0 = jl.getBounds().x / SIZE;// 得到标签的x坐标 int y0 = (jl.getBounds().y - 72) / SIZE;// 得到标签的y坐标 if (array[x0][y0] < 0) // 如果已经被选中 { int score = (int) (5 * Math.pow(gr.getscore(x0, y0), 2));// 得到此方块的分数 gr.clean();// 将方块清除并落下 mf.repaint();// 重回面板 // 播放方块破裂的声音 try { audio = Applet.newAudioClip(new File("assets/broken.wav") .toURL()); audio.play(); } catch (MalformedURLException e1) { e1.printStackTrace(); } jtfscore.setText(Integer.parseInt(jtfscore.getText()) + score + "");// 记录分数文本框 if (Integer.parseInt(jtfscore.getText()) > Integer.parseInt(jtmax .getText())) // 如果此时分数大于最高分 { gr.savamaxscore();// 保存最高分到文件 jtmax.setText(Integer.parseInt(jtfscore.getText()) + "");// 设置当前分数到最高分 } if (gr.judge()) // 如果游戏结束 { jtfscore.setText(Integer.parseInt(jtfscore.getText()) + gr.getresidue() + "");// 添加附加分数 if (Integer.parseInt(jtfscore.getText()) > Integer .parseInt(jtmax.getText())) // 如果此时分数大于最高分 { gr.savamaxscore();// 保存最高分到文件 jtmax.setText(Integer.parseInt(jtfscore.getText()) + "");// 设置最高分 } // 播放游戏结束声音 try { audio = Applet.newAudioClip(new File("assets/win.wav") .toURL()); audio.play(); } catch (MalformedURLException e1) { e1.printStackTrace(); } JOptionPane.showMessageDialog(null, "游戏结束!");// 弹出游戏结束对话框 } } else if (array[x0][y0] > 0)// 如果该标签没有被选中 { gr.returnback();// 重置被选中的标签 // 播放选择声音 try { audio = Applet.newAudioClip(new File("assets/select.wav") .toURL()); audio.play(); } catch (MalformedURLException e1) { e1.printStackTrace(); } // 如果该标签只连接一个 if (gr.find(array[x0][y0], x0, y0) == 1) { gr.returnback();// 重置被选中标签 } } } }
最后,也是最重要的一步,就是建立游戏规则,我们建立游戏规则类:
/** * 记录游戏规则 * @author Administrator * */ public class GameRule implements Config { /** * 自动掉落 */ public void drop() { for (int i = 0; i < X; i++) { for (int j = 1; j < Y; j++) { // 如果上一行有空格 if (array[i][j] == 0) { // 把那一列向下移空格数 for (int k = j; k > 0; k--) { array[i][k] = array[i][k - 1]; } array[i][0] = 0; } } } turnleft(); } /** * 右边的自动左移 */ public void turnleft() { for (int i = 0; i < X - 1; i++) { if (sumline(i) == 0) { int line = 1; for (int k = i + 1; k < X; k++) { if (sumline(k) == 0) { line++; } else { break; } } for (int k = i; k < X - line; k++) { for (int j = 0; j < Y; j++) { array[k][j] = array[k + line][j]; } } for (int j = 0; j < Y; j++) { array[X - 1][j] = 0; } } } } /** * 求第i列的和 * * @param i列数 * @return */ public int sumline(int i) { int sum = 0; for (int j = 0; j < Y; j++) { sum += array[i][j]; } return sum; } /** * 得到这个砖块的个数 * * @param x * @param y * @return */ public int getscore(int x, int y) { int count = 0; for (int i = 0; i < X; i++) { for (int j = 0; j < Y; j++) { if (array[i][j] < 0) { count++; } } } return count; } /** * 根据颜色将砖块及周围的都变成相反数 * * @param color * @param x * @param y * @return */ public int find(int color, int x, int y) { int count = 0; if (array[x][y] == color) { count++; array[x][y] = -array[x][y]; } else { return 0; } if (x >= 1) { count += find(color, x - 1, y); } if (x < X - 1) { count += find(color, x + 1, y); } if (y >= 1) { count += find(color, x, y - 1); } if (y < Y - 1) { count += find(color, x, y + 1); } return count; } /** * 判断输赢 * * @return */ public boolean judge() { for (int i = 0; i < X; i++) { for (int j = 0; j < Y; j++) { if (array[i][j] != 0) { if (i >= 1) { if (array[i - 1][j] == array[i][j]) { return false; } } if (j >= 1) { if (array[i][j - 1] == array[i][j]) { return false; } } if (i < X - 1) { if (array[i + 1][j] == array[i][j]) { return false; } } if (j < Y - 1) { if (array[i][j + 1] == array[i][j]) { return false; } } } } } return true; } /** * 保存最高分到文件 * * @throws Exception */ public void savamaxscore() { try { File file = new File("src/bricks/save"); if (!file.exists()) { file.createNewFile(); } OutputStream os = new FileOutputStream(file); DataOutputStream dos = new DataOutputStream(os); dos.writeInt(Integer.parseInt(jtfscore.getText())); dos.flush(); os.close(); } catch (Exception e) { } } /** * 从文件中读取最高分 * * @return 最高分 * @throws Exception */ public int getmaxscore() { try { File file = new File("src/bricks/save"); if (!file.exists()) { file.createNewFile(); } InputStream is = new FileInputStream(file); DataInputStream dis = new DataInputStream(is); int score = dis.readInt(); jtmax.setText(score + ""); dis.close(); is.close(); return score; } catch (Exception e) { } return 0; } /** * 将选中的砖块清除 */ public void clean() { for (int i = 0; i < X; i++) { for (int j = 0; j < Y; j++) { if (array[i][j] < 0) { array[i][j] = 0; } } } drop(); } /** * 将选中的砖块还原 */ public void returnback() { for (int i = 0; i < X; i++) { for (int j = 0; j < Y; j++) { if (array[i][j] < 0) { array[i][j] = -array[i][j]; } } } } /** * 得到最后要加的分数 * * @return 最后要加的分数 */ public int getresidue() { int count = 0; for (int i = 0; i < X; i++) { for (int j = 0; j < Y; j++) { if (array[i][j] > 0) { count++; } } } int a[] = { 2000, 1980, 1920, 1820, 1680, 1500, 1280, 1020, 720, 380 }; if (count < 10) { return a[count]; } return 0; } }
这样,我们做的简单的POPSTAR就完成了!声音和图片我都在附件中给出,大家自己动手做一做吧~