我们的最终学校项目是创建一个实现具有投注能力的赛马动画的课程。我们必须确保它是多线程的,我们必须有用户可以点击的按钮才能开始比赛。五匹马需要同时开始比赛并进入终点线。我们已经完成了大部分项目要求,但是我们在让所有马匹移动方面遇到了麻烦。
有时按下开始按钮,只有两匹马会移动。有时三匹马会移动。有时候所有的马都会移动。有时没有一匹马会移动。我们当前使用的方法使用while循环将马的layoutX更改为当前layoutX加10的任何内容。我添加了一个打印输出语句,让我知道每当一匹马越过终点线时,并根据所有五匹马总是越过终点线。
但是,视觉上并没有发生这种情况。即使马的图像代表DOES,图像也会随机出现在任何地方。我确定它与我们如何移动图片或我们如何将它们插入程序有关,但以防万一我还会显示运行方法线程以及我们如何调用它。
这是我们用来添加五匹马图像的方法。
public ArrayList<ImageView> callAllHorses() {
//In this method, we have created an array of type image and an array list of type ImageView,
//Using a for loop, make a new Image, add to the image array,
//and add that array to the ArrayList. At the same, we set the spacing for the horses evenly
//using a mathematical expression. The first horse, in index 0, doesn't
//need any more space vertically beyond the first 50 pixels we leave open for our buttons.
Image[] allHorses;
ArrayList<ImageView> allHorseView = new ArrayList<ImageView>();
allHorses = new Image[5];
for (int i = 0; i < allHorses.length; i++) {
allHorses[i] = new Image("file:C:\\User\\Downloads\\finalhorse" + (i + 1) + ".png");
allHorseView.add(new ImageView(allHorses[i]));
allHorseView.get(i).setY(50 + (150 * i));
}
return allHorseView;
}
此arraylist将添加到窗格中,然后将其添加到组中。
这里是马的内心阶级和奔跑方法以及我们要求他们做的事情:
public class Horse implements Runnable {
//A horse inner class was needed in order to consolidate thread creation.
//AND in order to be able to store the horse's number into a rankings list.
//This will allow us to record where the horses placed in the race,
//and then compare the rankings to the user's bet.
Node horse;
int horseNumber;
public Horse(int i) {
horseNumber = i;
createHorse(horseNumber);
}
public void createHorse(int i) {
horse = horses.getChildren().get(i);
}
public int getHorseNumber() {
return horseNumber;
}
@Override
public void run() {
//In this run method, the horses will move 10 pixels to the right and then sleep for a random number
//between 1-500 milliseconds, then resume their progress. Once their tails have reached the 650 pixel
//mark they stop. This puts them right at the edge of the window. Change 650 to change when the horse stops.
//Once the horse has reached the point it needs to, it finishes running by adding the number it has to the rankings arraylist.
Random horseSlow = new Random();
// TODO Auto-generated method stub
while (horse.getLayoutX() < 650) {
horse.setLayoutX(horse.getLayoutX() + 10);
try {
Thread.sleep(horseSlow.nextInt(500));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
rankings.add(getHorseNumber() + 1);
}
}
// TODO Auto-generated method stub
}
这是我们的开始竞赛方法,我们使用内部类创建马匹,并将它们分配给相应的图像。所有的马都是单独的线程,都是通过执行者运行的。
public void beginRace(){
ExecutorService executor = Executors.newFixedThreadPool(5);
executor.execute(new Horse(0));
executor.execute(new Horse(1));
executor.execute(new Horse(2));
executor.execute(new Horse(3));
executor.execute(new Horse(4));
}
这是按下开始按钮时发生的动作事件。
startBtn.setOnAction(e -> {
beginRace();
System.out.println("This button is active.");
resetBtn.setDisable(false);
startBtn.setDisable(true);
});
我现在已经尝试解决这个问题三天了,对于我的生活,我无法弄明白。