5

我使用 OOP 创建了一个简单的保龄球游戏,我想为每个碗创建一个类,一个由两个碗组成的 Frame 类,一个由十个帧组成的 Game 类。

目前我有这样的事情

Bowl.java

public class Bowl {

int bowlScore = 0;

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

框架.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);
} 

游戏.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

设计保龄球游戏没有 100% 正确的方法;有许多可行的解决方案,甚至更多是行不通的。

您需要的是一个适合您和您的目标的解决方案。

如果你想显示一个分数,那么我建议你从一个getScore()方法开始。如果要显示获胜者,请从displayWinners()方法开始。

最终你会发现这些方法自然地绑定到各种名词。例如,您可能从getScore()依附于一个Game对象开始,但随后意识到这不自然地意味着您的游戏只能有一个分数。如果发生这种情况,您会将 移动getScore()到一个Player对象,并让游戏保留一个或多个玩家。

如果您正在使用一种自然属于其他地方的方法,那么您的代码中有许多提示可以指导您。最明显的暗示是一个方法似乎对另一个对象的数据特别感兴趣,甚至对它自己的数据也是如此。在上面的示例中,getScore()游戏对象中的 a 对 Player 的帧、球等过度感兴趣。

为了获得如何安全地将代码从一个地方移动到另一个地方的技能和指导,我建议阅读 Martin Fowler 的 Refactoring Book。

一个很好的例子,在这里演示了完全使用您的问题

祝你好运,一段时间后,由于获得的技能,您将能够跳过此过程中的一些;但是,第一次学习时,最好不要跳过这些探索性步骤(从头开始)。

PS。请记住,您的代码只会确保执行您测试它要做的事情,如果您不熟悉测试驱动开发,那么研究它可能是一个好主意(提示,这是一个严重的轻描淡写)。

于 2012-05-28T13:45:26.023 回答
4

正如 Edwin 所提到的,它们有很多方法可以模拟保龄球比赛。但是在这里,我将列出可能对您的代码进行的更正以改进它。
这里有很多需要改进的地方
1. score 属性只适用于 Bowl 类。所以从 Frame 和 Game 中删除 score 属性。
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.在游戏类中,你有构造函数,你只传递一帧?一名玩家的一场比赛由 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.如果你假设这个游戏只有一个玩家玩,这个模型也是有效的。对于多个玩家,上面的 Game 类实际上变成了 Player 类,您必须创建新的 Game 类。

于 2012-05-28T14:03:34.917 回答
1

我倾向于删除Bowl. 如果您发现自己处于这种情况,请问自己 - 我将如何处理 100 个实例BowlFrame考虑一下在游戏生命周期内必须创建和维护的十个实例。保留多个实例不是一个好主意,除非您需要多个实例来处理某些业务逻辑。

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你会注意到我在orFrame类中没有考虑到“罢工” 。这是因为它是一个需要满足的特殊情况,所以我把它留给你来实现。我的理解是,如果你在第一个碗上投出好球,你就不会得到第二个碗。

于 2012-05-28T14:07:13.277 回答