首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >数学题程序-“Java的艺术与科学”第5章第6章编程节选

数学题程序-“Java的艺术与科学”第5章第6章编程节选
EN

Code Review用户
提问于 2018-07-06 09:48:59
回答 4查看 1.9K关注 0票数 3

我写了以下程序:数学测验。这是来自“Java的艺术与科学”一书的第5章第6章的编程练习。

这个计划似乎正在起作用。不过,我希望能就我能改进的任何领域(任何坏习惯等)提出任何建议。

如果有任何更有效或优雅的方式随机选择符合下面所列标准的两个数字,我也会感到欣慰。

该方案应满足以下要求:

·它应该提出一系列五个问题--算术问题--编码为一个命名常数。

每个问题都应该包含一个简单的加法或减法问题,只涉及两个数字。

每个问题都应随机选择加法或减法。

·所涉及的数字,包括答案,都不应小于0或大于20 --在这些限制条件下,程序应随机选择数字。

·这个项目应该给学生三次回答每个问题的机会。如果学生给出正确的答案,程序应该以某种适当的祝贺方式表明这一事实。

·如果学生在三次尝试中没有得到答案,程序应该给出答案,然后再继续处理另一个问题。

代码语言:javascript
复制
/*
 * File: MathQuiz.java
 * ---------------------
 */

import acm.program.*;
import acm.util.*;

public class MathQuiz extends ConsoleProgram {

    private static final int NUMBER_OF_QUESTIONS = 5;

    public void run() {

        println("Welcome to MathQuiz");

// Starts a function which will ask questions 

        for (int i=0; i < NUMBER_OF_QUESTIONS; i++) {

// Draws a random number between 0 and 20 

            int x = getRandomX();

// Draws a random sign - plus or minus with a probability of 50 per cent            

            String sign = getPlusOrMinus(); 

// Initializes a second variable which will be used for second random number

            int y = 0;

// Initializes a variable where the good answer to the arithmetic problem will be kept      

            int goodanswer = 0;

// Draws a second random number between 0 and 20-x (method getRandomYPlus) if the drawn sign is + or between 0 and x (method getRandomYMinus) if the drawn sign is -
// I have created two methods because that numbers have to be such so that the answer will not be greater than 20 or less than zero 

            if (sign == "+") {

                y = getRandomYPlus(x);

                goodanswer = x + y;

            } else {

                y = getRandomYMinus(x);

                goodanswer = x-y;

            }

// Poses an arithmetic problem with the two random numbers and a random sign

            int answer = readInt("What is " + x + sign + y + "? ");

// Initializes a variable which will count the number of answers

            int count = 0;

// Students gets three chances to give a correct answer 

            while (answer != goodanswer && count !=3) {

                answer = readInt("That`s incorrect - try a different answer: ");

                count ++;
            }

            if (answer == goodanswer) {

                println("You got it!");

// After three wrong answers program gives a correct answer and moves to another problem                

            } else {

                println ("No, the answer is " + goodanswer + ".");


            }
        }

    }

// Method which draws a random number between 0 and 20 

    private int getRandomX() {

        int x = 0;

        x = rgen.nextInt(0,20);

        return x;
    }


// Method which draws a random sign - plus or minus - with a probability of 50 per cent

    private String getPlusOrMinus() {

        String sign = null;

        sign = rgen.nextBoolean() ? "+" : "-";

        return sign;
    }

// Draws a second random number between 0 and 20-x (method getRandomYPlus) if the drawn sign is + or between 0 and x (method getRandomYMinus) if the drawn sign is -
// I have created two methods because that numbers have to be such so that the answer will not be greater than 20 or less than zero 


    private int getRandomYPlus(int x) {

        int y = 0;

        y = rgen.nextInt(0,20-x); 

        return y;
    }

    private int getRandomYMinus(int x) {

        int y = 0;

        y = rgen.nextInt(0,x);

        return y;
    }

// Creates an instance variable for random number generator 

    private RandomGenerator rgen = new RandomGenerator();

}
EN

回答 4

Code Review用户

发布于 2018-07-06 12:20:17

最大的问题是,您有硬编码的最大数目大小(20)在多个地方。就像子弹的数量一样,这应该是一个常数。

你应该取消使用通配卡的进口。始终只导入要使用的特定类。否则,当两个包声明了同名类时,您将很难计算出名称冲突。

将RandomGenerator的初始化移到类的开头,这样人们就不需要猜测变量rgen是什么。您还可以将其设置为finalstatic,因为它不会改变,您(可能)可以对类的所有实例使用相同的实例。

应避免将变量初始化为不使用的值:

