韩顺平老师java视频中的坦克大战的问题

看了韩顺平老师JAVA循序渐进视频,自己也做了tank大战,遇到了一些问题,作为java初学者的小弟在此希望请问代码中的问题所在。

for(int i=0;i<v.size();i++)//画敌人
{
if(v.get(i).islive)
drawtank(v.get(i),g);
for(int j=0;j<v.get(i).zhav.size();j++)//画敌人子弹
{
if(v.get(i).zhav.get(j).islive)
drawzha(v.get(i).zhav.get(j),g);
else
{
v.get(i).zhav.remove(j);
}
}
}

for(int i=0;i<=hero.zhav.size();i++)//画我方子弹
{
    if(hero.zhav.get(i).islive)
    {
        System.out.println("画子弹");
        drawzha(hero.zhav.get(i),g);
    }
    else
    {
        hero.zhav.remove(i);
    }
}
    ###############;i<=hero.zhav.size();i+多了个等号---------知道了吧。

----------------------biu~biu~biu~~~在下问答机器人小D,这是我依靠自己的聪明才智给出的答案,如果不正确,你来咬我啊!

public void paint(Graphics g)
{

    super.paint(g);
    for(int i=0;i<wallnum;i++)//画墙
    {

        drawwall(walls.get(i).x,walls.get(i).y,g);
    }
    for(int i=0;i<v.size();i++)//画敌人
    { 
        if(v.get(i).islive)
            drawtank(v.get(i),g);
        for(int j=0;j<v.get(i).zhav.size();j++)//画敌人子弹
            {
                if(v.get(i).zhav.get(j).islive)
                drawzha(v.get(i).zhav.get(j),g);
                else
                {
                    v.get(i).zhav.remove(j);
                }
            }
    }

    for(int i=0;i<=hero.zhav.size();i++)//画我方子弹
    {
        if(hero.zhav.get(i).islive)
        {
            System.out.println("画子弹");
            drawzha(hero.zhav.get(i),g);
        }
        else
        {
            hero.zhav.remove(i);
        }
    }
    drawtank(hero,g);//画我
    drawbase(base.x,base.y,g);//画基地
}

运行后出错的提示是Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 0
at java.util.Vector.get(Unknown Source)
at 练习.MyPanel.paint(Ta.java:85)
这是说数组指针越界了? 85行的话是话我方子弹的那个循环,但是为什么同样是画子弹,画敌人子弹的时候数组指针就不会越界,小弟诚心请教问题所在。

前面好像说不太清除,我还是把我所有的代码贴出来吧

package 练习;

import java.util.Vector;

