java第三次实验

北京电子科技学院(BESTI)

              

课程:Java程序设计   班级:1352       姓名:陈实  学号:20135224

成绩:             指导教师:娄嘉鹏      实验日期:

实验密级:         预习程度:             实验时间:

仪器组次:          必修/选修:选修       实验序号:3

实验名称:                敏捷开发与XP实践                           

实验目的与要求:                                                        

完成实验、撰写实验报告,实验报告以博客方式发表在博客园,注意实验报告重点是运行结果,遇到的问题(工具查找,安装,使用,程序的编辑,调试,运行等)、解决办法(空洞的方法如“查网络”、“问同学”、“看书”等一律得0分)以及分析(从中可以得到什么启示,有什么收获,教训等)。报告可以参考范飞龙老师的指导                             

                                                                     

实验仪器:

名称

型号

数量

Pc

 

1

 

 

 

重构:

一、一个完整的重构流程包括:

  1. 从版本控制系统代码库中Check out code
  2. 读懂代码(包括测试代码)
  3. 发现bad smell
  4. Refactoring
  5. 运行所有的Unit Tests
  6. 往代码库中Check in code

二、重构技能

三、何时需要重构

四、举例:

rename

move

TDD测试:

游戏: TankGame

游戏描述:控制己方tank击杀敌方坦克。方向键控制移动,ctrl发射子弹,shift发射超级子弹,F1复活。

代码如下:

package MyFrame;

import java.awt.Color;

public class Constant {
public static final int FX=400;
public static final int FY=100;
public static final int FWID=800;
public static final int FHEI=600;
public static final int TW=30;
public static final int TH=30;
public static final Color BACK=new Color(0,0,255);
public static final int TSPEED=7;
public static final int MissileW=10;
public static final int MissileH=10;
public static final int MSPEED=10;
public static final int WW=50;
public static final int WH=300;
}

package MyFrame;

import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;

import Mygame.Explode;
import Mygame.Missile;
import Mygame.Tank;
import Mygame.Tank.Direction;
import Mygame.greatWall;

public class MyFrame extends Frame {
public Tank t1 = new Tank(Constant.FWID - Constant.TW, Constant.FHEI
- Constant.TH, true, Direction.STOP, this);
public List<Missile> missiles = new ArrayList<Missile>();
public List<Tank> enemyTanks = new ArrayList<Tank>();
public List<Explode> bongs = new ArrayList<Explode>();
public greatWall gw = new greatWall(500, 300);
public static int EnemyCount = 10;
public static int Times = 0;
Image offScreenImage = null;

public void launchFrame() {
addEmpty();
setTitle("TankWar");
setBounds(Constant.FX, Constant.FY, Constant.FWID, Constant.FHEI);
setVisible(true);
setBackground(Constant.BACK);
addWindowListener(new WindowAdapter() {

@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}

});
setResizable(false);
new Thread(new TThread()).start();
addKeyListener(new keyMonitor());

}

/**
* 双缓冲技术就是在屏幕背后再定义一张图 在图上画有相同的背景 在闪烁的时候把图画到前面
*/
@Override
public void update(Graphics g) {// 双缓冲消除闪烁
if (offScreenImage == null) {
offScreenImage = this.createImage(Constant.FWID, Constant.FHEI);
}
Graphics gOffScreen = offScreenImage.getGraphics();// 获得画屏幕后面场景的画笔
Color c = gOffScreen.getColor();
gOffScreen.setColor(Constant.BACK);
gOffScreen.fillRect(0, 0, Constant.FWID, Constant.FHEI);
gOffScreen.setColor(c);
paint(gOffScreen);
g.drawImage(offScreenImage, 0, 0, null);// 把图片画到前面

}

@Override
public void paint(Graphics g) {
if (enemyTanks.size() == 0) {
Times++;
EnemyCount += 5;
addEmpty();
}
g.drawString("子弹数:" + missiles.size(), 700, 50);
g.drawString("敌方坦克数:" + enemyTanks.size(), 700, 70);
g.drawString("关卡数:" + Times, 700, 90);
g.drawString("血量:" + t1.getLife(), 700, 100);
g.drawString("复活次数:" + t1.getTimes(), 700, 120);
gw.draw(g);
for (int i = 0; i < missiles.size(); i++) {
Missile missile = missiles.get(i);
if (missile.destroy(enemyTanks) || missile.destroy(t1)
|| missile.hitWall(gw)) {
missiles.remove(i);
}
if (missile.isLive()) {
missile.draw(g);
}
}
t1.draw(g);
for (int i = 0; i < enemyTanks.size(); i++) {
Tank tank = enemyTanks.get(i);
tank.hitWall(gw);
tank.pengTank(enemyTanks);
if (tank.isLive())
tank.draw(g);
}
for (int i = 0; i < bongs.size(); i++) {
Explode e = bongs.get(i);
if (e.isLive()) {
e.draw(g);
} else {
bongs.remove(i);
}
}

}

