国庆假期完成了结对项目,今天在这里总结学习心得
一、 总体需求
本次项目在中小学数学卷子的生成程序的基础上要求添加GUI,以及短信验证注册、计算、评分、修改密码等功能
二、 总体设计
本次项目为结对项目,因此分为两个模块一个是GUI模块,还有就是出题的模块。GUI是运用了事件驱动风格,通过对每个按钮的监听然后响应跳转到下一页面。下面我主要分析本次项目中的出题模块。
本次项目是根据上一个项目的基础进行修改以及添加,总计思路没有变,因此有些不足的地方还是保留了下来,就比如在出题选择初中或者高中的时候,那些高级运算符只设计出现在第一个数那里。还做了计算题目、设计正确答案等功能。
三、 代码分析
出题部分:
采用个人项目的思路,稍微改了一下,我们先生成一个仅含有加减乘除的表达式,记录下每个操作数的位置,然后在添加括号。完成以后在将高级运算符插入到第一个操作数的前面。
String title = ""; // 需输出的题目 String title_r = " "; // 简单处理后方便计算的题目 int caozuo = 0; // 操作数 Random rand = new Random(); if (type.equals("小学")) { caozuo = rand.nextInt(4) + 2; } else { caozuo = rand.nextInt(2) + 2; } int addr_head[] = new int[caozuo];// 记录每个操作数左地址 int addr_last[] = new int[caozuo];// 记录每个操作数右地址 addr_head[0] = 0; int count = 1; Random rand1 = new Random(); int number1 = rand1.nextInt(100) + 1; // 随机数1-100 String str10 = Integer.toString(number1); addr_last[0] = addr_head[0] + str10.length() - 1; title += str10; // 添加数字 for (int i = 1; i < caozuo; i++)// 生成一个含加减乘除的式子 { Random rand2 = new Random(); int carac = rand2.nextInt(4); // 随机4个运算符号 String carr = ""; switch (carac) { case 0: carr = "+"; break; case 1: carr = "-"; break; case 2: carr = "*"; break; case 3: carr = "/"; } title += carr;// 添加运算符 addr_head[count] = title.length(); count++; Random randn = new Random(); int numbern = randn.nextInt(100) + 1; // 随机数1-100 String strn = Integer.toString(numbern); addr_last[count - 1] = addr_head[count - 1] + strn.length() - 1; title += strn; // 添加数字 } addr_last[caozuo - 1] = title.length() - 1;
if (caozuo >= 3)// 在式子里添加括号 { int ch = rand.nextInt(caozuo - 1) + 1; // 3个操作数则生成随机数 1 2 // 4则生成 1 2 3 // 其中1为不加括号 if (ch > 1) { StringBuilder aha1 = new StringBuilder(title); aha1.insert(addr_last[ch - 1] + 1, ")"); title = aha1.toString(); StringBuilder aha2 = new StringBuilder(title); aha2.insert(0, "("); title = aha2.toString(); for (int i = 0; i < caozuo; i++)// 记录操作数位置移动 { addr_head[i]++; addr_last[i]++; } for (int i = ch; i < caozuo; i++)// 记录操作数位置移动 { addr_head[i]++; addr_last[i]++; } } }
if (type.equals("初中")) // 初中高级运算符添加 { int ch = 0; Random rand4 = new Random(); ch = rand4.nextInt(2) + 1; if (ch == 1)// 添加平方 { StringBuilder aha3 = new StringBuilder(title); aha3.insert(addr_last[0] + 1, "^2"); title = aha3.toString(); for (int i = 1; i < caozuo; i++) { addr_head[i] += 2; addr_last[i] += 2; } } else// 添加根号 { StringBuilder aha4 = new StringBuilder(title); aha4.insert(addr_head[0], "√"); title = aha4.toString(); for (int i = 0; i < caozuo; i++) { addr_head[i] += 1; addr_last[i] += 1; } } } if (type.equals("高中"))// 高中高级运算符添加 { int ch = 0; Random rand5 = new Random(); ch = rand5.nextInt(3) + 1; if (ch == 1) // 添加sin { StringBuilder aha5 = new StringBuilder(title); aha5.insert(addr_head[0], "sin"); title = aha5.toString(); } else if (ch == 2) // 添加cos { StringBuilder aha6 = new StringBuilder(title); aha6.insert(addr_head[0], "cos"); title = aha6.toString(); } else // 添加tan { StringBuilder aha7 = new StringBuilder(title); aha7.insert(addr_head[0], "tan"); title = aha7.toString(); } for (int i = 0; i < caozuo; i++) { addr_head[i] += 3; addr_last[i] += 3; } }
计算部分:
首先处理高级运算符,需要找到运算符的位置,然后找到对应的操作数,进行计算以后可以返回一个新的字符串并记录计算以后的数据即可完成。
public String SolveSquare(String s, String fuhao)// 处理平方和 { int last = s.indexOf(fuhao) - 1; // 查找符号 int head = last; // 操作数的位置 for (; head >= 0; head--) { if (s.charAt(head) < '0' || s.charAt(head) > '9') { head++; break; } } if (head < 0) { head = 0; } String str = s.substring(head, last + 1); double data = Double.valueOf(str); String str2 = " "; if (fuhao.equals("^2"))// 将平方数转化成结果 { str += "^2"; data *= data; str2 = Double.toString(data); } s = s.replace(str, str2); return s; // 返回处理后 的结果 }
public String SolveSqrt(String s, String fuhao)// 处理平方根 { int head = s.indexOf(fuhao) + 1; int last = head; for (; last < s.length(); last++) { if (s.charAt(last) < '0' || s.charAt(last) > '9') { break; } } if (last > s.length()) { last--; // 操作数的位置 } String str = s.substring(head, last); double data = Double.valueOf(str); String str2 = " "; if (fuhao.equals("√"))// 将平方数转化成结果 { str = "√" + str; data = Math.sqrt(data); str2 = DouStr(data); } s = s.replace(str, str2); return s; // 返回处理后 的结果 }
public String SolveTriangle(String s, String fuhao)// 处理三角函数 { int head = s.indexOf(fuhao) + 3; int last = head; for (; last < s.length(); last++) { if (s.charAt(last) < '0' || s.charAt(last) > '9') { break; } } if (last > s.length()) { last--; // 操作数的位置 } String str = s.substring(head, last); double data = Double.valueOf(str); String str2 = " "; if (fuhao.equals("sin")) // 转化sin结果 { str = "sin" + str; data = Math.sin(data); str2 = DouStr(data); } else if (fuhao.equals("cos"))// 转化cos结果 { str = "cos" + str; data = Math.cos(data); str2 = DouStr(data); } else// 转化tan结果 { str = "tan" + str; data = Math.tan(data); str2 = DouStr(data); } s = s.replace(str, str2); return s;// 返回处理三角函数的式子 }
然后根据算术优先级进行操作,优先级高的先计算,有括号的先计算
if (optStack.empty()) // 运算符栈栈顶为空则直接入栈 { optStack.push(curOpt); } else { if (curOpt.equals("(")) // 当前运算符为左括号,直接入运算符栈 { optStack.push(curOpt); } else if (curOpt.equals(")")) // 当前运算符为右括号,触发括号内的字表达式进行计算 { directCalc(optStack, numStack, true); } else if (curOpt.equals("=")) // 当前运算符为等号,触发整个表达式剩余计算,并返回总的计算结果 { directCalc(optStack, numStack, false); return numStack.pop().doubleValue(); } else// 当前运算符为加减乘除之一,要与栈顶运算符比较,判断是否要进行一次二元计算 { compareAndCalc(optStack, numStack, curOpt); } }
选项设计部分:
因为本次设计的不仅仅是出题做题,还需要进行答案的设计,需要制作错误答案来填入其他选项,我设计的是在正确答案的上下不超过20的范围以内随机生成,且不能出现重复。
int wrr = rand1.nextInt(4); double A = 0, B = 0, C = 0, D = 0; switch (wrr) { case 0:// 正确答案给A { rightchoice = "A"; m_A = DouStr(rightnumber); B = rightnumber + rand.nextInt(20) - 10; while (B == A) { B = rightnumber + rand.nextInt(20) - 10; } C = rightnumber + rand.nextInt(20) - 10; while (C == A || C == B) { C = rightnumber + rand.nextInt(20) - 10; } D = rightnumber + rand.nextInt(20) - 10; while (D == C || D == B || D == A) { D = rightnumber + rand.nextInt(20) - 10; } m_B = DouStr(B); m_C = DouStr(C); m_D = DouStr(D); } break; case 1:// 正确答案给B { rightchoice = "B"; m_B = DouStr(rightnumber); A = rightnumber + rand.nextInt(20) - 10; while (B == A) { A = rightnumber + rand.nextInt(20) - 10; } C = rightnumber + rand.nextInt(20) - 10; while (C == A || C == B) { C = rightnumber + rand.nextInt(20) - 10; } D = rightnumber + rand.nextInt(20) - 10; while (D == C || D == B || D == A) { D = rightnumber + rand.nextInt(20) - 10; } m_A = DouStr(A); m_C = DouStr(C); m_D = DouStr(D); } break; case 2: // 正确答案给C { rightchoice = "C"; m_C = DouStr(rightnumber); A = rightnumber + rand.nextInt(20) - 10; while (A == C) { A = rightnumber + rand.nextInt(20) - 10; } B = rightnumber + rand.nextInt(20) - 10; while (B == A || B == C) { B = rightnumber + rand.nextInt(20) - 10; } D = rightnumber + rand.nextInt(20) - 10; while (D == A || D == B || D == C) { D = rightnumber + rand.nextInt(20) - 10; } m_A = DouStr(A); m_B = DouStr(B); m_D = DouStr(D); } break; case 4: // 正确答案给D { rightchoice = "D"; m_D = DouStr(rightnumber); A = rightnumber + rand.nextInt(20) - 10; while (A == D) { A = rightnumber + rand.nextInt(20) - 10; } B = rightnumber + rand.nextInt(20) - 10; while (B == A || B == D) { B = rightnumber + rand.nextInt(20) - 10; } C = rightnumber + rand.nextInt(20) - 10; while (C == A || C == B || C == D) { C = rightnumber + rand.nextInt(20) - 10; } m_A = DouStr(A); m_B = DouStr(B); m_C = DouStr(C); } }
四、 总结
本次项目正逢假期,在学习的过程中遇到很多困难,因为出题部分是结合我先前的个人项目,而个人项目是用C++写的,这次需要设计GUI因此在选择编程语言的时候选择JAVA,而JAVA运用不是很熟练,在每次都要构建类的时候会出现一些奇怪的错误,在认真学习了以后完成的本次项目。同时也遇到了一些算法上的困难,比如说在进行正确答案的计算的时候,判断运算符优先级的时候面对括号实在是无从下手,在网上学习了以后才晓得解决。
本次项目耗时较长,虽然说不是很复杂,但是第一次进行这个编程的确很不熟悉。但是通过这次学习以后我学到了很多收获了很多。