首页
动态
归档
Github
留言
工具箱
更多
邻居
壁纸
音乐
Search
1
欢迎访问我的日志空间
8,244 阅读
2
C语言读写程序文件-学习三十二
742 阅读
3
WEB音乐播放器源码
712 阅读
4
Typecho - Joe主题魔改版(持续更新)
660 阅读
5
Typecho-1.1/17.10.30-定制版源码
639 阅读
学习笔记
源码库
BUG
第九艺术
登录
Search
标签搜索
学习笔记
C语言
typecho
Java
扫雷
源码
PHP
插件
网站源码
音乐播放器
模板
git
github
bug
XG.孤梦
累计撰写
50
篇文章
累计收到
44
条评论
首页
栏目
学习笔记
源码库
BUG
第九艺术
页面
动态
归档
Github
留言
工具箱
邻居
壁纸
音乐
搜索到
50
篇与
的结果
2022-05-26
Java实现扫雷小游戏二
布雷上一篇已经完成了界面UI的实现,接下来开始功能的实现。定义布雷类(com.tools/LayMine.java)(1)布雷采用随机生成的布雷方式,玩家第一次点击小方格不应该是雷,故布雷功能设计在玩家第一次左键时开始布雷。参数row和col是第一次点击的鼠标坐标。public class LayMine { /** * labels:存储方格的二维数据 * row:当前鼠标点击的x值 * col:当前鼠标点击的y值 */ public static void lay(MineLabel[][] labels, int row, int col) { int count = 0; Random random = new Random(); // 随机 while (count<Tools.allcount) { int x = random.nextInt(Tools.rows); int y = random.nextInt(Tools.cols); if(!labels[x][y].isMineTag() && (x !=row && y!= col)) { // 布雷 labels[x][y].setMineTag(true); count++; } } countBomb(labels); }(2)计算小方格周围雷的数量分析当前方格(x,y)周围方格的坐标:设 x 和 y的最大值分别为 X 和 Y :([0, x+1],[0, y+1])([x-1, x+1],[0, y+1])([x-1, X],[0, y+1])([0, x+1],[y-1, y+1])([x-1, x+1],[y-1, y+1])([x-1, X],[y-1, y+1])([0, x+1],[y-1, Y])([x-1, x+1],[y-1, Y])([x-1, X],[y-1, Y])当前点(x,y)的周围方格x值最小值或者为0,或者为x-1,且不能小于0,x的最小值取Math.max(0, x- 1),x的最大值x+1,或者为X,且x+1最大不能超过X,故x的范围:Math.max(0, x - 1) 至 Math.min(Tools.rows - 1, x + 1)同理y的范围:Math.max(0, y - 1) 至 Math.min(Tools.cols - 1, y + 1)实现方法一理解简单,通俗易懂,代码执行效率较低,不推荐使用public static void countBomb(MineLabel[][] labels) { int count = 0; if (!mineLabel[i][j].isMine()) { // 计算雷块周围八个方向雷数 /** * 上 */ if (i > 0) { if (labels[i - 1][j].isMine()) { count++; } } /** * 左上 */ if (i > 0 && j>0) { if (labels[i - 1][j-1].isMine()) { count++; } } /** * 右上 */ if (i > 0&&j+1< Tools.cols) { if (labels[i - 1][j+1].isMine()) { count++; } } /** * 左 */ if (j>0) { if (labels[i][j-1].isMine()) { count++; } } /** * 右 */ if (j+1< Tools.cols) { if (labels[i][j+1].isMine()) { count++; } } /** * 左下 */ if (i+1< Tools.rows && j>0) { if (labels[i + 1][j-1].isMine()) { count++; } } /** * 下 */ if (i+1< Tools.rows) { if (labels[i + 1][j].isMine()) { count++; } } /** * 右下 */ if (i+1< Tools.rows && j+1< Tools.cols) { if (labels[i + 1][j+1].isMine()) { count++; } } } }实现方法二 /** * |计算周围雷数 */ public static void countBomb(MineLabel[][] labels) { int count = 0; for (int i = 0; i < Tools.rows; i++) { for (int j = 0; j < Tools.cols; j++) { count = 0; // 当前方格不是雷才计算周围雷的数量 if (!labels[i][j].isMineTag()) { for (int x = Math.max(i - 1, 0); x <= Math.min(i + 1, Tools.rows - 1); x++) { for (int y = Math.max(j - 1, 0); y <= Math.min(j + 1, Tools.cols - 1); y++) { if (labels[x][y].isMineTag()) { count++; } } } labels[i][j].setCountAround(count); } } } }编写测试类(test/TestBomb.java)测试布雷和计数是否准确public class TestBomb { /** * 测试类 */ public static void main(String[] args) { MainFrame mainframe = new MainFrame(); MineLabel[][] labels = mainframe.getBombJPanel().getLabels(); LayMine.lay(labels, 3, 3); // 假设当前鼠标点击位置【3,3】 LayMine.countBomb(labels); for (int i = 0; i < Tools.rows; i++) { for (int j = 0; j < Tools.cols; j++) { if (labels[i][j].isMineTag()) { labels[i][j].setIcon(Tools.mine); }else { int count = labels[i][j].getCountAround(); labels[i][j].setIcon(Tools.mineCount[count]); } } } } }运行效果鼠标事件监听添加鼠标事件监听(com.listener/MouListener)public class MouListener implements MouseListener { MainFrame mainframe; MineLabel[][] labels; Boolean isDoublePress = false;; public MouListener(MineLabel[][] labels, MainFrame mainframe) { this.labels = labels; this.mainframe = mainframe; }在 BombJPanel.java 中为雷区小方块添加事件监听 public BombJPanel(MainFrame mainframe) { this.mainframe = mainframe; //定义布局方式,网格布局 this.setLayout(new GridLayout(Tools.rows, Tools.cols)); listener = new MouListener(labels,mainframe); init(); } // 初始化 private void init() { // 实例化小方格 for(int i = 0;i<labels.length;i++) { for(int j = 0; j<labels[i].length;j++) { labels[i][j] = new MineLabel(i, j); labels[i][j].setIcon(Tools.blank); this.add(labels[i][j]); labels[i][j].addMouseListener(listener); } } // 实现边框效果 Border lowerBorder = BorderFactory.createLoweredBevelBorder(); Border emptyBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5); //边框大小 CompoundBorder compoundBorder = BorderFactory.createCompoundBorder(emptyBorder, lowerBorder) ; this.setBorder(compoundBorder); this.setBackground(Color.LIGHT_GRAY); } }需求分析:鼠标操作包含:左键、右键、左右键同时按下、右键一次、右键两次、右键三次。鼠标按下鼠标左键按下时效果:(1)设置笑脸为惊叹(2)左右键同时按下:设置鼠标所在位置周围小方格为背景效果左键按下时效果:(1)设置笑脸为惊叹(2)如果未被展开的,则显示鼠标所在位置的小方格的背景(3)已被展开则不做处理鼠标右键按下时效果:(1)第一次按下:标记插上红旗(2)第二次按下:标记显示问号(3)第三次按下:还原 // 鼠标按下时 @Override public void mousePressed(MouseEvent e) { MineLabel mineLabel = (MineLabel) e.getSource(); // 获取事件源 int row = mineLabel.getRowx(); int col = mineLabel.getColy(); // 判断是否是鼠标双击(左右键)操作 if (e.getModifiersEx() == InputEvent.BUTTON1_DOWN_MASK + InputEvent.BUTTON3_DOWN_MASK) { isDoublePress = true; doublePress(row, col); // 鼠标左键按下事件 } else if (e.getModifiers() == InputEvent.BUTTON1_MASK && !mineLabel.isFlagTag()) { // 对没有被展开或标记的方格 if (!mineLabel.isExpendTag()) { // 鼠标左键按下背景 mineLabel.setIcon(Tools.mineCount[0]); } // 表情变惊讶 mainframe.getFaceJPanel().getLabelFace().setIcon(Tools.face2); // 鼠标右键按下事件 } else if (e.getModifiers() == InputEvent.BUTTON3_MASK && !mineLabel.isExpendTag()) { // 右键点击数为 0 时 if (mineLabel.getRightClickCount() == 0) { mineLabel.setIcon(Tools.flag); // 设置旗子标记 mineLabel.setRightClickCount(1); mineLabel.setFlagTag(true); Tools.bombCount--; mainframe.getFaceJPanel().setNumber(Tools.bombCount); // 改变计数区雷数图片 // 右键点击数为 1 时 } else if (mineLabel.getRightClickCount() == 1) { mineLabel.setIcon(Tools.ask); // 设置问号标记 mineLabel.setRightClickCount(2); mineLabel.setFlagTag(false); Tools.bombCount++; mainframe.getFaceJPanel().setNumber(Tools.bombCount); // 改变计数区雷数图片 // 第3次点击还原回 未标记状态 } else { mineLabel.setIcon(Tools.blank); mineLabel.setRightClickCount(0); mineLabel.setFlagTag(false); } } }FaceJPanel.java类中添加:// 计数器 根据当前旗子数计算剩余雷数 public void setNumber(int count) { int b = 0; if (count < 0) { b = 10; } else { b = count / 100; } int g = Math.abs(count) % 10; int s = Math.abs(count) / 10 % 10; labelCountG.setIcon(Tools.timeCount[g]); labelCountS.setIcon(Tools.timeCount[s]); labelCountB.setIcon(Tools.timeCount[b]); }鼠标释放需求分析:包含左右键双击释放,左键释放,鼠标右键弹起没有任何动作。鼠标左右键双击释放(1)如果当前方格(被点击的方格)没有标记,且之前未被展开,则还原成点击前的状态(外观);(2)否则(已标记,或者已被展开),就判断方格周围雷的数量与周围被标记旗子的方格数是否相等,如果相等就展开周围的方格A.相等的情况有标记存在两种情况:标记正确:如下图对圆圈所在方格双击释放时将打开其周围的方格标记错误:会有惩罚,相当于触雷,游戏结束。即当前方格周围的雷全部并且正确标记,则会迅速打开当前方格周围未打开的方格,如果标记有错误,则进行惩罚B.不相等:还原小方格状态鼠标左键释放(1)如果是第一次点击,则布雷,且点击的方格不布雷,确保第一次点击不触雷。(2)如果踩到雷,则引发触雷,游戏结束(3)否则展开方格// 鼠标左右键同时按下 private void doublePress(int row, int col) { for (int x = Math.max(0, row - 1); x <= Math.min(Tools.rows - 1, row + 1); x++) { for (int y = Math.max(0, col - 1); y <= Math.min(Tools.cols - 1, col + 1); y++) { if (!labels[x][y].isExpendTag() && !labels[x][y].isFlagTag()) { int rightClickCount = labels[x][y].getRightClickCount(); // 对标记旗子或者展开的不做处理 if (rightClickCount == 1) { labels[x][y].setIcon(Tools.flag); } else { labels[x][y].setIcon(Tools.mineCount[0]); } } } } } // 左键展开方格 private void expand(int x, int y) { int count = labels[x][y].getCountAround(); if (!labels[x][y].isExpendTag() && !labels[x][y].isFlagTag()) { // 周围雷为0,递归调用继续展开 if (count == 0) { labels[x][y].setIcon(Tools.mineCount[count]); labels[x][y].setExpendTag(true); for (int i = Math.max(0, x - 1); i <= Math.min(Tools.rows -1, x + 1); i++) { for (int j = Math.max(0, y - 1); j <= Math.min(Tools.cols -1, y + 1); j++) { expand(i, j); } } } else { // 显示周围雷数 labels[x][y].setIcon(Tools.mineCount[count]); labels[x][y].setExpendTag(true); } } } @Override public void mouseReleased(MouseEvent e) { MineLabel mineLabel= (MineLabel) e.getSource(); // 当前方格 int row = mineLabel.getRowx(); int col = mineLabel.getColy(); // 鼠标双击释放(右键不做处理) if(isDoublePress) { isDoublePress = false; if (!mineLabel.isExpendTag() && !mineLabel.isFlagTag()) { backIcon(row, col); } else { boolean isEquals = isEquals(row, col); if (isEquals) { doubleExpend(row, col); } else { backIcon(row, col); } } mainframe.getFaceJPanel().getLabelFace().setIcon(Tools.face0); // 左键释放 }else if (e.getModifiers() == InputEvent.BUTTON1_MASK && !mineLabel.isFlagTag()) { if(!Tools.isStart) { // 第一次鼠标左键点击,在弹起事件中进行布雷 LayMine.lay(labels, row, col); // 布雷 Tools.isStart = true; //设置isStart=true,表示不是第一次点击了 mainframe.getTimer().start(); // 开启计时器 } if (mineLabel.isMineTag()) {//判断是否踩到地雷 bombAction(row, col); //如果踩到地雷,游戏结束,显示全部的地雷 mineLabel.setIcon(Tools.blood); mainframe.getFaceJPanel().getLabelFace().setIcon(Tools.face3); } else { mainframe.getFaceJPanel().getLabelFace().setIcon(Tools.face0); expand(row, col); } } //判断雷是否已全被清除完 isWin(); } // 左右键双击展开 private void doubleExpend(int i, int j) { for (int x = Math.max(0, i - 1); x <= Math.min(Tools.rows - 1, i + 1); x++) { for (int y = Math.max(0, j - 1); y <= Math.min(Tools.cols - 1, j + 1); y++) { if (labels[x][y].isMineTag()) { // 如果是雷 if (!labels[x][y].isFlagTag()) { // 没有旗子标记 bombAction(x, y); } } else { // 不是雷 if (!labels[x][y].isFlagTag()) { // 没有旗子标记 expand(x, y); } } } } } // 触雷 private void bombAction(int row, int col) { for (int i = 0; i < labels.length; i++) { for (int j = 0; j < labels[i].length; j++) { if (labels[i][j].isMineTag()) { // 是雷 if (!labels[i][j].isFlagTag()) { // 没有标记 labels[i][j].setIcon(Tools.mine0); } else { labels[i][j].setIcon(Tools.mine1); } } } } // 修改踩雷状态 Tools.isBoom = true; // 停止计时器 mainframe.getTimer().stop(); // 取消鼠标监听器 for (int i = 0; i < labels.length; i++) { for (int j = 0; j < labels[i].length; j++) { labels[i][j].removeMouseListener(this); } } } //还原方格显示效果(因为鼠标按下时显示背景) private void backIcon(int i, int j) { for (int x = Math.max(0, i - 1); x <= Math.min(Tools.rows - 1, i + 1); x++) { for (int y = Math.max(0, j - 1); y <= Math.min(Tools.cols - 1, j + 1); y++) { if (!labels[x][y].isFlagTag() && !labels[x][y].isExpendTag()) { int rightClickCount = labels[x][y].getRightClickCount(); if (rightClickCount == 2) { labels[x][y].setIcon(Tools.ask); } else { if(!labels[x][y].isFlagTag()){ labels[x][y].setIcon(Tools.blank); } } } } } } 计数区面板点击事件(1)计时(com.timer/Timers)在主窗体中添加计时器timer控件,并编写事件监听器 // 计时器 public class Timers implements ActionListener { private int times; MainFrame mainfame; public Timers(MainFrame mainfame){ this.mainfame = mainfame; } @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub Tools.timecount++; if(Tools.timecount>999){ Tools.timecount=999; }else{ mainfame.getFaceJPanel().setTime(Tools.timecount); } } }在FaceJPanel.java中添加:// 计时器 public void setTime(int count) { int b = 0; if (count < 0) { b = 10; } else { b = count / 100; } int g = Math.abs(count) % 10; int s = Math.abs(count) / 10 % 10; labelTimeG.setIcon(Tools.timeCount[g]); labelTimeS.setIcon(Tools.timeCount[s]); labelTimeB.setIcon(Tools.timeCount[b]); }(2)“笑脸”事件处理(com.panel/FaceJPanel.java)public class FacelabelListener extends MouseAdapter{ @Override public void mousePressed(MouseEvent e) { if (e.getModifiers() == InputEvent.BUTTON1_MASK) { mainframe.getTimer().stop(); labelFace.setIcon(Tools.face1); } } @Override public void mouseReleased(MouseEvent e) { if (e.getModifiers() == InputEvent.BUTTON1_MASK) { mainframe.getTimer().start(); mainframe.reStartGame(); labelFace.setIcon(Tools.face0); } }(3)重新开始方法(com.main/mainFrame.java) BombJPanel bombJPanel = new BombJPanel(this); FaceJPanel faceJPanel = new FaceJPanel(this); public void reStartGame() { // 游戏重新开始方法 this.remove(faceJPanel); this.remove(bombJPanel); Tools.bombCount = Tools.allcount; Tools.timecount = 0; Tools.isStart = false; Tools.isBoom = false; faceJPanel = new FaceJPanel(this); bombJPanel = new BombJPanel(this); this.add(faceJPanel, BorderLayout.NORTH); this.add(bombJPanel); this.pack(); this.validate(); getTimer().stop(); }在的init方法中添加 private void init() { // 菜单栏 this.setJMenuBar(menuBar); BorderLayout layout = new BorderLayout(); this.setLayout(layout); // 计数区 this.add(faceJPanel,layout.NORTH); // 雷区 this.add(bombJPanel,layout.CENTER); }扫雷成功需求分析:把不是雷的方格全部展开,如果不是雷的方格全部展开了,但雷没被标记也算扫雷成功,以下等式成立即可。被展开的方格数量 = 所有方格数量 - 雷的数量private void isWin() { int expendCount = 0; for (int i = 0; i < labels.length; i++) { for (int j = 0; j < labels[i].length; j++) { if (labels[i][j].isExpendTag()) { expendCount++; } } } if (Tools.rows * Tools.cols - expendCount == Tools.allcount) { for (int i = 0; i < Tools.rows; i++) for (int j = 0; j < Tools.cols; j++) { if (mainframe.getBombJPanel().getLabels()[i][j].isMineTag() && !mainframe.getBombJPanel().getLabels()[i][j].isFlagTag()) { mainframe.getBombJPanel().getLabels()[i][j].setIcon(Tools.flag); } // 移除监听 mainframe.getBombJPanel().getLabels()[i][j] .removeMouseListener(mainframe.getBombJPanel() .getListener()); } mainframe.getFaceJPanel().getLabelFace().setIcon(Tools.face4); mainframe.getFaceJPanel().setNumber(0); mainframe.getTimer().stop(); new Win(mainframe); //成功后弹出英雄记录版 Tools.isStart = false; } } //判断方格周围雷的数量与周围被标记的方格数是否相等 private boolean isEquals(int i, int j) { int count = labels[i][j].getCountAround(); int flagCount = 0; for (int x = Math.max(0, i - 1); x <= Math.min(Tools.rows - 1, i + 1); x++) { for (int y = Math.max(0, j - 1); y <= Math.min(Tools.cols - 1, j + 1); y++) { if (labels[x][y].isFlagTag()) { flagCount++; } } } if (count == flagCount) { return true; }else { return false; } }
2022年05月26日
260 阅读
0 评论
1 点赞
2022-05-18
Java扫雷源码
编译软件:IntelliJ IDEA / Eclipse环境: JDK1.5以上介绍:重写了一遍扫雷,代码更加规范,修复了一些小bug,优化了部分代码的算法,将各等级英雄榜独立运行效果图github项目地址:https://github.com/XG2020/Mine-sweeping{card-default width="100%" label="下载地址"}[btn href="https://www.lanzoum.com/iUNza0527yhg" type="primary"]点击下载[/btn] 复制密码: [copy]xggm[/copy] {/card-default}
2022年05月18日
318 阅读
0 评论
0 点赞
2022-05-18
Java实现扫雷小游戏一
实现项目结构分析主界面主窗体(com.main/MainFrame.java)包含菜单栏、计数区panel和雷区panel。(1)构造方法public MainFrame() { init(); this.setIconImage(Tools.getImageIcon().getImage()); // 设置图标 this.setTitle("扫雷"); // 设置标题 this.setSize(new Dimension(220,300)); // 窗口大小 this.setResizable(false); // 这样让窗口不可放大 this.setLocationRelativeTo(null); this.setLocation(new Point(800,300)); // 设置窗口位置 this.setVisible(true); // 设置窗口显示 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭窗口 }(2)初始化方法 private void init() { // 菜单栏 this.setJMenuBar(menuBar); }菜单栏(com.panel/BombJMenuBar.java)(1)添加菜单、菜单项等public class BombJMenuBar extends JMenuBar { // 菜单项 JMenu menuGame = new JMenu("游戏(G)"); JMenuItem menuItemStart = new JMenuItem("开局(N)"); JMenuItem menuItemLow = new JMenuItem("初级(B)"); JMenuItem menuItemMid = new JMenuItem("中级(I)"); JMenuItem menuItemHigh = new JMenuItem("高级(E)"); JMenu menuHero = new JMenu("英雄榜(T)"); JMenuItem menuHeroLow = new JMenuItem("初级英雄榜"); JMenuItem menuHeroMid = new JMenuItem("中级英雄榜"); JMenuItem menuHeroHigh = new JMenuItem("高级英雄榜"); JMenuItem menuItemOrder = new JMenuItem("自定义(C)"); JMenuItem menuItemExit = new JMenuItem("退出(X)"); JMenu menuHelp = new JMenu("帮助(H)"); JMenuItem menuItemAbout = new JMenuItem("关于扫雷(A)"); JMenuItem menuItemHole = new JMenuItem("外挂(W)"); // 需要在类中声明主窗体变量(属性):作为菜单栏与主窗体交互的媒介 // 声明主窗体对象 MainFrame mainframe; // 编写构造函数和初始化界面方面 public BombJMenuBar(MainFrame mainframe) { this.mainframe = mainframe; init(); }(2)初始化方法 public void init() { // 设置快捷键 menuGame.setMnemonic('G'); // Alt + G menuItemStart.setMnemonic('N'); menuItemLow.setMnemonic('B'); menuItemMid.setMnemonic('I'); menuItemHigh.setMnemonic('E'); menuHero.setMnemonic('T'); menuItemOrder.setMnemonic('C'); menuItemExit.setMnemonic('X'); menuHelp.setMnemonic('H'); menuItemAbout.setMnemonic('A'); menuItemHole.setMnemonic('W'); // 把菜单添加到菜单栏 // 游戏菜单 this.add(menuGame); menuGame.add(menuItemStart); menuGame.addSeparator(); // 添加分隔线 menuGame.add(menuItemLow); menuGame.add(menuItemMid); menuGame.add(menuItemHigh); menuGame.addSeparator(); menuGame.add(menuHero); menuHero.add(menuHeroLow); menuHero.add(menuHeroMid); menuHero.add(menuHeroHigh); menuGame.addSeparator(); menuGame.add(menuItemOrder); menuGame.addSeparator(); menuGame.add(menuItemExit); // 帮助菜单 this.add(menuHelp); menuHelp.add(menuItemAbout); menuHelp.addSeparator(); menuHelp.add(menuItemHole); }运行雷区(com.panel/BombJPanel)雷区是由小方格组成,在众多小方格中随机布雷。(先设计MineLable)(1)MineLablepublic class MineLabel extends JLabel { private boolean mineTag = false; // 判断是否是雷 private boolean expendTag = false; // 判断雷块是否展开 private boolean flagTag = false; // 判断雷块是否插了旗子 private int rowx; // 雷块所在的行 private int coly; // 雷块所在的列 private int countAround; // 计算雷块周围的雷数 private int rightClickCount; // 记录右键点击次数 }(2)编写构造方法public class BombJPanel extends JPanel { // 定义属性 MineLabel[][] labels = new MineLabel[9][9]; // 声明主窗体对象 MainFrame mainframe; MouListener listener; public BombJPanel(MainFrame mainframe) { this.mainframe = mainframe; //定义布局方式,网格布局 this.setLayout(new GridLayout(Tools.rows, Tools.cols)); listener = new MouListener(labels,mainframe); init(); }程序写到这里很多地方都需要要到图片以及雷区行列数等,故定义工具类定义好一些可能在程序中多次用到且后期会改变的资源或者变量。见工具类Tools(3)初始化private void init() { // 实例化小方格 for(int i = 0;i<labels.length;i++) { for(int j = 0; j<labels[i].length;j++) { labels[i][j] = new MineLabel(i, j); labels[i][j].setIcon(Tools.blank); this.add(labels[i][j]); labels[i][j].addMouseListener(listener); } }创建一个合成边框,指定了用于外部和内部边缘的 border 对象在init() 里插入 // 实现边框效果 Border lowerBorder = BorderFactory.createLoweredBevelBorder(); Border emptyBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5); //边框大小 CompoundBorder compoundBorder = BorderFactory.createCompoundBorder(emptyBorder, lowerBorder); this.setBorder(compoundBorder); this.setBackground(Color.LIGHT_GRAY);createLoweredBevelBorder();创建一个具有凹入斜面边缘的边框,将组件当前背景色的较亮的色度用于高亮显示,较暗的色度用于阴影。(在凹入边框中,阴影位于顶部,高亮显示位于其下。)BorderFactory.createEmptyBorder(5, 5, 5, 5);创建占用空间但不绘制的空边框,指定顶部、左侧、底部和右侧的宽度。运行在MainFrame的构造函数中添加 this.pack(); public MainFrame() { init(); ...... this.pack(); // 使控件更紧凑,窗口自动适应大小 ...... }运行计数区(com.panel/FaceJPanel)(1)定义雷的数量与时间显示public class FaceJPanel extends JPanel { // 雷数 private JLabel labelCountG = new JLabel(); // 个位 private JLabel labelCountS = new JLabel(); // 十位 private JLabel labelCountB = new JLabel(); // 百位 // 笑脸 private JLabel labelFace = new JLabel(); // 时间 private JLabel labelTimeG = new JLabel(); // 个位 private JLabel labelTimeS = new JLabel(); // 十位 private JLabel labelTimeB = new JLabel(); // 百位 // // 声明主窗体对象 MainFrame mainframe; (2)编写构造方法 public FaceJPanel(MainFrame mainframe) { this.mainframe = mainframe; this.setLayout(new BorderLayout()); this.setVisible(true); init(); }(3)初始化private void init() { JPanel panel = new JPanel(); // 布局盒子 BoxLayout boxLayout = new BoxLayout(panel, BoxLayout.LINE_AXIS); panel.setLayout(boxLayout); labelFace.addMouseListener(new FacelabelListener()); // 添加表情按钮监听器 // 添加计数区监听器 panel.addMouseListener(new MouseAdapter(){ public void mousePressed(MouseEvent arg0) { if(!Tools.isBoom) { labelFace.setIcon(Tools.face2); } } public void mouseReleased(MouseEvent arg0) { if(!Tools.isBoom) { labelFace.setIcon(Tools.face0); } } }); Icon icon0 = new ImageIcon("./image/d0.gif"); // 计算雷的每位数图片 Icon icon3 = new ImageIcon("./image/d" + Tools.allcount / 100 + ".gif");// 百位 Icon icon2 = new ImageIcon("./image/d" + Tools.allcount /10%10 + ".gif"); // 十位 Icon icon1 = new ImageIcon("./image/d" + Tools.allcount % 10 + ".gif"); // 个位 Icon iconSmile = new ImageIcon("./image/face0.gif"); // 雷数显示图片 labelCountG.setIcon(icon1); labelCountS.setIcon(icon2); labelCountB.setIcon(icon3); // 时间显示图片 labelTimeG.setIcon(icon0); labelTimeS.setIcon(icon0); labelTimeB.setIcon(icon0); // 表情显示图片 labelFace.setIcon(iconSmile); // 添加控件到panel panel.add(Box.createHorizontalStrut(2)); // 最左侧 panel.add(labelCountB); panel.add(labelCountS); panel.add(labelCountG); panel.add(Box.createHorizontalGlue()); // 添加水平方向的构件,占位 panel.add(labelFace); panel.add(Box.createHorizontalGlue()); panel.add(labelTimeB); panel.add(labelTimeS); panel.add(labelTimeG); panel.add(Box.createHorizontalStrut(2)); // 最右侧 // 实现边框效果 Border borderLow = BorderFactory.createLoweredBevelBorder(); // 内边框 Border borderEmpty = BorderFactory.createEmptyBorder(2, 2, 2, 2); Border borderCom1 = BorderFactory.createCompoundBorder(borderLow, borderEmpty); panel.setBorder(borderCom1); panel.setBackground(Color.LIGHT_GRAY); // 外边框 Border borderEmpty1 = BorderFactory.createEmptyBorder(5, 5, 0, 5); this.setBorder(borderEmpty1); this.setBackground(Color.LIGHT_GRAY); this.add(panel); }(4)在主窗体MainFrame中添加FaceJPanelpublic class MainFrame extends JFrame{ ...... private BombJMenuBar menuBar = new BombJMenuBar(this); FaceJPanel faceJPanel = new FaceJPanel(this); BombJPanel bombJPanel = new BombJPanel(this); ...... }在init方法中插入private void init() { ...... this.add(faceJPanel,layout.NORTH); ...... }运行工具类(com.tools/Tools)public class Tools { // 窗口图标 public static ImageIcon imageIcon = new ImageIcon("./image/icon.gif"); public static ImageIcon getImageIcon() { return imageIcon; } public static int rows = 9; // 雷区行数 public static int cols = 9; // 雷区列数 public static int timecount = 0; // 计时 public static int allcount = 10; // 所有雷的数量 public static int bombCount = allcount; // 剩余为未被标记雷数 public static boolean isBoom = false; // 是否踩雷 public static boolean isStart = false; // 是否开始 public static boolean isHole = false; // 是否开启后门外挂 // 排行榜 public static int time = 0; // 初级 public static int time1= 999; public static int time2= 999; public static int time3= 999; public static String name1="匿名"; public static String name2="匿名"; public static String name3="匿名"; // 中级 public static int time01= 999; public static int time02= 999; public static int time03= 999; public static String name01="匿名"; public static String name02="匿名"; public static String name03="匿名"; // 高级 public static int time001= 999; public static int time002= 999; public static int time003= 999; public static String name001="匿名"; public static String name002="匿名"; public static String name003="匿名"; // 游戏等级 public static final String LOWER_LEVEL = "初级"; public static final String MIDDLE_LEVEL = "中级"; public static final String HEIGHT_LEVEL = "高级"; public static final String CUSTOM_LEVEL = "自定义"; // 游戏当前等级 public static String currentLevel = LOWER_LEVEL; // 用来存放0-8地雷数字标签图片 public static ImageIcon mineCount[]; // 用来存放时间数字标签图片 public static ImageIcon timeCount[]; // 静态块 static { mineCount = new ImageIcon[9]; for (int i = 0; i <= 8; i++) { mineCount[i] = new ImageIcon("./image/" + i + ".gif"); } timeCount = new ImageIcon[11]; for (int i = 0; i < 10; i++) { timeCount[i] = new ImageIcon("./image/d" + i + ".gif"); } timeCount[10] = new ImageIcon("./image/d10.gif"); } // 笑脸表情标签图片 public static ImageIcon face0 = new ImageIcon("./image/face0.gif"); public static ImageIcon face1 = new ImageIcon("./image/face1.gif"); public static ImageIcon face2 = new ImageIcon("./image/face2.gif"); public static ImageIcon face3 = new ImageIcon("./image/face3.gif"); public static ImageIcon face4 = new ImageIcon("./image/face4.gif"); public static ImageIcon face5 = new ImageIcon("./image/face5.gif"); public static ImageIcon face6 = new ImageIcon("./image/face6.gif"); public static ImageIcon face7 = new ImageIcon("./image/face7.gif"); public static ImageIcon face8 = new ImageIcon("./image/face8.gif"); // 分别对应 mine雷标签图片 public static ImageIcon mine = new ImageIcon("./image/mine.gif"); public static ImageIcon mine0 = new ImageIcon("./image/mine0.gif"); public static ImageIcon mine1 = new ImageIcon("./image/mine1.gif"); //分别对应 ask问号标签图片 public static ImageIcon ask = new ImageIcon("./image/ask.gif"); public static ImageIcon ask1 = new ImageIcon("./image/ask1.gif"); public static ImageIcon iconTemp = new ImageIcon("./image/icon.gif"); public static Image icon = iconTemp.getImage(); public static ImageIcon blank = new ImageIcon("./image/blank.gif"); public static ImageIcon blood = new ImageIcon("./image/blood.gif"); public static ImageIcon error = new ImageIcon("./image/error.gif"); // 旗子标签图片 public static ImageIcon flag = new ImageIcon("./image/flag.gif"); // hole外挂标签图片 public static ImageIcon hole = new ImageIcon("./image/hole.gif"); }
2022年05月18日
233 阅读
0 评论
0 点赞
2022-05-15
HTTPS协议 Mixed Content报错解决办法
今天发现我博客的音乐播放器无法加载歌词,因为浏览器安全规矩,在 HTTPS 请求下进行 Java请求、HTTP请求或引进 HTTP协议资源文件,会报“Mixed Content”的错误,导致请求无法继续。触发原因也是莫名其妙的(控制台显示的请求地址是http请求,但是实际上我默认请求设置了https),在添加下面的语句解决问题后,注释掉这条语句,清除缓存刷新页面,又能正常的加载了,为了稳定性,而且我的网站都添加了SSL证书,所以还是让这条语句生效吧Mixed Content: The page at 'xxx' was loaded over HTTPS, but requested an insecure resource 'xxx'. This request has been blocked; the content must be served over HTTPS.解决办法网站的head标签中插入一条:语句的意思是自动将http的不安全请求强制转换为https请求。注意事项:使用时必须确定你的可升级的http地址都支持SSL证书协议,不然肯定报错会导致页面打不开,或者显示链接重置问题。
2022年05月15日
258 阅读
0 评论
1 点赞
2022-05-02
Java实现扫雷小游戏介绍
游戏介绍扫雷游戏是一款windows经典的电脑休闲小游戏,办公室打发无聊时间用的,非常受人喜爱,扫雷就是要把所有非地雷的格子揭开即胜利,踩到地雷格子就算失败。让玩家们找回童年玩此款游戏的乐趣,在游戏中只要掌握一些小技巧,闯关就会变得容易很多哦!初步分析通过扫雷界面图片可以分析出:界面是一个窗口,有菜单栏、标题栏和游戏区。菜单栏里有游戏和帮助两个菜单。游戏菜单里有:开局、初级、中级、高级、自定义、扫雷英雄榜、退出等7个子菜单;1、在游戏菜单里能够设置游戏的重新开局, 也可以通过点击游戏区里的笑脸来重新开局2、设置游戏的级别,分为初中高三个游戏级别:初级是由9*9的方格组成,雷数为10,非雷数71;中级由16*16的方格组成,排有40个雷,非雷数为216;高级是由16*30的方格组成,其中有99个雷,非雷数为381;3、自定义功能能够让玩家重新定义游戏的布局(行列范围9~30)与雷数(少于格子数且不能全是雷);4、表情 游戏仍然在继续的时候显示微笑的表情::(呵呵),当鼠标按住方格的时候显示惊讶的表情::(惊讶),踩中地雷的时候显示悲哀的表情::(泪),当你成功排除了所有雷,就会显示酷的表情::(酷)。5、在你翻开第一个方块起,计算器就开始计时,直到你成功排掉所有地雷或者踩中地雷的时候就结束计时。游戏规则与玩法游戏规则扫雷就是要把所有非地雷的格子揭开即胜利,踩到地雷格子就算失败;游戏主区域由很多个方格组成;使用鼠标左键随机点击一个方格,方格即被打开并显示出方格中的数字;方格中数字则表示其周围的8个方格隐藏了几颗雷;如果点开的格子为空白格,即其周围有0颗雷,则其周围格子自动打开,如果其周围还有空白格,则会引发连锁反应;在你认为有雷的格子上,点击右键即可标记雷,如果不能确定,可以双击右键即标记问号;如果一个已打开格子周围所有的雷已经正确标出,则可以在此格上同时点击鼠标左右键以打开其周围剩余的无雷格。玩法左键单击:在判断出不是雷的方块上按下左键,可以打开该方块。如果方块上出现数字,则该数字表示其周围3×3区域中的地雷数(一般为8个格子,对于边块为5个格子,对于角块为3个格子,所以扫雷中最大的数字为8);如果方块上为空(相当于0),则可以递归地打开与空相邻的方块;如果不幸触雷,则游戏结束。右键单击:在判断为地雷的方块上按下右键,可以标记地雷(显示为小红旗)。标记地雷后重复一次右击则标记(?),需要一次或两次操作右击来取消标雷)。双击:同时按下左键和右键完成双击。当双击位置周围已标记雷数等于该位置数字时操作有效,相当于对该数字周围未打开的方块均进行一次左键单击操作。地雷未标记完全时使用双击无效。若数字周围有标错的地雷,则游戏结束。需求分析扫雷的左键逻辑。扫雷中鼠标左键被用来打开当前地图上的方块,但是如果你仔细研究,就会发现方块被打开发生在鼠标左键抬起之后,而不是鼠标左键按下的时候,这一点非常重要。如果在已经开启的方块上点击鼠标是没有任何作用的,并且如果方块上方被标记为旗帜,则该方块也无法被鼠标左键开启,这也是为了防止误操作导致游戏意外结束。如果游戏在初始状态,鼠标左键的抬起事件会触发了雷区(或者称之为地图)的初始化以及方块打开操作,并开始计时。如果游戏处于运行状态,则要判断点击的位置是否为地雷,如果是地雷直接结束,否则执行默认的方块打开操作。鼠标右键主要是用来标记当前方块的属性,是地雷(旗帜)还是不确定(问号),这里需要注意的是标记的过程中,是鼠标点击的时候就进行了,而不是按键抬起之后。随着方块标记的转变,地雷的显示数量也随之改变。这里还有一个小细节,就是鼠标的右键操作并不会导致游戏开始计时,换句话说右键操作并不会让游戏进入运行状态。自动打开操作是扫雷游戏的基本规则。如果在双击(左右键)的位置存在一个数字,且周围 8 个方块上方已经被标记上了和数字相同的旗帜,则同时点击鼠标左右键会自动打开周围未标记的方块。方块被打开是在鼠标弹起操作后,双击按下只是显示相关方块的背景,给人的效果是方块被按下去。统计点击位置周围的标记数量,标记数量和显示数字一致的话,打开剩余方块。这里有个小细节,就是打开的时候并不是仅仅打开周围的 8 个方块,如果这 8 个方块中存在空白的情况,会触发成片开启的情况。软件功能框架图
2022年05月02日
396 阅读
0 评论
0 点赞
1
2
3
4
...
10