首页
归档
Github
留言
工具箱
邻居
壁纸
更多
音乐
直播
视频
Search
1
欢迎访问我的日志空间
76,419 阅读
2
Typecho - Joe主题魔改版(持续更新)
8,340 阅读
3
Typecho-Joe主题实现图片评论功能
7,028 阅读
4
WEB音乐播放器源码
6,209 阅读
5
Git上传项目到Github仓库教程
5,303 阅读
学习笔记
源码库
BUG
第九艺术
登录
/
注册
Search
标签搜索
学习笔记
C语言
typecho
Java
扫雷
源码
PHP
插件
网站源码
音乐播放器
模板
git
github
bug
QQBot
AI
机器人
框架
Nekro Agent
XG.孤梦
累计撰写
53
篇文章
累计收到
200
条评论
首页
栏目
学习笔记
源码库
BUG
第九艺术
页面
归档
Github
留言
工具箱
邻居
壁纸
音乐
直播
视频
搜索到
41
篇与
学习笔记
的结果
2025-06-05
字由客户端激活的字体提取方法
前言最近有对文本美化有需求,然后系统自带的字体不够理想于是就找到了一个字体软件【字由】,但是使用后发现关闭字由客户端后,设定的字体就消失了。不支持下载有个很严重的问题,比如进行web开发几乎就没法用,因为必须要根据页面上应用到的汉字制作精简版字体才能保证用户加载不超出浏览器内存限制。官方解释是:由于字体保存在字由云端,所以请保持字由在线使用。懂程序的小伙伴应该都知道win系统字体安装肯定是要缓存字体文件到本地,然后临时加载字体,所以本地肯定是有字体的源文件的,然后我就开始在网上查找攻略,发现方法大部分都失效了,经过仔细分析终于找到了字体文件。查找过程 第一个方法(经过测试无效) 一、打开字由客户端,选择自己喜欢的字体激活。二、进入C:Users用户名AppDataRoamingSystemDataTemp 这个目录。(文件夹没有这个目录)三、.按类型排序,我们会看到许多类似 0c42ff0cdbe7b418bf81a3ca13e03dcb 这样没有后缀的文件,这就是字体文件的本地缓存。四、在文件名末尾加上ttf后缀【可以批量重命名】,然后右击预览,根据预览中显示的信息更改文件名。五、右击,安装字体。第二个方法(经过测试还没有和谐,不过需要多个步骤)一、打开字由客户端,选择自己喜欢的字体激活。二、打开文件夹进入C:Users用户名AppDataRoaminghellofontCoreSyncpluginslivetyper 这个目录。当我在文件夹导航栏输入这个地址发现没有这个目录,然后查找上一层发现是空的文件夹难道又失效了吗?,我在目录附近查找了一番,一无所获,然后回到了这个目录,难道是隐藏起来了我立即右键查看文件夹的大小果然是隐藏起来了这里用的并不是普通的隐藏项目(在文件夹菜单栏勾选查看隐藏的项目是无效的)而是将字体文件设置成了受保护的操作系统文件,显示方法:第一种1.使用Windows + R快捷键打开「运行」对话框,执行control folders命令打开「文件资源管理器选项」2.切换到「查看」菜单,在「高级设置」中:取消勾选「隐藏受保护的操作系统文件(推荐)」选择「显示隐藏的文件、文件夹和驱动器」。点击应用第二种1.在要显示隐藏文件夹的目录下,创建一个新的文本文档。2.在文档中输入以下代码:attrib -h -r -s /s /d,作用是将清除文件夹的所有隐藏属性。3.保存并关闭文本文档后,选中刚刚的[新建文本文档.txt]将.txt后缀重命名为.bat。若看不到.txt和.bat这些后缀,需先在文件夹查看菜单勾选上文件扩展名。4.然后双击运行[新建文本文档.bat]批处理文件,文件夹应该就会显示出来。三.这时候回到之前的目录我们就能可见r文件夹打开里面我们会看到许多类似 99606-20250603142220000 这样没有后缀的系统文件,这就是字体文件的本地缓存。四、在文件名末尾加上ttf后缀【可以批量重命名】,然后双击或者在查看菜单打开预览,根据预览中显示的信息更改文件名。五、然后就可以正真的【“字”由】安装字体。教程结束,仅供思路参考,不对原本软件客户端造成任何破解及入侵,注意私自倒卖字体文件,属于违法行为请勿倒卖获取到的字体,如有侵权,请联系博主删除。
2025年06月05日
506 阅读
1 评论
6 点赞
2023-06-12
制作可变logo教程
前言使用joe主题的人应该都知道主题logo会随主题的明暗模式进行变换,那么这个是怎么实现的呢?其实这个有两种方法。替换文件法这个方法通常运用在图片(位图图像)通过在明暗模式切换的js代码中添加logo的文件路径替换,达到两张图片的切换效果。矢量图编辑法有学习过设计美术方面的或者使用过 Adobe Illustrator、Corel Draw 的人,应该都知道矢量图,有一个非常好的特性就是图像可以无限级缩放,对图形进行缩放,旋转或变形操作时,图形不会产生锯齿效果,而位图缩放和旋转容易失真,这个是这么实现的呢,其实你可以下载一个纯矢量图文件 文件格式通常以 .svg 结尾 ,右键以文本编辑器或者记事本方式打开然后,你就会看见一大段类似坐标点一样的代码(数学向量),就是因为这些坐标一样的数学向量组成了一张图像,所以矢量图可以使用css或者js对其就行编辑,从而达到图像变换的效果。位图与矢量图比较图像类型组成优点缺点常用制作工具点阵图像(位图)像素只要有足够多的不同色彩的像素,就可以制作出色彩丰富的图象,逼真地表现自然界的景象缩放和旋转容易失真,同时文件容量较大Photo Shop、画图等矢量图像数学向量文件容量较小,在进行放大、缩小或旋转等操作时图象不会失真不易制作色彩变化太多的图象AdobeIllustrator、Flash、CorelDraw等两种方法根据自己需要与实际需求自行选择教程开始方法一准备两张不同效果的logo图片(最好是透明镂空效果最佳)制作或者修改图片软件推荐使用 Photo Shop制作图片使用PS打开需要编辑的图片,根据自己需求设计,关于PS(Photo Shop)教程可自行去B站搜索相关教程这里就不过多赘述,就教一个简单的图片镂空,关于镂空不懂PS的小白可以使用AI自动抠图将图片镂空,当然效果可能不是很理想。一、 编辑图片用PS(Photo Shop)打开图片,这里拿老米的logo举例(如有侵权联系进行删除)在左边工具栏选择魔棒工具,然后点击logo图片的白色区域,如果图片背景比较复杂可以修改上面菜单栏的容差与勾选上连续一点一点选取。选取后点击删除键即可删除白色背景然后保存为以 .png 结尾的图片文件格式图片就制作到这里,然后上传图片到服务器文件夹里二、代码部分明暗模式的js代码在主题文件夹的 /assets/js/joe.config.js 文件夹里logo的代码在主题文件目录下的 /public/header.php 文件里使用合适的js替换代码将logo的图片地址替换即可,方法很多比如最常见的获取img图片对象的id,然后使用setAttribute()方法重新设置该id对象的src属性的值即可例子 <!--图片代码 --> <img id="img" src="img/logo.png" width="50" height="50"/> <!--切换按钮代码 --> <button onclick="myFunction()">更改logo图片</button> <!--js代码 --> <script> function myFunction() { var img=document.getElementById("img"); img.setAttribute("src","img/4.jpg"); } </script>方法二准备一张logo图片(最好是透明镂空效果最佳)制作或者修改图片软件使用到 Photo Shop、Adobe Illustrator制作矢量图一、编辑图片第一步与方法一一致将图片镂空,背景纯色也是可以的,然后加图片填充为纯色方便AI临摹图像,然后将保存好的图片用AI(Adobe Illustrator)打开选中图片然后在上面菜单栏中选择对象-->栅格化 背景选择透明然后选择对象图像描摹-->建立并扩展这个时候我们就得到了绘制出来的图像了,如果图案复杂的可以使用钢笔工具自己照着图勾出图像然后填充图像颜色即可然后保存为 .svg 结尾的图片文件格式用记事本打开图片文件可以看见一大段文字内容.svg格式的文件可以直接在浏览器中渲染出来,所以可以直接将这段内容复制代码中使用然后再通过js替换颜色代码达到变换效果,厉害一点的大佬也可以制作出动画效果我的joe主题logo代码在主题文件目录下的 /public/header.php 文件里,可以直接替换代码或者在主题设置的logo设置里粘贴这段代码或者文件路径地址即可这里的 <g fill="var(--main)"> 就是图像的颜色,因为我的logo比较简单就使用的一个颜色,你也可以添加一些css与js代码来美化logo,相关代码可以通过VS Code打开主题文件夹搜索 var(--main) 进行参考,时间有限就写到这里了请各位小伙伴自行探索吧[line]教程结束[/line]
2023年06月12日
2,772 阅读
1 评论
7 点赞
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日
2,776 阅读
0 评论
5 点赞
2022-08-10
Typecho-Joe主题实现图片评论功能
实现效果实际使用效果见本站,主题将在1.1.7版本中嵌入此功能,但是在开启前需要配置一些东西。使用我的主题模板搭建好图床直接把js里的图床API改成自己的就可以了效果图默认状态已选择文件点击插入 上传图片默认插入Markdown语法链接,目的方便实现评论点击图片大图预览效果开启判断文件类型在js中加入后缀判断文件类型,选择非图片类型时,会提示视频教程[hide][dplayer src="https://blog.xggm.top/video/m3u8/2022/08/28/8a1feb72/index.m3u8"/][/hide]准备修改后台设置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插入以下代码到图片位置,或者合适位置。[hide]<?php if($this->options->JCommentImg !== "off") : ?> <span class="showFileName"></span> <a href="javascript:;" id="upload" class="file"> <svg t="1629804953737" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2082" width="24" height="24"><path d="M740.693333 750.933333h-102.4c-20.48 0-34.133333-13.653333-34.133333-34.133333s13.653333-34.133333 34.133333-34.133333h102.4c58.026667 0 102.4-44.373333 102.4-102.4 0-47.786667-34.133333-88.746667-78.506666-98.986667-17.066667-3.413333-27.306667-20.48-27.306667-37.546667 3.413333-13.653333 3.413333-23.893333 3.413333-34.133333 0-112.64-92.16-204.8-204.8-204.8-88.746667 0-170.666667 61.44-197.973333 146.773333 0 13.653333-13.653333 23.893333-27.306667 23.893334-81.92 3.413333-146.773333 71.68-146.773333 153.6 0 85.333333 68.266667 153.6 153.6 153.6h51.2c20.48 0 34.133333 13.653333 34.133333 34.133333s-13.653333 34.133333-34.133333 34.133333H314.026667c-122.88 0-221.866667-98.986667-221.866667-221.866666 0-112.64 81.92-204.8 191.146667-218.453334 40.96-102.4 143.36-174.08 252.586666-174.08 150.186667 0 273.066667 122.88 273.066667 273.066667v13.653333c61.44 27.306667 102.4 88.746667 102.4 157.013334 0 95.573333-75.093333 170.666667-170.666667 170.666666z m-204.8 102.4V477.866667c0-13.653333-6.826667-23.893333-20.48-30.72-10.24-6.826667-23.893333-3.413333-34.133333 3.413333l-136.533333 102.4c-13.653333 10.24-17.066667 34.133333-6.826667 47.786667 10.24 13.653333 34.133333 17.066667 47.786667 6.826666l81.92-61.44v307.2c0 20.48 13.653333 34.133333 34.133333 34.133334s34.133333-13.653333 34.133333-34.133334z m129.706667-252.586666c10.24-13.653333 6.826667-37.546667-6.826667-47.786667l-34.133333-27.306667c-13.653333-10.24-37.546667-6.826667-47.786667 6.826667-10.24 13.653333-6.826667 37.546667 6.826667 47.786667l34.133333 27.306666c6.826667 3.413333 13.653333 6.826667 20.48 6.826667 10.24 0 20.48-3.413333 27.306667-13.653333z" fill="#3E2AD1" p-id="2083"></path></svg> <input id="fileControl" type="file" > </a> <button style="button:active {color: #fff;background: var(--theme);}" id="btn">插入</button> <?php endif; ?> [/hide]找到输出评论的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>[hide]$("#btn").click(function(){ var formData = new FormData(); var upfiles = $("#fileControl").get(0).files; formData.append("file", upfiles[0]); axios({ // 请求类型 method: "POST", url: "https://book.xggm.top/api.php", //XG图床API headers:{'Content-Type':'multipart/form-data'}, data:formData }).then((response) => { document.getElementById('comment-content').value=document.getElementById('comment-content').value+'!['+response.data.name+']'+'('+response.data.viewurl+')'; }); }); $(function() { //显示隐藏的文件名并上传状态切换 $('.showFileName').hide(); $('#btn').hide(); $("#upload").on("change", "input[type='file']", function() { var filePath = $(this).val(); // 如果不限制上传文件类型,请注释此条代码,删除下以后代码的注释 if(filePath.indexOf("jpg") != -1 || filePath.indexOf("png") != -1 || filePath.indexOf("gif") != -1 || filePath.indexOf("jpeg") != -1 || filePath.indexOf("ico") != -1 || filePath.indexOf("webp") != -1 || filePath.indexOf("bmp") != -1 || filePath.indexOf("tif") != -1 || filePath.indexOf("tiff") != -1) { // if(filePath) { $(".fileerrorTip").html("").hide(); var arr = filePath.split('\\'); var fileName = arr[arr.length - 1]; $('.showFileName').show(); $('#btn').show(); $(".showFileName").html("已选择文件名:" + fileName); } else { $('.showFileName').show(); $(".showFileName").html("请选择图片文件!"); $('#btn').hide(); return false } }); });[/hide]最后,再后台开启评论图片功能,清除缓存刷新页面,图片上传按钮就出现了,附一张评论图片成功的评论截图[line]教程结束[/line]
2022年08月10日
7,028 阅读
31 评论
9 点赞
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日
5,303 阅读
0 评论
4 点赞
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日
2,886 阅读
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日
1,707 阅读
0 评论
1 点赞
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日
1,866 阅读
0 评论
1 点赞
1
2
...
6