2013-02-21 71 views
0

我目前正在学习Java有几个原因,但其中一个主要原因是它是面向OOP的语言,并且使用Java编写代码真的帮助我理解OOP编程背后的核心概念。OOP:简单游戏设计中的对象继承和组合关系

但是,我很难定义我的类之间的关系。我理解继承和构图之间的区别,但是我看到整个画面时遇到了一些困难,以及我的所有类如何作为整体一起工作。

我将如何使用OOP编写一个简单的井字游戏的例子;

  1. 创建Game类 - 创建gameBoard类的实例, 决定谁第一个开始,跟踪比赛赢了,输了,开始 并结束游戏。

  2. 创建gameBoard类 - 更新井字棋板, 确定下一个玩家的回合,如果此举是合法的,并 决定时,有一个赢家

  3. 创建一个抽象Player类 - 保存的游戏者的瓦片(X或O),和 包含需要gameBoard实例作为参数和 通过引用

  4. 创建由玩家到实例所作的移动的方法3210类扩展Player类。包含 处理玩家从键盘输入的方法

  5. 创建一个Computer类,该类扩展了Player类。有 方法,它接受gameBoard实例作为论据和分析 的游戏键盘的获奖移动,阻挡移动,或任何其他 动,然后进行一招

这是我采取的方法。但是,我将所有类关联在一起时遇到了一些麻烦。在某些情况下,这条线似乎有些模糊,以至于某些方法和领域应该属于哪里。

编辑:修订问题:

什么是确定明确,定义的角色对我的班,没有在试图定义和ecapsulate我的程序的各个方面得到太多赶上了一个好方法?很多我的对象可以从其他类被调用来执行每个类具有的特定功能,即Player更新gameBoard,gameBoard更新Game,但我不知道这是好的做法,还是会使僵化和难以维护通过传递太多的对象引用来实现代码。

+1

您的问题太宽泛而无法合理回答。你能否进一步把它煮沸,并以你想要回答的具体问题结束(因为我可以在文本中看到很多问题,每个问题都不容易回答)? – Polygnome 2013-02-21 22:32:24

+0

我会尝试将我的问题转换成一个具体问题。 – 2013-02-21 22:36:00

+0

从堆栈溢出FAQ:“你的问题应该是合理的,如果你可以想象整本书能够回答你的问题,你就会问得太多。”这不是堆栈溢出的问题。 – antonijn 2013-02-21 22:36:28

回答

2

Martyn,尝试将问题中的每个关系归类为“is-a”或“has-a”。这将使得解决课堂关系更容易。

例如,

Game has-a Gameboard 
Human is-a Player 
Computer is-a Player 

然后

Game has-a Player1 
Game has-a Player2 

看你如何与去,你会回答许多自己的问题。祝你好运!

编辑:你写道:Player更新gameBoardgameBoard更新Game

你能做到这样,使“游戏”更为重要的游戏控制?

Game asks player to select next move from GameBoard 
Player looks on Gameboard to see possible legal moves 
Player selects a legal move and returns it to Game 
Game plays the move on the GameBoard 
Game checks the Gameboard to see if any player has won 
if not, Game ends the turn and goes to the next player 
... 
+0

我明白has-a和is-a的关系,但通过进一步将对象分解,添加不必要的抽象级别总是很诱人。我仍然试图在可重用性和抽象性之间找到适当的平衡点。 – 2013-02-21 23:03:06

+0

你的课堂想法相当好,但我可能会建议让游戏对游戏控制更加重要(请参阅我的编辑)。 – vikingsteve 2013-02-21 23:16:46

+0

我可以看到让游戏更加重视整体控制的好处。从对象关系来看,让玩家处理在GameBoard上进行移动似乎更自然,但就可重用性而言,让Game作为任何游戏正在播放的总体控制器似乎是合乎逻辑的,并且会增加额外的扩展Game类的游戏更易于自上而下管理。 – 2013-02-21 23:39:42

1

