5

OOPを使用して簡単なボウリングゲームを作成しています。各ボウルのクラス、2つのボウルで構成されるフレームクラス、および10のフレームで構成されるゲームクラスが必要です。

現時点で私はこのようなものを持っています

Bowl.java

public class Bowl {

int bowlScore = 0;

public Bowl(int pinsKnocked){
    bowlScore = pinsKnocked;
}
}

Frame.java

public class Frame{

int firstScore;
int secondScore;
public Bowl firstBowl;
public Bowl secondBowl;

public Frame (){
    firstBowl = new Bowl(0);
    secondBowl = new Bowl(0);
}

public Frame (int firstScore, int secondScore){
    firstBowl = new Bowl(firstScore);
    secondBowl = new Bowl(secondScore);
} 

Game.java

public class Game {

int totalScore;
public Frame firstFrame;
public Frame secondFrame;
...
    public Frame tenthFrame;

public Game(){
    firstFrame = new Frame();   
}

public Game(Frame f){
    firstFrame = f;
}

これはOOP機能を使用する正しい方法ですか、それともこれをどのように改善できますか?

4

3 に答える 3

4

Edwin が述べたように、それらはボウリング ゲームをモデル化する多くの方法です。ただし、ここでは、コードを改善するために可能なコードの修正をリストします。
ここには改善すべき点がたくさんあります
。 1. スコア属性はボウル クラスにのみ適用されます。そのため、フレームとゲームからスコア属性を削除します。
2. bowlScoreinBowlはプライベートであり、getter メソッドを提供する必要があります。
3. Frame クラスは次のようになります。

public class Frame{
    private Bowl firstBowl;
    private Bowl secondBowl;

    public Frame (int firstScore, int secondScore){
        firstBowl = new Bowl(firstScore);
        secondBowl = new Bowl(secondScore);
    }
    public int getFrameScore(){
       return (firstBowl.getScore()+secondBowl.getScore());
    }
} 

4. Game クラスで、フレームを 1 つだけ渡すコンストラクタがありますか? 1 人のプレーヤーによる 1 つのゲームは 10 フレームで構成されます。また、フレームに 10 個の変数を使用することもお勧めできません。この目的のために Java コレクションがあります。リストを使用できます。

public class Game {
    private java.uti.List<Frame> frames;
    public Game(List<Frame> frames){
      this.frames = frames;
    }
    public getGameScore(){
      // loop goes here to sum up scores from all frames
      //sum = sum+frames.get(i);
    }
}

}

5. また、このゲームが 1 人のプレーヤーだけでプレイされると想定している場合、このモデル化は有効です。複数のプレイヤーの場合、上記の Game クラスは実際には Player クラスになり、新しい Game クラスを作成する必要があります。

于 2012-05-28T14:03:34.917 に答える
4

ボウリング ゲームを設計するための 100% 正しい方法はありません。機能するソリューションは多数ありますが、機能しないソリューションはさらに多くあります。

あなたが必要としているのは、あなたとあなたの目標に適したソリューションです。

スコアを表示したい場合は、getScore()メソッドから始めることをお勧めします。勝者を表示する場合は、displayWinners()メソッドから始めます。

最終的には、これらのメソッドが自然にさまざまな名詞にバインドされることがわかります。たとえばgetScore()、物に執着することから始めたとしてもGame、ゲームのスコアが 1 つしかないことを不自然に意味することに気付くかもしれません。これが発生した場合は、 をオブジェクトに移動しgetScore()Playerゲームに 1 人以上のプレイヤーを維持させます。

当然別の場所に属するメソッドを使用している場合、コード内にガイドとなる多くのヒントがあります。最も明白なヒントは、メソッドが、それ自体のデータであっても、別のオブジェクトのデータに特に関心があるように見えることです。上記の例でgetScore()は、ゲーム オブジェクト内の は、プレーヤーのフレーム、ボールなどに過度に関心を持っています。

コードをある場所から別の場所に安全に移動する方法に関するスキルと指示を得るには、Martin Fowler の Refactoring Book を読むことをお勧めします。

あなたの問題を正確に使用した優れた例がここに示されています

頑張ってください。しばらくすると、習得したスキルにより、このプロセスの一部をスキップできるようになります。ただし、初めて学習する場合は、そのような探索ステップをスキップしない (最初から開始する) ことをお勧めします。

PS。テスト駆動開発に慣れていない場合は、コードを確認することをお勧めします (ヒント、これは非常に控えめな表現です)。

于 2012-05-28T13:45:26.023 に答える
1

の複数のインスタンスを削除する傾向がありますBowl。このような状況に陥った場合は、自問してみてくださいBowlFrameゲームの存続期間中に作成および維持する必要があるの 10 個のインスタンスを考えてみてください。ビジネス ロジックに複数のインスタンスが必要でない限り、複数のインスタンスを保持することはお勧めできません。

public class Bowl {

    private int bowlScore;

    // Use a no-argument constructor
    public Bowl() {
        this.bowlScore = 0;
    }

    public void setBowlScore( int score ) {
        this.bowlScore = score;
    }

    public int getBowlScore() {
        return this.bowlScore;
    }
}

Frameクラスについては、

public class Frame {

    private int frameScore;
    private Bowl bowlArray[];

    public Frame() {
        this.frameScore = 0;
        this.bowlArray = new Bowl[2];
    }

    public void setScoreForFirstBowl( int score ) {
        this.bowlArray[0] = score;
        this.frameScore += score;
    }

    public void setScoreForSecondBowl( int score ) {
        this.bowlArray[1] = score;
        this.frameScore += score;
    }

    public void setFrameScore( int score ) {
        this.frameScore = score;
    }

    public int getFrameScore() {
        return this.frameScore;
    }

    // this should not be used, left in for completeness
    public Bowl[] getBowlArray() {
        return this.bowlArray;
    }
}

そして、Game

public class Game {

     private int gameScore;
     private ArrayList<Frame> gameFrames;

     public Game() {
         this.gameScore = 0;
         this.gameFrames = new ArrayList<Frame>();
     }

     /* There are many ways of implementing the game logic. Here is an example.
        You will have to complete the rest :) */

     // @frame frame object with bowl data that is appended to list
     public void frameCompleted(Frame frame) {
         this.gameScore += frame.getFrameScore; // I assume this is what you want to do. Change if not
         this.gameFrames.add(frame);
     }

     /* The method written above can also be implemented by passing integer values
        for the score, bowl number and frame number. However, this would not be very
        OOP friendly. Essentially, this is 'Encapsulation' of the Frame data into the 
        Frame object. */

     // Add getters and setters for gameScore and gameFrames
}

さらに使用する例については、 ArrayListのドキュメントを参照してください。使用したくない場合は、配列に置き換えることができます。リスト機能を紹介するためだけに含めました。

カプセル化 の詳細については、こちらこちらをご覧ください。

BowlまたはFrameクラスで「ストライク」を考慮していないことに気付くでしょう。これは、ケータリングが必要な特殊なケースであるため、実装するために残しました。私の理解では、最初のボウルでストライクをロールしても、2 番目のボウルは得られません。

于 2012-05-28T14:07:13.277 に答える