public void addEmpty() {
for (int i = 0; i < EnemyCount; i++) {
Tank tanki = new Tank(i * 50 + Constant.TW, 50, false, Direction.D,
this);
enemyTanks.add(tanki);
}
}

private class keyMonitor extends KeyAdapter {

@Override
public void keyPressed(KeyEvent e) {
t1.keypressed(e);

}

@Override
public void keyReleased(KeyEvent e) {
t1.keyReleased(e);
}

}

private class TThread implements Runnable {

public void run() {
while (true) {
repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

}

package Mygame;

import java.awt.Color;
import java.awt.Graphics;

import MyFrame.MyFrame;

public class Explode {
private int x,y;
private boolean live=true;
int[] zhiJing={2,4,8,15,16,20,16,10,5,2};
private int step=0;
MyFrame mf=null;
public Explode(int x,int y,MyFrame mf) {
this.x = x;
this.y = y;
this.mf=mf;
}

public boolean isLive() {
return live;
}

public void setLive(boolean live) {
this.live = live;
}

public void draw(Graphics g){
if(!live)return;
if(step==zhiJing.length){
live=false;
step=0;
return;
}
Color c=g.getColor();
g.setColor(Color.BLACK);
g.fillOval(x, y, zhiJing[step], zhiJing[step]);
g.setColor(c);
step++;
}
}

package Mygame;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;

import MyFrame.Constant;

public class greatWall {
private int x,y;
private int wid=Constant.WW;
private int hei=Constant.WH;
public greatWall(int x, int y) {
this.x = x;
this.y = y;
}
public void draw(Graphics g){
Color c=g.getColor();
g.setColor(Color.GRAY);
g.fillRect(x, y, wid, hei);
g.setColor(c);
}
public Rectangle getRect(){
return new Rectangle(x,y,wid,hei);
}
}

package Mygame;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.List;

import MyFrame.Constant;
import MyFrame.MyFrame;
import Mygame.Tank.Direction;

public class Missile {
private int x, y;
private int missileW=Constant.MissileW;
private int missileH=Constant.MissileH;
private int Mspeed = Constant.MSPEED;
private boolean live = true;
private boolean good = true;
MyFrame mf;
Tank.Direction dir;

public Missile(int x, int y, Tank.Direction dir, boolean good ,MyFrame mf) {
this.x = x;
this.y = y;
this.mf=mf;
this.dir = dir;
this.good = good;
}

public void draw(Graphics g) {
if (live == true) {
Color c = g.getColor();
if(good)
g.setColor(Color.orange);
else 
g.setColor(Color.BLACK);
g.fillOval(x, y, missileW, missileH);
g.setColor(c);
fly();
}
}
public boolean hitWall(greatWall gw){
if(this.isLive()&&this.getRect().intersects(gw.getRect())){
this.setLive(false);
Explode ex = new Explode(x,y,mf);
mf.bongs.add(ex);
return true;
}
return false;
}
public boolean isLive() {
return live;
}

public void setLive(boolean live) {
this.live = live;
}

public void fly() {
switch (dir) {
case L:
x -= Constant.MSPEED;
break;
case LU:
x -= Constant.MSPEED;
y -= Constant.MSPEED;
break;
case LD:
x -= Constant.MSPEED;
y += Constant.MSPEED;
break;
case R:
x += Constant.MSPEED;
break;
case RU:
x += Constant.MSPEED;
y -= Constant.MSPEED;
break;
case RD:
x += Constant.MSPEED;
y += Constant.MSPEED;
break;
case U:
y -= Constant.MSPEED;
break;
case D:
y += Constant.MSPEED;
break;
case STOP:
break;
}
if (x <= 25 || x >= Constant.FWID - Constant.MissileW || y <= 0
|| y >= Constant.FHEI - Constant.MissileH) {
live = false;
mf.missiles.remove(this);
}
}

public int getX() {
return x;
}

public void setX(int x) {
this.x = x;
}

public int getY() {
return y;
}

public void setY(int y) {
this.y = y;
}

public Rectangle getRect() {
Rectangle r = new Rectangle(x, y, Constant.MissileW, Constant.MissileH);
return r;
}

public boolean destroy(Tank t1) {
if (this.isLive() && this.getRect().intersects(t1.getRect())
&& t1.isLive() && this.good != t1.isGood()) {
Explode ex = new Explode(x,y,mf);
mf.bongs.add(ex);
if(t1.isGood()){
this.setLive(false);
if(t1.getLife()>0){
t1.setLife(t1.getLife()-20);
}
if(t1.getLife()==0){
t1.setLive(false);
}
}else{
t1.setLive(false);
this.setLive(false);
}
return true;
}
return false;
}

public boolean destroy(List<Tank> enemyTanks) {
for (int i = 0; i < enemyTanks.size(); i++) {
Tank enemyTank = enemyTanks.get(i);
if (destroy(enemyTank)) {
enemyTank.setLive(false);
enemyTanks.remove(i);
return true;
}
}
return false;
}
}

package Mygame;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.List;
import java.util.Random;

import MyFrame.Constant;
import MyFrame.MyFrame;

/**
* 如果想用MyFrame中的成员或者方法必须在构造成员方法的时候把值添加进去

* @author dell
*
*/

public class Tank {
private int x, y;
private int w = Constant.TW;
private int h = Constant.TH;
private int speed = Constant.TSPEED;
private boolean good = true;
private boolean tL = false, tR = false, tU = false, tD = false;
private boolean live = true;
private int life = 100;
private BloodBar bb=new BloodBar();
public int getTimes() {
return times;
}

public void setTimes(int times) {
this.times = times;
}

private int times=0;
public int getLife() {
return life;
}

public void setLife(int life) {
this.life = life;
}

private int oldX, oldY;
MyFrame mf;

public enum Direction {
L, LU, LD, R, RU, RD, U, D, STOP
};

private Direction ptDir = Direction.D;// 定义一个炮筒的方向,默认朝上
private Direction direction = Direction.STOP;
private static Random r = new Random();
private int step = r.nextInt(15) + 5;

public Tank(int x, int y, boolean good) {
this.x = x;
this.y = y;
this.oldX = x;
this.oldY = y;
this.good = good;
}

public Tank(int x, int y, boolean good, Direction direction, MyFrame mf) {
this(x, y, good);
this.direction = direction;
this.mf = mf;
}

public void draw(Graphics g) {
if (!live)
return;
if (good) {
Color c = g.getColor();
g.setColor(Color.white);
g.fillOval(x, y, Constant.TW, Constant.TH);
g.setColor(c);
bb.draw(g);
} else {
Color c = g.getColor();
g.setColor(Color.red);
g.fillOval(x, y, Constant.TW, Constant.TH);
g.setColor(c);
}
switch (ptDir) {
case L:
g.drawLine(x + w / 2, y + h / 2, x, y + h / 2);
break;
case LU:
g.drawLine(x + w / 2, y + h / 2, x, y);
break;
case LD:
g.drawLine(x + w / 2, y + h / 2, x, y + h);
break;
case R:
g.drawLine(x + w / 2, y + h / 2, x + w, y + h / 2);
break;
case RU:
g.drawLine(x + w / 2, y + h / 2, x + w, y);
break;
case RD:
g.drawLine(x + w / 2, y + h / 2, x + w, y + h);
break;
case U:
g.drawLine(x + w / 2, y + h / 2, x + w / 2, y);
break;
case D:
g.drawLine(x + w / 2, y + h / 2, x + w / 2, y + h);
break;
}
move();
}
public void reStart(){
while(!this.isLive()){
this.x=Constant.FWID - Constant.TW;
this.y=Constant.FHEI- Constant.TH;
this.setLive(true);
this.setLife(100);
times++;
}
}
public Missile fire() {
if (!this.live)
return null;
Missile m1 = null;
if (this.good) {
m1 = new Missile(x + w / 2 - Constant.MissileW / 2, y + h / 2
- Constant.MissileH / 2, ptDir, true, mf);
mf.missiles.add(m1);
} else {
m1 = new Missile(x + w / 2 - Constant.MissileW / 2, y + h / 2
- Constant.MissileH / 2, ptDir, false, mf);
mf.missiles.add(m1);
}
return m1;
}

public Missile fire(Direction dir) {// 在此方法中为子弹初始化
if (!this.isLive())
return null;
int x1 = this.x + Constant.TW / 2 - Constant.MissileW / 2;
int y1 = this.y + Constant.TH / 2 - Constant.MissileH / 2;
Missile m = new Missile(x1, y1, dir, this.good, this.mf);
mf.missiles.add(m);
return m;
}

public void superFire() {
Direction[] dirs = direction.values();
for (int i = 0; i < dirs.length - 1; i++) {
fire(dirs[i]);
}
}

public void keypressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
tL = true;
break;
case KeyEvent.VK_RIGHT:
tR = true;
break;
case KeyEvent.VK_UP:
tU = true;
break;
case KeyEvent.VK_DOWN:
tD = true;
break;
}
chooseDirection();
}

public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_CONTROL:
fire();
break;
case KeyEvent.VK_SHIFT:
superFire();
break;
case KeyEvent.VK_LEFT:
tL = false;
break;
case KeyEvent.VK_RIGHT:
tR = false;
break;
case KeyEvent.VK_UP:
tU = false;
break;
case KeyEvent.VK_DOWN:
tD = false;
break;
case KeyEvent.VK_F1:
reStart();
break;
}
chooseDirection();
}

