我有一张桌子和几个机器人(仅适用于现在的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);
});
}
}