第一章 引言
游戏是人们活动中一项非常重要的内容,电脑对游戏的贡献有目共睹,现在 摸过电脑的人很少有没玩过电脑游戏的,喜欢游戏的人也很少有不玩电脑的。 24 点游戏,能把枯燥的基本数学计算变得趣味盎然,能大大提高计算能力和速度,使得思维灵活敏捷,是一种寓学于乐的智力竞赛游戏。24 点游戏是一款风靡全球的电视游戏机和掌上游戏机游戏,它曾经造成的 经济价值可以说是游戏史上的一件大事。这款游戏最初是由谁制作的已无从知道,它看似简单但却变化无穷,令人上瘾。相信大多数用户都还记得为它痴迷得茶不思饭不想的那个24 点游戏时代。
究其历史,24 点游戏最早还是出现在 PC 机上,而我国的用户都是通过红白机了解、喜欢上它的。现在联众又将重新掀起这股让人沉迷的24点游戏风潮。对一般用户来说,它的规则简单,容易上手,且游戏过程变化无穷,而在"联众 24 点游戏"中,更有一些联众网络游戏所独有的魅力――有单机作战与两人在线对战两种模式,用户可任选一种进行游戏。网络模式还增加了积分制,使用户既能感受到游戏中的乐趣,又能给用户提供了个展现自己高超技艺的场所。