// 判断坦克的方向
public void chooseDirection() {
if (tL && !tR && !tU && !tD)
direction = Direction.L;
if (tL && !tR && tU && !tD)
direction = Direction.LU;
if (tL && !tR && !tU && tD)
direction = Direction.LD;
if (!tL && tR && !tU && !tD)
direction = Direction.R;
if (!tL && tR && tU && !tD)
direction = Direction.RU;
if (!tL && tR && !tU && tD)
direction = Direction.RD;
if (!tL && !tR && tU && !tD)
direction = Direction.U;
if (!tL && !tR && !tU && tD)
direction = Direction.D;
if (!tL && !tR && !tU && !tD)
direction = Direction.STOP;
}

public void move() {
oldX = x;
oldY = y;
switch (direction) {
case L:
x = x - speed;
break;
case LU:
x = x - speed;
y = y - speed;
break;
case LD:
x = x - speed;
y = y + speed;
break;
case R:
x = x + speed;
break;
case RU:
x = x + speed;
y = y - speed;
break;
case RD:
x = x + speed;
y = y + speed;
break;
case U:
y = y - speed;
break;
case D:
y = y + speed;
break;
}
if (direction != Direction.STOP) {
ptDir = direction;
}
if (x < 0)
x = 0;// 使坦克不会出界
if (y < 25)
y = 25;
if (x > Constant.FWID - Constant.TW)
x = Constant.FWID - Constant.TW;
if (y > Constant.FHEI - Constant.TH)
y = Constant.FHEI - Constant.TH;
if (!good) {
Direction[] dir = Direction.values();
if (step == 0) {
step = r.nextInt(15) + 5;
int randomNum = r.nextInt(dir.length);// 在不超过数组长度的条件下产生随机数
direction = dir[randomNum];
fire();
}
step--;
}

}