代码语言:javascript
复制
private int getRandomX() {

    int x;

    x = rgen.nextInt(0,20);

    return x;
}

代码语言:javascript
复制
private int getRandomX() {

    int x = rgen.nextInt(0,20);

    return x;
}

甚至在某项功能中:

代码语言:javascript
复制
private int getRandomX() {
    return rgen.nextInt(0,20);
}

这样的话,人们就不需要弄清楚零的含义。它还有助于调试,因为如果忘记执行实际初始化,代码将不会编译。

例如,这段代码不会编译,因为goodanswer没有在else块中初始化。

代码语言:javascript
复制
        int y;
        int goodanswer;

        if (sign == "+") {

            y = getRandomYPlus(x);

            goodanswer = x + y;

        } else {

            y = getRandomYMinus(x);

        }

如果您已经离开了int goodanswer = 0;,那么代码将编译并运行,但是不能正常工作,您将不得不花时间查找错误。

票数 1
EN

Code Review用户

发布于 2018-07-06 13:37:24

  • 空格太多了。在每一行代码之间不需要空行。
  • 评论太多了。注释应该解释做出决定的原因,而不是代码所做的事情。代码已经说明了它能做什么。如果它太复杂,难以阅读,您需要修复代码,而不是添加注释。
  • 永远不要将字符串与==进行比较。始终使用equals()
  • 实例变量声明属于类的顶部,而不是方法中的底部或中间。
  • 一致地使用空格。例如,!=3应该是!= 3int i=0应该是int i = 0
  • this.rgen.nextInt(min, max)可以放在行内。您不需要为此声明三个单独的包装方法。
  • 积极使用final来减少读者的认知负荷。
  • 多字变量名应该使用camelCase,而不是小写.(goodAnswer,而不是goodanswer)
  • 虽然ygoodAnswer都依赖于符号,但我认为它们是分开的计算。为了清楚起见,最好用不同的方法来处理。
  • 20是一个幻数,应该是一个常量。
  • count应该更具描述性--也许是attempts
  • 比较<而不是!=是惯例,以防某些东西指定count大于3,如果它大于3,那么循环就会永远持续下去。
  • Bug --你做了四次尝试,而要求说你应该给三次。您应该在1开始count,因为您在分配count之前第一次询问。

如果我尝试重构您的代码以包含上面的想法,它可能如下所示:

代码语言:javascript
复制
public final class MathQuiz extends ConsoleProgram {

    private static final int NUMBER_OF_QUESTIONS = 5;
    private static final int BIGGEST_POSSIBLE_NUMBER = 20;

    private final RandomGenerator rgen = new RandomGenerator();


    public void run() {
        this.println("Welcome to MathQuiz");

        for (int i = 0; i < NUMBER_OF_QUESTIONS; i++) {
            final int x = this.rgen.nextInt(0, BIGGEST_POSSIBLE_NUMBER);
            final String sign = this.rgen.nextBoolean() ? "+" : "-";
            final int y = this.computeY(x, sign);
            final int goodAnswer = this.computeAnswer(x, sign, y);

            int answer = this.readInt("What is " + x + sign + y + "? ");
            int attempts = 1;
            while ((answer != goodAnswer) && (attempts < 3)) {
                answer = this.readInt("That`s incorrect - try a different answer: ");
                attempts++;
            }

            if (answer == goodAnswer) {
                this.println("You got it!");
            } else {
                this.println ("No, the answer is " + goodAnswer + ".");
            }
        }
    }

    /**
     * @return a value {@code y} such that {@code y} and the correct answer to the mathematical
     * operation are both less than {@link BIGGEST_POSSIBLE_NUMBER}.
     */
    private int computeY(final int x, final String sign) {
        return sign.equals("+") ? this.rgen.nextInt(0, BIGGEST_POSSIBLE_NUMBER - x) : this.rgen.nextInt(0, x);
    }

    private int computeAnswer(final int x, final String sign, final int y) {
        return sign.equals("+") ? x + y : x - y;
    }

}
票数 1
EN

Code Review用户

发布于 2018-07-09 12:41:17

已经有很好的答案了。我补充一点:

代码语言:javascript
复制
sign == "+"

是一个(潜在的)错误。请参阅字符串等于Java

最好是将符号存储在boolean (isPlus)中,或者更好地使用显式enum

例如:

代码语言:javascript
复制
enum Sign
{
  PLUS, MINUS
}

然后,您有一个显式类型,这是您的符号,您可以使用

代码语言:javascript
复制
if (sign == Sign.PLUS)
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

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

复制
相关文章

相似问题

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