1

我的任务是编写一个简单的游戏,模拟两名玩家接连进行 1-3 场比赛,直到牌堆消失。我设法让计算机选择随机匹配的值,但现在我想更进一步,让人类玩游戏。这是我已经拥有的:http: //paste.pocoo.org/show/201761/

类 Player 是一个电脑玩家,而 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;
}

}

4

3 回答 3

1

好吧,让我首先说,我认为你做的比你需要的更难。如果是我,我会创建一个“GameMaster”类,其工作是循环并告诉每个玩家何时轮到他们。您的播放器类没有循环,只有一个 takeTurn 方法。这样您就可以从您的播放器类中删除等待/通知行为。

如果您希望保留现有设计,我仍然会摆脱等待/通知并使用Semaphore。检查文档是否正确使用,但要点是您将删除挂起/恢复方法,并在循环顶部调用 acquire() 并在底部释放。只需确保在构造函数中将 fairness 设置为 true,这样您就不必担心玩家会通过连续两次获取信号量锁来连续两次转弯。

于 2010-04-14T14:01:13.000 回答
1

好的,所以我设法在没有 wait() 等的情况下做到了。

http://paste.pocoo.org/show/201966/

于 2010-04-14T23:01:57.350 回答
1

当您发现自己必须在线程之间建立通信以同步它们的执行,以便发生指定的事件序列(例如轮流玩游戏)时,这是一个好兆头,表明您可能拥有比您需要的更多的线程。

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

于 2010-04-14T23:28:06.307 回答