day04-应用线程03
JavaGUI-坦克大战04
7.线程的应用03
7.3坦克大战4.0版
7.3.4功能3:敌方坦克自由移动
功能3:让敌人的坦克也可以自由随机地上下左右移动
思路:
- 因为要求敌人的坦克自由移动,因此需要将敌人坦克当做线程使用,EnemyTank类实现Runnable接口
- 线程的run方法的具体操作为:根据当前的方向继续移动敌坦,然后改变敌坦移动方向,再继续移动,如此不断循环。break的条件是当前的敌人坦克被击中,即enemy.isLive == false。
- 在MyPanel类中,每创建一个敌人坦克对象就启动一个线程。
EnemyTank:
package li.TankGame.version04; import java.util.Vector; public class EnemyTank extends Tank implements Runnable { //在敌人坦克类使用Vector保存多个Shot Vector<Shot> shots = new Vector<>(); boolean isLive = true; public EnemyTank(int x, int y) { super(x, y); } @Override public void run() { while (true) { //根据坦克的方法来继续移动 switch (getDirect()) { case 0://上 //让坦克保持一个方向走30步 for (int i = 0; i < 100; i++) { moveUp(); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } break; case 1://右 //让坦克保持一个方向走30步 for (int i = 0; i < 100; i++) { moveRight();//走一步 try { Thread.sleep(50);//每走一步就休眠50毫秒 } catch (InterruptedException e) { e.printStackTrace(); } } break; case 2://下 for (int i = 0; i < 100; i++) { moveDown(); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } break; case 3://左 for (int i = 0; i < 100; i++) { moveLeft(); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } break; } //随机地改变坦克的方向 0-3 setDirect((int) (Math.random() * 4));//[0,4)的取整 //如果被击中了,就退出线程 if (!isLive) { break;//退出线程 } } } }
MyPanel:line 46-47


7.3.5功能4: 控制坦克移动范围
如图,坦克的绘图以图案的左上方坐标为参考。
在向上时,坦克的纵坐标限制为y>0,向下时,y+60<面板高度;向左时,x>0,向右时,x+60<面板宽度
EnemyTank:控制敌人的坦克不出界
package li.TankGame.version04; import java.util.Vector; public class EnemyTank extends Tank implements Runnable { //在敌人坦克类使用Vector保存多个Shot Vector<Shot> shots = new Vector<>(); boolean isLive = true; public EnemyTank(int x, int y) { super(x, y); } @Override public void run() { while (true) { //根据坦克的方法来继续移动 switch (getDirect()) { case 0://上 //让坦克保持一个方向走30步 for (int i = 0; i < 100; i++) { if (getY() > 0) { moveUp(); } try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } break; case 1://右 //让坦克保持一个方向走30步 for (int i = 0; i < 100; i++) { if (getX() + 60 < 700) {//700为面板宽度 moveRight();//走一步 } try { Thread.sleep(50);//每走一步就休眠50毫秒 } catch (InterruptedException e) { e.printStackTrace(); } } break; case 2://下 for (int i = 0; i < 100; i++) { if (getY() + 60 < 550) {//550为面板宽度 moveDown(); } try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } break; case 3://左 for (int i = 0; i < 100; i++) { if (getX() > 0) { moveLeft(); } try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } break; } //随机地改变坦克的方向 0-3 setDirect((int) (Math.random() * 4));//[0,4)的取整 //如果被击中了,就退出线程 if (!isLive) { break;//退出线程 } } } }
修改MyPanel类中的keyPressed方法,使我方坦克也不能走出边界:
//控制方向--处理 WSAD 键按下的情况 @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_W) {//按下W键-向上 //改变坦克的方向 hero.setDirect(0); //修改坦克的坐标 if (hero.getY() > 0) {//向上 hero.moveUp(); } } else if (e.getKeyCode() == KeyEvent.VK_D) {//按下D键-向右 hero.setDirect(1); if (hero.getX() + 60 < 750) {//向右 hero.moveRight(); } } else if (e.getKeyCode() == KeyEvent.VK_S) {//按下S键-向下 hero.setDirect(2); if (hero.getY() + 60 < 550) {//向下 hero.moveDown(); } } else if (e.getKeyCode() == KeyEvent.VK_A) {//按下A键-向左 hero.setDirect(3); if (hero.getX() > 0) {//向左 hero.moveLeft(); } } //如果用户按下j键,hero就发射子弹 if (e.getKeyCode() == KeyEvent.VK_J) { hero.shotEnemyTank(); } //让面板重绘 this.repaint(); }

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!