我正在努力进行连接四场比赛的总结。
该程序应该有三个线程 - 玩家1,玩家2和游戏控制器。游戏控制器线程负责将控制从一个玩家转移到另一个玩家,必须监视线程是否需要超过5秒执行,检查是否有胜利者等等。
玩家类必须实现的界面是:
public interface Player extends Runnable {
public int nextMove(int otherPlayerLastMove);
public void gameOver();
}
方法nextMove
返回玩家将其下一个标记放入的列数,并将选择的玩家放置其最后一个标记的列数作为参数。
必须从gameOver
线程调用方法game controller
以指示游戏结束并从播放器释放所有资源。
我自己实现游戏逻辑没有问题,但我正面临设计明智的问题。我不能把我的想法放在我需要什么课程以及他们应该如何互动上。显而易见的类是PlayerImpl
和GameController
- 我认为它应该保留游戏的表格(2D字符数组)并实现检查逻辑。或者我是否需要第三类,其中只包含表格,其他两个人可以访问该表格?
基本代码在这里:
public class GameController implements Runnable{
private static char [][] table;
private void initTable(){
table = new char[6][7];
for (int i = 0; i < table.length; i++) {
for (int j = 0; j < table[i].length; j++) {
table[i][j] = '*';
}
}
}
public void printTable(){
for (int i = 0; i < table.length; i++) {
for (int j = 0; j < table[i].length; j++) {
System.out.print(table[i][j] + " ");
}
System.out.println();
}
}
private char checkWinner(){
//check for horizontal line
for (int i = 0; i < table.length; i++) {
for (int j = 0; j < 4; j++) {
if ( table[i][j] != '*' && table[i][j+1] != '*' && table[i][j+2] != '*' && table[i][j+3] != '*' &&
table[i][j] == table [i][j+1] && table[i][j+1] == table[i][j+2] && table[i][j+2] == table[i][j+3])
return table[i][j];
}
}
//check for vertical line
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 7; j++) {
if ( table[i][j] != '*' && table[i+1][j] != '*' && table[i+2][j] != '*' && table[i+3][j] != '*' &&
table[i][j] == table [i+1][j] && table[i+1][j] == table[i+2][j] && table[i+2][j] == table[i+3][j])
return table[i][j];
}
}
// left to right diagonals
for (int i = 0; i < 3; i++) {
for (int j = 3; j < 7; j++) {
if ( table[i][j] != '*' && table[i+1][j-1] != '*' && table[i+2][j-2] != '*' && table[i+3][j-3] != '*' &&
table[i][j] == table [i+1][j-1] && table[i+1][j-1] == table[i+2][j-2] && table[i+2][j-2] == table[i+3][j-3])
return table[i][j];
}
}
// right to left diagonals
for (int i = 0; i < 2; i++) {
for (int j = 3; j >=0; j--) {
if ( table[i][j] != '*' && table[i+1][j+1] != '*' && table[i+2][j+2] != '*' && table[i+3][j+3] != '*' &&
table[i][j] == table [i+1][j+1] && table[i+1][j+1] == table[i+2][j+2] && table[i+2][j+2] == table[i+3][j+3])
return table[i][j];
}
}
return 0;
}
public void addToken(int column, char token){
for (int i = table.length ; i >= 0 ; i--) {
if(table[i][column] == '*'){
table[i][column] = token;
break;
}
}
}
@Override
public void run() {
// TODO Auto-generated method stub
}
}
那你怎么设计这样的问题呢?解释或只是一个UML图表会很棒。在此先感谢:)
答案 0 :(得分:0)
你Runnable
上有方法的事实告诉我你有点像演员模特。
这只是概念上的意思,你有玩家和控制器,都有自己的线程(他们都是“演员”),并通过发送消息进行通信。在您的情况下,您通过接受方法调用(nextMove
,gameOver
)来做到这一点。
这是使你的代码更接近演员模式的东西。
class User extends Runnable {
int userId;
Controller controller;
Queue<Message> msgQueue;
void nextMove(int whoMoved, int whatMove){
msgQueue.offer(new NextMove(whoMoved, whatMove));
}
void gameOver(){
msgQueue.offer(new GameOver());
}
run(){
while(true){
Message msg = msgQueue.poll();
if(msg != null){
// deal with it
// Maybe send message to controller
controller.nextMove(new NextMove(userId, 4));
} else {
// Do something else, like talking to user
// sleep to avoid hogging CPU
Thread.sleep(10);
}
}
}
}
代码有很多问题(比如它会扩展得非常严重,抽象不是很好等等),但我希望它能说明这种方法。典型的真实角色模型实现使用绿色线程来解决可伸缩性并提供发送和接收消息的标准化方法(例如,参见Akka,Erlang)。