public boolean hitWall(greatWall gw) {
if (this.isLive() && this.getRect().intersects(gw.getRect())) {
stay();
return true;
}
return false;
}

public Rectangle getRect() {
Rectangle rt = new Rectangle(x, y, Constant.TW, Constant.TH);
return rt;
}

public boolean pengTank(List<Tank> enemyTanks) {
for (int i = 0; i < enemyTanks.size(); i++) {
Tank enemyTank = enemyTanks.get(i);
if (this != enemyTank) {
if (this.isLive() && enemyTank.isLive()
&& this.getRect().intersects(enemyTank.getRect())) {
stay();
return true;
}
}
}
return false;
}

private class BloodBar {
public void draw(Graphics g) {
Color c = g.getColor();
g.setColor(Color.green);
g.drawRect(x, y - 10, Constant.TW, 10);
g.fillRect(x, y - 10, Constant.TW * life / 100, 10);
}
}

private void stay() {
x = oldX;
y = oldY;
}

public boolean isLive() {
return live;
}

public boolean isGood() {
return good;
}

public void setGood(boolean good) {
this.good = good;
}

public void setLive(boolean live) {
this.live = live;
}

}

package Mygame;

import java.awt.Color;
import java.awt.Graphics;

import MyFrame.MyFrame;

public class TankGame extends MyFrame{

public static void main(String[] args) {
TankGame t=new TankGame();
t.launchFrame();
}
}

界面如下:

出现问题及解决办法:

问题:使用enum(枚举)类型时,eclipse无法识别,显示错误。

解决方法:窗口-->首选项-->java-->编译器

将编译器一致性级别调至1.5以上,如图:

 实验总结:

实验完成有难度,在代码确定的情况下,测试也有一定的困难,在重构的操作中,类多容易给重构对象的判断造成干扰,在TDD测试中,没有完整的实行代码块,将很难调试通过。要相对代码进行重新编译。

结对同学:20135222胡御风

blog地址:http://www.cnblogs.com/huyufeng/ 

原文地址:https://www.cnblogs.com/chuishi/p/4553385.html