0

私は現在いくつかの理由でJavaを学んでいますが、主な理由の1つは、Javaが非常にOOP指向の言語であり、Javaでコードを書くことは、OOPプログラミングの背後にあるコアコンセプトを理解するのに本当に役立ちます。

しかし、クラス間の関係を定義するのに苦労しています。継承と構成の違いは理解できますが、全体像を把握するのが難しく、すべてのクラスが全体としてどのように連携する必要があるのか​​がわかりません。

OOPを使用してTic-TacToeの簡単なゲームを作成する方法の例。

  1. クラスの作成Game-クラスのインスタンスを作成し、gameBoard誰が最初に開始するかを決定し、勝ち負けのゲームを追跡し、ゲームを開始および終了します。

  2. クラスを作成するgameBoard-三目並べボードを更新し、移動が合法である場合は次のプレーヤーのターンを決定し、勝者がいついるかを決定します

  3. 抽象クラスを作成します-プレーヤーのタイル(XまたはO)を保持し、引数としてインスタンスを受け取り、プレーヤーが行った移動をインスタンス参照に渡すPlayerメソッドを含みますgameBoard

  4. Humanクラスを拡張するクラスを作成しますPlayer。キーボードからのプレーヤー入力を処理するメソッドが含まれています

  5. Computerクラスを拡張するクラスを作成しますPlayer。インスタンスを引数として取りgameBoard、ゲームボードを分析して勝利の動き、ブロックの動き、またはその他の動きを探し、次に動きを行うメソッドがあります

これが私がとるアプローチです。ただし、すべてのクラスを関連付けるのに少し問題があります。一部のメソッドとフィールドがどこに属するべきかについて、線が少しぼやけているように見える場合があります。

編集:改訂された質問:

プログラムのあらゆる側面を定義してカプセル化しようとすることにあまり夢中にならずに、クラスの明確で定義された役割を決定するための良い方法論は何でしょうか?私のオブジェクトの多くは、他のクラスから呼び出されて、各クラスが持つ特定の機能、つまりPlayer更新gameBoardgameBoard更新を実行できますGameが、これが良い習慣であるかどうかはわかりません。オブジェクト参照が多すぎます。

4

3 に答える 3

2

マーティン、問題のすべての関係を「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

ゲームには2人のプレーヤーと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 */
}

これは最も有用な答えではありませんが、私は推測しているだけであり、少なくとも少し推測的な質問のように見えました。うまくいけば、それはあなたの心を正しい方向に向かわせるのに役立つでしょう。

于 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 に答える