我有一个任务是编写简单的游戏,模拟两个玩家一个接一个地拿起1-3个匹配,直到堆消失。我设法为计算机选择匹配的随机值,但现在我想进一步让人类玩游戏。这是我已经拥有的:http://paste.pocoo.org/show/201761/
Class Player是一个电脑玩家,而PlayerMan应该是人类。问题是,PlayerMan的线程应该等到匹配的正确值,但我不能让它以这种方式工作。逻辑如下:线程运行直到匹配等于零。如果玩家编号正确,则调用函数pickMatches()。减少表上的匹配数后,线程应该等待,并且应该通知另一个线程。我知道我必须使用wait()和notify(),但我不能把它们放好。 Class Shared保留当前玩家的值以及匹配数量。
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 :(得分:1)
好吧,首先我要说的是,我认为你比你需要的更强硬。如果是我,我会创建一个'GameMaster'课程,它的工作是循环并告诉每个玩家轮到他们的时候。你的玩家类不会有循环,只是一个takeTurn方法。这样您就可以从播放器类中删除等待/通知行为。
如果你想保留你的设计,我仍然会摆脱等待/通知并使用Semaphore。检查文档是否正确使用,但要点是你要删除suspend / resume方法并在循环顶部调用acquire()并在底部释放。只需确保构造函数中的公平性设置为true,这样你就不必担心玩家通过连续两次获取信号量锁来连续两次转弯。
答案 1 :(得分:1)
好的,所以我设法做到了没有等待()等。
答案 2 :(得分:1)
当您发现自己必须在线程之间建立通信以同步其执行时,只是为了发生指定的事件序列(例如轮流玩游戏),这是一个好的迹象,表明您可能拥有比你需要。
在这种情况下,考虑在Player类的各种扩展上执行takeTurn()方法的单个线程可能会让您的生活更轻松。你可以使Player成为一个抽象的基类,强制命令.takeTurn(),然后让HumanPlayer和MachinePlayer类封装对该方法中每种类型的玩家都有意义的代码。与大量的wait()和notify()相比,这应该使更多的玩家扩展相对微不足道。