class Zha implements Runnable//子弹对象一经创建就是线程,能自动变化坐标
{
int speed=10;
int x,y;
int direction;
boolean islive;
public Zha(int x,int y,int direction)
{
this.x=x;
this.y=y;
this.direction=direction;
this.islive=true;
System.out.println(this.islive);

}
public void run()
{

    while(x>0&&y>0&&x<800&&y<800)
    {
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }

        switch (direction) 
        {
        case 0:
            y-=speed;
            break;
        case 1:
            y+=speed;
            break;
        case 2:
            x+=speed;
            break;
        case 3:
            x-=speed;
            break;
        default:
            break;
        }

    }
    islive=false;

}

}
class Tank
{
int x,y;//坐标
int type;//坦克种类,分敌方和我方
int speed=3;//速度
int direction;
boolean islive;//记录是否活着
int zhanum;//最大弹药数
Vector zhav=new Vector();//记录子弹集合
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 int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getDirection() {
return direction;
}
public void setDirection(int direction) {
this.direction = direction;
}

public Tank(int x,int y,int direction)
{
    this.x=x;
    this.y=y;
    this.direction=direction;
    this.islive=true;
}
public void shoot()//射击函数生成子弹对象
{
        if(zhav.size()<zhanum)
        {
            System.out.println("子弹发射");
            Zha zha=new Zha(x+20, y+15, direction);
            zhav.add(zha);
            System.out.println(zhav.size());
            System.out.println("目前子弹数量"+zhav.size());
            Thread thread=new Thread(zha);
            thread.start();     
        }
}
public void  moveup()
{
    if((y-speed)>100&&(y-speed)<700)
    y-=speed;

}
public void  movedown()
{
    if((y+speed)>100&&(y+speed)<700)
    y+=speed;

}
public void  moveleft()
{
    if((x-speed)>100&&(x-speed)<700)
    x-=speed;

}
public void  moveright()
{
    if((x+speed)>100&&(x+speed)<700)
    x+=speed;

}

}
class Hero extends Tank
{

public Hero(int x,int y,int direction)
{
    super(x,y,direction);
    type=1;//1表示我方
    zhanum=5;//规定我方弹药上限5
}

}
class Anemy extends Tank implements Runnable//敌方坦克对象一经生成,就是作为独立的线程变化坐标
{

public Anemy(int x,int y,int direction)
{
    super(x,y,direction);
    type=0;//0表示敌方
    zhanum=2;//规定敌方弹药上限2
}

@Override
public void run() {
    // TODO 自动生成的方法存根
    int x=0;
    int num=0;
    while(true)
    {
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
        if(num%8==0)
        x=(int)(Math.random()*5);
        if(x==0)
        {
            this.direction=0;
            this.moveup();
            num++;
        }
        else if(x==1)
        {   
            this.direction=1;
            this.movedown();
            num++;
        }
        else if (x==2)
            {
            this.direction=2;
            this.moveright();
            num++;
            }
        else if (x==3)
            {
            this.direction=3;
            this.moveleft();
            num++;
            }
        else if (x==4)
            {
                this.shoot();

            }
    }

}
}
class Wall
{
int x,y;
public Wall(int x,int y)
{

    this.x=x;
    this.y=y;
}

}
class Base
{
int x,y;
public Base(int x,int y)
{

    this.x=x;
    this.y=y;
}

}

package 练习;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;

import javax.swing.*;

