本帖最后由 fyxridd 于 2010-05-29 20:28:09 编辑

解决方案 »

  1.   


    package TankWar2;import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Rectangle;
    import java.util.ArrayList;
    import java.util.List;import TankWar2.TankWar.Direction;public class Tank {

    public static final int TANK_WIDTH = 27, TANK_HEIGHT = 27, TANK_XSPEED = 6, TANK_YSPEED = 6, LIFE_MAX = 100, HARM = 18, HEALTH_ADD = 20;
    public int x, y, team, life = LIFE_MAX;//team:0自己人    team:1敌人  
    public boolean isPlayer;//0:不是     1:是  
    public Direction dir, ptDir;

    public Tank(int x, int y, int team, boolean isPlayer, Direction dir,Direction ptDir) {
    this.x = x;
    this.y = y;
    this.team = team;
    this.isPlayer = isPlayer;
    this.dir = dir;
    this.ptDir = ptDir;
    }
    public void draw (Graphics g) {
    Color c = g.getColor();
    if (team == 0) {
    g.setColor(Color.BLUE);
    } else {
    g.setColor(Color.RED);
    }
    g.fillOval(x, y, TANK_WIDTH, TANK_HEIGHT);
    g.setColor(Color.BLACK);
    int x2 = 0, y2 = 0;
    switch (ptDir) {
    case U: x2 = x + TANK_WIDTH/2; y2 = y;break;
    case UR: x2 = x + TANK_WIDTH; y2 = y;break;
    case R: x2 = x + TANK_WIDTH; y2 = y + TANK_HEIGHT/2;break;
    case RD: x2 = x + TANK_WIDTH; y2 = y + TANK_HEIGHT;break;
    case D: x2 = x + TANK_WIDTH/2; y2 = y + TANK_HEIGHT;break;
    case DL: x2 = x; y2 = y + TANK_HEIGHT;break;
    case L: x2 = x; y2 = y + TANK_HEIGHT/2;break;
    case LU: x2 = x; y2 = y;break;
    }
    g.drawLine(x + TANK_WIDTH/2, y + TANK_HEIGHT/2, x2, y2);
    //血条
    g.setColor(Color.RED);
    g.drawRect(x, y - 10, TANK_WIDTH, 7);
    g.fillRect(x, y - 10, TANK_WIDTH * life / LIFE_MAX, 7);
    g.setColor(c);
    }

    public void move (List <Tank> tanks, List<Missile> missiles, List<Wall> walls, List<Blood> bloods) {
    int xOld = x, yOld = y;

    switch (dir) {
    case U: y = y - TANK_YSPEED;break;
    case UR: x = x + TANK_XSPEED; y = y - TANK_YSPEED;break;
    case R: x = x + TANK_XSPEED; break;
    case RD: x = x + TANK_XSPEED; y = y + TANK_YSPEED;break;
    case D:  y = y + TANK_YSPEED;break;
    case DL: x = x - TANK_XSPEED; y = y + TANK_YSPEED;break;
    case L: x = x - TANK_XSPEED; break;
    case LU: x = x - TANK_XSPEED; y = y - TANK_YSPEED;break;
    case STOP:break;
    }

    for (int i=0; i<bloods.size(); i ++) {
    if (new Rectangle(x, y, TANK_WIDTH, TANK_HEIGHT).intersects(TankWar.getRect(bloods.get(i)))) {
    life = life + HEALTH_ADD;
    if (life > LIFE_MAX) {
    life = LIFE_MAX;
    }
    bloods.remove(bloods.get(i));
    return ;
    }
    }

    for (int i=0; i<tanks.size(); i ++) {
    if (this.equals(TankWar.myTank)) {
    if (new Rectangle(x, y, TANK_WIDTH, TANK_HEIGHT).intersects(TankWar.getRect(tanks.get(i)))) {
    x = xOld;
    y = yOld;
    return ;

    } else {
    if (!this.equals(tanks.get(i)) && new Rectangle(x, y, TANK_WIDTH, TANK_HEIGHT).intersects(TankWar.getRect(tanks.get(i)))) {
    x = xOld;
    y = yOld;
    return ;

    }
    }
    if (x < 0 || y < 0 || x > (TankWar.GAME_WIDTH - TANK_WIDTH) || y > (TankWar.GAME_HEIGHT - TANK_HEIGHT)) {
    x = xOld;
    y = yOld;
    return ;
    }

    for (int i=0; i<walls.size(); i ++) {
    if (new Rectangle(x, y, TANK_WIDTH, TANK_HEIGHT).intersects(TankWar.getRect(walls.get(i)))) {
    x = xOld;
    y = yOld;
    return ;
    }
    }

    for (int i=0; i<missiles.size(); i ++) {
    if (new Rectangle(x, y, TANK_WIDTH, TANK_HEIGHT).intersects(TankWar.getRect(missiles.get(i)))) {
    this.beHit(missiles.get(i), tanks, missiles);
    return ;

    }
    }

    public void fire() {
    TankWar.missiles.add(new Missile(x + TANK_WIDTH/2 - Missile.MISSILE_WIDTH/2,y + TANK_HEIGHT/2 - Missile.MISSILE_HEIGHT/2, ptDir, team));
    }

    public void bigFire() {
    TankWar.missiles.add(new Missile(x + TANK_WIDTH/2 - Missile.MISSILE_WIDTH/2,y + TANK_HEIGHT/2 - Missile.MISSILE_HEIGHT/2, Direction.U, team));
    TankWar.missiles.add(new Missile(x + TANK_WIDTH/2 - Missile.MISSILE_WIDTH/2,y + TANK_HEIGHT/2 - Missile.MISSILE_HEIGHT/2, Direction.UR, team));
    TankWar.missiles.add(new Missile(x + TANK_WIDTH/2 - Missile.MISSILE_WIDTH/2,y + TANK_HEIGHT/2 - Missile.MISSILE_HEIGHT/2, Direction.R, team));
    TankWar.missiles.add(new Missile(x + TANK_WIDTH/2 - Missile.MISSILE_WIDTH/2,y + TANK_HEIGHT/2 - Missile.MISSILE_HEIGHT/2, Direction.RD, team));
    TankWar.missiles.add(new Missile(x + TANK_WIDTH/2 - Missile.MISSILE_WIDTH/2,y + TANK_HEIGHT/2 - Missile.MISSILE_HEIGHT/2, Direction.D, team));
    TankWar.missiles.add(new Missile(x + TANK_WIDTH/2 - Missile.MISSILE_WIDTH/2,y + TANK_HEIGHT/2 - Missile.MISSILE_HEIGHT/2, Direction.DL, team));
    TankWar.missiles.add(new Missile(x + TANK_WIDTH/2 - Missile.MISSILE_WIDTH/2,y + TANK_HEIGHT/2 - Missile.MISSILE_HEIGHT/2, Direction.L, team));
    TankWar.missiles.add(new Missile(x + TANK_WIDTH/2 - Missile.MISSILE_WIDTH/2,y + TANK_HEIGHT/2 - Missile.MISSILE_HEIGHT/2, Direction.LU, team));
    }

    public void beHit(Missile mis, List<Tank> tanks ,List<Missile> missiles) {
    if (mis.team == this.team) {
    return;
    }
    missiles.remove(mis);
    life = life - HARM;
    if (life <= 0) {
    if (isPlayer) {
    System.exit(0);
    } else {
    tanks.remove(this);
    TankWar.collisions.add(new Collision(x, y));
    }
    }
    }
    }
      

  2.   


    package TankWar2;import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Rectangle;public class Wall {
    public int x, y, width, height;

    public Wall(int x, int y, int width, int height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    } public void draw (Graphics g) {
    Color c = g.getColor();
    g.setColor(Color.BLACK);
    g.fillRect(x, y, width, height);
    g.setColor(c);
    }
    }
      

  3.   


    //   主操控程序 package TankWar2;
    import java.awt.Color;
    import java.awt.Frame;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.Rectangle;
    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 java.util.Random;
    public class TankWar extends Frame{
    public enum Direction {U,UR,R,RD,D,DL,L,LU,STOP};

    public static final int GAME_WIDTH = 800,GAME_HEIGHT = 600;
    public static final int FIRE_RATE = 8;
    public static final int MOVE_RATE = 8;
    public static final int GAME_SPEED = 1;
    public static final int BLOOD_RATE = 994;
    public static boolean pause = false;
    public static boolean uKey = false, rKey = false, dKey = false, lKey = false;
    public static Tank myTank = new Tank (700, 70, 0, true, Direction.STOP, Direction.D);
    public static List<Missile> missiles = new ArrayList<Missile> ();
    public static List<Tank> tanks = new ArrayList<Tank> ();
    public static List<Wall> walls = new ArrayList<Wall> ();
    public static List<Blood> bloods = new ArrayList<Blood> ();
    public static List<Collision> collisions = new ArrayList<Collision> ();
    public static Image image;
    public static Graphics g;
    public static Random random = new Random();

    public static void main (String [] args) {
    TankWar tw = new TankWar ();
    tw.setLocation(200, 100);
    tw.setSize(GAME_WIDTH, GAME_HEIGHT);
    tw.setTitle("坦克大战"); 
    tw.setResizable(false);
    tw.addWindowListener(new WindowAdapter() {public void windowClosing (WindowEvent e) {System.exit(0);}});
    tw.setVisible(true); tw.start();
    }

    public void start() {
    for (int i=0; i<=10; i++) {
    tanks.add(new Tank(30+i*35, 40, 0, false, Direction.D, Direction.D ));
    }
    for (int i=0; i<=10; i++) {
    tanks.add(new Tank(30+i*35, 500, 1, false, Direction.U, Direction.U ));
    }
      for (int i=0; i<=10; i++) {
      walls.add(new Wall(10 + i*88, 250, 35, 35));
      }
    g = this.getGraphics();
    paint (g);
    int x2, y2;
    boolean placeAble = true;

    this.addKeyListener (new KeyMoniter());
    while (true) {
    if (pause) continue;

    //是否产生血块
    if (random.nextInt(1000) >= BLOOD_RATE) {
    x2 = random.nextInt(GAME_WIDTH - Blood.BLOOD_WIDTH) + 1;
      y2 = random.nextInt(GAME_HEIGHT - Blood.BLOOD_HEIGHT) + 1;
      for (int i=0; i<walls.size(); i++) {
    if (new Rectangle(x2, y2, Blood.BLOOD_WIDTH, Blood.BLOOD_HEIGHT).intersects(getRect(walls.get(i)))) {
    placeAble = false;
    break;
    }
    placeAble = true;
      }
      if (placeAble) {
      for (int i=0; i<tanks.size(); i++) {
    if (new Rectangle(x2, y2, Blood.BLOOD_WIDTH, Blood.BLOOD_HEIGHT).intersects(getRect(tanks.get(i)))) {
    placeAble = false;
    break;
    }
    placeAble = true;
      }
      }
     
      if (placeAble) {
      for (int i=0; i<bloods.size(); i++) {
    if (new Rectangle(x2, y2, Blood.BLOOD_WIDTH, Blood.BLOOD_HEIGHT).intersects(getRect(bloods.get(i)))) {
    placeAble = false;
    break;
    }
    placeAble = true;
      }
     
      if (placeAble) {
      bloods.add(new Blood(x2, y2));
    }
    }
    }

    allMove();
    paint (g);

    try {
    Thread.sleep(GAME_SPEED);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }

    public void paint (Graphics g) {
    image = this.createImage(GAME_WIDTH, GAME_HEIGHT);
    Graphics h = image.getGraphics();
    h.setColor(Color.WHITE);
    h.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);

    myTank.draw(h);

    for (int i=0; i<walls.size(); i++ ) {
    walls.get(i).draw(h);
    }

    for (int i=0; i<tanks.size(); i++ ) {
    tanks.get(i).draw(h);
    }

    for (int i=0; i<missiles.size(); i++ ) {
    missiles.get(i).draw(h);
    }

    for (int i=0; i<bloods.size(); i++ ) {
    bloods.get(i).draw(h);
    }

    for (int i=0; i<collisions.size(); i++ ) {
    collisions.get(i).draw(h);
    }

    g.drawImage (image,0,0,null);
    }

    public void allMove () {
    for (int i=0; i<tanks.size(); i++ ) {
    if (random.nextInt(10) > MOVE_RATE) {
    switch (random.nextInt(8)) {
    case 0:tanks.get(i).ptDir = tanks.get(i).dir = Direction.U;break;
    case 1:tanks.get(i).ptDir = tanks.get(i).dir = Direction.UR;break;
    case 2:tanks.get(i).ptDir = tanks.get(i).dir = Direction.R;break;
    case 3:tanks.get(i).ptDir = tanks.get(i).dir = Direction.RD;break;
    case 4:tanks.get(i).ptDir = tanks.get(i).dir = Direction.D;break;
    case 5:tanks.get(i).ptDir = tanks.get(i).dir = Direction.DL;break;
    case 6:tanks.get(i).ptDir = tanks.get(i).dir = Direction.L;break;
    case 7:tanks.get(i).ptDir = tanks.get(i).dir = Direction.LU;break;
    default: break;
    }
    }
    tanks.get(i).move(tanks, missiles, walls, bloods);
    if (random.nextInt(10) > FIRE_RATE) {
    tanks.get(i).fire();
    }
    } for (int i=0; i<missiles.size(); i++ ) {
    missiles.get(i).move(tanks, missiles, walls);
    }
    }

    public static final Rectangle getRect(Missile mis) {
    return new Rectangle( mis.x, mis.y, Missile.MISSILE_WIDTH, Missile.MISSILE_HEIGHT);
    } public static final Rectangle getRect(int x, int y, int x2, int y2) {
    return new Rectangle( x, y, x2, y2);
    } public static final Rectangle getRect(Blood blood) {
    return new Rectangle( blood.x, blood.y, Blood.BLOOD_WIDTH, Blood.BLOOD_HEIGHT);
    } public static final Rectangle getRect(Tank tank) {
    return new Rectangle( tank.x, tank.y, Tank.TANK_WIDTH, Tank.TANK_HEIGHT);
    }

    public static final Rectangle getRect(Wall wall) {
    return new Rectangle( wall.x, wall.y, wall.width, wall.height);
    }

    public static class KeyMoniter extends KeyAdapter {

    public void dir() {
    if (uKey && !rKey && !dKey && !lKey) {
    myTank.dir = myTank.ptDir = Direction.U;
    } else  if (uKey && rKey && !dKey && !lKey) {
    myTank.dir = myTank.ptDir = Direction.UR;
    } else  if (!uKey && rKey && !dKey && !lKey) {
    myTank.dir = myTank.ptDir = Direction.R;
    } else  if (!uKey && rKey && dKey && !lKey) {
    myTank.dir = myTank.ptDir = Direction.RD;
    } else  if (!uKey && !rKey && dKey && !lKey) {
    myTank.dir = myTank.ptDir = Direction.D;
    } else  if (!uKey && !rKey && dKey && lKey) {
    myTank.dir = myTank.ptDir = Direction.DL;
    } else  if (!uKey && !rKey && !dKey && lKey) {
    myTank.dir = myTank.ptDir = Direction.L;
    } else  if (uKey && !rKey && !dKey && lKey) {
    myTank.dir = myTank.ptDir = Direction.LU;
    } else {
    myTank.dir = Direction.STOP;
    return;
    }
    myTank.move(tanks, missiles, walls, bloods);
    }

    public void keyPressed (KeyEvent e) {
    switch (e.getKeyCode()) {
    case KeyEvent.VK_UP: 
    if (pause) return;
    uKey = true;
    break;
    case KeyEvent.VK_RIGHT: 
    if (pause) return;
    rKey = true;
    break;
    case KeyEvent.VK_DOWN:
    if (pause) return;
    dKey = true;
    break;
    case KeyEvent.VK_LEFT:
    if (pause) return;
    lKey = true;
    break;
    case KeyEvent.VK_CONTROL: 
    if (pause) return;
    myTank.fire();
    break;
    case KeyEvent.VK_SPACE:
    if (pause) return;
    myTank.bigFire();
    break;
    case KeyEvent.VK_ENTER:
    if (pause) pause = false;
    else pause = true;
    break;
    default :break;
    }
    dir();
    }

    public void keyReleased (KeyEvent e) {
    switch (e.getKeyCode()) {
    case KeyEvent.VK_UP: 
    uKey = false;
    break;
    case KeyEvent.VK_RIGHT: 
    rKey = false;
    break;
    case KeyEvent.VK_DOWN:
    dKey = false;
    break;
    case KeyEvent.VK_LEFT:
    lKey = false;
    break;
    default :break;
    }
    dir();
    }
    }
    }
      

  4.   

    1.将主类中paint方法改名成update,同时去掉
    h.setColor(Color.WHITE);
    h.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);当然几个paint方法的调用也要去掉,只要在Thread.sleep后换成repaint,同时将sleep时间提高,自己调试而定2.有些重复代码可以优化一下,有些方法名称的提示性可以加强,按重构,过复杂的方法可以extract成某些逻辑集中的小方法,增加可阅读性