Java程序设计
大作业报告
题目: 欢乐五子棋
学院: 软件学院
姓名:
学号:
专业班级:
任课教师:
截止时间: 2022年6月11日
大作业要求:
请根据本学期所学的Java和面向对象的思想实现一个完整的系统。开发环境和工具不限,大作业题目和内容自定,代码总行数不低于800行(含注释)。鼓励围绕这次疫情期间产生的学习、生活、工作的需求来开发相应程序。
具体要求如下:
- 采用面向对象程序设计,要运用继承、多态等机制;
- 代码规范需遵循Java编码规范要求;
- 具备文件读写功能,程序中的数据要以文件方式保存;
- 程序中要求具备异常处理;
- 使用第三方类库或者插件需在报告和程序中注明来源和版权信息,并详细说明使用了该第三方类库或者插件哪部分功能。
- 要求具备菜单功能,根据用户的输入,执行相应的操作。在菜单选项中,必须包含“关于”一项,该菜单项用来显示本作业的基本信息,包括程序名称、版本、完成时间,姓名、学号、班级等信息;
- 程序要求做到界面友好,对于用户的输入操作要有明确的提示信息,并对输入的数据进行合法性和正确性的检查;
- 每个文件、类、方法的前面都必须有规范的注释,注释中要说明作者是谁、主要功能、编写时间等信息。变量、常量、关键语句等都必须有注释说明。
- 所有源程序代码(含注释)都要拷贝到大作业报告的【3.3 程序实现】中。
- 源代码为多文件项目,合理分配好各个源代码文件内容。
- 本报告文档是作业的一个重要内容,文档中的每个内容都必须认真按照要求撰写,否则扣分。
模板格式说明:
- 正文模板中的红色文字部分为说明文字,请仔细阅读后撰写正式的内容。
- 排版要求:
页面设置:上2.54cm,下2.54cm,左3.67cm,右2.67cm,页眉1.5cm,页脚1.75cm,行间距1.35倍。
全文中文字体采用宋体,英文字体采用Times New Roman字体,一级标题使用小三号字体,二级、三级标题均使用四号字体,正文内容采用小四号字体,代码字体大小为五号。
目 录
一、需求分析1
1.1、开发环境1
1.2、功能需求1
二、系统分析与设计1
2.1、本程序需解决的关键技术问题1
2.2、总体功能图1
2.3、类图2
2.4、程序流程图(至少画1个关键性功能的流程图)2
三、程序设计与实现2
3.1、项目文件组织结构2
3.2、程序设计3
3.3、程序实现3
四、系统测试3
五、本程序高内聚低耦合的特点,易扩展、易维护3
六、总结与体会4
七、自评分4
- 需求分析
1.1、开发环境
操作系统及版本:win 10
开发工具及版本:IntelliJ IDEA Educational Edition 2021.3.2
1.2、功能需求
欢乐五子棋
- 设置程序只能在限定的棋盘上落子,开始游戏后,当鼠标在棋盘上点击时,绘制棋子
- 完成五子棋的基本规则——任一方先在棋盘上形成横向、竖向、斜向的连续的相同颜色的五个(含五个以上)棋子的一方为胜,结束游戏。
- 设置倒计时功能,单位为分钟,令游戏更加合理
- 设置悔棋功能,防止因一些客观原因落子失败
- 设置认输功能
- 设置历史对局功能,查看历史对局输赢情况
- 设置退出功能
- 系统分析与设计
2.1、本程序需解决的关键技术问题
1、如何令鼠标在限定的范围内落子而不越界
2、如何实现黑子白子轮流进行落子
3、如何实现任一种颜色棋子在任意方向上练成五个时判定某一方胜利
4、如何令菜单上的功能在规定的点击范围内响应
5、如何令棋子落在棋盘的网格线上且当两个棋子选择下在同一个网格上时,怎样解决上一个棋子被覆盖的问题
6、怎样完成时间的设置,并且当使用者输入正整数和0以外的数字使不产生bug
7、如何将对局输赢情况(包含时间线)存储在文件中不出现bug,以及如何将对局内容呈现在窗口中
2.2、总体功能图
2.3、类图
2.4、程序流程图(至少画1个关键性功能的流程图)
函数:paint函数,MyFrameChess函数,mousePressed函数,judge函数,run函数
- 程序设计与实现
3.1、项目文件组织结构
3.2、程序设计
mainmenu类:用于调用MyFrameChess类
MyFrameChess类:用于构建棋盘,控制落子,判断胜负,设置时间等功能
关键知识点:继承,封装,多态,多线程运行,JFrame和鼠标监听器的相关知识
主要成员函数:
MyFrameChess构造函数:初始化相关变量
paint函数:用于设置界面,包括背景图片的导入,棋盘的绘制,落子方的提示信息。
mousePressed函数:
设计意图:监听鼠标位置,实现棋盘上各项功能
功能:获取x,y的坐标,根据由paint函数记录的数据绘制棋子,判断游戏是否结束。
实现“开始游戏”选项,点击重新开始,清空棋盘,开始游戏
实现“倒计时”选项,以分钟为单位设置时间,输入数为0时,设置时间无限制
实现“游戏说明”选项,点击游戏说明,弹出对话框以介绍游戏规则
实现“关于”选项,点击关于,弹出对话框介绍游戏制作相关内容
实现“悔棋”选项,点击悔棋,撤回上一步,但不可连续重复执行
实现“认输”选项,点击认输,判断当前落子的人败北,游戏结束
实现“历史对局”选项,点击显示历史对局的输赢情况
实现“退出游戏”选项,点击退出,结束程序
judge函数: 用于判断当前落子位置是否存在其余四个相同颜色棋子使当前一方连成五子
run函数: 用于实现多线程运作
3.3、程序实现
paint函数:利用鼠标监听器获取棋盘的范围,再通过for循环划出棋盘,同时使用Graphics类对界面进行相应优化
MyFrameChess构造函数:主要用于初始化各个变量
mousePressed函数:使用if函数进行各类判断确定各类功能作用范围,利用JFrame的弹窗设置各类提示信息,显示时间maxtime本是正整数,运用一些方法设置为时分秒的形式,代码如下:
- if(maxTime > 0){
- bTime = maxTime/3600+":"+
- (maxTime/60-maxTime/3600*60)+
- ":"+(maxTime-maxTime/60*60);
- wTime = maxTime/3600+
- ":"+(maxTime/60-maxTime/3600*60)+
- ":"+(maxTime-maxTime/60*60);
悔棋选项利用记录最后落子坐标的方法进行撤回,代码如下:
- //设置悔棋选项
- //限定选项范围
- if(e.getX()>=505&&e.getX()<=598&&e.getY()>=280&&e.getY()<=320){
- //判断当前棋盘上是否有棋子
- if(allchess[finalx][finaly]!=0&&Goon==true){
- //弹出选择对话框,根据选项决定是否执行悔棋程序
- int result = JOptionPane.showConfirmDialog(this,
- "请问是否进行悔棋操作?");
- //若选择坚持执行悔棋程序,则进行以下操作
- if(result == 0){
- //将最后一步的棋子设置为无,即清除该点的棋子
- allchess[finalx][finaly] = 0;
- //返回到落子前的棋盘状态
- if(Black == true){
- //若悔棋时是黑子,则将棋子颜色设置为白色
- Black = false;
- //将游戏信息变换为对应的内容
- message = "轮到白方";
- }else{
- //若悔棋时是黑子,则将棋子颜色设置为黑色
- Black = true;
- //将游戏信息变换为对应的内容
- message = "轮到黑方";
- }
- //重绘棋盘
- this.repaint();
- }
- }else{
- //若棋盘上无棋子或连续执行悔棋操作,则弹出该窗口
- JOptionPane.showMessageDialog(this,"无效操作!");
- }
- }
judge函数:设置判断五子是否相连的方法
若存在相同颜色的五个棋子任意方向相连,则返回true值
该类的算法判断依据为:
每落子一次便进行判定一次
当判定当前棋子周围任意一个方向上有相同颜色棋子相连时
则设置改棋子为最后落的棋子,将结束游戏条件设置为true
部分代码如下:
- //初始化为不相连
- boolean flag = false;
- //记录相同颜色棋子相连的数量
- int count = 1;
- //将本轮下的棋子颜色作为参考颜色
- int color = allchess[x][y];
- //用于判断横向是否有五个棋子相连
- int one = 1;
- //首先判断横向右方的棋子情况
- //防止向右越界异常处理
- while(x+one>=0&&x+one<=18&&
- y>=0&&y<=18&&
- color == allchess[x+one][y]){
- //若横向右方有相同颜色的棋子,则计数加一
- count++;
- //判断范围再往右前进一格
- one++;
- }
- //将判断范围初始化
- one = 1;
- //判断横向左方的棋子情况
- //防止向左越界异常处理
- while(x-one>=0&&x-one<=18&&
- y>=0&&y<=18&&
- color == allchess[x-one][y]){
- //若横向左方有相同颜色的棋子,则计数加一
- count++;
- //判断范围再往左前进一格
- one++;
- }
- //若相同连续的棋子计数达到五个,则更改flag的值
- if(count >= 5){
- //使上层判定游戏结束,其中一方获得胜利
- flag = true;