public class Ta extends JFrame{

public static void main(String[] args) {
    // TODO 自动生成的方法存根
    Ta ta=new Ta();

}
public Ta()
{
    MyPanel mp=new MyPanel();
    Thread thread=new Thread(mp);
    thread.start();
    this.addKeyListener(mp);
    this.add(mp);
    this.setVisible(true);
    this.setSize(800,800);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

}
class MyPanel extends JPanel implements KeyListener,Runnable
{
int anemynum=2;
int wallnum=20;
Base base=null;
Hero hero=null;
JTextField jTextField=null;
Vector v=new Vector();
Vector walls=new Vector();
public MyPanel()
{
base=new Base(350,680);//初始化基地

    for(int i=0;i<wallnum;i++)//初始化围墙
    {
        Wall wall=new Wall((i+3)*30, 350);
        walls.add(wall);
    }
    for(int i=0;i<anemynum;i++)//初始化敌人
    {
        Anemy a=new Anemy((i+3)*100, 150, 1);
        Thread th1=new Thread(a);   
        th1.start();

        System.out.println(" "+a.direction);
        v.add(a);
    }
    hero =new Hero(300, 690, 0);//初始化我

}
public void paint(Graphics g)
{

    super.paint(g);
    for(int i=0;i<wallnum;i++)//画墙
    {

        drawwall(walls.get(i).x,walls.get(i).y,g);
    }
    for(int i=0;i<v.size();i++)//画敌人
    { 
        if(v.get(i).islive)
            drawtank(v.get(i),g);
        for(int j=0;j<v.get(i).zhav.size();j++)//画敌人子弹
            {
                if(v.get(i).zhav.get(j).islive)
                drawzha(v.get(i).zhav.get(j),g);
                else
                {
                    v.get(i).zhav.remove(j);
                }
            }
    }

    for(int i=0;i<=hero.zhav.size();i++)//画我方子弹
    {
        if(hero.zhav.get(i).islive)
        {
            System.out.println("画子弹");
            drawzha(hero.zhav.get(i),g);
        }
        else
        {
            hero.zhav.remove(i);
        }
    }
    drawtank(hero,g);//画我
    drawbase(base.x,base.y,g);//画基地
}
public boolean disdray(Zha z,Tank t)
{
        int zhax,zhay,tankx,tanky;
        zhax=z.x;
        zhay=z.y;
        tankx=t.getX();
        tanky=t.getY();

            if((zhax<tankx+40)&&(zhax>tankx)&&(zhay<tanky+40)&&(zhay>tanky)&&z.islive)
            {
                  z.islive=false;
                  t.islive=false;
                  System.out.println("击毁敌机");
                  anemynum--;
                  return true;
            }
            else
            {
                return false;
            }



}
public void drawbase(int x,int y,Graphics g)//画基地
{
    g.fill3DRect(x, y, 100, 50, false);
    g.setColor(Color.black);
    g.drawLine(x, y, x+100, y+50);
    g.drawLine(x+100, y, x, y+50);


}
public void drawwall(int x,int y,Graphics g)//画墙
{

    g.fill3DRect(x, y, 30, 30, false);
}
public  void drawzha(Zha z,Graphics g)//画子弹
{
    if(z.islive)
    {
        g.setColor(Color.black);
    g.fill3DRect(z.x, z.y, 5, 5, false);
    }
}
public void  drawtank(Tank t,Graphics g)//画坦克
{
    switch (t.type) 
    {
    case 0:
        g.setColor(Color.yellow);
        break;
    case 1:
        g.setColor(Color.red);
        break;
    default:
        break;
    }
    switch (t.direction) {
    case 0://朝上
        g.fill3DRect(t.getX(), t.getY(), 10,30, false);
        g.fill3DRect(t.getX()+30, t.getY(), 10, 30, false);
        g.fill3DRect(t.getX()+10, t.getY()+5, 20, 20, false);
        g.drawLine(t.getX()+20, t.getY()+15,t.getX()+20, t.getY()-25);


        break;
    case 1://朝下
        g.fill3DRect(t.getX(), t.getY(), 10,30, false);
        g.fill3DRect(t.getX()+30, t.getY(), 10,30, false);
        g.fill3DRect(t.getX()+10, t.getY()+5, 20, 20, false);
        g.drawLine(t.getX()+20, t.getY()+15,t.getX()+20, t.getY()+45);
        break;
    case 2://朝右
        g.fill3DRect(t.getX(), t.getY(), 30,10, false);
        g.fill3DRect(t.getX(), t.getY()+30, 30,10, false);
        g.fill3DRect(t.getX()+5, t.getY()+10, 20, 20, false);
        g.drawLine(t.getX()+15, t.getY()+20,t.getX()+45, t.getY()+20);
        break;
    case 3://朝左
        g.fill3DRect(t.getX(), t.getY(), 30,10, false);
        g.fill3DRect(t.getX(), t.getY()+30, 30,10, false);
        g.fill3DRect(t.getX()+5, t.getY()+10, 20, 20, false);
        g.drawLine(t.getX()+15, t.getY()+20,t.getX()-15, t.getY()+20);
        break;
    default:
        break;
    }

}
@Override//键盘监听事件处理
public void keyPressed(KeyEvent e) {
    // TODO 自动生成的方法存根
    if(e.getKeyCode()==KeyEvent.VK_DOWN)
    {   
        System.out.println("下");
        hero.movedown();
        hero.direction=1;
        repaint();
    }
    else if(e.getKeyCode()==KeyEvent.VK_UP)
    {   
        System.out.println("上");
        hero.moveup();
        hero.direction=0;
        repaint();
    }
    else if(e.getKeyCode()==KeyEvent.VK_LEFT)
    {   
        System.out.println("左");
        hero.moveleft();
        hero.direction=3;
        repaint();
    }
    else if(e.getKeyCode()==KeyEvent.VK_RIGHT)
    {   
        System.out.println("右");
        hero.moveright();
        hero.direction=2;
        repaint();
    }
     if(e.getKeyCode()==KeyEvent.VK_X)
    {   
        //System.out.println("shoot");
        hero.shoot();
    }

}
@Override
public void keyReleased(KeyEvent e) {
    // TODO 自动生成的方法存根

}
@Override
public void keyTyped(KeyEvent e) {
    // TODO 自动生成的方法存根

}
@Override//做线程。每50msrepaint一次
public void run() {
    // TODO 自动生成的方法存根

    while(true)
    {
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }

        if(anemynum!=0)
        repaint();
        else
            {
            jTextField=new JTextField("恭喜");
            this.add(jTextField);
            repaint();
            }



    }

}

}