Java编写掷骰子游戏
废话不多说了,直接奔主题。
**多线程&&观察者模式
题目要求:《掷骰子》窗体小游戏,在该游戏中,玩家初始拥有1000的金钱,每次输入押大还是押小,以及下注金额,随机3个骰子的点数,如果3个骰子的总点数小于等于9,则开小,否则开大,然后判断玩家是否押对,如果未押对则扣除下注金额,如果押对则奖励和玩家下注金额相同的金钱。
分析:这个题目要求灵活运用多线程的相关知识,达到点击开始按钮时,有3个线程启动,分别控制3颗骰子的转动,在3颗骰子全部转完以后,回到主线程计算游戏结果。
//个线程控制颗骰子 thread t = new thread(); thread t = new thread(); thread t = new thread(); //启动个线程 t.start(); t.start(); t.start(); //将个线程加入主线程 t.join(); t.join(); t.join();
but,,,写完代码以后发现,这样做虽然能够保证游戏能够正确运行,但是当我点击开始按钮时,由于3个骰子线程都是直接开在主线程上的,点击开始按钮时,按钮出现下沉情况,子线程一直在后台运行,我窗体中的图片根本不会发生改变,而是直接显示最后的结果,意思就是骰子一直在后台转动,不在前台的窗体中及时更新显示。后来在网上苦苦找寻,大神们说如果想要通过点击jbutton使窗体中的jlabel/jtextfeild等其他组件及时更新,直接在jbutton的监听事件的实现方法里面直接创建匿名线程,也就是说直接在actionperformed()方法中修改代码即可,这样能保证你的组件中内容的及时变换,实现非常炫酷的效果。
代码如下:
public void actionperformed(actionevent e) { new thread(new runnable() { @override public void run() { //将外部线程类转移到窗体内部 } }).start(); }
but,,,but,,, 虽然非常炫酷了,能够实现图片的及时更新了,游戏结果却错了,每次我的骰子还在转动呢,我的游戏结果却早早的就出来了。
原因:3根骰子线程属于子线程,窗体线程属于主线程,问题就在于:子线程可以通过变成精灵线程来保持与主线程的同生死,但是主线程却无法控制子线程何时死亡,只有等待子线程执行完所属的run()方法,结束线程后才知道。
解决方法:在主线程(main)中开3个子线程(t1,t2,t3),在每个子线程上再开一个子子线程(t11,t21,t31)。
t1,t2,t3只运行一次,负责创建子子线程;t11,t21,t31每个线程运行多次,负责控制窗体中的图标及时更新。
这样主线程就不受子线程的影响,开始按钮也不回出现下沉的情况。
但是同样在此处使用join方法也是hold不住子线程的,毕竟t1,t2,t3只运行了一次,join对他们来说根本不起作用,想要掌控t11,t21,t31,最容易理解的办法,就是使用观察者模式了。
将窗体看做观察者,子线程看做被观察者。子线程运行完时,通知观察者我已经运行完成,当观察者观察到子线程全都运行完时,才开始运行后续步骤。
全部代码:
1.窗体
package com.sxt.dice; import java.awt.color; public class diceframe extends jframe implements actionlistener, observer { /** * 《掷骰子》控制台小游戏,在该游戏中,玩家初始拥有的金钱,每次输入押大还是押小, * 以及下注金额,随机个骰子的点数,如果个骰子的总点数小于等于,则开小,否则开大, * 然后判断玩家是否押对,如果未押对则扣除下注金额,如果押对则奖励和玩家下注金额相同的金钱。 * * 运用观察者模式 个子线程分别控制个骰子,都已经结束时,通知观察者窗体,窗体观察到所有子线程都结束时,计算游戏结果 * */ private static final long serialversionuid = l; private jtextfield txtput; private jbutton btnstart; private jlabel labresult; private jcombobox<string> combobox; private jlabel labbigorsmall; private jlabel labput; private jlabel labsummoney; private jlabel labdice; private jlabel labdice; private jlabel labdice; private jlabel labsum; private jlabel labmes; private static list<icon> imgs = new arraylist<icon>(); public static void main(string[] args) { new diceframe(); } public diceframe() { this.setlocationrelativeto(null); this.setbounds(, , , ); this.setdefaultcloseoperation(jframe.dispose_on_close); getcontentpane().setlayout(null); this.setresizable(false); labdice = new jlabel(""); labdice.seticon(new imageicon("img/dices.jpg")); labdice.setbounds(, , , ); getcontentpane().add(labdice); labsum = new jlabel("\u\uf\ud\ud\uffa"); labsum.setbounds(, , , ); getcontentpane().add(labsum); labdice = new jlabel(""); labdice.seticon(new imageicon("img/dices.jpg")); labdice.setbounds(, , , ); getcontentpane().add(labdice); labdice = new jlabel(""); labdice.seticon(new imageicon("img/dices.jpg")); labdice.setbounds(, , , ); getcontentpane().add(labdice); labsummoney = new jlabel(""); labsummoney.setforeground(color.red); labsummoney.setbounds(, , , ); getcontentpane().add(labsummoney); labput = new jlabel("\uc\ub\ueb\uce\uffa"); labput.settooltiptext("."); labput.setbounds(, , , ); getcontentpane().add(labput); txtput = new jtextfield(); txtput.setbounds(, , , ); getcontentpane().add(txtput); txtput.setcolumns(); labbigorsmall = new jlabel("\ubc\uffa"); labbigorsmall.setbounds(, , , ); getcontentpane().add(labbigorsmall); combobox = new jcombobox<string>(); combobox.setbounds(, , , ); getcontentpane().add(combobox); combobox.additem("大"); combobox.additem("小"); labresult = new jlabel(""); labresult.setbounds(, , , ); getcontentpane().add(labresult); btnstart = new jbutton("start"); btnstart.setbounds(, , , ); getcontentpane().add(btnstart); labmes = new jlabel("<html><font size= color=red>*</font></html>"); labmes.setbounds(, , , ); getcontentpane().add(labmes); this.setvisible(true); imgs.add(new imageicon("img/.png")); imgs.add(new imageicon("img/.png")); imgs.add(new imageicon("img/.png")); imgs.add(new imageicon("img/.png")); imgs.add(new imageicon("img/.png")); imgs.add(new imageicon("img/.png")); btnstart.addactionlistener(this); } @override public void actionperformed(actionevent e) { if (e.getsource() == btnstart) { // 清除上次游戏的结果 labresult.settext(""); // 获取当前下注金额,用户余额,用户押大还是押小 string txt = txtput.gettext().trim(); string remain = labsummoney.gettext().trim(); // 余额不足,不能开始游戏,提示用户充值 if (integer.parseint(remain) <= ) { joptionpane.showmessagedialog(null, "当前余额不足,请充值!"); return; } // 下注金额合法性检查 if (txt.length() == ) { // 提示用户输入 labmes.settext("*请输入下注金额"); labmes.setforeground(color.red); return; } // 检查用户下注金额是否在有效范围内 if (integer.parseint(txt) <= || integer.parseint(txt) > integer.parseint(remain)) { txtput.settext(""); labmes.settext("下注金额应在~" + remain + "之间"); return; } // 游戏开始后相关项不可更改 txtput.setenabled(false); labmes.settext(""); combobox.setenabled(false); //在主线程上开t,t,t 个子线程 thread t = new thread() { @override public void run() { //每个子线程上再开子子线程,控制图标变换 iconthread t = new iconthread(labdice, imgs); //给t添加观察者,即当前窗体 t.addobserver(diceframe.this); new thread(t).start(); } }; thread t = new thread() { @override public void run() { iconthread t = new iconthread(labdice, imgs); t.addobserver(diceframe.this); new thread(t).start(); } }; thread t = new thread() { @override public void run() { iconthread t = new iconthread(labdice, imgs); t.addobserver(diceframe.this); new thread(t).start(); } }; t.start(); t.start(); t.start(); } } /** * 获取骰子点数和 * * @param lab * @return sum */ private int result(jlabel lab) { // 获取当前骰子图片 icon icon = lab.geticon(); int sum = ; for (int i = ; i < imgs.size(); i++) { if (icon.equals(imgs.get(i))) { sum += (i + ); break; } } return sum; } // 构建所有被观察者的集合 vector<observable> allobservables = new vector<observable>(); @override public void update(observable o, object arg) { system.out.println(o + "................."); // 如果集合中不包含当前被观察者,将此被观察者加入集合 if (allobservables.contains(o) == false) { allobservables.add(o); } // 如果集合中被观察者个数为,说明个骰子线程已经全部结束 if (allobservables.size() == ) { // 获取当前下注金额,用户余额,用户押大还是押小 string txt = txtput.gettext().trim(); string remain = labsummoney.gettext().trim(); string bigorsmall = combobox.getselecteditem().tostring(); // 获取每个骰子点数 int sum = result(labdice); int sum = result(labdice); int sum = result(labdice); system.out.println(sum + "-" + sum + "-" + sum); int sum = sum + sum + sum; system.out.println(sum); if (sum > && "大".equals(bigorsmall) || sum <= && "小".equals(bigorsmall)) { // 奖励玩家相应金额 remain = string.valueof(integer.parseint(remain) + integer.parseint(txt)); labsummoney.settext(remain); // 显示游戏结果 labresult.settext("win"); labresult.setforeground(color.green); labresult.setfont(new font("宋体", font.bold, )); } else { // 扣除玩家相应金额 remain = string.valueof(integer.parseint(remain) - integer.parseint(txt)); labsummoney.settext(remain); labresult.settext("fail"); labresult.setforeground(color.red); labresult.setfont(new font("宋体", font.bold, )); } txtput.setenabled(true); combobox.setenabled(true); // 本次游戏结束后移除集合中所有线程 allobservables.removeall(allobservables); } } }
2.线程
package com.sxt.dice; import java.util.list; import java.util.observable; import java.util.random; import javax.swing.icon; import javax.swing.jlabel; public class iconthread extends observable implements runnable { /** * 运用观察者模式,将子线程作为被观察对象,一旦子线程运行完,发生改变,通知观察者 */ jlabel lab; random random = new random(); list<icon> imgs; public iconthread(jlabel lab, list<icon> imgs) { this.lab = lab; this.imgs = imgs; } @override public void run() { //设置每颗骰子转动次 int count = ; while (count > ) { //获取一个随机数[~) int index = random.nextint(); //从imgs集合中取相应图片放入lab中 lab.seticon(imgs.get(index)); count--; try { thread.sleep(); } catch (interruptedexception e) { // todo auto-generated catch block e.printstacktrace(); } } this.setchanged();// 子线程运行完,发生改变 this.notifyobservers();// 通知观察者 } }
以上所述就是关于java编写掷骰子游戏的全部内容,希望大家喜欢。
上一篇: linux内核引导参数解析及添加
下一篇: 采样-Gibbs采样
推荐阅读
-
Java编写掷骰子游戏
-
Eclipse下编写java程序突然不会自动生成R.java文件和包的解决办法
-
实例解析使用Java实现基本的音频播放器的编写要点
-
Java的Struts框架中Action的编写与拦截器的使用方法
-
Java 中利用 axis2 进行webservice 客户端编写 博客分类: webservice axis2webservicejava
-
Java 中利用 axis2 进行webservice 客户端编写 博客分类: webservice axis2webservicejava
-
使用Java编写一个简单的Web的监控系统
-
java编写的简单移动方块小游戏代码
-
30条Java代码编写经验分享
-
Java Web项目中编写定时任务的实现