二柱子的三个阶段——随机生成四则运算题目(java语言版)
今日下午在课上的最后40分钟遇到了经典的二柱子测试有个阶段组成,难度逐层增加,需求逐步增多,长话短说直接进入正题:



测试一和测试二较为简单,生成随机数并且保证不会有重复的题目,就可以完成
在这我将测试一和测试二合并完成,先简单描述一下我对问题的思路:
首先确定打印问题的数量,自己定义输入即可: Scanner sc=new Scanner (System.in); int num=sc.nextInt();
在这我们可以看到这里是两个操作数参与运算,所以我就简单定义了两个数组,用于存放两个参与随机运算的操作数,int []num1=new int[num+1];
int []num2=new int[num+1];
这里参与循环,循环结束的条件就是生成要求的题目数量
num1[i]=r.nextInt(100);
num2[i]=r.nextInt(100);
有多少道题就有多少个操作数,num+1是为了在接下的循环导致数组下标越界。
进行随机生成运算符的操作,这里只是简单的+-*/,所以我采用了这种方式表示:Random r=new Random();int ch=r.nextInt(3);ch的取值范围是(0,1,2,3),将ch对4取余,余数为0,1,2,3分别对应 + - * /。
判断题目是否重复也是我定义两个数组的原因:在每次生成两个随机数中只要有一个随机数没有出现重复,就可以认为这道题不被重复,当然这种做法也有点不合理
下面为代码展示:
package Secondweek;
import java.util.Random;
import java.util.Scanner;
public class Question {
public static void main(String[] args)
{
System.out.println("请输入出题数目:");
Scanner sc=new Scanner(System.in);
int sum=sc.nextInt();
int n=0;
int []num1=new int[sum+1];
int []num2=new int[sum+1];
System.out.println("请输入操作数个数:");
int num=sc.nextInt();
for(int i=0;i<=sum;i++)
{
Random random=new Random();
num1[i]=random.nextInt(100);
num2[i]=random.nextInt(100);
int ch=random.nextInt(3);
switch(ch)
{
case 0:
for(int j=0;j<i;j++)
{
if((num1[i]!=num1[j])||(num2[i]!=num2[j]))
{
System.out.println(num1[i]+"+"+num2[i]);
break;
}
}
n++;
break;
case 1:
for(int j=0;j<i;j++)
{
if((num1[i]!=num1[j])||(num2[i]!=num2[j]))
{
System.out.println(num1[i]+"-"+num2[i]);
break;
}
}
n++;
break;
case 2:
for(int j=0;j<i;j++)
{
if((num1[i]!=num1[j])||(num2[i]!=num2[j]))
{
System.out.println(num1[i]+"*"+num2[i]);
break;
}
}
n++;
break;
case 3:
for(int j=0;j<i;j++)
{
if((num1[i]!=num1[j])||(num2[i]!=num2[j]))
{
System.out.println(num1[i]+"*"+num2[i]);
break;
}
}
n++;
break;
}
}
}
}
因为这道题的题目是逐层递进的,要求是逐层增多的,到了第三阶段,额,我先给大家展示一下第三阶段的要求:
就一个定制操作数个数的要求让我对接下来的思考找不到方向,我不能定义任意个数组,有人推荐我使用二维数组,我当场就放弃了,主要还是自己所学的知识有限(数组就是那种没学会的那种),对于刚上大二,对于任何一门编程语言都是半吊子的我,但借鉴班里的大佬这点脸皮我还是有的,接下来为大家展示第三阶段的代码,这里面的加括号的要求我还有些不理解,其它的都已经能够完成,当然这段生成括号的代码我想也没能完成题目的要求
代码如下:
package Secondweek;
import java.util.Scanner;
import java.util.Random;
public class Secondzhu {
public static void main(String[] args)
{
Secondzhu A=new Secondzhu();
System.out.println("请输入你要出题数量:");
Scanner sc=new Scanner(System.in);
int num1=sc.nextInt();
System.out.println("请输入题目的操作数个数:");
int num2=sc.nextInt();
System.out.println("请输入操作数的取值范围:");
int range=sc.nextInt();
System.out.println("请选择有无乘除法(1:有,0:无)");
int op1=sc.nextInt();
System.out.println("请选择有无括号(1:有,0:无)");
int op2=sc.nextInt();
if(op1==1||op2==0)
{
A.questionTool(num1,num2,op1,op2,range);
}else
{
System.out.println("输入错误请重新输入!");
return;
}
}
//定义一个方法生成题目
public void questionTool(int num1,int num2,int op1,int op2,int range)
{
Random r=new Random();
int []str1=new int[num1*100]; //生成题目的数量
int []str2=new int[num2*2-1]; //每道题有数组中的元素构成,分别由操作数和运算符组成,且他们的关系运算符个数为操作数减一
//int mark=0;//定义一个记号防止生成的题目是否重复
for(int j=0;j<num1/*-mark*/;j++)//循环生成题目
{
boolean x=true;
//定义两个括号的位置,我也不清楚为什么这样定义
int frontk=r.nextInt(num2-1);
int behindK=r.nextInt(num2-frontk)+frontk+1;
//生成所有的随机数,符号另作处理
for(int i=0;i<num2*2-1;i++)
{
str2[i]=r.nextInt(range);
}
//定义一个流氓算法(计算生成每道题目的随机数总和,若总和相同则就被认为重复),防止出现重复的题目,这个算法是有缺陷的
for(int t=0;t<num2;t++)
{
str1[j]+=str2[t*2]*t; //*t有种更保险的感觉
}
//判断是否重复
for(int n=0;n<j;n++)
{
if(str1[n]==str1[j])
{
num1++;
x=false;
break;
}
}
//生成题目的过程,在一道题目数组中,操作数的下标永远为偶数(不考虑符号),运算符的下标为奇数,所以在下表偶数是输出随机数,在奇数下标讨论输出运算符
if(x)
{
for(int i=0;i<num2*2-1;i++)
{
if(op2==1)//先从判断有无括号选择分支结构
{
if(2*frontk==i)
System.out.print("(");
if(i%2==0&&i!=num2*2-2) //下标为偶数
{
System.out.print(str2[i]+" ");
if(2*str2[i]-2==i)
System.out.println(")");
}else if(i == num2*2-2) //当下表为最后一个偶数时,对括号的增加另作处理。
{
System.out.print(str2[i]);
if( 2*behindK - 2 == i)
System.out.print(")");
System.out.println(" =");
}else if(i%2==1)
{
if(op1==1) //有无乘除
{
if(str2[i]%4==0)
{
System.out.print("+");
}
else if(str2[i]%4==1)
{
System.out.print("-");
}
else if(str2[i]%4==2)
{
System.out.print("*");
}
else if(str2[i]%4==3)
{
System.out.print("/");
}
}else if(op1==0)
{
if(str2[i]%2==0)
{
System.out.print("+");
}
else if(str2[i]%2==1)
{
System.out.print("-");
}
}
}
}else
{
if(i%2 == 0 && i!= num2*2-2)
{
System.out.print(str2[i] + " ");
}
else if(i == num2*2-2)
{
System.out.println(str2[i] + " =");
if( 2*behindK - 1 == i)
System.out.print(")");
}else if(i%2==1)
{
if(op1==1) //有无乘除
{
if(str2[i]%4==0)
{
System.out.print("+");
}
else if(str2[i]%4==1)
{
System.out.print("-");
}
else if(str2[i]%4==2)
{
System.out.print("*");
}
else if(str2[i]%4==3)
{
System.out.print("/");
}
}else if(op1==0)
{
if(str2[i]%2==0)
{
System.out.print("+");
}
else if(str2[i]%2==1)
{
System.out.print("-");
}
}
}
}
}
}
}
}
}
这个整体的思路就与我相差很多,但我自己为这段代码添加了注释也方便你们理解,令我脑洞大开的是他将一道题目以数组的形式来完成,这个需要对一道题目的构成分解到为,思路十分清晰,众所周知,变成就是将我们难以下手的问题分解,分解到我们能够解决的程度,他这里将一道题目分解到了数组中的元素程度上,让我对分解这一操作认识更加深刻,如有疑问欢迎评论等方式与我交流。

浙公网安备 33010602011771号