2010-04-14 69 views
1

我有一个任务,写一个简单的游戏,模拟两个玩家一个接一个地玩1-3场比赛,直到堆不见了。我设法为计算机选择随机匹配的值,但现在我想进一步让人类玩这个游戏。这是我已经有:http://paste.pocoo.org/show/201761/控制线程流

类播放器是一个电脑播放器,和PlayerMan应该是人类。问题是,PlayerMan的这个线程应该等到合适的匹配值给出,但我不能使它以这种方式工作。逻辑如下:线程运行,直到匹配等于零。如果在调用函数pickMatches()时玩家号码正确。在减少表上的匹配数之后,线程应该等待,并且应该通知另一个线程。我知道我必须使用wait()和notify(),但是我不能把它们放在正确的位置。 类共享保持当前玩家的价值,以及比赛的数量。

public void suspendThread() { 
    suspended = true; 
} 

public void resumeThread() { 
    suspended = false; 
} 

@Override 
public void run(){ 
    int matches=1; 
    int which = 0; 
    int tmp=0; 
    Shared data = this.selectData(); 
    String name = this.returnName(); 
    int number = this.getNumber(); 

    while(data.getMatches() != 0){ 

     while(!suspended){ 

      try{    
       which = data.getCurrent(); 

       if(number == which){ 

        matches = pickMatches(); 

        tmp = data.getMatches() - matches; 
        data.setMatches(tmp, number); 

        if(data.getMatches() == 0){ 
         System.out.println("       "+ 
          name+" takes "+matches+" matches."); 
         System.out.println("Winner is player: "+name); 
         stop(); 
        } 

        System.out.println("       "+ 
          name+" takes "+matches+" matches."); 

        if(number != 0){ 
         data.setCurrent(0); 
        } 
        else{ 
         data.setCurrent(1); 
        } 
       } 
       this.suspendThread(); 
       notifyAll(); 
       wait(); 

      }catch(InterruptedException exc) {}  
     } 
    } 
} 

@Override 
synchronized public int pickMatches(){ 
    Scanner scanner = new Scanner(System.in); 
    int n = 0; 
    Shared data = this.selectData(); 

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

     if(data.getMatches() == 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); 
     } 
    return n; 
} 

}

+0

@owca太多的代码!尝试使其更符合Short Self-Contained Compilable Example(sscce):http://mindprod.com/jgloss/sscce.html – Kiril 2010-04-14 14:19:43

回答

1

好了,让我先说,我认为你正在比你需要这个强壮。如果是我,我会创建一个'GameMaster'类,它的任务是循环并告诉每个玩家何时轮到他们。你的玩家类不会有循环,只是一个takeTurn方法。这样你就可以从玩家类中删除等待/通知行为。

如果你想保留你的设计,我仍然会摆脱等待/通知,并使用Semaphore。检查文档的正确用法,但要点是您将删除挂起/恢复方法,并在循环顶部有一个acquire()调用,并在底部释放。只需确保构造函数中的公平设置为true,这样就不必担心连续两次获取信号量锁定而连续进行两次回合的玩家。

1

当你发现自己不必设置线程之间的交流,其执行同步,只是让一个特定序列事件发生(比如轮流玩游戏),这是一个好兆头,你可能有比你需要的线程更多的线程。

在这种情况下,考虑在Player类的各种扩展上执行takeTurn()方法的单个线程可能会让您的生活更轻松。你可以让Player成为一个强制使用.takeTurn()的抽象基类,然后让HumanPlayer和MachinePlayer类封装对于该方法中每种类型的播放器都有意义的代码。与大量的wait()和notify()相比,这应该扩展到更多的玩家相对微不足道。