我必须使用 Swing 在 Java 中编写一个小游戏,并且我需要做一件非常具体的事情,但我一生都无法弄清楚。
问题方法如下:
static void aiTurn() {
boolean attackableNeighbour = true;
while (attackableNeighbour) {
attackableNeighbour = false;
for (int i = 0; i < DicePanel.ROWS; i++) {
for (int j = 0; j < DicePanel.COLUMNS; j++) {
if (!cells[i][j].getIsPlayer()) {
int min = 9;
int minI = 0;
int minJ = 0;
for (int neighbourI = Math.max(0, i - 1);
neighbourI <= Math.min(i + 1, cells.length - 1); neighbourI++) {
for (int neighbourJ = Math.max(0, j - 1);
neighbourJ <= Math.min(j + 1, cells[0].length - 1); neighbourJ++) {
if (neighbourI != i && neighbourJ != j
&& cells[neighbourI][neighbourJ].getIsPlayer()
&& cells[neighbourI][neighbourJ].getDiceNumber() < min) {
min = cells[neighbourI][neighbourJ].getDiceNumber();
minI = neighbourI;
minJ = neighbourJ;
}
}
}
if (cells[i][j].getDiceNumber() >= min) {
attackableNeighbour = true;
cells[minI][minJ].setBackground(new Color(119, 82, 168));
cells[i][j].setBackground(new Color(121, 204, 88));
//pause here for a second (background needs to change)
attackAI(i, j, minI, minJ);
cells[i][j].setBackground(new Color(61, 153, 49));
if (cells[minI][minJ].getIsPlayer()) {
cells[minI][minJ].setBackground(new Color(100, 50, 168));
}
//pause here as well
}
}
}
}
}
}
我需要做的是能够在那里暂停。问题是,由于所有这些都在 EDT 中,我不能只使用计时器或使用
Thread.sleep()
- GUI 不会更新。我想要的效果是 GUI 根据我的代码进行更新,而不进行下一个更改。
我尝试过使用不同的线程来执行逻辑,但无论我尝试什么,它要么不起作用,要么 EDT(for 循环)上的代码继续运行,并且新线程延迟严重,以至于破坏了整个系统。
这是我尝试过的:
if (cells[i][j].getDiceNumber() >= min) {
attackableNeighbour = true;
final int altMinI = minI;
final int altMinJ = minJ;
final int altI = i;
final int altJ = j;
cells[minI][minJ].setBackground(new Color(119, 82, 168));
cells[i][j].setBackground(new Color(121, 204, 88));
SwingWorker worker = new SwingWorker<Object, String>() {
@Override
protected Object doInBackground() throws Exception {
attackAI(altI, altJ, altMinI, altMinJ);
Thread.sleep(1000);
cells[i][j].setBackground(new Color(61, 153, 49));
if (cells[minI][minJ].getIsPlayer()) {
cells[minI][minJ].setBackground(new Color(100, 50, 168));
}
return null;
}
};
worker.execute();
}
这会破坏游戏,因为方法
attackAI()
在初始 for 循环结束后很长时间才会被调用。我尝试阅读很多有关多线程的帖子,但我不知所措。非常感谢您的帮助!
我将为所有像我一样陷入困境的人发布我自己问题的答案。谢谢camickr;他的评论帮助我实现了我想做的事。
这是更新后的代码,可以按照我的意愿工作:
static void aiTurn() {
SwingWorker<Object, String> worker = new SwingWorker<Object, String>() {
@Override
protected Object doInBackground() throws Exception {
boolean attackableNeighbour = true;
while (attackableNeighbour) {
attackableNeighbour = false;
for (int i = 0; i < DicePanel.ROWS; i++) {
for (int j = 0; j < DicePanel.COLUMNS; j++) {
if (!cells[i][j].getIsPlayer() && cells[i][j].getDiceNumber() > 1) {
int min = 9;
int minI = 0;
int minJ = 0;
for (int neighbourI = Math.max(0, i - 1);
neighbourI <= Math.min(i + 1, cells.length - 1); neighbourI++) {
for (int neighbourJ = Math.max(0, j - 1);
neighbourJ <= Math.min(j + 1, cells[0].length - 1); neighbourJ++) {
if (neighbourI != i && neighbourJ != j
&& cells[neighbourI][neighbourJ].getIsPlayer()
&& cells[neighbourI][neighbourJ].getDiceNumber() < min) {
min = cells[neighbourI][neighbourJ].getDiceNumber();
minI = neighbourI;
minJ = neighbourJ;
}
}
}
if (cells[i][j].getDiceNumber() >= min) {
attackableNeighbour = true;
Thread.sleep(700);
cells[minI][minJ].setBackground(new Color(119, 82, 168));
cells[i][j].setBackground(new Color(121, 204, 88));
Thread.sleep(1000);
attackAI(i, j, minI, minJ);
cells[i][j].setBackground(new Color(61, 153, 49));
if (cells[minI][minJ].getIsPlayer()) {
cells[minI][minJ].setBackground(new Color(100, 50, 168));
}
Thread.sleep(300);
}
}
}
}
}
endTurnAI();
return null;
}
};
worker.execute(); }
我的疏忽是,当我只将 for 循环内的内容放入不同的线程中时,循环会在线程休眠时继续,因此会完全延迟。
但是由于每个 GUI 更改都发生在事件线程中,我可以将整个 for 循环放在不同的线程中,然后在我希望它暂停时休眠它 - GUI 仍然会更改(因为 EDT 当时为空) )并且不会有任何延迟,因为一切本质上仍然在单个线程中工作。