实现功能:
1.整数和真分数的四则运算, 运算数和运算结果都可以是整数或分数;
2.能生成任意个运算数的算式;
3.算式的个数、数的范围、运算数的个数由命令行输入;
4.保证生成的算式不重复;
5.支持括号。
实现思路:
1.新定义了表达式类,数据成员包含表达式的值,表达式的字符串形式,以及两个子表达式中间的算符。
方法成员包括两个构造函数,其中一个随机生成算式并计算结果,另一个是默认的,用来分配空间;一个输出函数,用来打印算式;以及其他辅助函数。
构造函数的思路:构造两个较短的子表达式,然后用随机的算符连接在一起。递归的边界是当表达式的长度为1或者2。
2.在运算数类中,数据成员包括分子和分母,此外新增了一个数据成员:运算数的字符串形式,
新增了两个构造函数,其中一个用来随机生成运算数,另一个是默认的,用来分配空间。
3.在主类里调用表达式类的方法,来生成和输出算式;接受用户输入并判断正误。
结果截图:
程序代码:
GitHub地址:https://github.com/EverBlue1997/MyFirstRepository/tree/master/Week1v2.0
主类Week1:
import java.util.Scanner;
public class Week1 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int r = Integer.parseInt(args[0]); //运算数的范围,由命令行输入
int n = Integer.parseInt(args[1]); //算式的数量,由命令行输入
int l = Integer.parseInt(args[2]); //运算数的个数,由命令行输入
int count = 0; //用户答对的题数
expression e[]; //创建一个算式数组
e = new expression[n];
int same = 0; //重复标志
for (int i = 0; i < n; i ++ ) {
do {
same = 0;
e[i] = new expression (l, r);
for (int j = 0; j < i; j ++) { //判断与之前的算式是否重复
if ((e[j].exp).equals(e[i].exp)) {
same = 1;
break;
}
}
} while (same == 1);
e[i].print(); //将算式打印到屏幕上
if (scan.nextLine().equals (e[i].value.str)) { //接受用户输入的答案并判断正误
System.out.println("回答正确!\n");
count ++;
}
else {
System.out.println("回答错误! 正确答案是: " + e[i].value.str + "\n");
}
}
//输出分数
System.out.println("您答对了" + count + "道题目,得分:" + 100 * count / n + "!\n");
scan.close();
}
}
运算数类number:
/*
* 操作数类的定义
*/
public class number {
int n; //分子
int d; //分母
String str; //字符串形式
/*
* 操作数类的构造函数
* 参数range为分子和分母的取值范围
*/
public number (int range) {
d = (int) (Math.random() * range + 1.0); //分子
n = (int) (Math.random() * range + 1.0); //分母
if (d < n) { //如果分子大于分母,则当做整数处理
d = 1;
}
yf(); //约分
str = new String();
if (d == 1) { //生成这个数的字符串形式
str += n;
}
else {
str += n + "/" + d;
}
}
/*
* 默认的构造函数
*/
public number () {
str = new String ();
}
/*求最大公约数*/
public int GCD (int a, int b) {
int gcd = 1;
for (int i = 1; i <= a; i ++) {
if (a % i == 0 && b % i == 0) {
gcd = i;
}
}
return gcd;
}
/*对分数进行约分*/
public void yf () {
int gcd = GCD (d, n);
d /= gcd;
n /= gcd;
}
}
表达式类expression:
/*
* 表达式类的定义
*/
public class expression {
String exp; //表达式的字符串形式
number value; //表达式的值
char op = ' '; //两个子表达式中间的算符
/*
* 表达式类的构造函数
* 参数length为表达式的长度, range为运算数的范围
*/
public expression (int length, int range) {
exp = new String ();
value = new number();
char opr[] = {'+','-','*','/'}; //四则运算符
if (length == 1) { //递归边界,表达式长度为1
number num = new number (range);
exp += num.str;
value = num;
}
else if (length == 2) { //递归边界,表达式长度为2
number n1 = new number (range);
number n2 = new number (range);
op = opr[(int) (Math.random() * 4)];
exp += n1.str + " " + op + " " + n2.str;
value = solve (n1, n2, op);
}
else { //如果表达式的长度大于2,则要递归生成表达式
int temp = (int) (Math.random() * (length-1)) + 1;
op = opr[(int) (Math.random() * 4)];
//将表达式分解为两个子表达式,子表达式的长度随机生成
expression e1 = new expression (temp, range);
expression e2 = new expression (length - temp, range);
//将子表达式拼接在一起
if (temp == 1 //如果子表达式长度为1,或者长度为2且算符为乘除,则不用加括号
|| (temp == 2 && (e1.op == '*' || e1.op == '/'))) {
exp += e1.exp;
}
else {
exp += "(" + e1.exp + ")";
}
exp += " " + op + " ";
if (length - temp == 1 //如果子表达式长度为1,或者长度为2且算符为乘除,则不用加括号
|| (length - temp == 2 && (e2.op == '*' || e2.op == '/'))) {
exp += e2.exp;
}
else {
exp += "(" + e2.exp + ")";
}
//计算结果
value = solve (e1.value, e2.value, op);
}
}
/*
* 默认的构造函数
*/
public expression () {
exp = new String();
value = new number();
}
/*输出表达式*/
public void print () {
System.out.println(exp + " = ");
}
/*求两运算数表达式的值*/
public number solve (number x, number y, char op) {
number t1 = new number(), t2 = new number();
int lcm = LCM (x.d, y.d);
t1.n = x.n * lcm / x.d; //将两数通分
t2.n = y.n * lcm / y.d;
t1.d = t2.d = lcm;
switch (op) { //计算结果
case '+':
t1.n += t2.n;
break;
case '-':
t1.n -= t2.n;
break;
case '*':
t1.n = x.n * y.n;
t1.d = x.d * y.d;
break;
case '/':
t1.n = x.n * y.d;
t1.d = x.d * y.n;
break;
default:
break;
}
t1.yf(); //将结果进行约分
if (t1.d == 1) { //生成结果的字符串形式
t1.str += t1.n;
}
else {
t1.str += t1.n + "/" + t1.d;
}
return t1;
}
/*求最小公倍数*/
public int LCM (int a, int b) {
return a * b / GCD(a,b);
}
/*求最大公约数*/
public int GCD (int a, int b) {
int gcd = 1;
for (int i = 1; i <= a; i ++) {
if (a % i == 0 && b % i == 0) {
gcd = i;
}
}
return gcd;
}
}