Есть ли быстрый способ закрыть поток перед продолжением основного кода? - PullRequest
0 голосов
/ 31 мая 2019

У меня есть ученики, работающие над Simon Game для финального проекта в школе, и я целый день пытаюсь решить ее проблему. Она пытается создать игру Simon. Программа случайным образом выбирает последовательность цветов и выделяет эти цвета, изменяя цвета 4 цветных кнопок с обычного цвета на белый в течение нескольких секунд, а затем обратно. Вместо того, чтобы выделять один цвет за раз белым, при программировании все цвета кажутся белыми одновременно. Таким образом, пользователи не знают последовательность.

Я искал проблемы с запуском нескольких потоков и пытался использовать функцию .join (). Однако, когда это используется, никакие цвета не становятся белыми.

// выделяет цвета, которые в данный момент находятся в массиве


public void play() {

   //loop through the array and look at all the colours so far     
   for(int i=0; i<round;i++){

             //red is the position in the array
             if(colours[i]==1){

                  Thread sleep=new Thread(new Runnable(){
                     @Override
                     public void run(){
                         //change the colour of the red button to white
                         redButton.setBackground(Color.WHITE);
                         redButton.setOpaque(true);


                            //wait 
                            try {
                                Thread.currentThread().sleep(1000);
                                }
                             catch (InterruptedException e) {
                                e.printStackTrace();
                                }
                            //change the colour back
                        redButton.setBackground(Color.RED);
                         redButton.setOpaque(false);
                     }
                 });

                        sleep.start();


             }




             //yellow
             else if(colours[i]==2){
                 Thread sleep=new Thread(new Runnable(){
                     @Override
                     public void run(){
                         yellowButton.setBackground(Color.WHITE);
                         yellowButton.setOpaque(true);


                            try {
                                Thread.currentThread().sleep(1000);
                                }
                             catch (InterruptedException e) {
                                e.printStackTrace();
                                }
                         yellowButton.setBackground(Color.YELLOW); 
                        yellowButton.setOpaque(false);
                     }
                 });
                 sleep.start();




             }
             //green
             else if(colours[i]==3){
                 Thread sleep=new Thread(new Runnable(){
                     @Override
                     public void run(){
                         greenButton.setBackground(Color.WHITE);
                         greenButton.setOpaque(true);


                            try {
                                Thread.currentThread().sleep(1000);
                                }
                             catch (InterruptedException e) {
                                e.printStackTrace();
                                }
                         greenButton.setBackground(Color.GREEN); 
                        greenButton.setOpaque(false);


                     }
                 });
                 sleep.start();



             }
             //blue
             else if(colours[i]==4){
                 Thread sleep=new Thread(new Runnable(){
                     @Override
                     public void run(){
                         blueButton.setBackground(Color.WHITE);
                         blueButton.setOpaque(true);


                            try {
                                Thread.currentThread().sleep(1000);
                                }
                             catch (InterruptedException e) {
                                e.printStackTrace();
                                }
                         blueButton.setBackground(Color.CYAN); 
                         blueButton.setOpaque(false);


                     }
                 });
                 sleep.start();




             }  

   }

}

Ответы [ 2 ]

0 голосов
/ 01 июня 2019

Хотя вы хотите изменить цвет каждой кнопки на 1 секунду, ваша основная нить слишком быстрая и заканчивается в течение этой секунды.Вот почему кажется, что все источники света изменяются одновременно.

Простое решение состоит в том, чтобы также заставить внешний поток спать некоторое время, но это не гарантирует последовательность потоков.Я бы предложил использовать java.util.concurrent.CountDownLatch, чтобы внешняя нить ожидала завершения внутренней нити.

    for (int i = 0; i < round; i++) {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        // red is the position in the array
        if (colours[i] == 1) {
            Thread sleep = new Thread(new Worker(redButton, Color.RED, countDownLatch))
            sleep.start();

        }

        // yellow
        else if (colours[i] == 2) {
            Thread sleep = new Thread(new Worker(yellowButton, Color.YELLOW, countDownLatch))
            sleep.start();

        }
        // green
        else if (colours[i] == 3) {
            Thread sleep = new Thread(new Worker(greenButton, Color.GREEN, countDownLatch))
            sleep.start();

        }
        // blue
        else if (colours[i] == 4) {
            Thread sleep = new Thread(new Worker(blueButton, Color.CYAN, countDownLatch))
            sleep.start();

        }
        countDownLatch.await();
    }
}

class Worker implements Runnable {
    Button button;
    Color color;
    CountDownLatch countDownLatch;

    public Worker(Button button, Color color, CountDownLatch countDownLatch) {
        this.button = button;
        this.color = color;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        button.setBackground(Color.WHITE);
        button.setOpaque(true);

        try {
            Thread.currentThread().sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        button.setBackground(color);
        button.setOpaque(false);
        countDownLatch.countDown();

    }
}

Как только индикатор меняет цвет на 1 секунду, вы начинаете обратный отсчет с помощью countDownLatch.countDown(), и вы ждете, пока обратный отсчет не достигнет нуля с countDownLatch.await() во внешней нити.

0 голосов
/ 31 мая 2019

код там в основном говорит.

для всех шагов в последовательности начинайте каждый поток.
затем каждый из этих потоков (все начались очень скоро друг за другом, а не до завершения предыдущего). Установите фон белым на 1 секунду.потом обратно.

Обычно вы хотите обновить пользовательский интерфейс в фоновом режиме, чтобы продолжить взаимодействие, но в этом случае вы воспроизводите последовательность и не хотите никакого ввода.если требуется обновление в фоновом режиме, поместите весь цикл в поток, и вы захотите спать между итерациями этого цикла.в противном случае просто сделайте это в главном потоке.как только последовательность будет воспроизведена для пользователя, она передаст управление обратно в цикл обработки событий для ожидания нажатий.

также задержка должна быть .3с

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...