bjfu

bjfu,第1张

一、实验要求:

1. 掌握Java多线程的原理和编程方法。

2. 在本实验的编程过程中,对于导d、拦截器、主界面等应该使用不同的线程,注意线程创建、开始运行和消亡的过程控制。

二、实验内容和步骤 1. 实验背景介绍

红旗-9是我国第三代中高空中远程防空导d系统。本实验模拟防空导d拦截过程。

2. 系统具体要求

        界面上有5个按钮:

        “开始”按钮:游戏开始或游戏继续。开始按压之后,“停止”按钮失效变灰。开始之后,屏幕上出现自左至右和自右至左的导d,圆形蓝色。出现的高度是随机的(但不能太靠近画板的上下边缘),高度始终保持不变,直至碰到左或右边框后消失。如果被拦截导d击中,也会和拦截器一起消失。一旦开始,计时器开始计时,并且把秒数记录在窗口的左下角。导d从边缘出现的时间是随机的,不能有任何时间周期方面的规律。

        “停止”按钮:游戏开始之前,这个按钮是失效灰色的。点击“开始”按钮后,这个按钮才可以正常点击生效。停止后,“停止”按钮立即失效变灰,“开始”按钮可以点击生效。停止后,所有的导d和拦截器都静止不动。计时器停止,但计时秒数不清零,下一次点击“开始”按钮后,计时器在以前保留的计数的基础上增加。

        “拦截”按钮:点击“拦截”按钮,会自底向上垂直发出拦截器。拦截器的速度要大于导d的速度。可以使用相对速度来设置速度。例如,导d自左至右飞行1秒的话,如果拦截器的相对速度是导d的2倍,则它应该在0.5秒的时间从画板底部飞行至画板上边缘。可以多次发射,发射多个拦截器。但是运行中的拦截器的数量有一个上限,例如10,当超过这个数时,“拦截”按钮将变灰失效。

        “加速”按钮使得所有导d和拦截器的速度提升一截。速度一共有多个挡,例如5档,当速度在第5档时,“加速”按钮失效变灰。

        “减速”按钮使得所有的导d和拦截器都同时降速。如果处在1档,则“减速”按钮失效变灰。

3. 实验样例图

 三、实验结果展示及讲解 应实验查重要求只展示部分代码,但会提供各功能的思路 讲解不易,为防止高度相似请自行定义变量名  1. 结果展示

        ①正常运行(请点击链接进入观看)

RedFlag之正常运行结果-CSDN直播

        ②加速、减速(请点击链接进入观看)

RedFlag之加速减速结果展示-CSDN直播

2. 实验讲解

        ①窗体的实现

         窗体的布局形式自然是采用BorderLayout方式,我建议功能区除了按钮之外的部分都用JLabel,因为这在后续的输出上会很省事,用个setText(String)方法就行了,比如你要是在计时的显示上用JTextArea的话它就是可手动更改的,显然我们用不可手动更改的JLabel更符合要求。最后功能区套一个JPanel合到一块儿作为SOUTH即可。

        在设置布局信息的时候(也就是写RedFlag类无参构造的时候),要将各组件初始化,也就是哪个按钮可用不可用的问题,各组件大小设置的问题,重写监听函数等等。

        此外,在RedFlag类中,要注意设置一个boolean类型的变量,专门用来记录程序运行的状态,未点击开始时设为false,开始后设为true,停止后设为false。这个变量很关键,它贯穿所有线程的运行状态。

        ②导d类的定义

        导d应该包含的信息有坐标、速度、大小、方向(从左到右还是从右到左),并在类内构造画导d与擦除导d的方法。在后面会讲到,画导d是为了将导d输出到画布中,而擦除导d的功能就是为了掩盖导d的运动轨迹,也就是在画完导d之后等待几十毫秒(这个就是你定义的游戏的帧率或者画布刷新频率)擦除当前小球的痕迹。

导d类应含有的信息,其他getter、setter、带参构造等方法请自主补全(关键信息已全部展示)
(讲解不易,为防止高度相似请自行定义变量名)

private int x, y;					//坐标
private int speed;					//速度,根据刷新率和延迟可以推导出移动距离
private int missileSize; 			//导d的大小,用于绘制
private int direction;              //导d的方向

//画导d
public void drawMissile(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
	g2.setColor(Color.BLUE);
	g2.fillOval(getX(), getY(), missileSize, missileSize);
}
	
//擦除导d
public void cleanMissile(Graphics g) {
	Graphics2D g2 = (Graphics2D)g;
	g2.setColor(Color.WHITE);
	g2.fillOval(getX(), getY(), missileSize, missileSize);
}

        ③拦截器类的定义

        拦截器的信息与导d类的定义差不多,只不过少了方向,拦截器的方向始终自下到上,其余一样。

拦截器类应含有的信息,其他getter、setter、带参构造方法请自主补全(关键信息已全部展示)
(讲解不易,为防止高度相似请自行定义变量名)

private int x, y;					//坐标
private int speed;					//速度,根据刷新率和延迟可以推导出移动距离
private int interceptorSize; 		//拦截器的大小,用于绘制

//画拦截器
public void drawInterceptor(Graphics g) {
	Graphics2D g2 = (Graphics2D)g;
	g2.setColor(Color.RED);
	g2.fillOval(getX(), getY(), interceptorSize, interceptorSize);
}
	
//擦除拦截器
public void cleanInterceptor(Graphics g) {
	Graphics2D g2 = (Graphics2D)g;
	g2.setColor(Color.WHITE);
	g2.fillOval(getX(), getY(), interceptorSize, interceptorSize);
}

        ③画布类的定义

        既然这是个多线程问题(包括计时器、计数器、导d、拦截器四个线程),计时器、计数器我们可以在RedFlag本类中定义并使用肯定是最方便的,那么剩下两个线程直接在画布类中实现就会少了get当前画布信息的步骤,这样会省很多很多很多(此处省略1w个很多)……事,至于导d和拦截器各自的运动我们后面再讲。因此我们可以将整个程序分为三个主要的线程:计时器、计数器、画布。因此画布也要implements Runnable。

        在画布类中也要定义一个boolean类型的变量用于记录线程的运行状态,值与RedFlag中定义的记录状态的量始终保持一致。

        此外,既然要记录导d和拦截器,那必然需要在画布类中定义导d集合和拦截器集合,各设一个ArrayList即可。如下:

画布类的变量信息
(讲解不易,为防止高度相似请自行定义变量名)

//导d集合
ArrayList missileList = new ArrayList();
private int 当前导d数量(自行定义变量名) = 0;		        //当前导d数量
private int 生成的导d总数量(自行定义变量名) = 0;	        //生成的导d总数量
private int 初始速度(自行定义变量名) = 自定义一个初始速度;	//初始速度

//拦截器集合
ArrayList interceptorList = new ArrayList();
private int 当前拦截器数量(自行定义变量名) = 0;		        //当前拦截器数量
private int 已拦截的数量(自行定义变量名) = 0;		        //已拦截的数量

        上篇到此就结束了,主要先讲解大致的类的定义,在下篇将更新具体方法的实现,包括怎样运行多线程、计时器功能的实现、计数器功能的实现、导d和拦截器运动的实现、导d和拦截器碰撞的实现、导d和拦截器出界的判断等,此外在实验中各位uu遇到的bug或者其他待解决问题可以留言,我将在半天内回复。

(留言区评论 “快出下篇HurryUp” 以催更)

转载请注明出处。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/876595.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存