首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java OOP心理数学程序

Java OOP心理数学程序
EN

Code Review用户
提问于 2019-12-21 17:12:21
回答 1查看 614关注 0票数 1

目前,我正在使用Java开发一个面向对象的心理数学程序。由于我对面向对象的设计原则比较陌生,所以很高兴知道代码与OOP主体的一致性如何,以及需要做哪些改进,包括:

  • 如果可以引入子类,特别是对MathQuestionGenerator (例如AdditionQuestionGeneratorSubtractionQuestionGenerator等)。
  • 如果有更好的方法来处理分数,而不是在会话尚未完成时返回-1

项目概述:下面的代码本质上是一个GUI可以用来处理心理数学会话的模型。代码将生成20个随机问题,并跟踪时间和错误问题的数量。它可以处理5种类型的会话(加法、减法、乘法、除法或混合)和3种难度设置(容易、中等、困难)。

MathSession.java --表示用户回答20个问题的心理数学课。图形用户界面将调用startSession()并继续到submitAnswer(),直到所有20个问题都完成为止。然后,图形用户界面可以通过getFinalScore()获得用户的计算分数。

代码语言:javascript
复制
public class MathSession {
    public SessionType type;
    public SessionDifficulty difficulty;
    public MathQuestionGenerator generator;
    public MathQuestion currentQuestion;
    public int progress;
    public int numberWrongQuestions;
    public final int numberOfQuestions = 20;
    private long startTime;
    private long endTime;

    // Returns whether or not the session has completed
    public boolean isComplete() {
        return progress == numberOfQuestions;
    }

    // Calculates and returns a final score
    // Returns -1 when the session has not been completed yet
    public int getFinalScore() {
        if (!isComplete()) {
            return -1;
        } else {
            double secondsElapsed = (endTime - startTime)/ 1000;
            double penalty = numberWrongQuestions * 5;
            int score = (int) Math.round(secondsElapsed + penalty);
            return score;
        }
    }

    public MathSession(SessionType operator, SessionDifficulty difficulty) {
        this.type = operator;
        this.difficulty = difficulty;
        this.generator = new MathQuestionGenerator(operator, difficulty);
    }

    // Starts the session
    public void startSession() {
        startTime = System.currentTimeMillis();
        progress = 0;
        numberWrongQuestions = 0;
        currentQuestion = generator.generateQuestion();
    }

    // The user submits an answer, it is either right (returns true) or wrong (returns false)
    public boolean submitAnswer(int answer) {
        if (answer == currentQuestion.correct) {
            progress++;
            if (isComplete()) {
                endTime = System.currentTimeMillis();
            } else {
                currentQuestion = generator.generateQuestion();
            }
            return true;
        } else {
            numberWrongQuestions++;
            return false;
        }
    }
}

MathQuestionGenerator.java --生成具有难度和会话类型的心理数学问题。

代码语言:javascript
复制
public class MathQuestionGenerator {
    public SessionType type;
    public SessionDifficulty difficulty;
    private Random random;

    public MathQuestionGenerator(SessionType type, SessionDifficulty difficulty) {
        this.type = type;
        this.difficulty = difficulty;
        random = new Random();
    }

    // Generates a random math question given the session type and difficulty
    public MathQuestion generateQuestion() {
        int num1Max, num2Max, num1, num2, min = 1;

        MathOperator operation = null;
        if (type == SessionType.Addition) {
            operation = MathOperator.Addition;
        } else if (type == SessionType.Subtraction) {
            operation = MathOperator.Subtraction;
        } else if (type == SessionType.Multiplication) {
            operation = MathOperator.Multiplication;
        } else if (type == SessionType.Division) {
            operation = MathOperator.Division;
        } else if (type == SessionType.Mixed) {
            // Choose an operation randomly
            operation = random.nextInt(1) == 0 ? 
                    (random.nextInt(1) == 0 ? MathOperator.Addition : MathOperator.Subtraction) : 
                    (random.nextInt(1) == 0 ? MathOperator.Multiplication : MathOperator.Division);
        }

        if (operation == MathOperator.Addition || operation == MathOperator.Subtraction) {
            if (difficulty == SessionDifficulty.Easy) {
                num1Max = 12;
                num2Max = 12;
            } else if (difficulty == SessionDifficulty.Medium) {
                num1Max = 100;
                num2Max = 100;
            } else {
                num1Max = 10000;
                num2Max = 10000;
            }
        } else {
            if (difficulty == SessionDifficulty.Easy) {
                num1Max = 12;
                num2Max = 12;
            } else if (difficulty == SessionDifficulty.Medium) {
                num1Max = 100;
                num2Max = 10;
            } else {
                num1Max = 100;
                num2Max = 100;
            }
        }

        num1 = min + random.nextInt(num1Max - min);
        num2 = min + random.nextInt(num2Max - min);

        MathQuestion question;
        if (type == SessionType.Addition) {
            question = new MathQuestion(MathOperator.Addition, num1, num2, num1 + num2);
        } else if (type == SessionType.Subtraction) {
            question = new MathQuestion(MathOperator.Subtraction, num1 + num2, num1, num2);
        } else if (type == SessionType.Multiplication) {
            question = new MathQuestion(MathOperator.Multiplication, num1, num2, num1 * num2);
        } else {
            question = new MathQuestion(MathOperator.Division, num1 * num2, num2, num1);
        }

        return question;
    }
}

