随着社会的发展,人们的工作压力变大,为了释放人们的压力,丰富人们的空闲时间,我们通过java语言开发了一款蜘蛛纸牌。
本次课设主要利用java语言实现了游戏的难度选择、开局、重新发牌、提示以及可视化的相关操作界面。并通过设计鼠标事件,引入线程,构建游戏程序框架完成了对该游戏的难度选择、开局、发牌、提示和显示可执行操作的各个基本功能。
关键词:蜘蛛纸牌;java语言;操作界面
目录
1绪论...................................................................1
1.1编写目的.........................................................1
1.2系统分析与设计....................................................1
1.3小组分工..........................................................2
2详细设计................................................................3
2.1程序功能介绍......................................................3
2.2程序流程..........................................................3
3功能分析................................................................4
3.1主要界面..........................................................4
3.2 初始化纸牌及发牌操作..............................................6
3.4 回收纸牌操作.....................................................11
3.5 帮助菜单功能的实现...............................................12
3.6 退出功能的实现...................................................13
4调试分析与结果测试......................................................14
总结....................................................................17
参考文献................................................................18
致谢....................................................................19
Java语言是当今流行的网络编程语言,它具有面向对象、跨平台、分布应用等特点。面向对象的开发方法是当今世界最流行的开发方法,它不仅具有更贴近自然的语义,而且有利于软件的维护和继承。为了进-步巩固课堂.上所学到的知识,深刻把握Java语言的重要概念及其面向对象的特性,使我们能够熟练的应用面向对象的思想和设计方法解决实际问题的能力。通过此次课程设计,巩固所学Java语言基本知识,增进Java语言编辑基本功,掌握JDK、Eclipse 等开发工具的运用,拓宽常用类库的应用。使学生通过该教学环节与手段,把所学课程及相关知识加以融会贯通,全面掌握Java语言的编程思想及面向对象程序设计的方法,为今后从事实际工作打下坚实的基础。本设计使用JAVA语言开发扑克游戏程序,将电脑多次分发给你的牌按照相同的花色由大至小排列起来。
本次详细设计说明书是针对蜘蛛纸牌游戏的课程作业而编写的程序。目的是对该软件进行详细设计,在概要设计的基础上进一步明确系统结构,详细地介绍系统的各个模块,为进行后面的实现和测试作准备。本详细设计说明书的预期读者为本项目小组的成员以及对该系统感兴趣,在以后想对系统进行扩展和维护的人员。
参照windows游戏蜘蛛纸牌,自己编写设计实现其功能,它具有如下一些功能:
a.设计一个游戏界面,包括玩牌区、发牌区和回收区。
b.纸牌以及其背景的设定。
c.移动纸牌。使用鼠标将较小的纸牌拖放到较大的纸牌下方,可以拖动一组纸牌,当要求这组纸牌是同一个花色,并且这- -组纸牌从上到下是从大到小排列的,且不间断。
d.回收纸牌。当某列出现同-“花色,从上到下依次是从K到A的不间组合时,这组纸牌将被回收到回收区中。
e.发牌。用鼠标单击发牌区,若发牌区还有剩余的纸牌,则将发出一叠纸牌共10张,依次添加到玩牌区的10列纸牌最下方,但要求这10列纸牌没有空白列。
f.若玩家不了解游戏规则可以点击帮助获得游戏方法。
g.级别设定。点击“游戏”菜单中选取游戏难以级别,有3种级别,分别对应初级、中级、高级。
h.退出游戏。
本次课设的组长为XXX,组员为XXX,XXX。设计程序由三人共同完成,在设计程序过程中,XXX主要在网上查找相关资料,XXX负责编写程序,XXX负责在图书馆借阅书籍查找相关资料。
在程序编写完之后,有个别错误,老师修改之后可以正常运行;在编写说明书过程中,XXX负责说明书的排版,其中包括绪论、总体设计、详细说明、调试分析四大板块;XXX负责调试程序并截图,XXX负责画相关流程图,相关文字说明由三个人共同完成,XXX负责编写绪论板块下的文字说明,XXX负责编写总体设计、调试分析两大板块下的文字说明,XXX负责详细说明下的文字说明。
本次课设小组三人分工明确,集体配合较好,沟通融洽,相互探讨,相互学习,相互监督。设计出的蜘蛛纸牌系统比较实用,也达到了预想的目的,虽然在某些方面遇到较大问题,但最后经过询问老师,查阅资料,较好的完成了本次课程设计。
该游戏可分为以下各项功能:
a.Spide.java用于实现纸牌初始化、设置游戏等级以及异常处理。
b.PKCard.java用于定义纸牌的显示的各种属性以及鼠标事件的相应属性。
c.SpiderMenu.java用于添加游戏下拉菜单的各个选项,包含图用户界面的构建,组件监听的实现,以及显示可执行操作的线程。
d.SpiderMenu.class生成Spider.class,AboutDialog.class和PKCard.class。
该游戏的开发及相关功能的实现需要在Eclipse下建立javaproject同时写Spider.java、PKCard.java、SpiderMenu.java、AboutDialog.class,另外将纸牌的图片文件保存在images文件夹中。
程序从运行开始首先进入游戏界面,分为菜单,帮助,声明。菜单栏分为等级,开始,退出游戏。游戏开始后进入发牌,移牌,消牌,游戏结束,返回菜单栏,进入下一次游戏开始界面。程序流程图如图下图2.1所示。
以下是主菜单界面的主要代码:
JMenu jNewGame = new JMenu( " 游戏 " );
JMenu jHelp = new JMenu( " 帮助 " );
JMenuItem jItemAbout = new JMenuItem( " 关于 " );
JMenuItem jItemOpen = new JMenuItem( " 开始新游戏 " );
JMenuItem jItemDeal = new JMenuItem( " 发牌 " );
JMenuItem jItemExit = new JMenuItem( " 退出 " );
JRadioButtonMenuItem jRMItemEasy = new JRadioButtonMenuItem( " 初级:单花色 " ); // 菜单中的可选项按钮
JRadioButtonMenuItem jRMItemNormal = new JRadioButtonMenuItem( " 中级:双花色 " );
JRadioButtonMenuItem jRMItemHard = new JRadioButtonMenuItem( " 高级:四花色 " );
public SpiderMenuBar( Spider spider) {
this . main = spider;
jNewGame .add( jItemOpen );
jNewGame .add( jItemDeal );
jNewGame .addSeparator(); // 添加划分线
jNewGame .add( jRMItemEasy );
jNewGame .add( jRMItemNormal );
jNewGame .add( jRMItemHard );
jNewGame .addSeparator();
jNewGame .add( jItemExit );
ButtonGroup group = new ButtonGroup(); // (用来获取 JRadioButtonMenuItem 的值)
group.add( jRMItemEasy );
group.add( jRMItemNormal );
group.add( jRMItemHard );
jHelp .add( jItemAbout );
this .add( jNewGame );
this .add( jHelp ); // 添加到菜单栏
以下是游戏窗口界面初始化的主要代码:
pane = this .getContentPane(); // 获得容器
pane .setBackground( new Color(0, 112, 26)); // 设置背景颜色
clickLabel = new JLabel(); // 发牌区的鼠标点击响应区域
clickLabel .setBounds(890, 580, 110, 96); // 设置响应区域大小与坐标
clickLabel .setBorder(javax.swing.BorderFactory
. createEtchedBorder (javax.swing.border.EtchedBorder. RAISED ));
pane .add( clickLabel ); // 将响应区域添加到容器中
this .initCards(); // 纸牌初始化
this .randomCards(); // 随机分配纸牌
this .setCardsLocation(); // 为纸牌设置坐标位置
this .deal(); // 从右下角发出一叠纸牌。游戏刚开始时,需要先发出一叠纸牌。
groundLabel = new JLabel[10]; // 创建背景框数组,一共有 10 个背景框。
int x = 20; // 背景框的 x 坐标, 10 个背景框是并排放置的, y 坐标相等。第一个背景框的 x 坐标为 20 。
for ( int i = 0; i < 10; i++) { // 循环创建背景框,并设置其坐标大小等属性
groundLabel [i] = new JLabel(); // 创建背景框
groundLabel [i]
.setBorder(javax.swing.BorderFactory . createEtchedBorder (javax.swing.border.EtchedBorder. RAISED )); // 为 Label 设置边框
// ,
// 形成背景框
groundLabel [i].setBounds(x, 25, 71, 96); // 设置背景框的大小与坐标
x += 101; // 相邻的背景框的 x 坐标差值为 101 。
this . pane .add( groundLabel [i]); // 将背景框添加到容器中
}
this .setVisible( true ); // 显示窗口
初始化纸牌的主要代码(包括所有纸牌生成及存入数组,右下角发牌区纸牌初始化以及表面显示纸牌初始化):
所有纸牌的生成及存入数组代码:
public void initCards() {
// 如果纸牌已被赋值,即将其从框架的面板中移去
if ( cards [0] != null ) {
for ( int i = 0; i < 104; i++) {
pane .remove( cards [i]);
}
}
int n = 0;
// 通过难度等级,为 n 赋值
if ( this . grade == Spider. EASY ) {
n = 1;
} else if ( this . grade == Spider. NATURAL ) {
n = 2;
} else {
n = 4;
}
// 为 card 赋值
for ( int i = 1; i <= 8; i++) {
for ( int j = 1; j <= 13; j++) {
cards [(i - 1) * 13 + j - 1] = new PKCard((i % n + 1) + "-" + j,
this ); // 当 n 为 1 时, i%8 的值永远是 0 ,所以 i%8+1 的值永远是 1 ,因此 n 为 1 时,创建的 card 的名称是 1
// -1 到 1-13 ,全是黑桃。其他等级类似。
}
}
}
// 纸牌随机分配
public void randomCards() { // 将纸牌的顺序打乱,否则牌号的将是从 A 到 K 的出现规律
PKCard temp = null ;
// 随机生成牌号
for ( int i = 0; i < 52; i++) {
int a = ( int ) (Math. random () * 104);
int b = ( int ) (Math. random () * 104);
temp = cards [a];
cards [a] = cards [b];
cards [b] = temp;
}
}
右下角发牌区纸牌的初始化代码:
int x = 883; // 将坐标定位到右下角发牌区
int y = 580;
for ( int i = 0; i < 6; i++) { // 初始化右下角发牌区的纸牌,共 6 叠
for ( int j = 0; j < 10; j++) {
int n = i * 10 + j;
pane .add( cards [n]);
// 将 card 转向背面
cards [n].turnRear();
// 将 card 放在固定的位置上
cards [n].moveto( new Point(x, y));
// 将 card 的位置及相关信息存入
map .put( new Point(x, y), cards [n]);
}
x += 10; // 共 6 叠纸牌,最上面一叠纸牌的 x 坐标为 883 ,再往下, x 依次增加 10
}
表面显示纸牌初始化:
x = 20; // 将坐标定位到上方玩牌区的左边起点,也就是第一个背景框的坐标位置
y = 45;
/** 初始化表面显示的纸牌 */
for ( int i = 10; i > 5; i--) { // 初始化玩牌区的纸牌,共 5 行
for ( int j = 0; j < 10; j++) { // 共 10 列
int n = i * 10 + j; // 生成索引值
if (n >= 104) { // 如果索引值超出数组下标
continue ; // 退出本次循环,执行外层循环
}
pane .add( cards [n]); // 将索引处的纸牌添加到容器中
cards [n].turnRear(); // 将纸牌转向背面
cards [n].moveto( new Point(x, y)); // 将纸牌放在固定的位置上
map .put( new Point(x, y), cards [n]); // 将纸牌及其坐标值存入 map 中
x += 101; // 每两列之间的 x 坐标相距 101 个像素
}
x = 20; // x 坐标回到起点位置
y -= 5; // 主坐标向上移 5 个像素
}
发牌操作功能代码:
public void deal() { // 发牌,指从右下角的发牌区发牌
this .setNA();
// 判断 10 列中是否有空列
for ( int i = 0; i < 10; i++) {
if ( this .getLastCardLocation(i) == null ) {
JOptionPane. showMessageDialog ( this , " 有空位不能发牌! " , " 提示 " ,
JOptionPane. WARNING_MESSAGE );
return ;
}
}
int x = 20;
for ( int i = 0; i < 10; i++) {
Point lastPoint = this .getLastCardLocation(i);
// 这张牌应 “ 背面向上 ”
if ( c == 0) { // 当还没有发过牌时,玩牌区的纸牌列中,每两张纸牌之间的 y 坐标值相差 5 ,
// 指的是背面牌与背面牌之间以及背面牌与第一张正面牌之间的 y 距离
lastPoint. y += 5;
}
// 这张牌应 “ 正面向上 ”
else { // 两张正面牌之间的 y 距离
lastPoint. y += 20;
}
map .remove( cards [ c + i].getLocation());
cards [ c + i].moveto(lastPoint);
map .put( new Point(lastPoint), cards [ c + i]);
cards [ c + i].turnFront();
cards [ c + i].setCanMove( true );
// 将组件 card 移动到容器中指定的顺序索引。
this . pane .setComponentZOrder( cards [ c + i], 1);
Point point = new Point(lastPoint);
if ( cards [ c + i].getValue() == 1) {
int n = cards [ c + i].whichColumnAvailable(point);
point. y -= 240;
PKCard card = (PKCard) this . map .get(point);
if (card != null && card.isCanMove()) {
this .haveFinish(n);
}
}
x += 101;
}
c += 10;
}
// 用鼠标拖动纸牌
public void mouseDragged(MouseEvent arg0) {
if ( canMove ) {
int x = 0;
int y = 0;
Point p = arg0.getPoint();
x = p. x - point . x ;
y = p. y - point . y ;
this .moving(x, y);
}
}
/*
* 方法:放置纸牌
*/
public void setNextCardLocation(Point point) {
PKCard card = main .getNextCard( this );
if (card != null ) {
if (point == null ) {
card.setNextCardLocation( null );
main . map .remove(card.getLocation()); // 先从 HashMap 中删除 card
card.setLocation(card. initPoint ); // 为 card 设置新的坐标
main . map .put(card. initPoint , card); // 再将 card 添加到 HashMap 中
} else {
point = new Point(point);
point. y += 20;
card.setNextCardLocation(point);
point. y -= 20;
main . map .remove(card.getLocation());
card.setLocation(point);
main . map .put(card.getLocation(), card);
card. initPoint = card.getLocation();
}
}
}
回收纸牌及过关判定功能主要代码:
public void haveFinish( int column) {
Point point = this .getLastCardLocation(column);
PKCard card = ( PKCard ) this . map .get(point);
do {
this . map .remove(point);
card.moveto( new Point(20 + finish * 10, 580));
// 将组件移动到容器中指定的顺序索引。
pane .setComponentZOrder(card, 1);
// 将纸牌新的相关信息存入 HashMap
this . map .put(card.getLocation(), card);
card.setCanMove( false );
point = this .getLastCardLocation(column);
if (point == null )
card = null ;
else
card = this . map .get(point);
} while (card != null && card.isCanMove());
finish ++;
// 如果 8 付牌全部组合成功,则显示成功的对话框
if ( finish == 8) {
JOptionPane. showMessageDialog ( this , " 恭喜你,顺利通过! " , " 成功 " ,
JOptionPane. PLAIN_MESSAGE );
}
if (card != null ) {
card.turnFront();
card.setCanMove( true );
}
}
}
主要代码如下:
public class AboutDialog extends JDialog {
JPanel jMainPanel = new JPanel();
JTabbedPane jTabbedPane = new JTabbedPane();
private JPanel jPanel1 = new JPanel();
private JTextArea jt1 = new JTextArea(
" 将电脑多次分发给你的牌按照相同的花色由大至小排列起来。直到桌面上的牌全都消失。 " );
public AboutDialog() {
setTitle( " 蜘蛛牌 " );
setSize(300, 200);
setResizable( false );
setDefaultCloseOperation(WindowConstants. DISPOSE_ON_CLOSE );
Container c = this .getContentPane();
jt1 .setSize(260, 200);
jt1 .setEditable( false );
jt1 .setLineWrap( true );
jt1 .setFont( new Font( " 楷体 _GB2312" , java.awt.Font. BOLD , 13));
jt1 .setForeground(Color. BLUE );
jPanel1 .add( jt1 );
jTabbedPane .setSize(300, 200);
jTabbedPane .addTab( " 游戏规则 " , null , jPanel1 , null );
jMainPanel .add( jTabbedPane );
c.add( jMainPanel );
pack();
this .setVisible( true );
}
}
主要代码如下:
// “ 退出 ”
jItemExit . addActionListener ( new ActionListener() {
public void actionPerformed(ActionEvent e) {
main .dispose();
System. exit (0);
}
}
);
通过对游戏的运行,包括移牌 、发牌、开始游戏、选择等级等等 。未发现明显异常现象。在这里:我们将测试的结果图片贴在了下面:
进入游戏主界面如下图4.1所示
游戏菜单:打开帮助菜单如下图4.2所示
这次课程设计的设计时间比较紧迫,所以我们组成小组共同完成此次课程设计。在这次课程设计中我们遇到了很多问题,我们通过网上查询以及咨询同学对各种问题有了简单的了解,基本上完成了此次课程设计的任务。数据库作为现代数据管理最先进的手段,掌握数据库系统设计的基本方法和步骤是对现代软件开发人员的基本要求。本次通过一个小型图书管理系统的设计,了解了数据库系统开发的基本知识。本次课程设计让我们学到了许多知识,受益匪浅。掌握了界面设计的一些方法和技巧,对Java语言的使用更加深入。对书本上学到的SQL语句的使用也更加熟悉。真正做到了把书本上学到的知识应用到实践中来。对我们的动手能力和团队合作能力都有所加强。在编写程序方面,学会了规范化的编程方法,例如按功能将一组代码放在一起,并添加注释,方便自己和他人阅读。
不过本次课程设计中也出现了许多问题,对各个界面的设计还不够完善,系统的功能还不够强大等等,在老师的帮助和小组成员的不懈努力下,大部分问题得到了解决。本次课程设计只是一个小型系统的研究,并没有考虑运行效率等方面的诸多问题,我们还可以对这些方面进行研究和实现,或者在此基础上增加新的功能,使系统的可用性更为强大。
[1] 李尊朝.Java语言程序设计(第三版):中国铁道出版社,2013
[2] 陈明.Java语言程序设计课程实践:清华大学出版社,2009
[3] 朱福喜,黄方胜编著.Java项目开发实训教程 . 北京:中国电力出版社,2007
[4] 刘兆宏等编著.Java语言程序设计案例教程.北京:中国铁道出版社,2014
[5] 袁然,邹丰义编著.Java案例开发集锦.北京:机械工业出版社,2008
[6] 李明,吴琼著. Java程序设计案例教程. 北京:清华大学出版社,2013
[7] 赵凤芝编著. Java程序设计案例教程. 北京:清华大学出版社,2011
[8] 杨小平编著.Java项目案例导航 .上海:同济大学出版社,2011
本次课程设计学习中,老师严谨的治学态度、丰富渊博的知识、精益求精的工作态度以及侮人不倦的师者风范是我终生学习的楷模,谢谢老师在大的方向上进行指导,让我茅塞顿开,虽然有同学和浏览器的帮助 ,但是在某些方面老师给的指导更多。教会了我专业知识,教会了我如何学习。正是他们,我才能在各方面取得显著的进步,在此向他们表示我由衷的谢意。
并在这个过程当中,给予我们各种方便,使我们在这学期快要结束的时候,能够将学到的知识应用到实践中,增强了我们实践操作和动手应用能力,提高了独立思考的能力。
首先我要感谢我的老师在课程设计上给予我的指导、提供给我的支持和帮助,这是我能顺利完成这次设计的主要原因,更重要的是老师帮我解决了许多技术上的难题,让我能把系统做得更加完善。在此期间,我不仅学到了许多新的知识,而且也开阔了视野,提高了自己的设计能力。其次,我要感谢帮助过我的同学,他们也为我解决了不少我不太明白的设计上的难题。
最后再一次感谢所有在设计中帮助过我的良师益友。