《Java课程设计——蜘蛛纸牌游戏.doc》由会员分享,可在线阅读,更多相关《Java课程设计——蜘蛛纸牌游戏.doc(34页珍藏版)》请在三一办公上搜索。
1、Java课程设计蜘蛛纸牌游戏(陈浩 数学与应用数学专业091班)摘要本游戏通过java语言编写,实现了游戏的难度选择、开局、重新发牌以及可视化的相关操作界面。并通过设计鼠标事件,引入线程,构建游戏程序框架完成了对该游戏的难度选择、开局、发牌、显示可执行操作的各个基本功能。关键词蜘蛛纸牌 java语言 操作界面 1. 问题重述该游戏通过鼠标操作,将电脑多次分发的纸牌,按照相同的花色由大到小排列起来,直到桌面上的纸牌全都消失,即为胜利。包括如下功能:a.难度选择:包括简单(单色)、中级(双色)、高级(四色)。b.开局:任何时候可以重新开始一盘新的游戏。c.发牌。d.显示可行操作:提示当前可行操作。
2、e.简单的帮助文档:对软件的简单介绍和编制说明。2.理论分析 参照windows游戏蜘蛛纸牌,自己编写设计实现其功能,它具有如下一些功能: a.设计一个游戏界面,包括玩牌区、发牌区和回收区。 b.纸牌以及其背景的设定。 C.移动纸牌。使用鼠标将较小的纸牌拖放到较大的纸牌下方,可以拖动一组纸牌,当要求这组纸牌是同一个花色,并且这一组纸牌从上到下是从大到小排列的,且不间断。 d.回收纸牌。当某列出现同一花色,从上到下依次是从K到A的不间组合时,这组纸牌将被回收到回收区中。 e.发牌。用鼠标单击发牌区,若发牌区还有剩余的纸牌,则将发出一叠纸牌共10张,依次添加到玩牌区的10列纸牌最下方,但要求这10
3、列纸牌没有空白列。 f.若玩家不了解游戏规则可以点击帮助获得游戏方法。 g.级别设定。点击“游戏”菜单中选取游戏难以级别,有3种级别,分别对应初级、中级、高级。 h.退出游戏。3.模型该游戏可分为以下各项功能: a.Spider.java 用于实现纸牌初始化、设置游戏等级以及异常处理。 b.PKCard.java用于定义纸牌的显示的各种属性以及鼠标事件的相应属性。c.SpiderMenu.java用于添加游戏下拉菜单的各个选项,包含图形用户界面的构建,组件监听的实现,以及显示可执行操作的线程。d.SpiderMenu.class生成Spider.class,AboutDialog.class和
4、PKCard.class4.程序流程图5.程序设计技术文档编写程序以实现游戏蜘蛛纸牌的功能。1、设计游戏界面。2、纸牌以及其背景的设定。3、移动纸牌。4、回收纸牌。5、发牌。6、若玩家不了解游戏规则可以点击帮助获得游戏方法。7、级别设定。8、退出游戏。该游戏的开发及相关功能的实现需要在Eclipse下建立java project,同时编写Spider.java、PKCard.java、SpiderMenu.java、AboutDialog.class,另外将纸牌的图片文件保存在images文件夹中。6.程序使用说明6.1 主要界面:以下是主菜单界面的主要代码:JMenu jNewGame =
5、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(初级:单花色);/菜单中的可选项按钮JRadioButtonMenu
6、Item 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(jRMIte
7、mNormal);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);/添加到菜单栏以下是游戏窗口界面初始化的主
8、要代码: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(c
9、lickLabel); / 将响应区域添加到容器中this.initCards();/ 纸牌初始化this.randomCards();/ 随机分配纸牌this.setCardsLocation();/ 为纸牌设置坐标位置this.deal(); / 从右下角发出一叠纸牌。游戏刚开始时,需要先发出一叠纸牌。groundLabel = new JLabel10;/ 创建背景框数组,一共有10个背景框。int x = 20;/ 背景框的x坐标,10个背景框是并排放置的,y坐标相等。第一个背景框的x坐标为20。for (int i = 0; i 10; i+) / 循环创建背景框,并设置其坐标大小等
10、属性groundLabeli = new JLabel();/ 创建背景框groundLabeli.setBorder(javax.swing.BorderFactory.createEtchedBorder(javax.swing.border.EtchedBorder.RAISED);/ 为Label设置边框/ ,/ 形成背景框groundLabeli.setBounds(x, 25, 71, 96);/ 设置背景框的大小与坐标x += 101; / 相邻的背景框的x坐标差值为101。this.pane.add(groundLabeli);/ 将背景框添加到容器中this.setVisib
11、le(true);/ 显示窗口6.2初始化纸牌及发牌操作: 初始化纸牌的主要代码(包括所有纸牌生成及存入数组,右下角发牌区纸牌初始化以及表面显示纸牌初始化): 所有纸牌的生成及存入数组代码:public void initCards() / 如果纸牌已被赋值,即将其从框架的面板中移去if (cards0 != null) for (int i = 0; i 104; i+) pane.remove(cardsi);int n = 0;/ 通过难度等级,为n赋值if (this.grade = Spider.EASY) n = 1; else if (this.grade = Spider.NA
12、TURAL) 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 =
13、null;/ 随机生成牌号for (int i = 0; i 52; i+) int a = (int) (Math.random() * 104);int b = (int) (Math.random() * 104);temp = cardsa;cardsa = cardsb;cardsb = temp;右下角发牌区纸牌的初始化代码:int x = 883;/ 将坐标定位到右下角发牌区int y = 580;for (int i = 0; i 6; i+) / 初始化右下角发牌区的纸牌,共6叠for (int j = 0; j 5; i-) / 初始化玩牌区的纸牌,共5行for (int
14、j = 0; j = 104) / 如果索引值超出数组下标continue; / 退出本次循环,执行外层循环pane.add(cardsn); / 将索引处的纸牌添加到容器中cardsn.turnRear(); / 将纸牌转向背面cardsn.moveto(new Point(x, y); / 将纸牌放在固定的位置上map.put(new Point(x, y), cardsn); / 将纸牌及其坐标值存入map中x += 101; / 每两列之间的x坐标相距101个像素x = 20; / x坐标回到起点位置y -= 5; / 主坐标向上移5个像素发牌操作功能代码:public void de
15、al() / 发牌,指从右下角的发牌区发牌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 =
16、 0) / 当还没有发过牌时,玩牌区的纸牌列中,每两张纸牌之间的y坐标值相差5,/ 指的是背面牌与背面牌之间以及背面牌与第一张正面牌之间的y距离lastPoint.y += 5;/ 这张牌应“正面向上”else / 两张正面牌之间的y距离lastPoint.y += 20;map.remove(cardsc + i.getLocation();cardsc + i.moveto(lastPoint);map.put(new Point(lastPoint), cardsc + i);cardsc + i.turnFront();cardsc + i.setCanMove(true);/ 将组件
17、card移动到容器中指定的顺序索引。this.pane.setComponentZOrder(cardsc + i, 1);Point point = new Point(lastPoint);if (cardsc + i.getValue() = 1) int n = cardsc + i.whichColumnAvailable(point);point.y -= 240;PKCard card = (PKCard) this.map.get(point);if (card != null & card.isCanMove() this.haveFinish(n);x += 101;c +
18、= 10;6.3纸牌移动放置操作: /用鼠标拖动纸牌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 (
19、point = null) card.setNextCardLocation(null);main.map.remove(card.getLocation();/ 先从HashMap中删除cardcard.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.
20、remove(card.getLocation();card.setLocation(point);main.map.put(card.getLocation(), card);card.initPoint = card.getLocation();6.4回收纸牌操作:回收纸牌及过关判定功能主要代码:public void haveFinish(int column) Point point = this.getLastCardLocation(column);PKCard card = (PKCard) this.map.get(point);do this.map.remove(point
21、);card.moveto(new Point(20 + finish * 10, 580);/ 将组件移动到容器中指定的顺序索引。pane.setComponentZOrder(card, 1);/ 将纸牌新的相关信息存入HashMapthis.map.put(card.getLocation(), card);card.setCanMove(false);point = this.getLastCardLocation(column);if (point = null)card = null;elsecard = this.map.get(point); while (card != nu
22、ll & card.isCanMove();finish+;/ 如果8付牌全部组合成功,则显示成功的对话框if (finish = 8) JOptionPane.showMessageDialog(this, 恭喜你,顺利通过!, 成功,JOptionPane.PLAIN_MESSAGE);if (card != null) card.turnFront();card.setCanMove(true);6.5帮助菜单功能的实现:主要代码如下:public class AboutDialog extends JDialog JPanel jMainPanel = new JPanel();JTa
23、bbedPane 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
24、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);
25、c.add(jMainPanel);pack();this.setVisible(true);6.6退出功能的实现:主要代码如下:/ “退出”jItemExit.addActionListener(new ActionListener() public void actionPerformed(ActionEvent e) main.dispose();System.exit(0););7.调试验证运行情况 通过对游戏的运行,包括移牌、发牌、开始游戏、选择等级等等。未发现明显异常现象。在这里:我们将测试的结果图片贴在了下面:进入游戏主界面:游戏菜单: 打开帮助菜单: 拖动纸牌:发牌以及收牌:完
26、成游戏:选择难度(高级):有空位不能发牌:8.设计总结通过这次JAVA课程设计实验,让我对java程序设计语言有了更进一步的认识,同时让我对这门程序设计语言有了浓厚的兴趣。在这次java的编程的实践过程中让我进一步体会到了面向对象编程思想在解决实际问题中的应用,让我受益匪浅。同时在这次课程设计实验中,遇到了不少技术难题,例如引入线程以及对鼠标操作事件的控制。但最终通过询问别人和查阅各种资料把这些问题都一一解决了。希望自己今后能在进一步学习计算机编程语言,为以后就业打下坚实的基础。参考文献Java程序设计,朱庆生,古平等著,清华大学出版社,2011,1Java编程,王伟平等著,清华大学出版社,2
27、010,5Java课程设计案例精编黄晓东编著,中国水利水电出版社出版Java程序设计实用教程张永常主编,电子工业出版社出版附录(程序部分代码):import javax.swing.*;import java.awt.*;/* *“关于”窗口*/public class AboutDialog extends JDialogJPanel jMainPane = new JPanel();JTabbedPane jTabbedPane = new JTabbedPane();private JPanel jPanel1 = new JPanel();private JPanel jPanel2
28、= new JPanel();private JTextArea jt1 = new JTextArea(将电脑多次分发给你的牌按照相同的花色由大至小排列起来。直到桌面上的牌全都消失。); private JTextArea jt2 = new JTextArea(该游戏中,纸牌的图片来自于Windows XP的纸牌游戏,图片权属于原作者所有!); /*构造函数*/public AboutDialog()setTitle(蜘蛛牌);setSize(300,200);setResizable(false);setDefaultCloseOperation (WindowConstants.DIS
29、POSE_ON_CLOSE); Container c = this.getContentPane();jt1.setSize(260,200);jt2.setSize(260,200);jt1.setEditable(false);jt2.setEditable(false);jt1.setLineWrap(true); jt2.setLineWrap(true); jt1.setFont(new Font(楷体_GB2312, java.awt.Font.BOLD, 13);jt1.setForeground(Color.blue);jt2.setFont(new Font(楷体_GB23
30、12, java.awt.Font.BOLD, 13);jt2.setForeground(Color.black);jPanel1.add(jt1);jPanel2.add(jt2);jTabbedPane.setSize(300,200);jTabbedPane.addTab(游戏规则, null, jPanel1, null);jTabbedPane.addTab(声明, null, jPanel2, null);jMainPane.add(jTabbedPane);c.add(jMainPane);pack();this.setVisible(true); import java.aw
31、t.*;import java.awt.event.*;import javax.swing.*;public class PKCard extends JLabel implements MouseListener, MouseMotionListener /纸牌的位置Point point = null; Point initPoint = null;int value = 0; int type = 0;String name = null; Container pane = null;Spider main = null;boolean canMove = false; boolean
32、 isFront = false; PKCard previousCard = null; public void mouseClicked(MouseEvent arg0) public void flashCard(PKCard card)/启动Flash线程new Flash(card).start();/不停的获得下一张牌,直到完成if(main.getNextCard(card) != null)card.flashCard(main.getNextCard(card); class Flash extends Threadprivate PKCard card = null;pub
33、lic Flash(PKCard card)this.card = card;/*线程的run()方法*为纸牌的正面设置白色图片*/public void run()boolean is = false;ImageIcon icon = new ImageIcon(images/white.gif);for (int i = 0; i 4; i+)tryThread.sleep(200);catch (InterruptedException e)e.printStackTrace();if (is)this.card.turnFront();is = !is;elsethis.card.se
34、tIcon(icon);is = !is;/ 根据当前外观将card的UI属性重置card.updateUI(); /*点击鼠标*/public void mousePressed(MouseEvent mp) point = mp.getPoint(); main.setNA(); this.previousCard = main.getPreviousCard(this); /*释放鼠标*/public void mouseReleased(MouseEvent mr)Point point = (JLabel) mr.getSource().getLocation();/判断可行列int
35、 n = this.whichColumnAvailable(point);if (n = -1 | n = this.whichColumnAvailable(this.initPoint)this.setNextCardLocation(null);main.table.remove(this.getLocation();this.setLocation(this.initPoint);main.table.put(this.initPoint, this);return;point = main.getLastCardLocation(n);boolean isEmpty = false
36、;PKCard card = null;if (point = null)point = main.getGroundLabelLocation(n);isEmpty = true;elsecard = (PKCard) main.table.get(point);if (isEmpty | (this.value + 1 = card.getCardValue()point.y += 40;if (isEmpty) point.y -= 20;this.setNextCardLocation(point);main.table.remove(this.getLocation();point.
37、y -= 20;this.setLocation(point);main.table.put(point, this);this.initPoint = point;if (this.previousCard != null)this.previousCard.turnFront();this.previousCard.setCanMove(true);this.setCanMove(true);elsethis.setNextCardLocation(null);main.table.remove(this.getLocation();this.setLocation(this.initPo
38、int);main.table.put(this.initPoint, this);return; point = main.getLastCardLocation(n); card = (PKCard) main.table.get(point); if (card.getCardValue() = 1)point.y -= 240;card = (PKCard) main.table.get(point);if (card != null & card.isCardCanMove()main.haveFinish(n);/*方法:放置纸牌*/public void setNextCardL
39、ocation(Point point)PKCard card = main.getNextCard(this);if (card != null)if (point = null)card.setNextCardLocation(null);main.table.remove(card.getLocation();card.setLocation(card.initPoint);main.table.put(card.initPoint, card);elsepoint = new Point(point);point.y += 20;card.setNextCardLocation(point);point.y -= 20;main.table.remove(card.getLocation();card.setLocation(point);main.table.put(card.getLocation(), card);card.initPoint = card.getLocation(); /*返回值:int*方法:判断可用列*/public int whichColumnAv