游戏有两名玩家和董事会。在董事会表示游戏结束之前,它应该询问每个玩家轮流发现他们想要的举措。然后它应该把这个举动传递给董事会。如果董事会接受它,因为它是有效的,那么下一个玩家轮流。如果董事会拒绝这一举动,因为它是无效的,那么它会要求同一位玩家再次采取行动。

记住这一点,一些伪代码可能采取的形式;

class Game { 
    Player p1, p2, current; 
    Board board; 

    public Game() { 
     Board = new TicTacToeBoard(); 
     p1 = new Human('X'); 
     p2 = new Compooterwooter('O'); 

     current = p1; 
    } 
} 

abstract class Player { 
    char label; 
    Move getMove(Board); 
} 

abstract class Board { 
    boolean makeMove(Move); 
    Position getPosition(); 
    boolean gameIsUp(); /* has the game finished? */ 
} 

class Move { 
    int x, y; 
} 

class Position { 
    boolean isVacant(int x, int y); 
    char whoHasPlayed(int x, int y); 
} 

class Human extends Player { 
    Move getMove(Board b) { /* ask user for move */ } 
} 

class Compooterwooter extends Player { 
    Move getMove(Board b) { /* compute move */ 
} 

class TicTacToeBoard extends Board { 
    boolean makeMove(int x, int y) { /* check valid move */ 
} 

这不是最有用的答案,但我只是猜测,而且似乎至少是一个有点投机的问题。希望这将有助于让你的头脑朝着正确的方向前进。

+0

以伪代码来看它确实有助于可视化解决方案。也许我的问题是,我试图想象我头脑中的结构,而没有先计划好结构,并且在开始将键击输入到IDE之前尝试将所有东西都处理完毕。也许首先用UML规划我的设计可以帮助我更好地形象化类和对象之间的关系,而不是在定义结构之前尝试将所有东西都弄清楚。 – 2013-02-21 22:58:44

+0

这可能有助于做一点规划,是的。但同样重要的是要认识到你只是在学习,并且通过完成某些事情而不是在一两天内用UML来炫耀你将学到更多东西。祝你的项目好运:-) – deau 2013-02-21 23:05:53

+0

谢谢。是的,你说得很对。我将更多地从我的计划中采取行动,而不是过度计划。 – 2013-02-21 23:18:59

1

从类似下面的代码开始。

然后使其工作,以便您可以从命令行手动双方播放。

然后将你的代码重构成一些玩家类和其他需要的东西。

enum State { 
    x('x'),o('o'),vacant(' '); 
    State(char c) { 
     this.c=c; 
    } 
    char c; 
} 
class Game { 
    Game() { 
     for(int i=0;i<3;i++) 
      for(int j=0;j<3;j++) 
       board[i][j]=State.vacant; 
    } 
    void makeMove(int i,int j,State state) { 
     if(board[i][j]!=State.vacant) 
      throw new RuntimeException("bad move!"); 
     board[i][j]=state; 
    } 
    boolean isGameOver() { 
     // ... 
     return false; 
    } 
    public String toString() { 
     String s=""; 
     for(int i=0;i<3;i++) { 
      s+='|'; 
      for(int j=0;j<3;j++) 
       s+=""+board[i][j].c+'|'; 
      s+='\n'; 
     } 
     return s; 
    } 
    final State[][] board=new State[3][3]; 
} 
public class So15013410 { 
    public static void main(String[] args) { 
     Game game=new Game(); 
     System.out.println(game); 
     game.makeMove(0,0,State.x); 
     System.out.println(game); 
     game.makeMove(0,1,State.o); 
     System.out.println(game); 
    } 
} 
+0

谢谢。首先创建一个可用的游戏板,然后重构我的代码以处理玩家交互,并定义我的类来处理每个特定的游戏方面,这将是有意义的。它可能会让我更好地了解我需要哪些类,而不是尝试从偏移量中创建它们。 – 2013-02-21 23:27:30

+0

我希望我能接受两个答案,因为你的代码已经为我提供了一个非常好的起点,我可以使用它,并且提供了一个很好的枚举工作示例。非常感激。 – 2013-02-22 00:03:51

+0

np,他的回答很好。它涉及到阶级关系。 – 2013-02-22 00:28:06