题目
学 院: 职业技术学院
专 业: 计算机科学与技术
班 级: 计科职112班
学 号: 1120020363
学生姓名: 毛朋艺
20xx年7月2号
目录
第一章 设计目的 ............................................................................................................................ 3
第二章 需求分析 ........................................................................................................................... 4
2.1 硬件环境 ............................................................................................................................ 4
2.2 软件环境 ............................................................................................................................ 4
2.3扫雷游戏概述 ..................................................................................................................... 4
2.3.1扫雷的操作方法 ............................................................................................................ 4
2.3.2游戏具有的功能 .......................................................................................................... 4
第三章 总体设计 ........................................................................................................................... 6
3.1 MineGame.java(主类) ........................................................................................................ 7
3.2 MineArea.java ..................................................................................................................... 7
3.3 Block.java ........................................................................................................................... 7
第四章 详细设计 ........................................................................................................................... 8
4.1 MineGame类 ...................................................................................................................... 8
4.2 MineArea类 ....................................................................................................................... 9
4.3 Block类 ............................................................................................................................ 10
第五章 编码实现 ......................................................................................................................... 12
5.1 MineGame.java(主类) ................................................................................................... 12
5.2 MineArea.java ................................................................................................................... 17
5.3 Block.java ......................................................................................................................... 22
第六章 系统测试 ......................................................................................................................... 24
第七章 实验总结 ......................................................................................................................... 26
第一章 设计目的
随着现在生活节奏的加快,人们在工作之余需要一个轻松娱乐的放松环境。因此我们小组编写此软件的目的,一方面作为初学者来了解Android的开发,另一方面开发此软件使用户能在娱乐休闲的同时拓展思维能力。同时进一步拓展研究,做到将扫雷层次升级,能够在多人连机的情况下,一起分工来进行对战 。如 一方放雷, 另一方排雷。
第二章 需求分析
2.1 硬件环境
一台完整的电脑,包括键盘、鼠标,最小硬盘空间1GHz 1.1 386,486,586及兼容机.640K基本内存; 2.1 1M以上扩充内存,10M以上的显示内存.
2.2 软件环境
开发环境:本系统的设计采用的是TC语言开发 WindowsWindowsWindowsWindows 操作系统,TurboTurboTurboTurbo C 2.0C 2.0C 2.0C 2.0汉化版
2.3扫雷游戏概述
扫雷是一种具有迷惑性的对记忆和推理能力的简单测试,它是长久以来最受欢迎的 Windows 游戏之一。游戏目标:找出空方块,同时避免触雷。
2.3.1扫雷的操作方法
游戏主区域由很多个方格组成。使用鼠标随机点击一个方格,方格即被打开并显示出方格中的数字;方格中数字则表示其周围的8个方格隐藏了几颗雷;如果点开的格子为空白格,即其周围有0颗雷,则其周围格子自动打开。
例如,方格中出现1,说明上下左右及斜角合计有一颗雷,依次类推,2则有2颗,3则有3颗。
2.3.2游戏具有的功能
I.能够显示主菜单和界面
游戏需要提供主菜单让玩家进行游戏设置,同时能够显示当前剩余的地雷数量及当前花费时间等相关信息到界面上。
II.能够接收鼠标输入功能
能够接收玩家的鼠标输入功能,左键和右键输入。
III. 能够根据规则翻转相应的格子
翻动指定位置的格子。
IV. 能够标示指定格子的功能
即能够对确定或者怀疑是地雷的格子进行"旗子"和"?"符号的标示。 V.游戏胜负判断功能
当玩家单击的格子中有地雷时,判定玩家失败,游戏结束。当扫雷游戏中全部格子被打开时,判定玩家成功。
VI英雄榜记录更新
当有玩家把当前等级的地雷全部扫出来后,并且时间比记录中的时间短时,在结束游戏时,要求玩家把名字保存下来。游戏初始时时间为999秒。
例如,当第一个玩家把全部地雷扫出来的时间为120秒,这时玩家的记录时间将被保存下来并作为记录时间线。直到有玩家的时间少于120秒,才能更新当前记录时间线并保存玩家的名字。
第三章 总体设计
在设计扫雷游戏时,需要编写8个Java源文件:MineGame.java、MineArea.java、Block.java、BlockView.java、userDefine.java、LayMines.java、Record.java和ShowRecord.java.扫雷游戏除了需要编写上述8个Java源文件所给出的类外,还需要Java系统提供的一些重要的类,例如File、JButton和JLabel等类。扫雷游戏所用到的一些重要的类以及之间的组合关系如图1-1所示,系统功能图如图1-2所示。
3.1 MineGame.java(主类)
MineGame类负责创建扫雷游戏主窗口,该文件含有main方法。扫雷游戏从该类开始执行。
3.2 MineArea.java
MineArea类创建的对象是MineArea类最重要的成员之一,代表“扫雷区域”。
3.3 Block.java
Block类是雷区中“方块”的类封装,含有关于“方块”的属性以及操作,即负责为雷区创建代表“方块”的Block对象。
第四章 详细设计
4.1 MineGame类
MineGame类是javax.swing包中JFrame的一个子类,并实现了ActionListener接口。标明该类的只要成员变量和方法的UML图如图2-1所示。
以下是UML图中有关数据和方法的详细说明。
1) 成员变量
a. bar和fileMenu提供菜单操作,单击游戏菜单项为“开始”、“初级”、“中级”、“高级”、“扫雷英雄榜”、“自定义”和“退出”。单击帮助菜单项为“关于”。 b. mineArea是扫雷区域,提供有关扫雷的主要功能。
c. “英雄榜”负责存放三个级别的扫雷最好成绩。
d. showHeroRecord负责显示英雄榜中的数据。
2) 方法
A. MineGame()是构造方法,负责完成窗口的初始化。
B. ActionPerformed(ActionEven)方法是MineGame类实现的ActionListener接
口中的方法,该方法负责执行菜单发出的有关命令。用户选择菜单中的菜单项可触发ActionEvent事件,导致actionPerformed(ActionEvent)方法执行相应的操作,例如将mineArea创建的雷区设置为初级、中级、高级。
C. main(String[])方法是程序运行的入口方法。
4.2 MineArea类
MineArea类是javax.swing包中JPanel容器的子类,实现了ActionListener和MouseListener接口,所创建的对象:mineArea是MineGame类中最重要的成员之一,作为一个容器添加到MineGame窗口的中心。标明MineArea类的主要成员变量、方法以及和MineGame类之间组合关系的UML图如图2-2所示。
以下是UML图中有关数据和方法的详细说明。
1)成员变量
a. Block是Block类型的数组,用来确定雷区有多少需进行扫雷的方块。 b. blockView是Blockview类型的数组,负责为block数组中的Block对象提供视图。
c. Lay是LayMines类型的对象,负责设置block数组中的哪些方块是雷或不是雷。
d. Record负责提供保存成绩的界面,是一个对话框,默认不可见。用户只有扫雷成功后(用时最少),才能看见该对话框。
e. reStart是一个按钮对象,用户单击它重新开始游戏。
f. time是计时器对象,负责计算用户的用时。
2)方法
A. initMineArea(int,int,int,int)方法可根据参数提供的数据设置雷区的宽度,高度,雷的数目以及雷区的级别。
B. actionPerformed(ActionEvent)是MIneArea类实现ActionListener接口中的方法。当用户单击blockView中的某个方块时,actionPerformed
(ActionEvent)方法负责执行有关算法,例如,当用鼠标左键单击方块上的按钮后,若该方块下有雷,actionPerformed(ActionEvent)方法将使用户输掉本局,若该方块下又雷,actionPerformed(ActionEvent)方法将显示BlockView对象中的标签,该标签上是一个数字,该数字代表当前方块的周围的8个方块中总共有多少颗雷。
C. show()方法是一个递归方法。actionPerformed(ActionEvent)方法执行时将调用show方法进行扫雷。
D. mousePress(MouseEvent)方法是MineArea类实现的MouseListener接口中的方法,当用户按下鼠标右键时,mousePress(MouseEvent)方法负责让方块上显示一个探雷标记。
E. inquireWin()方法用来判断用户是否扫雷成功,如果成功该方法负责让record对话框可见。所谓扫雷成功是指不仅找到了全部的雷而且用时最少。
4.3 Block类
Block对象负责封装雷区中方块中的数据以及对这些数据的操作,外观效果由Blockview负责提供(见后面的BlockView)。
Block类创建的对象是数组block的单元的对象。Block型数组block是MineArea类的重要成员之一。标明Block类的主要成员变量和方法以及和
MineArea类之间的组合关系的UML图如下图2-3所示。
图4-3 Block类的UML图
以下是UML图中有关数据的方法的详细说明。
1)成员变量
a. name是方块上的名字。
b. aroundMineNumber是方块周围雷的数目。
c. mineIcon是方块上雷的图标。
d. sMine用来表示方块是否是雷。
e. isMark用来表示方块是否被标记。
f. isOpen用来表示方块是否被挖开。
2)方法
A. setAroundMineNumber(int)方法用来设置aroundMineNumber的值。
B. getAroundMineNumber()方法用来获取aroundMineNumber的值。
第五章 编码实现
前三个类的的主要源代码实现如下:
5.1 MineGame.java(主类)
import java.awt.event.*;//包含事件类
import java.awt.*;//包含抽象窗口工具集中的图形文本、窗口GUI类 import javax.swing.*;//包含SWING组件
import javax.swing.Box.Filler;
import javax.swing.border.*;//包含布局类
import java.util.*;//包含有用的数据类型类
import java.util.List;
import java.io.*;//包含输入流和输出流类
import javax.swing.ImageIcon;//包含图标
public class MineGame extends JFrame implements ActionListener{ JMenuBar menubar; //负责创建菜单条
JMenuItem 开始,初级,中级,高级,扫雷英雄榜,自定义,退出,关于;//负责创建菜单项
JMenu fileMenu,helpMenu;//负责创建菜单
ImageIcon app;//负责创建标题栏的图标
JLabel l1,l2,l3,l4;
JTextArea ta;
MineArea mineArea=null;
File 英雄榜=new File("英雄榜.txt");//创建文件保存记录 Hashtable hashtable=null;
ShowRecord showHeroRecord=null;
userDefine userdefine=new userDefine();//调用userDefine类 MineGame(){
mineArea=new MineArea(8,8,10,1);
add(mineArea,BorderLayout.CENTER); app=new ImageIcon("app.gif");//给标题栏创建图标
setIconImage(app.getImage());//获取图标并调用类实现 setTitle("扫雷"); //加入标题字段
menubar=new JMenuBar();//创建菜单条
JMenu fileMenu=new JMenu("游戏(G)");//创建菜单
JMenu helpMenu=new JMenu("帮助(H)");//创建菜单
fileMenu.setMnemonic('G');
helpMenu.setMnemonic('H');
开始=new JMenuItem("开始");//创建菜单项
开
始.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F2,0));//添加快捷方式
初级=new JMenuItem("初级");
中级=new JMenuItem("中级");
高级=new JMenuItem("高级");
扫雷英雄榜=new JMenuItem("扫雷英雄榜");
扫雷英雄
榜.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4,0)); 自定义=new JMenuItem("自定义",KeyEvent.VK_S);
自定
义.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5,0)); 退出=new JMenuItem("退出");
关于 = new JMenuItem("关于");
关
于.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1,0)); fileMenu.add(开始); //加入菜单的容器
fileMenu.addSeparator();//加入分隔符
fileMenu.add(初级);
fileMenu.add(中级);
fileMenu.add(高级);
fileMenu.addSeparator();
fileMenu.add(扫雷英雄榜);
fileMenu.addSeparator();
fileMenu.add(自定义);
fileMenu.addSeparator();
fileMenu.add(退出);
helpMenu.add(关于);
menubar.add(fileMenu);//加入菜单条的容器 menubar.add(helpMenu);
setJMenuBar(menubar);//完成封装
//添加事件监听器
开始.addActionListener(this);
初级.addActionListener(this);
中级.addActionListener(this);
高级.addActionListener(this);
扫雷英雄榜.addActionListener(this); 自定义.addActionListener(this);
退出.addActionListener(this);
关于.addActionListener(this);
//设置英雄榜
hashtable=new Hashtable();
hashtable.put("初级","初级#"+999+"#匿名"); hashtable.put("中级","中级#"+999+"#匿名"); hashtable.put("高级","高级#"+999+"#匿名"); if(!英雄榜.exists()) {
try{ FileOutputStream out=new FileOutputStream(英雄榜); ObjectOutputStream objectOut=new
ObjectOutputStream(out);
objectOut.writeObject(hashtable);
objectOut.close();
out.close();
}
catch(IOException e){}
}
showHeroRecord=new ShowRecord(this,hashtable);
setBounds(100,100,300,300);
setVisible(true);//设为可见
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//结束窗体所在的应用程序
validate(); }
//负责执行菜单发出的有关命令
public void actionPerformed(ActionEvent e){
if(e.getSource()==开始){
mineArea.initMineArea(8,8,10,1);//默认为初级 }
if(e.getSource()==初级){
mineArea.initMineArea(8,8,10,1);
setBounds(100,100,300,300);
mineArea.showTime.setText("0");
mineArea.time.stop(); }
if(e.getSource()==中级){
mineArea.initMineArea(16,16,40,2);
setBounds(100,100,500,500);
mineArea.showTime.setText("0");
mineArea.time.stop(); }
if(e.getSource()==高级){
mineArea.initMineArea(22,22,99,3);
setBounds(100,100,650,650);
mineArea.showTime.setText("0");
mineArea.time.stop(); }
if(e.getSource()==扫雷英雄榜){
if(showHeroRecord!=null)
showHeroRecord.setVisible(true); }
if(e.getSource()==自定义){
userdefine.setVisible(true); }
if(e.getSource()==退出){
System.exit(0); }
if(e.getSource()==关于){
JDialog dialog=new JDialog();
dialog.setTitle("关于帮助");
FlowLayout fl=new FlowLayout();
dialog.setLayout(fl);
dialog.setSize(500,500);
dialog.setVisible(true);
String s="扫雷游戏的规则如下:";
final JLabel l1 = new JLabel();
l1.setText(s);
l1.setForeground(new Color(0,0,0));
l1.setFont(new Font("Dialog",10,20));
// l1.setBounds(60,84,345,26);
final JLabel l2 = new JLabel("1,游戏区包括雷区、地雷计数器和计时器.");
final JLabel l3 = new JLabel("2,通过单击即可挖开方块,如果挖开的是地雷,则您输掉游戏.");
final JLabel l4 = new JLabel("3,如果方块上出现数字,表示在其周围的八个方块中共有多少颗地雷"); dialog.add(l1);
dialog.add(l2);
dialog.add(l3);
dialog.add(l4);
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
if(dialog!=null){
dialog.setVisible(true); }
}
validate(); }
public static void main(String args[]){
MineGame mg = new MineGame();} }
5.2 MineArea.java
public MineArea(int row,int colum,int mineCount,int grade) { reStart=new JButton("重新开始");
mark=new ImageIcon("flag.gif"); //探雷标记
time=new Timer(1000,this);
showTime=new JTextField(3);
showMarkedMineCount=new JTextField(3);
showTime.setHorizontalAlignment(JTextField.CENTER);
showMarkedMineCount.setHorizontalAlignment(JTextField.CENTER);
showMarkedMineCount.setFont(new Font("Arial",Font.BOLD,16)); showTime.setFont(new Font("Arial",Font.BOLD,16));
showTime.setEditable(false);//不可更改
showMarkedMineCount.setEditable(false);
pCenter=new JPanel();//创建面板
pSouth=new JPanel();
la1 = new JLabel(new ImageIcon("app.gif"));
la2 = new JLabel(new ImageIcon("time.gif"));
pCenter.setBorder(BorderFactory.createLoweredBevelBorder()); lay=new LayMines();
initMineArea(row,colum,mineCount,grade); //初始化雷区 reStart.addActionListener(this);
pSouth.add(la1);
pSouth.add(showMarkedMineCount);
pSouth.add(reStart);
pSouth.add(showTime);
pSouth.add(la2);
setLayout(new BorderLayout());
add(pSouth,BorderLayout.SOUTH);
add(pCenter,BorderLayout.CENTER); }
public void initMineArea(int row,int colum,int mineCount,int grade){ pCenter.removeAll();
spendTime=0;
markMount=mineCount;
this.row=row;
this.colum=colum;
this.mineCount=mineCount;
this.grade=grade;
block=new Block[row][colum];
for(int i=0;i<row;i++){
for(int j=0;j<colum;j++)
block[i][j]=new Block();
}
lay.layMinesForBlock(block,mineCount);
blockView=new BlockView[row][colum];
pCenter.setLayout(new GridLayout(row,colum));
for(int i=0;i<row;i++) {
for(int j=0;j<colum;j++) {
blockView[i][j]=new BlockView();
blockView[i][j].giveView(block[i][j]); //给block[i][j]提供视图
pCenter.add(blockView[i][j]);
blockView[i][j].getBlockCover().addActionListener(this);
blockView[i][j].getBlockCover().addMouseListener(this);
blockView[i][j].seeBlockCover();
blockView[i][j].getBlockCover().setEnabled(true); blockView[i][j].getBlockCover().setIcon(null); }
}
showMarkedMineCount.setText(""+markMount);
validate();
}
//当用户单击BlockView中的某个方块时,执行有关算法
public void actionPerformed(ActionEvent e) {
//点击Block方块区域
if(e.getSource()!=reStart&&e.getSource()!=time) {
time.start(); //开始计时
int m=-1,n=-1;
for(int i=0;i<row;i++) {
for(int j=0;j<colum;j++) {
if(e.getSource()==blockView[i][j].getBlockCover()){ m=i;
n=j;
break;
}
}
}
//鼠标左键单击方块上的按钮,
if(block[m][n].isMine()) {//如果该方块有雷,则用户输掉本局 for(int i=0;i<row;i++) {
for(int j=0;j<colum;j++) {
blockView[i][j].getBlockCover().setEnabled(false); if(block[i][j].isMine())
blockView[i][j].seeBlockNameOrIcon();
}
}
time.stop();
spendTime=0;
markMount=mineCount;
}
else { //若该方块下面没有雷
show(m,n); //见本类后面的show方法
}
}
else if(e.getSource()==reStart) {
initMineArea(row,colum,mineCount,grade);
time.stop(); showTime.setText("0");
}
else if(e.getSource()==time){
spendTime++;
showTime.setText(""+spendTime);
}
inquireWin();
}
//显示周围雷数
public void show(int m,int n) {
if(block[m][n].getAroundMineNumber()>0&&block[m][n].getIsOpen()==false){ //周围有雷
blockView[m][n].seeBlockNameOrIcon();
block[m][n].setIsOpen(true);
return;
}
else
if(block[m][n].getAroundMineNumber()==0&&block[m][n].getIsOpen()==false){
//周围没有雷
blockView[m][n].seeBlockNameOrIcon();
block[m][n].setIsOpen(true);
for(int k=Math.max(m-1,0);k<=Math.min(m+1,row-1);k++) { for(int t=Math.max(n-1,0);t<=Math.min(n+1,colum-1);t++) show(k,t);
}
}
}
public void mousePressed(MouseEvent e){
JButton source=(JButton)e.getSource();
for(int i=0;i<row;i++) {
for(int j=0;j<colum;j++) {
//单击右键的情况下
if(e.getModifiers()==InputEvent.BUTTON3_MASK&&
source==blockView[i][j].getBlockCover()){
if(block[i][j].getIsMark()) {//方块未被标记 source.setIcon(null);
block[i][j].setIsMark(false);
markMount=markMount+1;
showMarkedMineCount.setText(""+markMount); }
else{//方块被标记
source.setIcon(mark);
block[i][j].setIsMark(true);
markMount=markMount-1;
showMarkedMineCount.setText(""+markMount);}
}
} }
5.3 Block.java
public void setName(String icon) { //设置不是雷的情况
this.icon=icon; }
public String getName() { //获取名字,即雷的图标
return icon; }
public void setAroundMineNumber(int n) { //设置周围的雷数 aroundMineNumber=n; }
public int getAroundMineNumber() {//获取周围的雷数
return aroundMineNumber; }
public boolean isMine() {//判断是否是雷
return isMine; }
public void setIsMine(boolean b) {//设置是否是雷 isMine=b; }
public void setMineIcon(ImageIcon icon){//设置是雷时的图标 mineIcon=icon; }
public ImageIcon getMineicon(){//获取图标
return mineIcon; }
public boolean getIsOpen() {
return isOpen; }
public void setIsOpen(boolean p) {//是否被挖开
isOpen=p; }
public boolean getIsMark() {
return isMark; }
public void setIsMark(boolean m) {//是否被标记
isMark=m; }
第六章 系统测试
1 .游戏主界面,运行结果如图4-1所示:
图6-1 扫雷游戏初始界面
2点击“游戏”,显示游戏菜单项,运行结果如图4-2所示:
6-2 扫雷游戏“游戏”菜单项
3点击“帮助”,显示帮助菜单项,运行结果如图4-3所示:
图6-3 扫雷游戏“帮助”菜单项
第七章 实验总结
这次历时两周的课程设计,是基于Java的图形界面设计。我做的题目是扫雷游戏设计。在课程设计途中遇到颇多问题,最后也让身边的同学各显身手,大家一起解决各种报错以及修改方案。在和同学一起讨论的同时,各自也在增进对程序的认识程度。
在刚开始看到题目的时候,说实话怎不知道要怎么做。不过又逼迫自己不得不做,所以,就近原则的选择区图书馆查询。终于找到了合适的书,但看了里面的程序运行出的结果,就决定在此基础上加些自己认为比较好的设计。例如说,在一些地方加上图标,从而显得更美观和人性化。所以我在文件标题栏加上了图标,加图标的时候总是报错,说所用到的方法不对,最后边查书边试探,终于发现在自定义的类里面添加标题图标,和在系统定义的类里添加是有些区别的。在自定义类里添加图标,要事先定义变量把图标放进变量里,然后再调用方法获取,例如:
app=new ImageIcon("app.gif");//给标题栏创建图标
setIconImage(app.getImage());//获取图标并调用类实现
而在系统类里设置图标,例如:
ImageIcon mineIcon=new ImageIcon("app.gif");; //创建雷的图标 不需要引用到变量。
除此之外,我还参照Window 7的扫雷游戏,在显示剩余雷数和计时器的
JFieldText前面分别加上了雷、时钟的图标,方便用户区别两者,更有可观赏性。 在玩自己做的扫雷游戏时,有一次不小心把包含在文件夹里得图标放错了位置,结果一直不能显示点击后显示的雷图标和右键点击设置的标记图标。找来班长过来试试,他直接说,若在程序内部没有设置路径,那么图标的默认路径是在根目录里。我就直接把图标移到根目录,结果就问题就解决了。
继续参照Window 7的扫雷游戏,我发现,自己的程序给不知道扫雷这个程序的人,就完了,所以我在原来类的基础上,添加了“关于”菜单项,用以说明扫雷游戏的玩法,让更多的玩家来了解扫雷,让扫雷游戏拥有更多的用户群。
做完扫雷游戏后,相较于其他人做的成果,也有我觉得不足的地方,就是在自定义的时候,做触发器的时候有些考虑不周,导致与最后功能没有完全实现。
我觉得,扫雷作为一类休闲且益智的游戏,可以在其上加上声音,可以的话,能自定义怎样播放声音和自由选择各类声音,如果嫌声音太占内存,也可以联合一些音乐播放器,从而在播放器上自选歌曲。还可以设计一些东西,有必要的话保存一下用户的操作步骤,然后用flash播放,也不失为一种有意思构思。