24点游戏游戏可以说是随计算机的发展而发展,并不断推出新演变的各种类似游戏, 深受广大玩家喜爱。这个游戏有的简单, 有的复杂, 但其根本原理是一 样的,都是对数字进行组合, 来训练玩家的心算能力。谈到游戏软件, 大多数人都认为其神妙莫测, 高不可及。而一般游戏软件也确实具有很高的技术难度, 随 着开发工具及软件开发方法学的不断发展, 动手开发游戏也不是十分困难的。24 点游戏游戏是一种古老而又有趣的游戏, 游戏软件不计其数, 网上就有好多关于实现的复杂算法和设计, 其难度让一般初学者望而却步。 本文提出一种用JAVA语言实现的简易方法, 对初学者可仿此开发类似游戏, 并了解游戏软件的设计与开发过程。
第二章 系统需求分析
2.1 引言
对软件需求分析就是通过调查研究,建立系统的数据模型、功能模型、 行为模型,用户和开发人员在“系统必须做什么”这个问题上实现相互理解,达到共识,从而形成双方认可的软件产品的需求规格说明书。这样有益于提高软件开发过程中的能见度,便于对软件开发过程中的控制与管理,便于采用工程方法开发软件,提高软件的质量,便于开发人员、维护人员、管理人员之间的交流、协作,并作为工作成果的原始依据,并且在向潜在用户传递 软件功能、性能需求,使其能够判断该软件是否与自己的需求相关。
2.2 游戏需求
4点游戏是一种是用一种使用扑克牌进行的益智游戏,游戏内容是:游戏开始前,软件随机产生4张牌,并显示给玩家,玩家根据这4张牌,要写出一个表达式,软件对这个表达式进行计算,判断结果是否为24,如果是则回答正确,如果不是则提示错误。每次游戏的时间应限定在一定的时间内(如20秒),时间到则开始新的一次,并记录失败。将游戏过程的数据保存到文件中,并能显示游戏成绩排名前10的记录。在不同版本中,对J、Q和K的处理有细微的差异。一个常见的版本是把J、Q和K去除,或当成10处理;还有一个版本是把J、Q和K对应表示为11、12和13.本次设计采用将J表示11、Q表示12和K表示13,使4张牌在1-13这13张牌中随机抽取。 游戏功能需求如下:
游戏界面需求:设计良好的游戏界面可以让玩家充分感受到游戏带来的娱乐性,游戏的背景色是动画,给玩家带来一定的娱乐性。
游戏形状需求:根据数字及颜色的不同,显示不同的纸牌。
鼠标处理事件需求:通过点击菜单栏中相应的菜单项,可以实现游戏的开始、结束,数字的计算,分数的显示,以及游戏选择等功能。
显示需求:随机出现四个数字,将其计算为24 即可。
2.3基本步骤
1 随机产生四个1-13的书,分别代表 13张牌
2 提示玩家输入算式
3 判断玩家输入的表达时是否合法,其中算式中的四个数字只能是程序所给的四 个数字,非法则回到1
4 如果玩家认为这四张牌算不出24点(如:1,1,1,1),可只输入?,程序将判 断这四张牌是否能得出24点,如果能,则程序将给出算式,如果不能,并回到1
5 当用户正确输入算式后,用“四则运算”的原理求出结果并判断是否为24,得出用户是输是赢的结果
6 询问用户是否继续,是则回到1,否则结束程序
2.4基本要求
2.4.1 输入输出要求
输入的运输符只能是+、-、、/、(、)六个,输入的数字为程序随机产生的四个数,而且每一个数都只能用一次
2.4.2 设计要求
设计游戏的核心算法
设计可视化的界面
能随机产生4个1位数并显示
用户能利用鼠标或键盘选择给出的数和运算
程序能判别正误并计分
能给出帮助和能重新产生数
2.5 软硬件需求
硬、软件配置
CPU :赛扬2.8 RAM :1G 硬盘 :320G
操作系统 :Windows xp java :jdk1.6.0_22
开发环境:Eclipse 3.5 ADT 0.95
2.6 接口控制
本游戏通过鼠标进行操作,在Windows的操作系统下,利用鼠标的左、右键 对纸牌进行计算,要使用鼠标的接口事件。
2.7 需求方案论证
学校现已开设的课程有C语言、C++、java等,通过网上以及图书馆的资料,知道可以通过C,C++,VB,Delphi,Java实现24点游戏方块游戏的设计。
第三章 系统概要设计
3.1 程序首页界面设计
应用程序首页应包含三个主要的用户模块界面,这里需要进一步分析每个用户模块界面中应该包括哪些显示内容。
在“开始游戏”按钮中,则直接进入游戏主界面。在“英雄榜”中,显示在游戏模式下当前的具体数据。
3.2 程序模块设计
从功能需求上分析可以看出,整个应用程序应划分为4个模块,分别是程序启动、用户界面、后台服务和数据库适配器,各模块之间的关系如图4-1所示。
图3.1系统模块
从模块结构图中不难看出,后台服务是整个应用程序的核心,主要是“数据获取模块”,负责随机产生数字。后台服务在程序启动时就由AppWidgetProvider启动,也可由用户界面通过startService()进行启动,启动后的后台服务将一直保持运行状态。
3.2.1功能模块
24算法游戏的功能模块不多,也比较容易实现。基本思想就是由程序先随机产生4张扑克牌,每张扑克牌对应一个整数,所以首先要有一个随机产生扑克牌的模块。接下来就是用户用程序产生的扑克牌来算24点了,所以要有一个输入用户去接表达式的模块。用户输入完成后,程序就开始计算表达式了,所以要有一个计算表达式的模块。程序计算完表达式后就要判断用户输入的表达式是不是为24点了,所以还有一个判断表达式正误的模块。这4个模块是逐步递进的,是要前一个模块的功能完成后,才能执行后一个模块,否则程序就将出错。程序所涉及的数据结构主要为整型和字符型,整型数据结构主要是用来计算表达式的,字符型数据结构主要是用来输入表达式的。程序所涉及的数据库结构主要有数组和栈,数组在计算表达式和产生扑克牌是都要用到,栈只是用来计算表达式的。
3.3 游戏流程图
图 3.2 游戏流程图
3.4 游戏运行界面
3.4.1 进入游戏界面模块图
图3.3
进入游戏模式,输入昵称,如下图 3.4所示 :
图 3.4
3.4.2 进入游戏界面
显示倒计时,随机显示4张纸牌。Pass按钮是在游戏回答不出来时,选择再来一次或是重新发牌;return按钮,是在退出游戏模式时的按钮。如图3.5所示:
图3.5
从随机出来的四个数字间让其等于24,回答正确界面加4分,如图3.6所示:
图3.6
回答错误,或时间到(60秒以内),如图3.7所示:
图3.7
显示游戏历史分数,如图3.8所示:
图3.8
第四章 系统详细设计
4.1 游戏详细设计类
4.1.1 定义卡片类card
1.定义两个私有属性number,variety,得到纸牌的大小和种类。大小就是1-13个数字,种类是黑桃、红桃、草花、方块。
2.定义两个静态常量back,backs,用于获得纸牌图形:
final private static Icon back=new ImageIcon("image/card/back.png");
final private static Icon backS=new ImageIcon("image/cardS/back.png");
3.分别用于得到number,variety:
public int getNumber() { return number; }
public String getVariety() { return VARIETY[variety]; }
4.1.2定义接口variety类
(1)用于设置纸牌的四个种类黑桃、红桃、草花和方块的变量所赋值分别为Spade=0、Heart=1、Club=2、Diamond=3;
(2)用数组定义了四个类:
String[] VARIETY=new String[]{"Spade", "Heart", "Club", "Diamond"};
4.1.3定义CalculateExpression类
(1)该对象拥有3个私有变量:
Expression,用于记录表达式;isCorrect,表示表达式是否规范;results,表达式计算结果。
(2)该对象拥有以下方法供外部调用:
setExpression(String input):输入表达式,无返回
getExpression():返回表达式
isCorrect():返回表达式是否规范
isCorrect(int n):返回表达式是否规范,式中的数字个数也为判断依据
getNumbers():返回表达式中的数字
getResult():返回表达式的计算结果,类型Int
getDoubleResult():返回表达式中的计算结果,类型double
compareNumbers(int[] n):比较表达式中的数字是否与给出的数相同
(3)该对象拥有以下私有方法:
Check():判断表达式是否规范,并自动修正,返回类型为Boolean
calStep1(),calStep2(),calStep3():计算表达式结果的三步,返回类型均为double
(4)main方法见源文件CalculateExpression.java
4.1.4定义FindExpression类
1.该对象拥有3个私有变量
expressionResult,所需结果;maxLine,输出结果每页行数;error,是否出错。
2.该对象拥有以下方法供外部调用:
setNumbers(double[] n):输入用来运算的数,4个时才能计算
setMaxLine(int n):输入每页的行数
getMaxLine():返回每页的行数
setExpressionResult(double n):输入所需结果
getExpressionResult():返回所需结果,类型为double
getExpression():返回可得出所需结果的表达式
3.四个数的计算表达过程:
Cal1(),将4个数计算一次后返回3个数
private double[] cal1(double[] n, int t, int c);
Cal2(),将3个数计算一次后返回2个数
private double[] cal2(double[] n, int t, int c);
Cal(),将2个数计算后返回结果
private double[] cal (double[] n1, int n2, int c);
4. main方法见源文件FindExpression.java
4.1.5定义GameMode类
1. JButton组件:
JButton b1=new JButton(new ImageIcon("image/Pass.png"));
JButton b2=new JButton(new ImageIcon("image/Return.png"));
JButton bO1=new JButton(new ImageIcon("image/+.png"));
JButton bO2=new JButton(new ImageIcon("image/-.png"));
JButton bO3=new JButton(new ImageIcon("image/×.png"));
JButton bO4=new JButton(new ImageIcon("image/÷.png"));
JButton bO5=new JButton(new ImageIcon("image/(.png"));
JButton bO6=new JButton(new ImageIcon("image/).png"));
JButton bO7=new JButton(new ImageIcon("image/=.png"));
JButton bO8=new JButton("Clear");
2.创建新的JLabel组件:
JLabel JLbExpression=new JLabel("");
JLabel JLbTime=new JLabel("Time : ");
3.鼠标事件MouseEvent e:
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
4.计分方法
JOptionPane.showMessageDialog(null,"回答正确,加上"+score+"分",
JOptionPane.showMessageDialog(null,"回答错误,扣除1分",
JOptionPane.showMessageDialog(null,"时间到,扣除1分",
5. main方法见源文件GameMode.java
4.1.6定义RankList类
1.读取带缓存的BufferedReader字符流:
BufferedReader input=new BufferedReader(new FileReader("RankList.dat"));
2.读取带缓存的BufferedWriter字符流:
BufferedWriter output=new BufferedWriter(new FileWriter("RankList.dat"));
3. main方法见源文件RankList.java
4.1.7定义test类
1. JButton组件:
JButton b1=new JButton(new ImageIcon("image/NewGame.png"));
JButton b3=new JButton(new ImageIcon("image/RankList.png"));
JButton b4=new JButton(new ImageIcon("image/QuitGame.png"));
2. 鼠标事件MouseEvent e:
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
3. main方法见源文件test.java
4.2 javax.swing的描述
1.由所有Java图形用户界面GUI组件所构成,可运行在任意支持Java虚拟机JVM的本地平台上。由于这些组件全都是用Java语言编写的,因此他们可以提供比本地平台GUI组件更多的功能。Java swing是Java foundation classes的一部分。在swing中,sun开发了一个经过仔细设计的、灵活而强大的GUI工具包。Swing是在AWT组建基础上构建的。他所提供的功能要比AWT提供的更为广泛。他也是Java技术的一种标准配置。
2.swing包的组成:
javax.swing:基本swing包,包括swing容器、组件及相关设置的类和接口
javax.swing.colorchooser:与颜色选择相关的类和接口
javax.swing.event:包括事件处理相关的类和接口
javax.swing.tree:包括对树形组件进行操作的类和接口
3.常用swing组件:
按钮:JButton; 文本区:JTextarea; 文本字段:JTextfield
4.3游戏实现主要方法
//添加鼠标监听器
addMouseListener(this);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800,600);
setLocationRelativeTo(null);
setVisible(true);
//设置分数方法
void right() {
int score=card[0].getScore()+card[1].getScore()+card[2].getScore()+card[3].getScore();
JOptionPane.showMessageDialog(null,"回答正确,加上"+score+"分","24点游戏-游戏模式",JOptionPane.PLAIN_MESSAGE, new ImageIcon("image\\right.gif"));
new RankList().addPlayer(name, score);
start();
}
void fault() {
JOptionPane.showMessageDialog(null,"回答错误,扣除1分",
"24点游戏-游戏模式",JOptionPane.PLAIN_MESSAGE, new ImageIcon("image\\fault.gif"));
new RankList().addPlayer(name, -1);
start();
}
第五章 性能测试与分析
5.1 系统测试
软件测试就在受控制的条件下对系统或应用程序进行操作并评价操作结果的过程。所为控制条件应包括正常条件与非正常条件。软件测试过程中应该故意的去促使错误的发生,也就是在不该出现的时候出现或者在应该出现的时候没有出现。
5.1.1 性能的测试
软件的测试与证明是软件设计中必不可少的阶段,只有通过测试和证明,软件的质量才能得到肯定,才能投入正式的使用。测试是保证软件质量的重要手段,其主要方式是在设计测试用例在基础上检验软件的各个组成部分。
5.1.2 测试目的
软件的测试是为了发现软件的错误,软件的测试与证明是软件设计中必不可少的阶段,只有通过测试和证明,软件的质量才能得到肯定,才能投入正式的使用。
5.2 游戏界面菜单选项的功能测试
“控制”菜单测试
点击“游戏”--->“开始”
输出:游戏开始
结果:正常
点击“游戏”--->“返回”
输出:结束游戏
结果:正常
“查看”菜单测试
点击“查看”--->“排名 ”
输出:在游戏面板中间跳出分数显示框
结果:正常
“显示”菜单测试
点击“游戏”--->“纸牌出来 ”
输出:在游戏面板中显示纸牌
结果:正常
时间倒计时
输出:显示时间
结果:正常
5.3 按键事件的功能测试
纸牌运算测试
游戏过程中,点击鼠标左、右键
输出:纸牌结果:正常
5.4 纸牌的运算测试
纸牌出现使用运算符
输出:可以使用
结果:正常
纸牌运算
输出:正确与否
结果:正常
5.5 测试结果分析
经过测试,本游戏实现了基本的功能,不过整体功能还不是很强大,作为开发的第一个版本,游戏在很多方面还需要进一步完善。
第六章 小结
课程设计是培养学生综合运用所学知识、发现、提出、分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学技术发展的日新日异,当今计算机应用在生活中可以说得是无处不在。因此作为二十一世纪的大学来说掌握计算机开发技术是十分重要的。
回顾起此次课程设计,至今我仍感慨颇多,从拿到题目到完成整个编程,从理论到实践,在整整两个礼拜的日子里,可以学到很多很多的的东西,同时不仅巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,首先对图形设计一点都不了解,翻阅图书,查找资料花费了我很多的时间和精力。同时在设计的过程中发现了自己的许多不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,所以在做课设的过程之中老是需要翻教材,这严重影响了我完成课设的进度。不过两周的时间还算是充裕的,所以我还有时间在最后将程序和实验报告写好。我所做的24点算法游戏是一个经典的课题,并且算一个相对容易的课题。其主要思路是有程序来随机产生4个扑克牌,每个扑克牌对应一个整数,然后让用户用这4个整数去计算24点,每张扑克牌对应的整数只能够用一次,并且所用的运算符也只能说+、-、、/、(、)这六个。如果用户输入的表达式有不是程序随机产生的扑克牌所对应的整数或用了除上面六个运算符以外的运算符的话,程序要能自行的检查出来,并要求用户重新输入或退出程序。要实现随机产生扑克牌还是很容易做到的,但是要结合图形将扑克牌输出来就有点难了,这就要求我要对图形设计有所了解,而我以前从未接触过图形设计,在做课设前也只是匆匆看了一点书,所以只能够写一些非常简单的程序,所以我的程序在做出来之后,只能显示4个扑克牌和背景颜色,对于界面的布局不甚了解,所以界面就没设计的很好看,只是勉强将图形显示了出来。我想这应该是我本次课设应该着重需要完善的地方。本次课程设计的重点是对表达式的计算,这才是数据结构问题。计算表达式要用到重要的数据结构栈,要用栈先将算术表达式转换成后缀表达式,程序才能执行计算表达式功能。所以只要对栈的知识掌握了,就会很容易完成表达式的计算的设计。总体来说,本次课设相对来说比较简单,只要用心去做,是可以顺利完成的。通过这次课程设计之后,一是把以前所学过的知识重新温习了一下,二是又学到了新的知识,而且对图形设计发生了很大的兴趣,我会在课设完成之后再去钻研图形设计的。
附录:
1、CalculateExpression
import java.util.StringTokenizer;
import java.util.Arrays;
public class CalculateExpression {
private String expression;
private boolean isCorrect;
private double result;
/ setExpression(String<表达式>),输入表达式 /
public void setExpression(String input) {
expression=input;
isCorrect=check();
//JOptionPane.showMessageDialog(null,expression,"Test2",JOptionPane.INFORMATION_MESSAGE);
if (isCorrect) {
result=calStep1();
} else
result=0;
}
/ getExpression(),输出表达式 /
public String getExpression() {
return expression;
}
/ check(),判断表达式规范与否,并自动修正 /
private boolean check() {
char t,tt=expression.charAt(0);
int sum=0,add=0; //计算左右括号,计算修正位数
boolean hasNum=false;
StringBuffer s=new StringBuffer(expression);
if (tt=='+' || tt=='-' || tt=='.') {
s.insert(0,'0');
add++;
} else
if (tt==')' || tt=='' || tt=='/') {
return false;
}
for (int i=0; i<expression.length(); i++) {
t=tt;
if (i!=expression.length()-1) {
tt=expression.charAt(i+1);
} else tt='E';
if (t>='0' && t<='9') {
hasNum=true;
if (tt=='(') {
s.insert(i+add+1,'');
add++;
}
} else
if (t=='(') {
sum++;
if (tt=='.' || tt=='+' || tt=='-') {
s.insert(i+add+1,'0');
add++;
} else
if (tt=='' || tt=='/' || tt==')') {
return false;
}
} else
if (t==')') {
sum--;
if (tt>='0' && tt<='9') {
s.insert(i+add+1,'');
add++;
} else
if (tt=='.') {
return false;
}
} else
if (t=='+') {
if (tt=='+' || tt=='-') {
s.deleteCharAt(i+add);
add--;
} else
int DIAMOND=3;
}