跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

智能无人机平台 V4 版本功能升级与实现

智能无人机平台 V4 版本的更新内容。主要改进包括为入侵者添加可视化血条,新增任务系统允许玩家指挥无人机前往指定位置,以及重构无人机移动方法使其基于状态码调用不同逻辑。文章提供了完整的 Java 代码实现,涵盖无人机、入侵者、任务管理及线程控制等核心模块。

无尘发布于 2026/4/6更新于 2026/9/1080 浏览

V3 版本回顾

在 V3 版本中,实现了无人机的自动索敌追踪、并在扫描到入侵者后将信息广播给其他无人机,其他巡逻状态的无人机可以协同该无人机进行围剿行为。

V4 版本提升

  • 为入侵者加入了可视化的血条,便于玩家更直观地看到入侵者血量减少的过程
  • 加入了任务系统,现在玩家可以通过点击守卫区中的位置来指挥最近的巡逻状态无人机前往该位置
  • 将无人机的 move 方法内部的庞大代码分成几个小的方法,并通过不同的限定条件来调用不同的方法。同时为了便于后期功能的添加,现在将无人机移动方案的限定条件改为由状态码的不同来决定无人机的移动方式

V4 版本的具体实现

可视化血条的添加

思路:只需要在入侵者的正上方画出一个矩形边框和一个实心矩形即可,通过改变实心矩形的宽度来达到显示血量的效果

具体实现

Color color3 = new Color(0, 0, 0);
g.setColor(color3);
g.drawRect(x, y - 5, size, 6);
Color color4 = new Color(124, 244, 21);
g.setColor(color4);
g.fillRect(x + 1, y - 4, (int)(blood / 200.0 * (size - 1)), 5);

任务系统的添加

思路及代码:

在上个版本中,无人机的 move 方法过于庞大且判定条件没有统一化,导致后续再添加其他功能时非常麻烦。在 V4 版本中改进了 move 方法,让 move 方法通过状态码来调用对应的移动方法来完成操作。代码实现如下

public void move() {
    if (state == 2) {
        moveToTask();
    } else if (state == 1) {
        // 先判断目标是否在守卫区外,若在守卫区外则不在追逐
        if (target != null) {
             (target.x + target.size /  <  || target.x + target.size /  >  || target.y + target.size /  <  || target.y + target.size /  > ) {
                state = ;
                target = ;
            }  {
                moveToHunt();
            }
        }  {
            state = ;
        }
    }   (state == ) {
        moveToFind();
    }
}

   {
       targetTask.x + targetTask.size /  - (x + scanSize / );
       targetTask.y + targetTask.size /  - (y + scanSize / );
       Math.sqrt(dx * dx + dy * dy);
     (distance > ) {
        huntingSpeedx = ()(dx / distance * huntingSpeed);
        huntingSpeedy = ()(dy / distance * huntingSpeed);
    }  {
        huntingSpeedx = ;
        huntingSpeedy = ;
        System.out.println();
        state = ; 
        targetTask.state = ;
        targetTask = ; 
    }
    
    limit();
}

   {
       target.x + target.size /  - (x + scanSize / );
       target.y + target.size /  - (y + scanSize / );
       Math.sqrt(dx * dx + dy * dy);
     (distance > ) {
        huntingSpeedx = ()(dx / distance * huntingSpeed);
        huntingSpeedy = ()(dy / distance * huntingSpeed);
    }  {
        huntingSpeedx = ;
        huntingSpeedy = ;
    }
    
    limit();
}

   {
    x += speedx;
    y += speedy;
     (x <  || x > ) {
        speedx = -speedx;
    }
     (y <  || y > ) {
        speedy = -speedy;
    }
}

   {
       x + huntingSpeedx;
       y + huntingSpeedy;
    x = Math.max(, Math.min( - scanSize, newX));
    y = Math.max(, Math.min( - scanSize, newY));
}
if
2
200
2
900
2
100
2
600
0
null
else
else
0
else
if
0
public
void
moveToTask
()
int
dx
=
2
2
int
dy
=
2
2
double
distance
=
if
20
int
int
else
0
0
"完成任务"
0
// 完成任务
2
null
// 任务完成后清除任务目标
// 硬限位,防止出界
public
void
moveToHunt
()
int
dx
=
2
2
int
dy
=
2
2
double
distance
=
if
20
int
int
else
0
0
// 硬限位,防止出界
public
void
moveToFind
()
if
200
900
if
100
600
public
void
limit
()
int
newX
=
int
newY
=
200
1000
100
700

