diff --git a/src/GamePanel.java b/src/GamePanel.java new file mode 100644 index 0000000..8d65325 --- /dev/null +++ b/src/GamePanel.java @@ -0,0 +1,518 @@ +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.Serial; +import java.util.HashSet; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.Timer; + +/** + * 描述: 游戏布局 游戏的核心逻辑代码 + **/ +public class GamePanel extends JPanel { + @Serial + private static final long serialVersionUID = 2L; + private static final int sx = 50;// 左边距 + private static final int sy = 50;// 上边距 + private static final int w = 40; // 小方格宽高 + private static final int rw = 400; // 网格总宽高 + private static int GAME_DURATION = 100000; // 游戏持续时间,单位为毫秒(这里设置为100秒) + private int pj = 0, pi = 0; // 记录两个点击选中的按钮,第一个被点击的按钮坐标 + private int cc = 0;// 被点击选中的按钮个数 + private int[][] map;// 存放游戏数据的二维数组 + private boolean isEnd = false; // 游戏结束标志 + private JButton[][] btnMap; // 存放按钮的二维数组,与map对应 + private int score; // 记录分数 + private int count = 0;//记录闯关关数 + private JButton restart; // 重新开始按钮 + private Timer timer; // 计时器,用于显示游戏经过的时间 + private Timer gameTimer;//定时器,用于控制游戏时间 + private int timestamp; // 时间戳 + private boolean end=false;//判断游戏是否因超时结束 + private int flag = 0; + + public GamePanel() { + // 设置布局为不使用预设的布局 + setLayout(null); + } + + /** + * 开始游戏 + */ + public void start() { + count += 1; + // 创建游戏数据地图 + map = MapTool.createMap1(); + btnMap = new JButton[10][10]; + score = 0; + timestamp = 0; + isEnd = false; + + // 创建按钮,设置按钮属性,监听事件,并添加到按钮数组和窗体中 + for (int i = 0; i < map.length; i++) { + for (int j = 0; j < map[i].length; j++) { + JButton btn = new JButton(map[i][j] + ""); + btn.setBounds(sx + 100 + (j * w) + 2, sy + 50 + (i * w) + 2, w - 2, w - 2); + btn.setForeground(Color.RED); + btn.setFont(new Font("Arial", 0, 30));//文本字体样式 +// btn.setBackground(Color.WHITE); + btn.setBorder(BorderFactory.createRaisedBevelBorder()); + btn.setFocusPainted(false); + btn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // 如果游戏结束,返回,不执行后面的代码 + if (isEnd) { + return; + } + for (int i = 0; i < btnMap.length; i++) { + for (int j = 0; j < btnMap[i].length; j++) { + if (e.getSource().equals(btnMap[i][j])) { + // 被选中的方格个数增加一个 + cc++; + compare(j, i); + } + } + } + + } + }); + btnMap[i][j] = btn; + this.add(btn); + } + } + + if (restart != null) { + restart.setVisible(false); + this.remove(restart); + restart = null; + } + repaint(); + + // 计时器,用来刷新时间 + timer = new Timer(1000, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + timestamp++; + repaint(); + } + }); + timer.start();//启动计时器 + + if(StartFrame.ch==1){//如果是闯关模式,就添加定时器 + addGameTimer(); + } + } + + + public void start2(){ + count+=1; + // 创建游戏数据地图 + map = MapTool.createMap2(); + //创建游戏按钮地图 + btnMap = new JButton[15][15]; + //分数 + score = 0; + + timestamp = 0; + //游戏结束标志 + isEnd = false; + + flag=1; + // 创建按钮,设置按钮属性,监听事件,并添加到按钮数组和窗体中 + //按钮变多,难度变大 + for (int i = 0; i < map.length; i++) { + for (int j = 0; j < map[i].length; j++) { + JButton btn = new JButton(map[i][j] + ""); + btn.setBounds(sx + (j * w) + 2, sy + (i * w) + 2, w - 4, w - 4); + btn.setForeground(Color.RED); + btn.setFont(new Font("Arial", 0, 25));//文本字体样式 +// btn.setBackground(Color.WHITE); + btn.setBorder(BorderFactory.createRaisedBevelBorder()); + btn.setFocusPainted(false); + btn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // 如果游戏结束,返回,不执行后面的代码 + if (isEnd) { + return; + } + for (int i = 0; i < btnMap.length; i++) { + for (int j = 0; j < btnMap[i].length; j++) { + if (e.getSource().equals(btnMap[i][j])) { + // 被选中的方格个数增加一个 + cc++; + compare(j, i); + } + } + } + + } + }); + btnMap[i][j] = btn; + this.add(btn); + } + } + + if (restart != null) { + restart.setVisible(false); + this.remove(restart); + restart = null; + } + repaint(); + + // 定时器,用来刷新时间 + timer = new Timer(1000, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + timestamp++; + repaint(); + } + }); + timer.start(); + if(StartFrame.ch==1){//如果是闯关模式,就添加定时器 + GAME_DURATION=100000; + addGameTimer(); + } + } + + public void start3(){ + //关数加一 + count+=1; + // 创建游戏数据地图 + map = MapTool.createMap3(); + //创建游戏按钮地图 + btnMap = new JButton[20][20]; + //分数 + score = 0; + + timestamp = 0; + //游戏结束标志 + isEnd = false; + //标志网格线的划分 + flag=2; + // 创建按钮,设置按钮属性,监听事件,并添加到按钮数组和窗体中 + //按钮变多,难度变大 + for (int i = 0; i < map.length; i++) { + for (int j = 0; j < map[i].length; j++) { + JButton btn = new JButton(map[i][j] + ""); + btn.setBounds(sx + (j * w) + 2 , sy + (i * w) + 2 , w - 4, w - 4 ); + btn.setForeground(Color.RED); + btn.setFont(new Font("Arial", 0, 25));//文本字体样式 + btn.setBackground(Color.WHITE); + btn.setBorder(BorderFactory.createRaisedBevelBorder()); + btn.setFocusPainted(false); + btn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // 如果游戏结束,返回,不执行后面的代码 + if (isEnd) { + return; + } + for (int i = 0; i < btnMap.length; i++) { + for (int j = 0; j < btnMap[i].length; j++) { + if (e.getSource().equals(btnMap[i][j])) { + // 被选中的方格个数增加一个 + cc++; + compare(j, i); + } + } + } + + } + }); + btnMap[i][j] = btn; + this.add(btn); + } + } + + if (restart != null) { + restart.setVisible(false); + this.remove(restart); + restart = null; + } + repaint(); + + // 定时器,用来刷新时间 + timer = new Timer(1000, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + timestamp++; + repaint(); + } + }); + timer.start(); + + if(StartFrame.ch==1){//如果是闯关模式,就添加定时器 + GAME_DURATION=200000;//最后一关的限时为200s + addGameTimer(); + } + + } + + + public void addGameTimer(){//添加定时器 + gameTimer = new Timer(GAME_DURATION, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + //游戏时间到,结束游戏 + endGame(); + end=true;//游戏异常结束 + repaint();//重新绘制界面 + timer.stop();//关闭计时器 + gameTimer.stop();//关闭定时器 + } + }); + gameTimer.setRepeats(false);//只执行一次,时间到了就结束 + gameTimer.start();//启动定时器 + } + + + /** + * 判断是否游戏结束 + * 1、判断二维数组map中的所有元素是否均为0, 全部为0返回true表示游戏结束 + * 2、有不为0的,判断二维数组map中是否还有重复值,没有重复值返回true表示游戏结束 + * 否则返回false游戏继续 + * map 二维数组,元素为int类型 + */ + public boolean isEnd(int[][] map) { + int count_0 = 0; + int count = 0; + HashSet hashSet = new HashSet(); + for (int[] ms : map) { + for (int m : ms) { + count++; + if (m != 0) { + hashSet.add(m); + } else { + count_0++; + } + } + } + + for (int[] ms : map) { + for (int m : ms) { + if (m != 0) { + //地图里没有重复的元素了 + return hashSet.size() + count_0 == count;//如果有重复元素,那么hashSet.size+count_030)isEnd=true; + // 游戏结束 + if (isEnd) { + //绘制游戏结束画面 + endGame(); + //如果是闯关模式且关数小于3 + if(StartFrame.ch==1&&count<3){ + //下一关按钮 + JButton nextOne = new JButton("下一关"); + nextOne.setForeground(Color.RED); + nextOne.setFont(new Font("微软雅黑", 0, 20)); + nextOne.setBounds(180,430,120,40); + nextOne.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if(count==1)start2();//开启第二关 + else if(count==2)start3();//开启第三关 + nextOne.setVisible(false); + } + }); + this.add(nextOne);//添加"下一关"按钮 + } + repaint();//绘制游戏结束画面 + } + } + + repaint(); + } + + + public void endGame(){ + // 关闭计时器 + timer.stop(); + if(StartFrame.ch==1){ + //关闭定时器 + gameTimer.stop(); + } + // 隐藏剩余的按钮 + for (int i = 0; i < map.length; i++) { + for (int j = 0; j < map[i].length; j++) { + if (map[i][j] != 0) { + btnMap[i][j].setVisible(false); + } + } + } + // 创建添加重新开始按钮 + restart = new JButton("重新开始"); + restart.setBackground(Color.WHITE); + restart.setBounds(180, 350, 120, 40); + restart.setBorder(BorderFactory.createRaisedBevelBorder()); + restart.setFocusPainted(false); + restart.setForeground(Color.RED); + restart.setFont(new Font("微软雅黑", 0, 20)); + + //游戏结束后点击重新开始按钮回到开始页面 + restart.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + new StartFrame(); + } + }); + //添加”重新开始按钮“ + this.add(restart); + } + + /** + * 打印网格数据 + */ + private void printMap(int ci, int cj) { + if (ci == pi && cj == pj) { + System.out.println("ci:" + ci + ", cj:" + cj); + } else { + System.out.println("ci:" + ci + ", cj:" + cj + ", pi:" + pi + ", pj:" + pj); + } + for (int i = 0; i < map.length; i++) { + for (int j = 0; j < map[i].length; j++) { + if (ci == pi && cj == pj) { + System.out.print(((ci == i && cj == j) ? "[" + map[i][j] + "]" : " " + map[i][j] + " ") + " "); + } else { + System.out.print( + ((ci == i && cj == j || pi == i && pj == j) ? "[" + map[i][j] + "]" : " " + map[i][j] + " ") + + " "); + } + } + System.out.println(); + } + } +} \ No newline at end of file