0

我目前正在学习 Java 有几个原因,但其中一个主要原因是它是一种非常面向 OOP 的语言,而用 Java 编写代码确实有助于我理解 OOP 编程背后的核心概念。

但是,我很难定义我的类之间的关系。我理解继承和组合之间的区别,但是我很难看到整个画面,以及我的所有类应该如何作为一个整体一起工作。

我如何使用 OOP 编写简单的井字游戏的示例;

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

  2. 创建一个gameBoard类 - 更新井字棋盘,确定下一个玩家的回合,如果移动是合法的,并确定何时有赢家

  3. 创建一个抽象Player类 - 保存玩家的棋子(X 或 O),并包含一个将gameBoard实例作为参数并将玩家所做的移动传递给实例引用的方法

  4. 创建一个Human扩展类的Player类。包含处理来自键盘的玩家输入的方法

  5. 创建一个Computer扩展类的Player类。有一个方法,该方法将gameBoard实例作为参数并分析游戏板的获胜动作、阻挡动作或任何其他动作,然后进行动作

这是我会采取的方法。但是,我在将所有课程联系在一起时遇到了一些麻烦。在某些情况下,关于某些方法和字段应该属于哪里的界限似乎有点模糊。

编辑:修改后的问题:

在为我的类确定清晰、已定义的角色时,什么是一种好的方法,而不是太忙于定义和封装我的程序的各个方面?我的很多对象可以从其他类调用来执行每个类具有的特定功能,即Player更新gameBoardgameBoard更新Game,但我不知道这是否是一种好的做法,或者会通过传递来使代码变得僵硬且难以维护对象引用过多。

4

3 回答 3

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
...
于 2013-02-21T22:46:10.777 回答
2

一个游戏有两个玩家和一个棋盘。在棋盘说游戏结束之前,它应该轮流询问每个玩家以发现他们想要的动作是什么。然后它应该将该动作传递给董事会。如果董事会接受它,因为它是有效的,那么它就是下一个玩家轮到的。如果棋盘因为无效而拒绝该棋步,则它会要求同一玩家再次走棋。

记住这一点,一些伪代码可能采用以下形式;

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 */
}

这不是最有用的答案,但我只是在推测,这似乎至少是一个有点推测的问题。希望它会帮助你的思想朝着正确的方向前进。

于 2013-02-21T22:47:25.510 回答
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);
    }
}
于 2013-02-21T22:57:45.363 回答