1

我有一张桌子和几个机器人(现在只有 2 个),它们试图在表格中找到从起点到目标的最短路径。

每个 bot 都是一个线程,用于保持表中阻塞和未阻塞单元格的状态。

每个线程都订阅了其他线程。当某个线程执行并移动时,它会向其他线程发送通知,告知它已经释放了先前占用的单元并阻塞了另一个。

看起来像这样

在此处输入图像描述

每个线程的主循环是这样的

@Override
public void run() {
    // render original position
    notifyObserver(ChangeStateEvent
        .builder()
        .identifier(npc.getIdentifier())
        .newState(
            NPCWalkState.builder()
                .row(startVertex.getRow())
                .column(startVertex.getColumn())
                .build())
        .build());
    while (!startVertex.equals(goalVertex)) {
        ThreadUtils.delaySeconds(speed);

        Vertex nextStep = pathSearch.find(startVertex, goalVertex, cellStates).get(1);

        ChangeStateEvent event = ChangeStateEvent.builder()
            .identifier(npc.getIdentifier())
            .newState(
                NPCWalkState.builder()
                    .row(nextStep.getRow())
                    .column(nextStep.getColumn())
                    .build())
            .previousState(
                NPCWalkState.builder()
                    .row(startVertex.getRow())
                    .column(startVertex.getColumn())
                    .build())
            .build();
        notifyObserver(event);
        startVertex = new Vertex(nextStep);
    }
}

侦听器方法看起来像这样

@Override
public void receiveNotification(ChangeStateEvent data) {
    if (null != data.getPreviousState()) {
        // freed cells
        int free_row = data.getPreviousState().getRow();
        int free_column = data.getPreviousState().getColumn();
        // blocked cells
        int blocked_row = data.getNewState().getRow();
        int blocked_column = data.getNewState().getColumn();

        cellStates[free_row][free_column] = false;
        cellStates[blocked_row][blocked_column] = true;
    } else {
        // blocked cells
        int blocked_row = data.getNewState().getRow();
        int blocked_column = data.getNewState().getColumn();

        cellStates[blocked_row][blocked_column] = true;
    }
}

cellStates是一个基本的布尔矩阵

private boolean[][] cellStates;

但有时那些移动的机器人会相互重叠——所以它们会同时进入同一个单元格。最终他们达到了预期的目的地。

但是我想摆脱这种行为。如何做到这一点?

据我了解,我应该阻止搜索,直到消息中的状态cellState更新,或者如果搜索开始,则receiveNotification阻止更新。cellState

我也不排除表本身负责重叠 - 因为它也订阅了线程事件

@Override
public void receiveNotification(ChangeStateEvent data) {
    if (null != data.getPreviousState()) {
        int previousRow = data.getPreviousState().getRow();
        int previousColumn = data.getPreviousState().getColumn();
        int currentRow = data.getNewState().getRow();
        int currentColumn = data.getNewState().getColumn();
        SwingUtilities.invokeLater(() -> {
            List<T> oldCellContent = (List<T>) table.getValueAt(previousRow, previousColumn);
            oldCellContent.remove(data.getIdentifier());
            table.setValueAt(oldCellContent, previousRow, previousColumn);

            List<T> newCellContent = (List<T>) table.getValueAt(currentRow, currentColumn);
            newCellContent.add(0, (T) data.getIdentifier()); // on top TODO: player should be prioritized
            table.setValueAt(newCellContent, currentRow, currentColumn);
        });
    } else {
        int currentRow = data.getNewState().getRow();
        int currentColumn = data.getNewState().getColumn();
        SwingUtilities.invokeLater(() -> {
            List<T> newCellContent = (List<T>) table.getValueAt(currentRow, currentColumn);
            newCellContent.add(0, (T) data.getIdentifier());
            table.setValueAt(newCellContent, currentRow, currentColumn);
        });
    }
}
4

0 回答 0