我有一个应该同时运行多个线程的程序。
这是对纸牌游戏Uno的模拟,你应该为每个玩家都有一个主题。
现在这里有一个问题:每当一名玩家手中有一张卡片的数量和颜色相同的卡片,但不是这个玩家的回合,他可以“切断”线并将卡放下。切断线的玩家旁边的玩家继续。
我有一个班级玩家:
class Player implements Runnable {
public boolean isHisTurn = false;
public Thread makeMove(final Card topCard, final boolean isHisTurn) {
Thread thread = new Thread(this);
thread.start();
return thread;
}
}
thread.start()然后启动run方法,我有逻辑和决策。在run()的开始时,线程会随机休眠3到300-700毫秒,以便在这段时间内使切割线成为可能。
我的问题是,我应该将线程存储在某个地方,如果是这样,那么,当它是不同的玩家时,我如何在线程之间切换?我知道它与boolean isHisTurn有关,我只是不知道如何使用它。
是的,这是家庭作业,但我只是要求它的一小部分,我不想要一个完整的答案,只是让我朝着正确的方向发展。
答案 0 :(得分:3)
如何在不同的玩家回合时切换线程?
线程的显着特征是几个线程可以同时运行。如果您不使用该功能,则使用线程没有意义。由于玩家在轮到他的时候也可以移动,所以所有玩家同时活跃实际上是有意义的。因此,我为每个玩家创建(并开始)一个线程。该线程将在睡眠和移动之间交替。
这留下了线程如何交互的问题。为此,我创建了一个类:
class Game {
Card topCard;
Player nextPlayer;
...
}
并将游戏实例提供给每个玩家线程。当比赛线程正在考虑他的移动时,他可以看看顶牌,以及轮到他了。在进行移动时,他只需更新Game实例中的字段。
当然,由于不同的线程可以同时处于活动状态,因此两个玩家可能会同时尝试移动(换句话说,玩家可能决定玩牌,但另一个玩家更快,使初始玩家的移动不再有效)。通过同步对Game
实例的访问来最容易地防止这种情况。对于现实主义,您可能会在查看游戏状态时进行同步,然后进行思考,然后再次同步以进行移动。但是,在整个“外观,思考和移动”周期中进行同步可能更容易,因为这可以确保玩家不会干扰彼此思考,并减少需要处理的角落案例数量。
另一个皱纹是终止。一旦第一个玩家没有牌,游戏就会结束,所以其他玩家需要一种方法来注意这个事实。最简单的可能是整理玩家声明自己是胜利者(例如,通过在winningPlayer
实例中设置字段Game
)以及其他线程在声明获胜者后立即终止。
答案 1 :(得分:0)
很难帮助完成一个家庭作业问题,因为通常教授正在寻找某种解决方案并正确解决问题,但是错误的方式仍然会被计算在内。例如,说你应该为每个玩家提供一个线程是非常有帮助的,因为有很多其他有效的方法可以做到这一点,但如果你这样做,那么你的作业就错了。因此,如果您有其他信息可以分享预期的解决方案,请分享。我认为选择这个问题是因为你还没有等到信号量。
如果你打算为每个玩家提供一个主题,那么你可以根据人类玩家的游戏方式对该程序进行建模。每个玩家都知道转储顶部的牌,其他玩家是谁,他们玩的顺序,最后一个玩家以及玩过什么。因此,您希望在所有线程可以看到的某些对象中表示所有这些事实。
每个线程(播放器)也有自己的手,只有它可以看到,所以应该建模为每个线程的对象。
关键是玩家(线程)会做出动作!你的主程序只是启动线程并等待游戏完成。玩家可以随意睡觉一段时间,然后醒来,看看他们是否可以移动,如果他们可以移动,然后再回去睡觉。