首页
动态
归档
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
留言
工具箱
邻居
壁纸
音乐
搜索到
39
篇与
的结果
2022-08-14
Tyepcho找回密码增加请求限制教程
前言之前有人请教我怎么限制typecho邮件通知里的找回密码请求,我看了看这好像是个挺严重的问题,如果没有限制请求频率,可能一些不怀好意的人会一直恶意请求,导致发送邮箱账号被封号,或者标记为垃圾邮箱,所以我研究了一会儿,想了比较多的方案,比如:前端js拦截(设置多少秒解除提交按键的禁用属性)但是因为typecho插件的性质组件初始化的顺序不同,可能js提前加载无法绑定到按钮,而且每次进入都禁用一些时间,非常影响体验,所以pass掉了。设置cookie临时存储提交的时间,找通过js拦截请求的发起,很明显这个实现比第一个体验上好了一点,但是这个办法有漏洞清除掉cookie就又可以请求,而且实现起来有点难度,因此也pass了。最后我想到了一个好办法,比上面两个实现起来容易且能稳定运行,通过查询数据库验证请求,我最后选择了这种方法,方法已经更新到了插件和我的定制版后台里,下载最新版本安装后,取消插件里XGComment/Action.php大概307-309行的代码注释即可开启功能,加注释防止有人安装到官方的Typecho,请求数据库查不到表单报错。教程1.打开数据库找了typecho_users表,点击结构添加一列名称rtime类型int长度 10允许为空 默认填充 0用来存储提交时写入数据库的时间戳。2.打开插件的 Plugin.php 文件在 找回密码过期时间 的下一行插入以下代码 // 找回密码请求间隔时间 $public_rtime = new Typecho_Widget_Helper_Form_Element_Text('public_rtime', NULL, '180', _t('请求间隔时间'), _t('防止恶意请求,开启需要定制版typecho且删除Action.php中相关的代码注释,此处定义找回密码请求间隔时间,单位为秒')); $form->addInput($public_rtime);3.打开插件的 Action.php 文件找到 doForget() 方法,这是验证并创建重置密码链接发送邮件的方法。只要在验证处添加一个时间戳验证,设置好时间间隔,这样每次点击提交找回密码请求后,方法就会查询数据库比较时间将 doForget() 方法的以下片段替换成下面的片段 // 查询用户数据 $user = $this->db->fetchRow($this->select()->where('mail = ?', $this->request->mail)); $now = time(); $retime = $user['rtime']; // 没有用户 if ( !$user ) { // 输出错误 $this->widget('Widget_Notice')->set(_t('邮箱地址错误, 请核对后重新输入'), 'error'); // 返回上一页 $this->response->goBack(); } if ( $now<=$retime ) { // 输出错误 $this->widget('Widget_Notice')->set(_t($this->request->mail.'您已申请过重置密码请求,请稍后重试!'), 'error'); // 返回上一页 $this->response->goBack(); } $addtime = $this->_plugin->public_rtime ? $this->_plugin->public_rtime : 180; $setime = $now + $addtime; $this->update(array('rtime' => $setime), $this->db->sql()->where('mail = ?', $this->request->mail));
2022年08月14日
197 阅读
0 评论
3 点赞
2022-08-10
Typecho-Joe主题实现图片评论功能
实现效果实际使用效果见本站,主题将在1.1.7版本中嵌入此功能,但是在开启前需要配置一些东西。使用我的主题模板搭建好图床直接把js里的图床API改成自己的就可以了效果图默认状态已选择文件点击插入 上传图片默认插入Markdown语法链接,目的方便实现评论点击图片大图预览效果开启判断文件类型在js中加入后缀判断文件类型,选择非图片类型时,会提示视频教程隐藏内容,请前往内页查看详情准备修改后台设置1.首先进入Typecho后台,找到评论设置开启评论Markdown语法。2.只开启Markdown语法是不够的,因为评论区默认禁用HTML标签,所以要添加允许的HTML标签。 在评论设置的最下方找到允许使用的HTML标签和属性,插入以下代码。<img src="" data-original="" width=""> <a href="" data-fancybox="">如果还想在评论区播放视频,自行查看网站的video标签和属性值一同加入进去。注意因为解除了a标签后可以写入JS脚本语句,造成安全隐患,强烈建议开启主题设置里的禁止使用JS脚本评论。3.图床API接口,推荐自己搭建。 可以使用我源码库中的外链网盘源码搭建,我的博客使用的也是这个源码的API,为了减轻服务器负担我加了域名验证,我的接口只允许了本站,要是实在不会动手可以打赏,请我喝一杯奶茶,我开放你的域名授权,不过还是建议自己搭建,因为方便自己管理上传上来的文件。使用本主题1.1.7之后版本只需要在主题文件夹的根目录下的js文件夹里找到img.js,打开找到图床API把链接换成自己的接口链接就可以正常使用了。[line]准备阶段完成[/line]实现修改functions.php在合适位置插入以下代码,其他的joe主题自行修改 setAttribute(); 中加入的属性。 $JCommentImg = new Typecho_Widget_Helper_Form_Element_Select( 'JCommentImg', array('off' => '关闭(默认)', 'on' => '开启'), 'off', '是否开启评论图片功能', '介绍:开启后,评论区域可以选择图片进行评论' ); $JCommentImg->setAttribute('class', 'j-setting-content j-setting-other'); $form->addInput($JCommentImg->multiMode());修改评论区文件 comment.php找到评论区文件,我的主题是在主题文件根目录下的 pblic/comment.php插入以下代码到图片位置,或者合适位置。隐藏内容,请前往内页查看详情找到输出评论的div标签,添加 id=markdown 的属性,不同的主题markdown解析的id可能不同,可以进入文章按f12,找到文章的父标签查看。添加css文件 btn.css美化上传和插入按钮,可根据喜好自己修改或者加入样式,创建好文件后复制下方代码粘贴保存即可,并在head.php或者header.php中引入文件。.file { position: relative; display: inline-block; background: #D0EEFF; border: 1px solid #99D3F5; border-radius: 4px; padding: 4px 5px; overflow: hidden; height: 32px; color: #1E88C7; text-decoration: none; text-indent: 0; line-height: 18px; } .file input { position: absolute; font-size: 100px; right: 0; top: 0; opacity: 0; } .file:hover { background: #AADFFD; border-color: #78C3F3; color: #004974; text-decoration: none; } .xgimg{ display: flex; align-items: center; justify-content: flex-end; } .xgimg button { background: var(--classD); padding: 0 15px; height: 32px; border: none; font-size: 13px; transition: all 0.35s; color: var(--main); } .xgimg button:active { color: #fff; background: var(--theme); } .showFileName{ width:40%; font-size: 12px; text-align: right; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } @media screen and (max-width: 768px){ .showFileName{ width:0px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } }创建js文件 img.js创建文件,复制下方代码粘贴,然后把图床API接口改成自己的,如果使用其他的图床接口,请根据接口的开发文档,使用formData.append(); 方法添加需要的参数即可,修改好后,在footer.php中引入文件,并且在它的上方 axios.min.js 因为上传使用的是axios方式请求。<script type="text/javascript" src="https://unpkg.com/axios@0.27.2/dist/axios.min.js"></script>隐藏内容,请前往内页查看详情最后,再后台开启评论图片功能,清除缓存刷新页面,图片上传按钮就出现了,附一张评论图片成功的评论截图[line]教程结束[/line]
2022年08月10日
300 阅读
5 评论
6 点赞
2022-07-14
Git上传项目到Github仓库教程
介绍Git:一个开源的分布式版本控制工具。Github: 一个面向开源及私有软件项目保存用户的数据、代码等文件的托管平台。准备阶段Github&创建仓库Github账号点击访问Github官网,如果访问速度很慢,可以开代理或者开加速器登录直接的github账号,如果没有账号点击右上角的 Sign up 跳转到注册界面注册账号。输入邮箱、密码、用户名信息点击继续,完成邮箱验证即注册成功,然后登录注册的账号创建仓库1.登录账号后,点击右上角的+ --> 点击 New repository2.输入仓库名称,勾选上 Add a README file,然后点击 Greate repository3.仓库创建完成安装git客户端;Git官网地址: https://git-scm.com/[line]下载[/line]Git官方版Windows版Mac版Linux版Git-GUI版WindowsGUI版MacGUI版LinuxGUI版选择适合的版本进入下载,按照安装向导完成安装,不需要配置其他的东西,直接Next。下面以Windows官方版进行演示,其他操作系统操作一致。连接仓库Git配置1.选择要上传的文件,右键鼠标选择 Git Bash Here2.输入命令 ssh-keygen -t rsa -C "your email@youremail.com" ,按提示输入一直回车即可生成秘钥,找到秘钥的文件路径。3.在文件夹中打开秘钥所在路径然后选择 id_rsa.pub 右键以记事本方式打开,复制里面的秘钥。github配置创建SSH秘钥1.点击头像 --> 点击Settings2.点击 SSH and GPG keys --> 点击New SSH Keys3.输入标题名称,然后粘贴从 id_rsa.pub 文件里复制的秘钥,点击 Add SHH key 4.验证连接,输入命令 ssh -T git@github.com 回车,根据提示输入 yes,出现图片中的提示就说明成功了。配置用户信息设置username和email,github每次commit都会记录这些信息。输入命令: git config --global user.name "注册时填写的名字" 输入命令:git config --global user.email "注册时填写的邮箱" 上传文件上面的环节配置完毕后,下次上传只需要执行以下命令选择要上传的文件,右键鼠标选择 Git Bash Here1.输入命令 git init 将本地项目变成 Git 可以管理的仓库2.输入命令 git add . 将项目的所有文件添加到暂存区3.输入命令 git commit -m "自己项目提交的描述" 将项目文件提交到仓库4.复制github仓库地址,点击 Code --> SSH --> 点击复制5.输入命令 git remote add origin 仓库地址链接 ,连接仓库6.输入命令 git pull --rebase origin master或者main 获取远程库与本地同步(远程仓库不为空需要这一步)7.输入命令 git push -u origin master 上传代码到github远程仓库更新文件进入要更新的项目文件根目录,右键鼠标选择 Git Bash Here1.输入命令 git status 查看当前的git仓库状态2.输入命令 git add * 添加全部更新3.输入命令 git commit -m "更新说明" 添加说明到项目文件4.输入命令 git pull 拉取当前分支最新代码,防止与他人更新代码冲突5.输入命令 git push origin master 更新上传代码到github远程仓库[line]教程到此结束[/line]
2022年07月14日
230 阅读
0 评论
3 点赞
2022-05-26
Java实现扫雷小游戏三
接下来是完成菜单栏的功能游戏菜单添加菜单监听器(com.panel/BombJMenuBar.java)在init()方法中插入// 开局事件处理 menuItemStart.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { mainframe.reStartGame(); } }); // 添加事件监听器 MenuListener listener = new MenuListener(mainframe); menuItemStart.addActionListener(listener); menuItemLow.addActionListener(listener); menuItemMid.addActionListener(listener); menuItemHigh.addActionListener(listener); menuItemOrder.addActionListener(listener); menuHeroLow.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { new Hero(mainframe); }}); menuHeroMid.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { new Hero1(mainframe); }}); menuHeroHigh.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { new Hero2(mainframe); }}); menuItemAbout.addActionListener(listener); // 后门外挂方便测试 menuItemHole.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { } }); menuItemExit.addActionListener(new ActionListener() { //加一个系统退出的处理监听 public void actionPerformed(ActionEvent e) { System.exit(0); } });编写等级菜单监听类(com.listener/MenuListener)// 等级菜单监听器 public class MenuListener implements ActionListener { JMenuItem jMenuItem; JTextField jTextField=new JTextField(); MainFrame mainframe; public MenuListener(MainFrame mainframe){ this.mainframe = mainframe; } public void actionPerformed(ActionEvent e) { if(e.getActionCommand().equals("开局(N)")){ this.mainframe.reStartGame(); } if(e.getActionCommand().equals("初级(B)")){ Tools.rows = 9; Tools.cols = 9; Tools.allcount = 10; Tools.currentLevel = Tools.LOWER_LEVEL; this.mainframe.reStartGame(); } if(e.getActionCommand().equals("中级(I)")){ Tools.rows = 16; Tools.cols = 16; Tools.allcount = 40; Tools.currentLevel = Tools.MIDDLE_LEVEL; this.mainframe.reStartGame(); } if(e.getActionCommand().equals("高级(E)")){ Tools.rows = 16; Tools.cols = 30; Tools.allcount = 99; Tools.currentLevel = Tools.HEIGHT_LEVEL; this.mainframe.reStartGame(); } if(e.getActionCommand().equals("自定义(C)")){ new UserDefined(mainframe); } if(e.getActionCommand().equals("关于扫雷(A)")){ new About(mainframe); } } }注意:在雷区BombJPanel.java中之前是把行和列写成固定的,实现初级、中级、高级时要进行下述修改:// MineLabel[][] labels = new MineLabel[9][9]; MineLabel[][] labels = new MineLabel[Tools.rows][Tools.cols];运行效果:自定义菜单项(com.dialog/UserDefined.java)需求分析:出现弹窗界面,数据校验不能超过三位,只能为数字。通过继承JDialog实现用户自定义对话框public class UserDefined extends JDialog { // 自定义 private static final long serialVersionUID = 1L; private JLabel jLabelHigh = new JLabel("高度: "); private JLabel jLabelWide = new JLabel("宽度: "); private JLabel jLabelBomb = new JLabel("雷数: "); private JLabel jLabelMessage = new JLabel(" "); private JTextField jTextFieldHigh; private JTextField jTextFieldWide; private JTextField jTextFieldBomb; private JPanel panel; private JButton buttonSure; private JButton buttonCancer; MainFrame mainFrame; public UserDefined(final MainFrame mainFrame) { super(mainFrame); this.mainFrame = mainFrame; this.setIconImage(Tools.getImageIcon().getImage()); jLabelMessage.setFont(new Font("楷书", Font.PLAIN, 12)); jLabelMessage.setForeground(Color.red); this.setTitle("自定义雷区"); this.add(getPanel()); this.add(jLabelMessage, BorderLayout.NORTH); this.setSize(new Dimension(200, 150)); this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); this.setLocationRelativeTo(null); this.setResizable(false); this.addWindowListener(new WindowAdapter() { @Override public void windowDeactivated(WindowEvent e) { mainFrame.reStartGame(); } }); this.setModal(true); this.setVisible(true); } public JPanel getPanel() { JPanel jPanel = new JPanel(); Border border1 = BorderFactory.createEmptyBorder(5, 20, 5, 5); panel = new JPanel(); panel.setLayout(new GridLayout(1, 2)); Box boxHigh = Box.createHorizontalBox(); jTextFieldHigh = new JTextField(Tools.rows + ""); jTextFieldHigh.setPreferredSize(new Dimension(30, 20)); jTextFieldHigh.addKeyListener(new KeyListener() { @Override public void keyReleased(KeyEvent e) { String text = jTextFieldHigh.getText(); Pattern pattern = Pattern.compile("^[0-9]{1,3}$"); Matcher matcher = pattern.matcher(text); if (!matcher.matches()) { jLabelMessage.setText("请输入数字,不能超过三位"); if (text.length() > 3) { jTextFieldHigh.setText(text.substring(0, 3)); } } } @Override public void keyTyped(KeyEvent e) { char ch = e.getKeyChar(); if ((ch < '0') || (ch > '9')) { jLabelMessage.setText("请输入数字,不能超过三位"); e.setKeyChar((char) 8); } else { jLabelMessage.setText(" "); } } @Override public void keyPressed(KeyEvent e) { } }); boxHigh.add(jLabelHigh); boxHigh.add(jTextFieldHigh); Box boxWide = Box.createHorizontalBox(); jTextFieldWide = new JTextField(Tools.cols + ""); jTextFieldWide.setPreferredSize(new Dimension(30, 20)); jTextFieldWide.addKeyListener(new KeyListener() { @Override public void keyReleased(KeyEvent e) { String text = jTextFieldWide.getText(); Pattern pattern = Pattern.compile("^[0-9]{1,3}$"); Matcher matcher = pattern.matcher(text); if (!matcher.matches()) { jLabelMessage.setText("请输入数字,不能超过三位"); if (text.length() > 3) { jTextFieldWide.setText(text.substring(0, 3)); } } } @Override public void keyTyped(KeyEvent e) { char ch = e.getKeyChar(); if ((ch < '0') || (ch > '9')) { jLabelMessage.setText("请输入数字,不能超过三位"); e.setKeyChar((char) 8); } else { jLabelMessage.setText(" "); } } @Override public void keyPressed(KeyEvent e) { } }); boxWide.add(jLabelWide); boxWide.add(jTextFieldWide); Box boxBomb = Box.createHorizontalBox(); jTextFieldBomb = new JTextField(Tools.bombCount + ""); jTextFieldBomb.setPreferredSize(new Dimension(30, 20)); jTextFieldBomb.addKeyListener(new KeyListener() { @Override public void keyReleased(KeyEvent e) { String text = jTextFieldBomb.getText(); Pattern pattern = Pattern.compile("^[0-9]{1,3}$"); Matcher matcher = pattern.matcher(text); if (!matcher.matches()) { jLabelMessage.setText("请输入数字,不能超过三位"); if (text.length() > 3) { jTextFieldBomb.setText(text.substring(0, 3)); } } } @Override public void keyTyped(KeyEvent e) { char ch = e.getKeyChar(); if ((ch < '0') || (ch > '9')) { jLabelMessage.setText("请输入数字,不能超过三位"); e.setKeyChar((char) 8); } else { jLabelMessage.setText(" "); } } @Override public void keyPressed(KeyEvent e) { } }); boxBomb.add(jLabelBomb); boxBomb.add(jTextFieldBomb); Box boxS = new Box(BoxLayout.Y_AXIS); boxS.add(boxHigh); boxS.add(Box.createVerticalStrut(8)); boxS.add(boxWide); boxS.add(Box.createVerticalStrut(8)); boxS.add(boxBomb); boxS.add(Box.createVerticalStrut(8)); boxS.setBorder(border1); Box boxT = new Box(BoxLayout.Y_AXIS); buttonSure = new JButton("确定"); UserDefinedListener definedListener = new UserDefinedListener(this, mainFrame); buttonSure.setPreferredSize(new Dimension(70, 30)); buttonSure.setMargin(new Insets(0, 2, 0, 2)); buttonSure.addActionListener(definedListener); buttonCancer = new JButton("取消"); buttonCancer.setMargin(new Insets(0, 2, 0, 2)); buttonCancer.setSize(new Dimension(70, 30)); buttonCancer.addActionListener(definedListener); boxT.add(buttonSure); boxT.add(Box.createVerticalStrut(25)); boxT.add(buttonCancer); boxT.setBorder(border1); panel.add(boxS); panel.add(boxT); Border border = BorderFactory.createEmptyBorder(3, 15, 5, 15); jPanel.setBorder(border); jPanel.add(panel); return jPanel; } }自定义窗口监听器(com.listener/UserDefinedListener.java)public class UserDefinedListener implements ActionListener { UserDefined userDefined; MainFrame mainFrame; public UserDefinedListener(UserDefined userDefined, MainFrame mainFrame) { this.mainFrame = mainFrame; this.userDefined = userDefined; } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == userDefined.getButtonCancer()) { userDefined.dispose(); mainFrame.reStartGame(); } else if (e.getSource() == userDefined.getButtonSure()) { String highT = userDefined.getjTextFieldHigh().getText(); Pattern pattern = Pattern.compile("^[0-9]{1,3}$"); Matcher matcher = pattern.matcher(highT); int row = 0; if (!matcher.matches()) { userDefined.getjLabelMessage() .setText("输入的行数范围应在9-30之间"); return; } else { row = Integer.parseInt(highT); if (row < 9 || row > 30) { userDefined.getjLabelMessage().setText( "输入的行数范围应在9-30之间"); return; } } String colT = userDefined.getjTextFieldWide().getText(); int col = 0; try { col = Integer.parseInt(colT); if (col < 9 || col > 30) { userDefined.getjLabelMessage().setText( "输入的列数范围应在9-30之间"); return; } } catch (Exception e2) { userDefined.getjLabelMessage().setText( "列数应该为数字且范围应在9-30之间"); return; } String mineT = userDefined.getjTextFieldBomb().getText(); int mine = 0; try { mine = Integer.parseInt(mineT); if (mine < 10) { mine = 10; } else { mine = Math.min(mine, Tools.rows * Tools.cols * 4 / 5); } } catch (Exception e3) { userDefined.getjLabelMessage().setText("雷数应该为数字"); return; } userDefined.dispose(); Tools.rows = row; Tools.cols = col; Tools.allcount = mine; mainFrame.reStartGame(); } } }运行效果:英雄榜弹出胜利窗口(com.dialog/Win.java)public class Win extends JDialog { MainFrame mainframe; private JTextField text; TreeSet<Own> LOWER = new TreeSet<Own>(); TreeSet<Own> MIDDLE = new TreeSet<Own>(); TreeSet<Own> HEIGHT = new TreeSet<Own>(); public Win(MainFrame mainframe){ this.mainframe = mainframe; this.setIconImage(Tools.getImageIcon().getImage()); this.setTitle("扫雷成功"); this.setLocationRelativeTo(null); this.setSize(200, 150); this.init(); this.setVisible(true); } private void init() { // 存放记入 JPanel panel = new JPanel(); panel.setLayout(new GridLayout(4,1)); JLabel label = new JLabel("好厉害!请留下你的大名"); panel.add(label); text = new JTextField(); panel.add(text); // times = mainframe.getTimer().getTimes(); JLabel labTime = new JLabel("你所使用的时间:"+Tools.timecount); panel.add(labTime); JButton butys = new JButton("保存"); butys.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if(Tools.currentLevel.equals("初级")){ if(Tools.time1>=Tools.timecount && Tools.time2>=Tools.timecount && Tools.time3>=Tools.timecount){ Tools.time3 = Tools.time2; Tools.name3 = Tools.name2; Tools.time2 = Tools.time1; Tools.name2 = Tools.name1; Tools.time1 = Tools.timecount; Tools.name1=text.getText(); }else if(Tools.time2>=Tools.timecount && Tools.time3>=Tools.timecount && Tools.time1<=Tools.timecount){ Tools.time3 = Tools.time2; Tools.name3 = Tools.name2; Tools.time2 = Tools.timecount; Tools.name2=text.getText(); }else if(Tools.time3>=Tools.timecount && Tools.time1<=Tools.timecount && Tools.time2<=Tools.timecount){ Tools.time3 = Tools.timecount; Tools.name3=text.getText(); } } if(Tools.currentLevel.equals("中级")){ if(Tools.time01>=Tools.timecount && Tools.time02>=Tools.timecount && Tools.time03>=Tools.timecount){ Tools.time03 = Tools.time02; Tools.name03 = Tools.name02; Tools.time02 = Tools.time01; Tools.name02 = Tools.name01; Tools.time01 = Tools.timecount; Tools.name01=text.getText(); }else if(Tools.time02>=Tools.timecount && Tools.time03>=Tools.timecount && Tools.time01<=Tools.timecount){ Tools.time03 = Tools.time02; Tools.name03 = Tools.name02; Tools.time02 = Tools.timecount; Tools.name02=text.getText(); }else if(Tools.time03>=Tools.timecount && Tools.time01<=Tools.timecount && Tools.time02<=Tools.timecount){ Tools.time03 = Tools.timecount; Tools.name03=text.getText(); } } if(Tools.currentLevel.equals("高级")){ if(Tools.time001>=Tools.timecount && Tools.time002>=Tools.timecount && Tools.time003>=Tools.timecount){ Tools.time003 = Tools.time002; Tools.name003 = Tools.name002; Tools.time002 = Tools.time001; Tools.name002 = Tools.name001; Tools.time001 = Tools.timecount; Tools.name001=text.getText(); }else if(Tools.time002>=Tools.timecount && Tools.time003>=Tools.timecount && Tools.time001<=Tools.timecount){ Tools.time003 = Tools.time002; Tools.name003 = Tools.name002; Tools.time002 = Tools.timecount; Tools.name002=text.getText(); }else if(Tools.time003>=Tools.timecount && Tools.time001<=Tools.timecount && Tools.time002<=Tools.timecount){ Tools.time003 = Tools.timecount; Tools.name003=text.getText(); } } Win.this.dispose(); } }); panel.add(butys); this.add(panel); } public JTextField getText() { return text; }运行效果:英雄榜类(com.dialog/Hero.java)英雄榜分为初级、中级、高级英雄榜;每个英雄榜类逻辑是一样的,通过胜利窗口的事件监听器判断是哪个等级的英雄榜数据,然后写入临时变量中保存。以此类推编写中级、高级英雄榜Hero1,Hero2,当然也可以只写一个类,不过需要多加一些判断条件。public class Hero extends JDialog{ private JLabel jlabel1; private JLabel jlabel2; private JLabel jlabel3; private JLabel jlabel4; private JLabel jlabel5; private JLabel jlabel6; private JLabel time1; private JLabel time2; private JLabel time3; private JLabel name1; private JLabel name2; private JLabel name3; private JButton jbutton1; private JButton jbutton2; private MainFrame mainframe; private JPanel jpanel; public Hero(MainFrame mainframe) { this.mainframe=mainframe; this.setIconImage(Tools.getImageIcon().getImage()); this.setTitle("初级英雄榜"); this.setVisible(true); this.setSize(220,220); this.setResizable(false); this.setLocationRelativeTo(mainframe); this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); init(); } public JLabel getJLabel1() { return jlabel1; } public void setJLabel1(JLabel jlabel1) { this.jlabel1 = jlabel1; } public JLabel getJLabel2() { return jlabel2; } public void setJLabel2(JLabel jlabel2) { this.jlabel2 = jlabel2; } public JLabel getJLabel3() { return jlabel3; } public void setJLabel3(JLabel jlabel3) { this.jlabel3 = jlabel3; } public JLabel getJLabel4() { return jlabel4; } public void setJLabel4(JLabel jlabel4) { this.jlabel4 = jlabel4; } public JLabel getJLabel5() { return jlabel5; } public void setJLabel5(JLabel jlabel5) { this.jlabel5 = jlabel5; } public JLabel getJLabel6() { return jlabel6; } public void setJLabel6(JLabel jlabel6) { this.jlabel6 = jlabel6; } public JLabel getTime1() { return time1; } public void setTime1(JLabel time1) { this.time1 = time1; } public JLabel getTime2() { return time2; } public void setTime2(JLabel time2) { this.time2 = time2; } public JLabel getTime3() { return time3; } public void setTime3(JLabel time3) { this.time3 = time3; } public JLabel getName1() { return name1; } public void setName1(JLabel name1) { this.name1 = name1; } public JLabel getName2() { return name2; } public void setName2(JLabel name2) { this.name2 = name2; } public JLabel getName3() { return name3; } public void setName3(JLabel name3) { this.name3 = name3; } public void init(){ HeroListener heroListener = new HeroListener(); jlabel1 = new JLabel(" 名次"); jlabel2 = new JLabel(" 成绩"); jlabel3 = new JLabel(" 玩家"); jlabel4 = new JLabel(" 第一名:"); jlabel5 = new JLabel(" 第二名:"); jlabel6 = new JLabel(" 第三名:"); time1 = new JLabel(""+Tools.time1); time2 = new JLabel(""+Tools.time2); time3 = new JLabel(""+Tools.time3); name1 = new JLabel(" "+Tools.name1); name2 = new JLabel(" "+Tools.name2); name3 = new JLabel(" "+Tools.name3); jbutton1=new JButton("确定"); jbutton1.addActionListener(heroListener); jbutton2=new JButton("重新设置"); jbutton2.addActionListener(heroListener); jpanel=new JPanel(); Box box1 = Box.createVerticalBox(); box1.add(jlabel1); box1.add(Box.createVerticalStrut(10)); box1.add(jlabel4); box1.add(Box.createVerticalStrut(10)); box1.add(jlabel5); box1.add(Box.createVerticalStrut(10)); box1.add(jlabel6); Box box2 = Box.createVerticalBox(); box2.add(jlabel2); box2.add(Box.createVerticalStrut(10)); box2.add(time1); box2.add(Box.createVerticalStrut(10)); box2.add(time2); box2.add(Box.createVerticalStrut(10)); box2.add(time3); Box box3 = Box.createVerticalBox(); box3.add(jlabel3); box3.add(Box.createVerticalStrut(10)); box3.add(name1); box3.add(Box.createVerticalStrut(10)); box3.add(name2); box3.add(Box.createVerticalStrut(10)); box3.add(name3); Box box4 = Box.createHorizontalBox(); box4.add(jbutton1); box4.add(Box.createHorizontalStrut(20)); box4.add(jbutton2); Box box5 = Box.createHorizontalBox(); box5.add(box1); box5.add(box2); box5.add(box3); Box box6 = Box.createVerticalBox(); box6.add(Box.createVerticalStrut(20)); box6.add(box5); box6.add(Box.createVerticalStrut(20)); box6.add(box4); jpanel.add(box6); this.add(jpanel); } class HeroListener implements ActionListener{ public void actionPerformed(ActionEvent e){ String command = e.getActionCommand(); if(command.equals("确定")){ dispose(); } else { Tools.time1 = 999; Tools.time2 = 999; Tools.time3 = 999; Tools.name1 = " 匿名"; Tools.name2 = " 匿名"; Tools.name3 = " 匿名"; time1.setText(""+Tools.time1); name1.setText(Tools.name1); time2.setText(""+Tools.time2); name2.setText(Tools.name2); time3.setText(""+Tools.time3); name3.setText(Tools.name3); //dispose(); } } } }运行效果:帮助菜单关于扫雷(com.dialog/About.java)可以根据自己的需求添加想要的窗口内容。public class About extends JDialog { MainFrame mainframe; public About(MainFrame mainframe){ this.setIconImage(Tools.getImageIcon().getImage()); this.mainframe = mainframe; this.setTitle("关于扫雷"); this.setLocationRelativeTo(null); this.setResizable(false); this.setSize(200, 130); this.init(); this.setVisible(true); } private void init() { Box box = Box.createVerticalBox(); JPanel jpanel = new JPanel(); JLabel jlabel = new JLabel("扫雷 ©2022"); JLabel jlabel1 = new JLabel("作者:XG.孤梦"); JLabel jlabel2 = new JLabel("我的博客:https://www.xggm.top"); box.add(jlabel); box.add(Box.createVerticalStrut(10)); box.add(jlabel1); box.add(Box.createVerticalStrut(10)); box.add(jlabel2); jpanel.add(box); this.add(jpanel); } }运行效果:外挂后门(com.listener/MenuListener.java)可以在布雷完成之后就编写这个方法,目的为了方便测试,节省时间,点击外挂,就会将是雷的小方格图片替换成其他图片,比如弄成中间有个小黑点的小方格// 后门外挂方便测试 menuItemHole.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (Tools.isStart) { Tools.isHole = true; // 判断每一个雷块是否是雷 for (MineLabel[] mineLabel : BombJMenuBar.this.mainframe .getBombJPanel().getLabels()) { for (MineLabel m : mineLabel) { if (m.isMineTag()) { m.setIcon(Tools.hole); } } } } } });运行效果:最后一个Java实现扫雷项目就这样完成了。
2022年05月26日
390 阅读
0 评论
0 点赞
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 点赞
1
2
...
8