在 Drone 类中构建 moveToTask 方法,让最近的无人机在接到任务后计算速度并前往,逻辑与追踪入侵者类似,并在无人机中心与任务点距离小于 20 时,将状态设置为任务完成,并清空任务目标。

无人机 move 方法的优化

在 DroneThread 线程中画出任务点,若任务完成,则移除任务对象且不进行绘制。具体代码实现如下

if (tasks != null) {
    for (int i = 0; i < tasks.size(); i++) {
        Task task = tasks.get(i);
        if (task.state == 2) {
            tasks.remove(i);
        } else {
            task.draw(bg);
        }
    }
}

创建任务线程类 TaskThread,在类中重写 run 方法。在 run 方法中遍历无人机与任务数组,将未被分配的任务分配给距离最近且处于巡逻状态的无人机,任务被分配后将任务的状态设置为已被领取,若此时没有空闲的无人机,则输出提示。

package com.drone.v4;
import java.util.ArrayList;

public class TaskThread extends Thread {
    ArrayList<Task> tasks;
    ArrayList<Drone> drones;

    @Override
    public void run() {
        for (;;) {
            if (tasks != null) {
                if (drones != null) {
                    for (int i = tasks.size() - 1; i >= 0; i--) {
                        Task task = tasks.get(i);
                        if (task.state != 1) {
                            int nearestIndex = -1;
                            double minDis = 1000.0;
                            for (int j = drones.size() - 1; j >= 0; j--) {
                                Drone drone = drones.get(j);
                                // 找到没有领取任务的无人机(只有巡逻状态的无人机可以接任务)
                                if (drone.state == 0) {
                                    // 计算距离并找出最近的
                                    double currentDis = calculateDis(task, drone);
                                    if (currentDis <= minDis) {
                                        minDis = currentDis;
                                        nearestIndex = j;
                                    }
                                }
                            }
                            if (nearestIndex != -1) {
                                drones.get(nearestIndex).state = 2; // 无人机状态设为正在执行任务
                                drones.get(nearestIndex).targetTask = task;
                                System.out.println("任务被领取");
                                task.state = 1; // 任务状态设为已被领取
                            } else {
                                System.out.println("没有可指挥的无人机");
                                task.state = 0;
                            }
                        }
                    }
                }
            }
            try {
                Thread.sleep(16);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    double calculateDis(Task task, Drone drone) {
        double dis = Math.sqrt((task.x - drone.x) * (task.x - drone.x) + (task.y - drone.y) * (task.y - drone.y) * 1.0);
        return dis;
    }
}

创建鼠标监听器,并在 DroneListener 类中加入鼠标监听器的相关内容。重写 mousePressed 方法,将鼠标点击的坐标作为参数构建 task 对象,使用共享内存的思路,并存入 tasks 动态数组,便于其他无人机领取任务。

public void mousePressed(MouseEvent e) {
    int x = e.getX();
    int y = e.getY();
    Task task = new Task(0, x, y);
    // 对任务点进行判断,不得超出守卫区的范围
    if (!(task.x < 200 + task.size / 2 + 50 || task.x > 1000 - task.size / 2 - 50 || task.y < 100 + task.size + 50 || task.y > 700 - task.size - 50)) {
        tasks.add(task);
    }
}

创建 Task 类,将玩家发布的任务封装起来,类中包括该任务点的坐标、状态属性以及可视化的绘制方法。

package com.drone.v4;
import java.awt.*;

public class Task {
    int x;
    int y;
    int size = 10;
    int state; // 0 未被领取的任务;1 被领取的任务;2 已完成的任务

    public Task(int state, int x, int y) {
        this.state = state;
        this.x = x;
        this.y = y;
    }

    public void draw(Graphics g) {
        g.setColor(Color.yellow);
        g.fillRect(x - size / 2, y - size / 2, size, size);
    }
}

V4 版本完整代码如下

package com.drone.v4;
import java.awt.*;
import java.awt.image.BufferedImage;

public class Drone {
    int x;
    int y;
    int stateSize = 16;
    int scanSize = 100;
    int size = 30;
    int state = 0; // 0 巡逻中;1 追踪中;2 执行任务中
    int speedx;
    int speedy;
    int huntingSpeedx;
    int huntingSpeedy;
    int rSquare = scanSize * scanSize / 4;
    int huntingSpeed = 4; // 设置追逐速度
    Intruder target = null;
    Task targetTask = null;

    public Drone(int x, int y, int speedx, int speedy) {
        this.x = x;
        this.y = y;
        this.speedx = speedx;
        this.speedy = speedy;
    }

    public void drawDrone(Graphics g) {
        Color color1 = new Color(52, 146, 241, 75);
        g.setColor(color1);
        g.fillOval(x, y, scanSize, scanSize);
        Color color2 = new Color(111, 200, 34);
        g.setColor(color2);
        g.fillOval(x + 35, y + 35, size, size);
        Color color3 = new Color(243, 82, 82);
        if (state == 0) {
            g.setColor(color3);
            g.fillOval(x + 42, y + 42, stateSize, stateSize);
        } else if (state == 1 || state == 2) {
            Color color4 = new Color(5, 25, 246);
            g.setColor(color4);
            g.fillOval(x + 42, y + 42, stateSize, stateSize);
        }
    }

    public void move() {
        if (state == 2) {
            moveToTask();
        } else if (state == 1) {
            // 先判断目标是否在守卫区外,若在守卫区外则不在追逐
            if (target != null) {
                if (target.x + target.size / 2 < 200 || target.x + target.size / 2 > 900 || target.y + target.size / 2 < 100 || target.y + target.size / 2 > 600) {
                    state = 0;
                    target = null;
                } else {
                    moveToHunt();
                }
            } else {
                state = 0;
            }
        } else if (state == 0) {
            moveToFind();
        }
    }

    public ScanResult scan(int x, int y, int size, BufferedImage img) {
        int distanceSquare;
        for (int i = x; i < x + size; i++) {
            for (int j = y; j < y + size; j++) {
                int roundX = x + scanSize / 2;
                int roundY = y + scanSize / 2;
                distanceSquare = (roundX - i) * (roundX - i) + (roundY - j) * (roundY - j);
                if (distanceSquare < rSquare) {
                    try {
                        int colorNum = img.getRGB(i, j);
                        Color color = new Color(colorNum);
                        Color targetColor1 = new Color(213, 15, 15);
                        Color targetColor2 = new Color(0, 0, 0);
                        if (isIntruderColor(color, targetColor1, 25) || isIntruderColor(color, targetColor2, 30)) {
                            ScanResult sr = new ScanResult(i, j);
                            return sr;
                        }
                    } catch (Exception e) {
                        continue;
                    }
                }
            }
        }
        return null;
    }

    // 颜色判断方法
    public boolean isIntruderColor(Color c1, Color c2, int tolerance) {
        return Math.abs(c1.getRed() - c2.getRed()) <= tolerance && Math.abs(c1.getGreen() - c2.getGreen()) <= tolerance && Math.abs(c1.getBlue() - c2.getBlue()) <= tolerance;
    }

    public void moveToTask() {
        int dx = targetTask.x + targetTask.size / 2 - (x + scanSize / 2);
        int dy = targetTask.y + targetTask.size / 2 - (y + scanSize / 2);
        double distance = Math.sqrt(dx * dx + dy * dy);
        if (distance > 20) {
            huntingSpeedx = (int)(dx / distance * huntingSpeed);
            huntingSpeedy = (int)(dy / distance * huntingSpeed);
        } else {
            huntingSpeedx = 0;
            huntingSpeedy = 0;
            System.out.println("完成任务");
            state = 0; // 完成任务
            targetTask.state = 2;
            targetTask = null; // 任务完成后清除任务目标
        }
        // 硬限位,防止出界
        limit();
    }

    public void moveToHunt() {
        int dx = target.x + target.size / 2 - (x + scanSize / 2);
        int dy = target.y + target.size / 2 - (y + scanSize / 2);
        double distance = Math.sqrt(dx * dx + dy * dy);
        if (distance > 20) {
            huntingSpeedx = (int)(dx / distance * huntingSpeed);
            huntingSpeedy = (int)(dy / distance * huntingSpeed);
        } else {
            huntingSpeedx = 0;
            huntingSpeedy = 0;
        }
        // 硬限位,防止出界
        limit();
    }

    public void moveToFind() {
        x += speedx;
        y += speedy;
        if (x < 200 || x > 900) {
            speedx = -speedx;
        }
        if (y < 100 || y > 600) {
            speedy = -speedy;
        }
    }

    public void limit() {
        int newX = x + huntingSpeedx;
        int newY = y + huntingSpeedy;
        x = Math.max(200, Math.min(1000 - scanSize, newX));
        y = Math.max(100, Math.min(700 - scanSize, newY));
    }
}
package com.drone.v4;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;

public class DroneListener implements ActionListener, MouseListener {
    Random rand = new Random();
    ArrayList<Drone> drones;
    ArrayList<Intruder> intruders;
    ArrayList<Task> tasks;

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("生产无人机")) {
            int x = rand.nextInt(700) + 200;
            int y = rand.nextInt(500) + 100;
            int speedx = rand.nextInt(5) - 2;
            while (speedx == 0) {
                speedx = rand.nextInt(5) - 2;
            }
            int speedy = rand.nextInt(5) - 2;
            while (speedy == 0) {
                speedy = rand.nextInt(5) - 2;
            }
            Drone drone = new Drone(x, y, speedx, speedy);
            drones.add(drone);
        } else if (e.getActionCommand().equals("生产入侵者")) {
            int x = rand.nextInt(1160);
            int y = rand.nextInt(760);
            while (true) {
                if (y < 60 || y > 700 || x < 160 || x > 1000) {
                    break;
                }
                x = rand.nextInt(1160);
                y = rand.nextInt(760);
            }
            int speedx = rand.nextInt(5) - 2;
            while (speedx == 0) {
                speedx = rand.nextInt(5) - 2;
            }
            int speedy = rand.nextInt(5) - 2;
            while (speedy == 0) {
                speedy = rand.nextInt(5) - 2;
            }
            Intruder intruder = new Intruder(x, y, speedx, speedy);
            intruders.add(intruder);
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {}

    @Override
    public void mousePressed(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        Task task = new Task(0, x, y);
        // 对任务点进行判断
        if (!(task.x < 200 + task.size / 2 + 50 || task.x > 1000 - task.size / 2 - 50 || task.y < 100 + task.size + 50 || task.y > 700 - task.size - 50)) {
            tasks.add(task);
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {}

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e) {}
}
package com.drone.v4;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

public class DroneThread extends Thread {
    Graphics g;
    ArrayList<Drone> drones;
    ArrayList<Intruder> intruders;
    ArrayList<Intruder> foundedIntruders = new ArrayList<>(); // 将所有被扫描到的入侵者存入这里
    ArrayList<Task> tasks;

    public DroneThread(Graphics g) {
        this.g = g;
    }

    @Override
    public void run() {
        for (;;) {
            BufferedImage image = new BufferedImage(1200, 800, 2);
            Graphics bg = image.getGraphics();
            bg.setColor(Color.white);
            bg.fillRect(0, 0, 1200, 800);
            bg.setColor(Color.red);
            bg.drawRect(200, 100, 800, 600);

            if (drones != null) {
                for (int i = 0; i < drones.size(); i++) {
                    Drone drone = drones.get(i);
                    drone.drawDrone(bg);
                    drone.move();
                }
            }

            if (intruders != null) {
                for (int i = 0; i < intruders.size(); i++) {
                    Intruder intruder = intruders.get(i);
                    intruder.drawIntruder(bg);
                    intruder.move();
                }
            }

            // 在这里用 bg 画笔画出任务点
            if (tasks != null) {
                for (int i = 0; i < tasks.size(); i++) {
                    Task task = tasks.get(i);
                    if (task.state == 2) {
                        tasks.remove(i);
                    } else {
                        task.draw(bg);
                    }
                }
            }

            if (drones.size() > 0) {
                for (int k = 0; k < drones.size(); k++) {
                    Drone drone = drones.get(k);
                    ScanResult sr = drone.scan(drone.x, drone.y, drone.scanSize, image);
                    if (sr != null) {
                        // 如果扫到目标
                        if (drone.state == 2) {
                            continue; // 正在执行任务中就不处理入侵者
                        }
                        Intruder intruder = getTargetIntruder(sr.targetX, sr.targetY);
                        // 通过坐标把这个目标找出来
                        if (intruder != null) {
                            // 找到目标后
                            drone.target = intruder; // 把自己的目标设置为这个
                            drone.state = 1;
                            foundedIntruders.add(intruder); // 把这个目标传入动态数组
                        }
                    } else {
                        // 如果没扫描到目标
                        if (drone.state == 0 && drone.target == null) {
                            if (foundedIntruders != null) {
                                // 看看动态数组里面有没有别人发现的目标
                                for (int i = foundedIntruders.size() - 1; i >= 0; i--) {
                                    Intruder intruder = foundedIntruders.get(i);
                                    if (intruder != null) {
                                        if (intruder.blood <= 0 || !isInRange(intruder)) {
                                            // 先判断这个目标还是否存在或在范围内
                                            foundedIntruders.remove(i); // 删掉死亡的或者逃跑的
                                        } else {
                                            drone.target = intruder; // 把自己的目标设置成这个目标
                                            drone.state = 1;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (intruders.size() > 0) {
                // 如果该入侵者被某个无人机列为目标,就进行扣血
                for (int k = 0; k < intruders.size(); k++) {
                    Intruder intruder = intruders.get(k);
                    for (int i = 0; i < drones.size(); i++) {
                        if (intruder == drones.get(i).target) {
                            intruder.underAttack();
                            System.out.println("第" + k + "个入侵者被扫到,血量剩余:" + intruder.blood);
                            if (intruder.blood <= 0 || !isInRange(intruder)) {
                                // 消灭入侵者
                                intruders.remove(k);
                                for (Drone drone : drones) {
                                    if (drone.target == intruder) {
                                        drone.target = null;
                                        if (drone.state == 1) {
                                            drone.state = 0;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            g.drawImage(image, 0, 0, null);
            try {
                Thread.sleep(16);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public Intruder getTargetIntruder(int scannedI, int scannedJ) {
        for (int k = 0; k < intruders.size(); k++) {
            Intruder intruder = intruders.get(k);
            int distanceSquare;
            for (int i = intruder.x; i < intruder.x + intruder.size; i++) {
                for (int j = intruder.y; j < intruder.y + intruder.size; j++) {
                    int roundX = intruder.x + intruder.size / 2;
                    int roundY = intruder.y + intruder.size / 2;
                    distanceSquare = (roundX - i) * (roundX - i) + (roundY - j) * (roundY - j);
                    if (distanceSquare < intruder.rSquare) {
                        if (i == scannedI && j == scannedJ) {
                            return intruder;
                        }
                    }
                }
            }
        }
        return null;
    }

    // 判断入侵者是否在守卫区内
    public boolean isInRange(Intruder intruder) {
        if (intruder.x < 200 + intruder.size || intruder.x > 1000 - intruder.size || intruder.y < 100 + intruder.size || intruder.y > 700 - intruder.size) {
            return false;
        } else {
            return true;
        }
    }
}
package com.drone.v4;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;

public class DroneUI extends JFrame {
    ArrayList<Drone> drones = new ArrayList<>();
    ArrayList<Intruder> intruders = new ArrayList<>();
    ArrayList<Task> tasks = new ArrayList<>();

    public DroneUI() {
        setTitle("智能无人机平台 4.0");
        setSize(1200, 900);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        JButton button1 = new JButton("生产无人机");
        JButton button2 = new JButton("生产入侵者");
        JPanel panel = new JPanel();
        panel.setBackground(Color.lightGray);
        panel.add(button1);
        panel.add(button2);
        add(panel, BorderLayout.SOUTH);
        setVisible(true);
        Graphics g = this.getGraphics();
        // 创建按钮监听器
        DroneListener droneListener = new DroneListener();
        // 在创建监听器后立刻为集合赋值,让集合真正可用
        droneListener.drones = drones;
        droneListener.intruders = intruders;
        droneListener.tasks = tasks;
        button1.addActionListener(droneListener);
        button2.addActionListener(droneListener);
        // 创建鼠标监听器
        addMouseListener(droneListener);
        // 创建无人机线程
        DroneThread droneThread = new DroneThread(g);
        // 创建任务线程
        TaskThread taskThread = new TaskThread();
        // 将共享内存的数组传入到两个线程中
        droneThread.drones = drones;
        droneThread.intruders = intruders;
        droneThread.tasks = tasks;
        // 要先将 DroneUI 类中的 tasks 传入给 droneThread,这样才能在执行 DroneThread 的时候保证此时的 tasks 不是 null
        taskThread.drones = drones;
        taskThread.tasks = tasks;
        droneThread.start();
        taskThread.start();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
    }

    public static void main(String[] args) {
        new DroneUI();
    }
}
package com.drone.v4;
import java.awt.*;

public class Intruder {
    int x;
    int y;
    int speedx;
    int speedy;
    int size = 30;
    int blood = 200;
    int rSquare = size * size / 4;

    public Intruder(int x, int y, int speedx, int speedy) {
        this.x = x;
        this.y = y;
        this.speedx = speedx;
        this.speedy = speedy;
    }

    public void drawIntruder(Graphics g) {
        if (blood > 0) {
            Color color1 = new Color(0, 0, 0);
            g.setColor(color1);
            g.fillOval(x, y, size, size);
            Color color2 = new Color(213, 15, 15);
            g.setColor(color2);
            g.fillOval(x + 5, y + 5, size - 10, size - 10);
            Color color3 = new Color(0, 0, 0);
            g.setColor(color3);
            g.drawRect(x, y - 5, size, 6);
            Color color4 = new Color(124, 244, 21);
            g.setColor(color4);
            g.fillRect(x + 1, y - 4, (int)(blood / 200.0 * (size - 1)), 5);
        }
    }

    public void move() {
        x += speedx;
        y += speedy;
        if (x <= 0 || x >= 1160) {
            speedx = -speedx;
        }
        if (y <= 0 || y >= 760) {
            speedy = -speedy;
        }
    }

    public void underAttack() {
        this.blood--;
    }
}
package com.drone.v4;

public class ScanResult {
    int targetX;
    int targetY;

    public ScanResult(int targetX, int targetY) {
        this.targetY = targetY;
        this.targetX = targetX;
    }
}
package com.drone.v4;
import java.awt.*;

public class Task {
    int x;
    int y;
    int size = 10;
    int state; // 0 未被领取的任务;1 被领取的任务;2 已完成的任务

    public Task(int state, int x, int y) {
        this.state = state;
        this.x = x;
        this.y = y;
    }

    public void draw(Graphics g) {
        g.setColor(Color.yellow);
        g.fillRect(x - size / 2, y - size / 2, size, size);
    }
}
package com.drone.v4;
import java.util.ArrayList;

public class TaskThread extends Thread {
    ArrayList<Task> tasks;
    ArrayList<Drone> drones;

    @Override
    public void run() {
        for (;;) {
            if (tasks != null) {
                if (drones != null) {
                    for (int i = tasks.size() - 1; i >= 0; i--) {
                        Task task = tasks.get(i);
                        if (task.state != 1) {
                            int nearestIndex = -1;
                            double minDis = 1000.0;
                            for (int j = drones.size() - 1; j >= 0; j--) {
                                Drone drone = drones.get(j);
                                // 找到没有领取任务的无人机(只有巡逻状态的无人机可以接任务)
                                if (drone.state == 0) {
                                    // 计算距离并找出最近的
                                    double currentDis = calculateDis(task, drone);
                                    if (currentDis <= minDis) {
                                        minDis = currentDis;
                                        nearestIndex = j;
                                    }
                                }
                            }
                            if (nearestIndex != -1) {
                                drones.get(nearestIndex).state = 2; // 无人机状态设为正在执行任务
                                drones.get(nearestIndex).targetTask = task;
                                System.out.println("任务被领取");
                                task.state = 1; // 任务状态设为已被领取
                            } else {
                                System.out.println("没有可指挥的无人机");
                                task.state = 0;
                            }
                        }
                    }
                }
            }
            try {
                Thread.sleep(16);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    double calculateDis(Task task, Drone drone) {
        double dis = Math.sqrt((task.x - drone.x) * (task.x - drone.x) + (task.y - drone.y) * (task.y - drone.y) * 1.0);
        return dis;
    }
}

总结

本次 V4 版本开发重点在于面向对象的设计规范与代码复用。通过将重复逻辑封装为独立方法,提升了代码的可维护性。前期设计的规范化为后续功能扩展预留了充足空间,状态机模式有效管理了无人机的不同行为模式。

目录

  1. V3 版本回顾
  2. V4 版本提升
  3. V4 版本的具体实现
  4. 可视化血条的添加
  5. 任务系统的添加
  6. 无人机 move 方法的优化
  7. V4 版本完整代码如下
  8. 总结

更多推荐文章

查看全部
  • Python内存管理深潜:从引用计数到GC机制的全面优化实战
  • 无需拓展插件:Copilot 接入第三方 OpenAI 接口方案
  • MySQL 服务器配置与管理
  • Java 中 TCP TIME_WAIT 状态的作用及服务端过多的原因分析
  • MCP 插件配置指南:以 browser-tools-mcp 为例
  • 手把手实现 STL Set/Map:从零编写一棵红黑树到完整容器封装
  • OpenClaw 与 Claude Cowork 桌面 AI Agent 深度对比评测
  • AI 图像生成指南:从原理到实战
  • 商汤开源 SenseNova-MARS 多模态自主推理模型
  • C++ 递归实战:合并两个有序链表与反转链表
  • ToDesk ToClaw 深度测评:OpenClaw 的云端自动化落地实践
  • Vue3 开发主流 AI 代码助手推荐与配置指南
  • AI 产品经理核心能力模型与职业转型指南
  • C# 扩展 Dynamics 365 Copilot:自定义插件与场景实战
  • 基于 Whisper-large-v3 的多语言翻译系统开发
  • Qt 与 Linux Socket 跨平台通信深度解析
  • 反爬虫:机器人点选验证原理及网站设计
  • 极化码 SC 译码算法原理、MATLAB 实现与优化策略
  • llama.cpp 多 GPU 分布式计算优化实践指南
  • Windows 11 安装 Git 完整指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online