MathQuestion.java -用两个数字表示一个数学问题,一个运算和一个正确的答案。

代码语言:javascript
复制
public class MathQuestion {
    public MathOperator operator;
    public int number1;
    public int number2;
    public int correct;

    public MathQuestion(MathOperator operator, int number1, int number2, int correct) {
        this.operator = operator;
        this.number1 = number1;
        this.number2 = number2;
        this.correct = correct;
    }
}

MathOperator.java

代码语言:javascript
复制
public enum MathOperator {
    Addition,
    Subtraction,
    Multiplication,
    Division
}

SessionType.java

代码语言:javascript
复制
public enum SessionType {
    Addition,
    Subtraction,
    Multiplication,
    Division,
    Mixed
}

SessionDifficulty.java

代码语言:javascript
复制
public enum SessionDifficulty {
    Easy,
    Medium,
    Hard
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2019-12-21 18:39:21

欢迎来到代码评论,并感谢您分享您的代码!

我就是这么想的:

形式方面

文件中元素的

顺序(

)

在java文件中有一个元素顺序的约定。您违反的最重要的是,构造函数位于任何(非静态)方法之前。

注释

注释应该解释为什么代码是这样的。您的评论只是重复代码本身所表达的内容,因此是无用的。

避免在构造函数

中工作

在构造函数MathSession()中,使用operatordifficulty两个参数创建MathQuestionGenerator实例。对于更多的这两个参数(分别是属性,它们被设置为),在类中不使用。

更好的方法是在MathQuestionGenerator之外创建MathSession()实例,并将MathQuestionGenerator实例作为构造函数参数传递给MathSession(),而不是operatordifficulty

极限能见度与力不变性

MathQuestion是一个数据传输对象。在对象的LifeTime期间,它的大多数属性不会改变。因此,它们应该是final

声明类public中的所有属性使它们可以从外部访问。这违反了OOP最重要的原则:信息隐藏/封装。因此,默认情况下声明属性private,并且只有在您有很好的理由这样做的情况下才更改它。

OOP

OOP并不意味着将代码“拆分”成具有随机继承关系的随机类。

OOP的最终目标是减少代码重复、提高可读性和支持重用以及扩展代码。

执行OOP意味着您遵循某些原则(除其他外):

  • 信息隐藏/封装
  • 单一责任
  • 分离关注点
  • 亲吻(保持简单)愚蠢。)
  • 干(不要重复自己)。
  • “告诉我!别问。”
  • 德米特定律(“不要和陌生人说话!”)

用多态性

代替分支

您创建了一些enum类型,这首先是一件好事。但是,您只使用枚举值来选择MathQuestionGenerator类中的执行分支。例如:

代码语言:javascript
复制
    MathOperator operation = null;
    if (type == SessionType.Addition) {
        operation = MathOperator.Addition;
    } else if (type == SessionType.Subtraction) {
        operation = MathOperator.Subtraction;
    } else if (type == SessionType.Multiplication) {
        operation = MathOperator.Multiplication;
    } else if (type == SessionType.Division) {
        operation = MathOperator.Division;
    } else if (type == SessionType.Mixed) {
        // Choose an operation randomly
        operation = random.nextInt(1) == 0 ? 
                (random.nextInt(1) == 0 ? MathOperator.Addition : MathOperator.Subtraction) : 
                (random.nextInt(1) == 0 ? MathOperator.Multiplication : MathOperator.Division);
    }

更好的方法是将各个分支中的“特殊行为”转换为枚举的各种常量:

代码语言:javascript
复制
public enum SessionType {
    Addition{
       return MathOperator.Addition;
    },
    Subtraction{
       return MathOperator.Subtraction;
    },
    Multiplication{
       return MathOperator.Multiplication;
    },
    Division{
       return MathOperator.Division;
    },
    Mixed{
       return random.nextInt(1) == 0 ? 
                (random.nextInt(1) == 0 ? MathOperator.Addition : MathOperator.Subtraction) : 
                (random.nextInt(1) == 0 ? MathOperator.Multiplication : MathOperator.Division);
    };
    public abstract MathOperator selectOperator();
}

您的原始代码将更改为:

代码语言:javascript
复制
MathOperator operation = type.selectOperator();

避免特殊返回值

您的方法getFinalScore()返回一个特殊的值来告诉调用者出了什么问题(用户还没有回答足够多的查询)。更好的方法是抛出一个异常。

例外的使用是一个地雷领域。经验法则是,您确实使用异常来发出异常行为的信号,而不是实现控制流。在我看来,你的例子是一个角落的例子,因为还没有回答所有的问题显然不是“快乐的一天之路”。

异常的另一种选择可能是返回一个Java8 8-可选的,而不是原始的int

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/234434

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档