2010-04-12 7 views
0

J'ai eu la tâche d'écrire un jeu simple simulant deux joueurs ramassant 1-3 matchs l'un après l'autre jusqu'à ce que la pile soit partie. J'ai réussi à le faire pour l'ordinateur en choisissant la valeur aléatoire des matchs, mais maintenant je voudrais aller plus loin et permettre aux humains de jouer le jeu. Voici ce que j'ai déjà: http://paste.pocoo.org/show/200660/Quelques problèmes java plus multitâches

Class Player est un lecteur d'ordinateur, et PlayerMan doit être un être humain. Le problème est, ce fil de PlayerMan devrait attendre jusqu'à ce que la valeur appropriée des allumettes soit donnée mais je ne peux pas le faire fonctionner de cette manière. Quand je tape les valeurs, il les attrape parfois et diminue le nombre de correspondances, mais ce n'est pas exactement ce que je faisais :) La logique est: Je vérifie la valeur du joueur actuel. Si cela correspond à celui du thread actuellement actif, j'utilise un scanner pour saisir le nombre de correspondances. Sinon j'attends une seconde (je sais que c'est une solution un peu dure, mais je n'ai aucune autre idée de comment le faire).
Classe partagée conserve la valeur du joueur en cours, ainsi que la quantité de matchs. Au fait, y a-t-il un moyen de rendre les attributs Player et Shared privés plutôt que publics et de faire fonctionner le code? CONSOLE et ENTRÉE-DIALOG est juste pour choisir la façon d'insérer des valeurs.

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(); 
     } 
    } 
} 

Répondre

1

Vous devez synchroniser avec les verrous de lecteur/graveur. EDIT: À la réflexion, une simple condition devrait suffire. Vous pouvez utiliser quelque chose comme ceci:

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(); 
} 

Le seul problème ici est que vous pouvez bloquer les deux threads en attente de leurs conditions si data.which est pas correctement initialisé quand ils arrivent ici. Vous devez vous assurer qu'il est initialisé avant en commençant leurs threads.

+0

Je viens de trouver quelque chose à ce sujet, aussi la méthode wait(). Donc devrais-je ajouter une méthode pour écrire le nombre de correspondances le synchroniser et l'insérer dans run()? – owca

+1

@owca Fondamentalement, toute donnée lue ou écrite par plus d'un thread doit être synchronisée. Vous pouvez utiliser le mot clé 'synchronized' pour les méthodes qui le font, vous pouvez utiliser' synchronized (object) {...} 'dans une méthode, vous pouvez utiliser des verrous, ou vous pouvez utiliser des conditions (indiquées dans la réponse mise à jour). N'essayez jamais d'utiliser simplement une variable, car les données ne sont pas forcément cohérentes entre les threads sans un quelconque verrou. –

Questions connexes