Еще несколько многозадачных проблем Java - PullRequest
0 голосов
/ 12 апреля 2010

У меня была задача написать простую игру, имитирующую двух игроков, собирающих по 1-3 матча один за другим, пока куча не исчезнет. Мне удалось сделать это для компьютера, выбирающего случайные значения совпадений, но теперь я хотел бы пойти дальше и позволить людям играть в игру. Вот что у меня уже есть: http://paste.pocoo.org/show/200660/

Класс Player - это компьютерный плеер, а PlayerMan должен быть человеком. Проблема в том, что поток PlayerMan должен ждать, пока не будет задано правильное значение совпадений, но я не могу заставить его работать таким образом. Когда я набираю значения, иногда они ловят их и уменьшают количество совпадений, но это не совсем то, что я задумал :) Логика такова: я проверяю значение текущего игрока. Если это соответствует этому потоку, в настоящее время активному, я использую сканер, чтобы поймать количество совпадений. Иначе я жду одну секунду (я знаю, что это довольно жесткое решение, но я не знаю, как это сделать).
Class Shared сохраняет значение текущего игрока, а также количество совпадений.

Кстати, есть ли способ сделать атрибуты Player и Shared закрытыми, а не общедоступными и при этом заставить код работать?

CONSOLE и INPUT-DIALOG просто для выбора способа ввода значений.

class PlayerMan extends Player{

    static final int CONSOLE=0;
    static final int INPUT_DIALOG=1;
    private int input;

    public PlayerMan(String name, Shared data, int c){
    super(name, data);
    input = c;
    }

@Override
    public void run(){
        Scanner scanner = new Scanner(System.in);
        int n = 0;

        System.out.println("Matches on table: "+data.matchesAmount);
        System.out.println("which: "+data.which);
        System.out.println("number: "+number);

        while(data.matchesAmount != 0){
            if(number == data.which){

                System.out.println("Choose amount of matches (from 1 to 3): ");
                n = scanner.nextInt();

                if(data.matchesAmount == 1){
                    System.out.println("There's only 1 match left !");
                    while(n != 1){
                        n = scanner.nextInt();
                    }
                }
                else{
                    do{
                        n = scanner.nextInt();
                    }
                    while(n <= 1 && n >= 3);
                }

                data.matchesAmount = data.matchesAmount - n;
                System.out.println("                          "+
                        name+" takes "+n+" matches.");
                if(number != 0){
                    data.which = 0;
                }
                else{
                    data.which = 1;
                }
            }
            else{
                try {
                    Thread.sleep(1000);
                } catch(InterruptedException exc) {
                    System.out.println("End of thread.");
                    return;
                }
            }
            System.out.println("Matches on table: "+data.matchesAmount);
        }
        if(data.matchesAmount == 0){
            System.out.println("Winner is player: "+name);
            stop();
        }
    }
}

1 Ответ

1 голос
/ 12 апреля 2010

Вы должны синхронизироваться с блокировками чтения / записи. РЕДАКТИРОВАТЬ : Если подумать, может быть, достаточно простого условия. Вы можете использовать что-то вроде этого:

private Lock playerLock = new ReentrantLock();
private Condition[] playerConditions = { playerLock.newCondition(), playerLock.newCondition() };

// Later on:
while (data.matchesAmount != 0) {
  while (number != data.which) {
    playerConditions[number].await();
  }
  // do work here

  // now release the other player -- this assumes there are only 2
  data.which = 1 - number;
  playerConditions[1 - number].signalAll();
}

Единственная проблема здесь в том, что вы можете заблокировать оба потока в ожидании их условий, если data.which не инициализирован должным образом, когда они попадут сюда. Вы должны убедиться, что он инициализирован до запуска их потоков.

...