Java拿火柴游戏实训报告
五一黄金周-北岛我不相信
Java实训报告
程序名:拿火柴游戏
姓名: 龙宇
学号: 2010221062
班级: 计应101班
指导教师: 郑晓东
时间:
2011.12.31
一、
程序功能介绍
火柴游戏的功能时通过用户与计算机相互对拿火柴的游戏程序,通过与计算机的对拿来训
练人脑的逻辑
思维能力。游戏简单,便于操作
二、 运行效果及玩法
该程序(火柴
游戏)的功能用户与计算机相互对拿火柴的游戏程序,游戏的玩法是用系统产生的随机函
数产生火柴数量
(大约在20—50之间),每次每一方最多拿三根,最少拿一根,谁拿到最后一根,即为胜者。
游戏的
运行效果如下图图1所示,电脑随机产生了若干根火柴棍,图画面上按左边“Computer
First”那个按
钮,就是电脑先拿,如果点击的是右边的“TAKE”按钮,就是人先拿。
图1
具体步骤如下图所示
1、如果是电脑先拿先单击Computer
First按钮,电脑随机拿走一根火柴,并在电脑按钮下方显示“Computer
takes 1
matches this time”提示信息,单击之后电脑拿走的按钮被禁用,直到用户单击自己的按钮之
后才能
再拿,具体情况如图2所示:
图2
2
、之后用户单击自己的Take按钮,根据自己的情况拿相应的火柴数,比如说用户那个三根火柴如图3所示:
图3
3、可以看到用户根据自己的需要拿了三根火柴,
之后电脑又拿了一根,如此循环,直到哪一方赢得比赛的胜
利。从图4,图5中可以看到用户赢得了比赛
的胜利。
图4
三、 设计主要内容:
该游戏程序设计的主要内容是使用java中的各种组件与容器互相搭配来完
成的一个小游戏。游戏设计中的主
要的知识要点包括java的awt包中的颜色类,图形类,图像类,
事件监听器类,和util包中的stack类,timer
类,和timertask类的使用方法,
以及swing包中的窗口类,按钮类,标签类,面板类,复选框类等一些常用
组件的用法。通过这些组
件来掌握事件监听器的用法,java中栈的用法,以及实现了Runnable类的TimerTask
类的用法,通过这个类实现线程技术,还有Graphics类中的主要方法的使用,学会运用这些方法来来绘
制火
柴,绘制图片的目的。
四、 源程序
import 引入颜色类
import ent;引入组件类
import
ion;引入封装单个对象中组件的宽度和高度(精确到整数)的类
import cs;引入图形类
import cs2D;引入二维图形类
import Event;引入事件类
import Listener;引入事件监听器类
import
edImage;引入缓冲图像类
import 引入栈类
import
;引入计时器类
import ask;引入了实现Runnable接口的类,并具有了线程的功能
import n;引入按钮类
import Box;引入下拉列表框类
import 引入主框架主窗口类
import 引入标签类
import
nPane;引入选项面板类
import 引入面板类
public
class Test定义一个公共的主类Test
{
public static void main(String[]
args)定义主方法main
{
new
Test();调用Test类的构造方法Test()
}
private
static final int MIN_CNT = 20;定义一个常量,设置为最小火柴棍数量为20
private static final int MAX_CNT =
50;定义一个常量,设置为最大火柴棍数量为50
private static final
int MAX_TAKE = 3;定义一个常量,设置为最大拿火柴数量为3
private
static final int DELAY = 1000;定义一个常量,设置为延迟时间为1000
private JFrame mainFrame;定义主框架变量
private
MyPaintPanel[] paints;定义我自己画的面板数组变量
private
JButton userBtn;定义我的按钮属性
private JComboBox
userNum;定义我的下拉列表
private JButton
compBtn;定义电脑按钮属性
private JLabel compTxt;定义电脑标签
private Timer timer;定义计时器的变量
private
Test()定义一个私有的构造方法,来完成游戏的初始化动作
{
mainFrame = new JFrame();实例化一个主窗口
izable(false);设置窗体大小不可调整
aultCloseOperation(_ON_CLOSE);设置默认的关闭
操作为关闭窗口
常量值
JPanel mainPanel = new
JPanel();实例化一个主面板对象
out(null);设置布局为空,即没有任何布局
ferredSize(new Dimension(600,
400));将组件的首选大小设置为
(mainPanel);将主面板添加到框架(窗口)中
JLabel lab11 = new JLabel(电脑);创建并设置标签按钮的内容为电脑
izontalAlignment();设置标签内容沿 X 轴的对齐方式
nds(0,
10, 200, 20);设置该标签显示位置为坐标(0,10),宽200,高20
(lab11);将标签加入主面板
JButton btn11 = new
JButton();定义一个重新来的按钮
ionListener(new
ActionListener()为“Reset”添加行为事件监听器,
采用匿名类的方式
{
@Override
public void
actionPerformed(ActionEvent e)实现监听器中的方法
{
init();当单击此按钮时,调用该初始化方法
}
});
nds(250, 10, 100,
20);设置重置按钮的位置,左上角坐标为(250,10),
大小为宽100,高20
(btn11);重来标签添加到主面板上
JLabel lab12 = new
JLabel(用户);定义用户标签
izontalAlignment();设置用户水平方式为居中
nds(400, 10,
200, 20);设置用户标签的位置,左上角坐标为(400,10),
大小为宽200,高20
(lab12);将用户标签添加到主面板上
听器
compBtn = new JButton();定义一个电脑首先拿的按钮
ionListener(new
ActionListener()为电脑开始按钮定义行为事件监
{
@Override
public void
actionPerformed(ActionEvent e)行为监听器中的默认方法
{
compTake();当单击电脑按钮时,调用电脑拿方法
}
});
nds(10, 40,
180, 20);设置电脑按钮的位置,左上角坐标为(10,40),
大小为宽180,高20
(compBtn);按钮添加到主面板上
compTxt = new
JLabel();定义一个空标签
nds(10, 70, 400,
20);设置空标签的位置,左上角坐标为(10,70),
大小为宽400,高20
(compTxt);将空标签加到主面板上
userBtn = new JButton();定义用户拿按钮
ionListener(new ActionListener()为用户按钮定义行为事件监听器
{
@Override
public void
actionPerformed(ActionEvent e)
{
userTake();当单击用户拿按钮时,调用用户拿方法
}
});
nds(400, 40, 90,
20);设置用户拿按钮的位置,左上角的坐标为
(400,40),大小为宽90,高20
(userBtn);用户按钮添加到主面板上
userNum = new
JComboBox();定义一个下拉列表框
for (int i = 0; i <
MAX_TAKE; i++)定义一个拿最大的循环
{
m(i +
1);通过循环给列表框逐个添加选项
}
nds(495, 40, 90,
20);设置下拉列表框中的位置,左上角的坐标为
(495,40),大小为宽90,高20
(userNum);将列表框添加到主面板上
paints = new
MyPaintPanel[3];定义我画的面板
for (int i = 0; i < 3;
i++)用3次循环来画出三个面板
{
paints[i] = new
MyPaintPanel();分别创建3个面板,并调用构造方法初始化三个面
板
paints[i].setBounds(5 + 200 * i, 110, 190,
285);设置三个面板的位置和坐
标,间距为5
(paints[i]);将三个面板分别添加到主面板上
}
();调整此窗口的大小,以适合其子组件的首选大小和布局。
ible(true);设置当前主窗口的可见性
init();调用初始化方法
}
private void init()定义初始化的方法
{
if (timer != null)如果计时器不为空的话就执行下面的语句
{
();快速终止计时器的任务执行线程
}
timer =
new Timer();实例化一个计时器的对象
t();设置空标签的文本为空
bled(true);设置是否启用电脑按钮组件,即电脑组件可用
bled(true);设置是否启用用户按钮组件,即用户组件可用
paints[0].reset();调用重置方法,来重新定义第一块面板
paints[1].reset();调用重置方法,来重新定义第二块面板
paints[2].reset();调用重置方法,来重新定义第三块面板
int num
= MIN_CNT + (int) ((MAX_CNT + 1 - MIN_CNT) *
());随
机产生一个大于20小于50的数
for (int i = 0; i <
num; i++)分别用for循环添加面板
{
paints[1].add(i + 1);分别将产生的随机数添加到第二块面板
}
}
private void userTake()定义一个用户拿火柴棒的方法
{
bled(false);设置按钮不可用
int takeCnt =
ectedIndex() + 1;定义用户拿得火柴棍的数量
int rel =
paints[1].getCnt();将自定义的第二个面板中的火柴棍的数量赋给rel
if
(takeCnt > rel)如果用户拿火柴棍的数量比面板中的数量大的话,执行下面的语句
{
ssageDialog(mainFrame, + rel
+
matches.);用标准对话框类调用显示”There is only
machines“的
对话框
return;
}
for
(int i = 0; i < takeCnt;
i++)定义一个将第二块面板中的火柴棍的数量移动到用
户面板的循环
{
量
int
index =
paints[1].remove();将第二个面板要移除的火柴棍的数量给index变
paints[2].add(index);将index的值添加到用户拿的面板上
}
if (takeCnt == rel)如果用户拿的火柴棍的数量和第二个相等执行下面的语句
{
ssageDialog(mainFrame, are the
winner.);显示”
你胜利的对话框“
init();并重新初始化
}
else如果不相等的话,执行下面的语句,
{
compTake();让电脑接着拿火柴棍
}
}
private void
compTake()定义电脑拿的方法
{
}
bled(false);设置电脑按钮的当前状态为不可用
bled(false);设置用户按钮的当前状态为不可用
MyTask task =
new MyTask();实例化一个MyTask的对象
le(task, DELAY);
执行线程,安排在指定延迟1秒后执行指定的任务
private class MyTask
extends TimerTask
定义一个继承了实现Runnable接口的类使自
己也具有线程功能
{
@Override
public void
run()因为TimerTask实现了Runnable接口,重写父类的run方法
{
int rel =
paints[1].getCnt();将火柴棍面板中的火柴的数量赋给rel
int
takeCnt = 0;设置当前拿火柴棍的数量为0
if (rel <=
MAX_TAKE)如果当前火柴棍的数量比最大拿火柴的数量小的话,执行下面的
{
takeCnt = rel;将火柴棍的数量赋给电脑要拿的数量
}
语句
else
if (rel % (MAX_TAKE + 1) >
0)如果面板中的火柴棍的数量对4取余大于0的
话执行下面的语句
{
takeCnt = rel % (MAX_TAKE +
1);将面板中的火柴的数量对4取余之后赋给电脑
要拿的火柴的数量
}
else
否则面板中的火柴棍的数量对4取余小于或等于0的话执行下面的语句
{
takeCnt = 1 + (int) (MAX_TAKE *
());随机产生一个小于4的
数,给电脑要拿的数量
}
for
(int i = 0; i < takeCnt; i++)
{
int index =
paints[1].remove();将火柴面板中的火柴移除并赋给index
paints[0].add(index);将移除的火柴添加到电脑拿的面板上
}
t(takes + takeCnt + matches this
time.);
设置电脑显示拿火柴的数量
if (takeCnt ==
rel)如果和电脑那的数量和面板中的数量相等执行下面的语句
{
ssageDialog(mainFrame, 显示信息对话框提示电脑胜
);
利了!
init();并重新初始化
}
bled(true);设置用户按钮重新可用
}
}
@SuppressWarnings()
private class
MyPaintPanel extends Component
定义一个自定义的面板类并继承了组件
类
{
private BufferedImage
bimg;创建一个BufferedImage的变量bimg
private
Stack
private
MyPaintPanel()构造我的初始面板的方法
{
bimg = new
BufferedImage(190, 285, _3BYTE_BGR);表
示一个具有 8 位
RGB 颜色分量的图像,
Graphics2D g2 =
Graphics();创建一个 Graphics2D,并将它绘制到
此
BufferedImage 中
or();设置要画的颜色,即面板的颜色
ct(0, 0, 190,
285);在坐标(0,0)处画一个大小为宽190,高为285的白
色矩形区域
e();释放此图形的上下文以及它使用的所有系统资源。调用 dispose 之后,
就不能再使用
Graphics 对象。
data = new
Stack
}
public void paint(Graphics
g)定义画图形的默认方法
{
age(bimg, 0, 0,
null);从坐标(0,0)出开始画图片
e();释放此图形的上下文以及它使用的所有系统资源。调用 dispose 之后,就
不能再使用
Graphics 对象。
}
private void add(int num)添加火柴棍的方法
{
Graphics2D g2 = Graphics();创建一个
Graphics2D,并将它绘制到
此 BufferedImage 中
int
loc = ();将当前栈的大小赋给变量loc
n(当前栈为
int
offX = loc % 3 * 65;动态的坐标
int offY = loc 3
* 15;动态的坐标
or();设置火柴棒的颜色为黄色
ct(offX + 8, offY + 5, 50, 6);填充火柴棒的颜色区域
or();设置火柴棒头的颜色为绿色
c(offX + 50, offY
+ 3, 10, 10, 0,
360);设置火柴棒头的坐标,大
小为宽和高为10的360度的弧
or();设置当前火柴棒的根数的颜色
ring(f(num), offX, offY
+ t().getSize());画出数字
(num);把数字1压入堆栈顶部
repaint();重画
e();释放此图形的上下文以及它使用的所有系统资源。调用 dispose 之后,
就不能再使用
Graphics对象
}
private int remove()定义一个移除火柴棍的方法
{
Graphics2D g2 = Graphics();创建一个
Graphics2D,并将它绘制到
此 BufferedImage 中
int
loc = () - 1;将当前栈的大小即火柴棍的数量减1
n(当前栈为
int offX = loc % 3 * 65;动态的获取坐标
int offY =
loc 3 * 15;动态的获取坐标
or();设置移除填充颜色为白色
ct(offX, offY, 60, 15);画出移除火柴棍的位置
e();释放此图形的上下文以及它使用的所有系统资源。调用 dispose 之后,
就不能再使用
Graphics 对象
repaint();调用重新画的方法
return ();移除堆栈顶部的对象,并作为此函数的值返回该对象。
}
private void
reset()定义一个重置的方法
{
();清楚该面板栈中的内容
Graphics2D g2 = Graphics();创建一个
Graphics2D,并将它绘制到
此 BufferedImage 中
or();设置颜色为白色
ct(0, 0, 190,
285);在坐标为(0,0)处填充大小为190,285的矩形区域
e();释放此图形的上下文以及它使用的所有系统资源。调用 dispose 之后,
就不能再使用
Graphics 对象。
repaint();重绘此组件。
}
private int
getCnt()定义一个返回第二个面板火柴棍的数量
{
return
();返回当前栈中的火柴棍数量
}
}
}
五、 遇到的问题和解决方法
在本次的实训过程中遇到一些以前没有碰到的问题,
首先是集成开发工具Eclipse的使用方法,经过多次的使
用学会了用它建立项目与类。并学会在编
辑的过程中处理发生的错误。随后又碰到了如Timer和Timetask类
的问题,自己上网后查询
了解到,这也是线程实现的一种技术之一,现在知道了要实现线程技术有三种方法,
实训中也了解到了g
etContentPane()方法的使用方法,以前不知道他是干什么的,现在知道了如果你用的是
JFrame类的话,由于这个类是由多个面板组成的,如果你要往其中添加组件的话,必须获取其中的内容面板
,
而这个方法就是获取内容面板的,而之后又遇到了Graphics的绘图方法的问题,如何绘制曲线
,如何绘制
直线,如何绘制矩形,如何绘制圆形等一些基本图形的绘制,经过自己与同学的讨论,学会了
图形类的使用
方法。也遇到浏览器中不能显示Applet程序的问题,经过自己的仔细研究发现这是由
于安装时没有安装所
需的差价所致,只要重新安装即可发现该问题,最后遇到了栈(Stack)的使用
方法,并学会了使用栈来存
取一些东西。并从了解到栈是一种先进后出的结构。
六、
后期加强改进
在以后的开发中可以给该游戏添加标题栏,开始界面以及退出的方式并添加一个改变背景
颜色的按钮等来实
现一个完整游戏的制作。