结对项目——自动生成小学四则运算
Posted vickyleung
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了结对项目——自动生成小学四则运算相关的知识,希望对你有一定的参考价值。
结对项目——自动生成小学四则运算
1.Github项目地址:
https://github.com/Vicky-Leung/demo
项目制作人:3218005081梁小燕 3218005083许梓莹
2.PSP表格:
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
60 |
159 |
· Estimate |
· 估计这个任务需要多少时间 |
60 |
159 |
Development |
开发 |
1770 |
2166 |
· Analysis |
· 需求分析 (包括学习新技术) |
235 |
409 |
· Design Spec |
· 生成设计文档 |
25 |
8 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
15 |
25 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
25 |
22 |
· Design |
· 具体设计 |
60 |
30 |
· Coding |
· 具体编码 |
1260 |
1602 |
· Code Review |
· 代码复审 |
30 |
10 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
120 |
60 |
Reporting |
报告 |
120 |
117 |
· Test Report |
· 测试报告 |
60 |
33 |
· Size Measurement |
· 计算工作量 |
30 |
10 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 |
72 |
合计 |
|
1950 |
2442 |
3.解题思路:
- 语言选择:java script
- 先随机生成运算数,运算符,并控制括号,从而生成题目
- 对生成的题目转换成后缀表达式并计算结果(逆波兰算法)
- 对结果和题目进行检查是否有重复题目
- 对用户输入的答案进行批改
- 提供题目和答案下载功能
4.设计实现过程:
- function pro (){} 生成题目,并存储运算数,运算符,并进行括号匹配
- function polish(){} 对生成的中缀表达式转换成后缀表达式‘’
- function workpolish(){} 计算中缀表达式(在计算过程中,分数一律按假分数进行运算,并且只在整道题目运算结束后才对结果进行化简,转换成真分数)
- function confoim(){} 对结果进行检查,以及检查是否出现了重复的题目(检查重复的题目:先检查结果是否相等,再检查运算符个数是否相等,最后检查运算符和运算数是否都相同)
- function showAnswer(){} 显示答案
- function making(){} 批改
- function downloadQuestion(){} 下载题目
- function downloadAnswer(){} 下载答案
5.代码说明:
部分代码:
1 function pro(){ 2 var operatorNum = randomNum(1,3); //题目会使用多少个符号? 3 arr[i][0] = operatorNum; 4 var num = 1, op = 1; 5 while (num <= operatorNum+1 && op <= operatorNum){ 6 if (arr[i][op-1] != "/") 7 s[i][num] = randomNum(0,range); //生成运算数 8 else 9 s[i][num] = randomNum(1,range); //生成运算数 10 arr[i][op] = randomOperator(); //生成运算符 11 num++; 12 op++; 13 } 14 var brack; //控制括号 15 switch (operatorNum) {//控制括号 16 case 1: 17 problem[i] = s[i][1] + arr[i][1] + s[i][2]; 18 break; 19 case 2: 20 brack = randomNum(1,2); 21 if (brack == 1) 22 problem[i] = s[i][1] + arr[i][1] + s[i][2] + arr[i][2] +s[i][3]; 23 else 24 problem[i] = s[i][1] + arr[i][1] + "(" + s[i][2] + arr[i][2] +s[i][3] + ")"; 25 break; 26 case 3: 27 brack = randomNum(1,5) 28 if (brack == 1) 29 problem[i] = s[i][1] + arr[i][1] + s[i][2] + arr[i][2] +s[i][3] + arr[i][3] + s[i][4]; 30 else if (brack == 2) 31 problem[i] = "(" + s[i][1] + arr[i][1] + s[i][2] + ")" + arr[i][2] +s[i][3] + arr[i][3] + s[i][4]; 32 else if (brack == 3) 33 problem[i] = s[i][1] + arr[i][1] + "(" + s[i][2] + arr[i][2] +s[i][3] + ")" + arr[i][3] + s[i][4]; 34 else if (brack == 4) 35 problem[i] = s[i][1] + arr[i][1] + s[i][2] + arr[i][2] + "(" +s[i][3] + arr[i][3] + s[i][4] + ")"; 36 else 37 problem[i] = s[i][1] + arr[i][1] +"(" + s[i][2] + arr[i][2] +s[i][3] + arr[i][3] + s[i][4] + ")"; 38 break; 39 }//end switch 40 }//end pro 41 42 43 function randomNum(min,max) { 44 return Math.floor(Math.random() * (max - min + 1) + min); 45 } 46 47 48 function randomOperator() { 49 var operator; 50 operator = randomNum(1,4); 51 if (operator == 1) 52 return "+"; 53 else if (operator == 2) 54 return "-"; 55 else if (operator ==3) 56 return "*"; 57 else 58 return "/"; 59 }
1 function polish() { //中缀转后缀 2 var str_p = problem[i].toString(); //中缀表达式转字符串 3 var middleArr = str_p.split(‘‘); //中缀表达式转数组 4 var opStack = []; //运算符栈 5 var outputQueue = []; //输出队列,后缀表达式 6 var pi = 0; 7 while (pi < middleArr.length) { 8 var ch = middleArr[pi].toString(); 9 var out; 10 switch (ch) { 11 case "+": 12 case "-": 13 if (opStack.length > 0) { //栈不空 14 out = opStack.pop(); //取出栈顶元素 15 if (out != "(") { //栈顶不是左括号 16 outputQueue.push(out); //栈顶元素添加到后缀表达式 17 } 18 else { //栈顶元素是左括号 19 opStack.push(out); //把刚刚的栈顶元素放回去 20 } 21 } 22 opStack.push(ch); //当前运算符进栈 23 pi++; 24 break; 25 26 case "*": 27 case "/": 28 if (opStack.length > 0) { //栈不空 29 out = opStack.pop(); //取出栈顶元素 30 if (out == "*" || out == "/") { //栈顶是乘号或除号 31 outputQueue.push(out); //栈顶元素添加到后缀表达式 32 } 33 else { //栈顶不是乘号也不是除号 34 opStack.push(out); //把刚刚的栈顶元素放回去 35 } 36 } 37 opStack.push(ch); //当前运算符进栈 38 pi++; 39 break; 40 41 case "(": 42 opStack.push(ch); 43 pi++; 44 break; 45 case ")": 46 out = opStack.pop(); //取出栈顶元素 47 while (out != null && out != "(") { //直到遇到左括号 48 outputQueue.push(out); //栈顶元素添加到后缀表达式 49 out = opStack.pop(); 50 } 51 pi++; 52 break; 53 54 default: //遇到数字 55 while ( pi < middleArr.length && (ch >= ‘0‘ && ch <= ‘9‘ ) ) { 56 outputQueue.push(ch); //直接添加到输出队列 57 pi++; 58 if (pi < middleArr.length) 59 ch = middleArr[pi]; 60 } 61 outputQueue.push(‘ ‘); //添加空格作为数值之间的分隔符 62 }//end switch 63 64 }//end while 65 66 while (opStack.length != 0){ //已遍历完中缀表达式,若运算符栈不为空 67 out = opStack.pop(); //取出栈顶元素 68 outputQueue.push(out); //添加到后缀表达式 69 } 70 71 return outputQueue; 72 73 }//end polish
1 function workPolish() { //计算后缀表达式 2 var value = ""; //用于还原运算数 3 var value2= ""; 4 var numStack = []; //运算数栈 5 // var vue = ""; 6 while (Queue.length > 0) { 7 var cur = Queue.shift(); //取队头 8 if (cur >= ‘0‘ && cur <= ‘9‘ ) { //遇到数字 9 value = ""; 10 while(cur != ‘ ‘) { //不是空格 11 value2 = cur; 12 value = value + value2; 13 cur = Queue.shift(); //继续取队头 14 } 15 numStack.push(value.toString()); //压入运算数栈 16 } 17 else if(cur != ‘ ‘){ //出现了运算符,则取出两个运算数 18 var y = numStack.pop(); 19 var x = numStack.pop(); 20 var vue = worktwo(x, y, cur); 21 numStack.push(vue); 22 } 23 }//end while 24 return numStack; //这个结果是还没化简的 25 } 26 27 28 function worktwo (fir, sec, cur) { 29 if(fir.toString().indexOf(‘/‘) == -1 && sec.toString().indexOf(‘/‘) == -1) { //两数都不是分数 30 fir = Number(fir); 31 sec = Number(sec); 32 switch(cur) { 33 case ‘+‘: return (fir + sec); 34 case ‘-‘: return (fir - sec); 35 case ‘*‘: return (fir * sec); 36 case ‘/‘: return fir + ‘/‘ + sec; 37 } 38 } 39 else if(fir.toString().indexOf(‘/‘) != -1 && sec.toString().indexOf(‘/‘) == -1){ //第一个数为分数 40 var fractional = fir.split(‘/‘); //字符串分割成数组 fractional【0】分子/fractional【1】分母 41 switch(cur) { 42 case ‘+‘: return ( Number(fractional[1]) * Number(sec) + Number(fractional[0]) ) + ‘/‘ + Number(fractional[1]); 43 case ‘-‘: return ( Number(fractional[0]) - Number(fractional[1]) * Number(sec) ) + ‘/‘ + Number(fractional[1]); 44 case ‘*‘: return ( Number(fractional[0]) * Number(sec) ) + ‘/‘ + Number(fractional[1]); 45 case ‘/‘: return Number(fractional[0]) + ‘/‘ + ( Number(fractional[1]) * Number(sec) ); 46 } 47 48 } 49 else if(fir.toString().indexOf(‘/‘) == -1 && sec.toString().indexOf(‘/‘) != -1){ //第二个数为分数 50 var fractional = sec.split(‘/‘); 51 switch(cur) { 52 case ‘+‘: return Number(fractional[1]) * Number(fir) + Number(fractional[0]) + ‘/‘ + Number(fractional[1]); 53 case ‘-‘: return ( Number(fractional[1]) * Number(fir) - Number(fractional[0]) ) + ‘/‘ + Number(fractional[1]); 54 case ‘*‘: return ( Number(fractional[0]) * Number(fir) ) + ‘/‘ + Number(fractional[1]); 55 case ‘/‘: return ( Number(fractional[1]) * Number(fir) ) + ‘/‘ + Number(fractional[0]); 56 } 57 } 58 else if(fir.toString().indexOf(‘/‘) != -1 && sec.toString().indexOf(‘/‘) != -1){ //两个数都是分数 59 var fractional1 = fir.split(‘/‘); 60 var fractional2 = sec.split(‘/‘); 61 switch(cur) { 62 case ‘+‘: return ( Number(fractional2[1]) * Number(fractional1[0]) + Number(fractional2[0]) * Number(fractional1[1]) ) + ‘/‘ + (Number(fractional1[1]) * Number(fractional2[1]) ); 63 case ‘-‘: return ( Number(fractional1[0]) * Number(fractional2[1]) - Number(fractional2[0]) * Number(fractional1[1]) ) + ‘/‘ + (Number( fractional1[1]) * Number(fractional2[1]) ); 64 case ‘*‘: return ( Number(fractional1[0]) * Number(fractional2[0]) ) + ‘/‘ + ( Number(fractional1[1]) * Number(fractional2[1]) ); 65 case ‘/‘: return ( Number(fractional1[0]) * Number(fractional2[1]) ) + ‘/‘ + ( Number(fractional1[1]) * Number(fractional2[0]) ); 66 } 67 } 68 } 69 70 71 function factor(fx, fy) { // 找最大公因数 72 var t = 0; 73 while(fy) { 74 t = fx%fy; //取余 75 fx = fy; 76 fy = t; 77 } 78 return fx; 79 } 80 81 82 function fenShu (a, b, ft) { // 分数化简 (a为分子,b为分母,mf为最大公因数) 83 if(ft == 1) { // 最大公因数是1 84 if(a > b) { // 分子大,则转化为真分式 85 return parseInt(a/b) + ‘’‘ + a%b + ‘/‘ + b; 86 } 87 else if(a < b) { // 分子小 88 return a + ‘/‘ + b; 89 } 90 //若最大公因数为1,且a==b,那么a=b=1,而b==1这种情况已经在huajian(num)里面解决了,所以这里不写 91 } 92 else { //最大公因数不是1,eg:a=12, b=18, ft=6 93 var fa = a/ft; 94 var fb = b/ft; 95 if( fb==1) { 96 return fa; 97 } 98 else { //此时最大公因数是1,回到前面部分,所以这里用递归 99 return fenShu(fa, fb, factor(fa, fb)); 100 } 101 } 102 } 103 104 105 function huajian(num) { 106 num = num.toString(); 107 if (num.indexOf(‘/‘) == -1) { //不是分数 108 if (num >= 0) return num; 109 else return "#"; //"#"用于标记无效题目 110 } 111 else { //若是分数,化简 112 var arr = num.split(‘/‘); 113 arr[0] = Number(arr[0]); //分子 114 arr[1] = Number(arr[1]); //分母 115 if (arr[0] < 0 || arr[1] <= 0) 116 return "#"; 117 if (arr[1] == 1) 118 return arr[0]; 119 else 120 return fenShu(arr[0], arr[1], factor(arr[0], arr[1])); 121 } 122 }
1 function conform() { 2 var ci = 1; 3 Queue = polish(); //Queue是一个全局队列,将会用于计算后缀表达式 4 sum = workPolish(); //sum此时暂存未化简的结果 5 sum = huajian(sum); //sum此时是化简后的分数 6 if (sum == "#") { 7 return 0; 8 } 9 if (sum != "#" ){ 10 arr[i][4] = sum; 11 for(ci = 1; ci < i; ci++){ 12 if (arr[ci][4].toString()==arr[i][4].toString()) { //与ci题结果相同 13 if (arr[ci][0]==arr[i][0]) { //运算符个数也相同 14 var str_a = ""; //存入ci题所有运算符 15 var str_b = ""; //存入ci题所有运算数 16 switch (arr[i][0]) { 17 case 1: //一个运算符 18 str_b = s[ci][1].toString() + s[ci][2].toString(); 19 if( arr[ci][1]==arr[i][1] && str_b.indexOf(s[i][1].toString())!=-1 ) //运算符和运算数也相同 20 return 0; 21 break; 22 case 2: 23 str_a = arr[ci][1] + arr[ci][2]; 24 str_b = s[ci][1].toString() + s[ci][2].toString() + s[ci][3].toString(); 25 if( str_a.indexOf(arr[i][1])!=-1 && str_a.indexOf(arr[i][2])!=-1 26 && str_b.indexOf(s[i][1].toString())!=-1 && str_b.indexOf(s[i][2].toString())!=-1 && str_b.indexOf(s[i][3].toString())!=-1 ) 27 return 0; 28 break; 29 case 3: 30 str_a = arr[ci][1] + arr[ci][2] + arr[ci][3]; 31 str_b = s[ci][1].toString() + s[ci][2].toString() + s[ci][3].toString() + s[ci][4].toString(); 32 if( str_a.indexOf(arr[i][1])!=-1 && str_a.indexOf(arr[i][2])!=-1 && str_a.indexOf(arr[i][3])!=-1 33 && str_b.indexOf(s[i][1].toString())!=-1 && str_b.indexOf(s[i][2].toString())!=-1 && str_b.indexOf(s[i][3].toString())!=-1 && str_b.indexOf(s[i][4].toString())!=-1 ) 34 return 0; 35 break; 36 }//end switch 37 } 38 } 39 } 40 return 1; 41 }//end if 42 }
1 function downloadQuestion(){ 2 if(sign ==0 ){alert("请先出题");return false;} 3 var question = quesitonshtmlArr.toString(); 4 var name = "question.txt"; 5 question = question.split("<input class=‘userA‘ type=‘text‘/></li>"); 6 question = question.join(" "); 7 question = question.split("<li>"); 8 question = question.join(""); 9 10 download(name,question) 11 } 12 13 14 function donloadAnswer(){ 15 if(sign ==0 ){alert("请先出题");return false;} 16 var answer =answerHtmlArr.toString(); 17 var name = "answer.txt"; 18 answer = answer.split("</li>"); 19 answer = answer.join(" "); 20 answer = answer.split("<li>"); 21 answer = answer.join(""); 22 download(name,answer) 23 } 24 25 26 function download(filename, text) { 27 var pom = document.createElement(‘a‘); 28 pom.setAttribute(‘href‘, ‘data:text/plain;charset=utf-8,‘ + encodeURIComponent(text)); 29 pom.setAttribute(‘download‘, filename); 30 if (document.createEvent) { 31 var event = document.createEvent(‘MouseEvents‘); 32 event.initEvent(‘click‘, true, true); 33 pom.dispatchEvent(event); 34 } else { 35 pom.click(); 36 } 37 }
全部代码:
1 <!DOCTYPE html> 2 <!DOCTYPE html> 3 <html> 4 <head> 5 <title>四则运算生成器</title> 6 <meta charset="utf-8"> 7 <link rel="stylesheet" type="text/css" href="index.css"> 8 <script src="index.js"></script> 9 </head> 10 <body> 11 <div class="site-header"> 12 <p>软件工程结对项目</p> 13 </div> 14 <div class="box"></div> 15 <div class="premises"> 16 <div class="premises-content1"> 17 <p>题目数量:<input type="txt" name="subject" id="subject" placeholder="如:10"></p> 18 <p>题目范围:<input type="txt" name="range" id="range" placeholder="如:20"></p> 19 <button class="premises-submit" onclick="start()">确定</button> 20 </div> 21 </div> 22 <div class="content"> 23 <p>生成题目内容如下:</p> 24 <div class="question"> 25 <ul id="question-text"> 26 27 </ul> 28 29 </div> 30 <div class="answer"> 31 <ul id="answer-text"> 32 <li>点击下方功能键查看答案</li> 33 </ul> 34 </div> 35 36 </div> 37 <div class="content2"> 38 39 <a class="change"><button class="bleft" onclick="marking()">自动批改</button></a> 40 <a class="change"><button class="bleft2" onclick="downloadQuestion()">下载题目</button></a> 41 <a class="change"><button class="bright2" onclick="donloadAnswer()">下载答案</button></a> 42 <a class="change"><button class="bright" onclick="showAnswer()">查看完整答案</button></a> 43 </div> 44 <div id="Right"> 45 <p>点击批改可查看正确题数<p> 46 </div> 47 <div id="Fault"> 48 <p>点击批改可查看错误题数</p> 49 </div> 50 51 </body> 52 </html>
1 window.sign=0; 2 3 4 function start() { 5 quesitonsHtmlArr = new Array();//所有题目字段,可用于下载 6 answerHtmlArr = new Array();//字符串,页面备用 7 answerSign=0; 8 9 10 subject = document.getElementById("subject").value; //题目数 11 range = document.getElementById("range").value; //数字范围 12 13 if(subject == 0 || subject < 0 || subject >10000 ) {alert("请输入正确题目数量,不大于10000道");return; } 14 if(range == 0 || range < 0) {alert("请输入正确题目范围");return; } 15 sign=1; 16 17 s = new Array(); //存数字 18 for (s_i = 0; s_i <= subject; s_i++) { 19 s [s_i] = new Array(); 20 for (s_j = 0; s_j <= 4; s_j++) { //s_j==1-4时,存运算数 21 s[s_i][s_j] = 1; 22 23 } 24 } 25 arr = new Array(); //存字符串 26 for (arr_i = 0; arr_i <= subject; arr_i++) { 27 arr [arr_i] = new Array(); 28 for (arr_j = 0; arr_j <= 4; arr_j++) { //arr_j==0时存运算符个数,arr_j==1-3时存入运算符,arr_j==4时存入结果 29 arr[arr_i][arr_j] = ‘‘; 30 } 31 } 32 problem = new Array(); //存储整道题目,用于打印和计算结果 33 34 i = 1; //第几号题目 35 while(i <= subject){ 36 pro(); 37 if (conform()){ 38 console.log(‘第‘+i+‘题: ‘); 39 console.log(problem[i]+" = " + arr[i][4].toString()); 40 quesitonsHtmlArr += (‘<li>‘ + ‘第‘ + i + ‘题: ‘ + problem[i].toString() + ‘ = ‘ + "<input class=‘userA‘ type=‘text‘/>" + ‘</li>‘ ); 41 i++; 42 } 43 } 44 document.getElementById("question-text").innerHTML = quesitonsHtmlArr; 45 } 46 47 48 function conform() { 49 var ci = 1; 50 Queue = polish(); //Queue是一个全局队列,将会用于计算后缀表达式 51 sum = workPolish(); //sum此时暂存未化简的结果 52 sum = huajian(sum); //sum此时是化简后的分数 53 if (sum == "#") { 54 return 0; 55 } 56 if (sum != "#" ){ 57 arr[i][4] = sum; 58 for(ci = 1; ci < i; ci++){ 59 if (arr[ci][4].toString()==arr[i][4].toString()) { //与ci题结果相同 60 if (arr[ci][0]==arr[i][0]) { //运算符个数也相同 61 var str_a = ""; //存入ci题所有运算符 62 var str_b = ""; //存入ci题所有运算数 63 switch (arr[i][0]) { 64 case 1: //一个运算符 65 str_b = s[ci][1].toString() + s[ci][2].toString(); 66 if( arr[ci][1]==arr[i][1] && str_b.indexOf(s[i][1].toString())!=-1 ) //运算符和运算数也相同 67 return 0; 68 break; 69 case 2: 70 str_a = arr[ci][1] + arr[ci][2]; 71 str_b = s[ci][1].toString() + s[ci][2].toString() + s[ci][3].toString(); 72 if( str_a.indexOf(arr[i][1])!=-1 && str_a.indexOf(arr[i][2])!=-1 73 && str_b.indexOf(s[i][1].toString())!=-1 && str_b.indexOf(s[i][2].toString())!=-1 && str_b.indexOf(s[i][3].toString())!=-1 ) 74 return 0; 75 break; 76 case 3: 77 str_a = arr[ci][1] + arr[ci][2] + arr[ci][3]; 78 str_b = s[ci][1].toString() + s[ci][2].toString() + s[ci][3].toString() + s[ci][4].toString(); 79 if( str_a.indexOf(arr[i][1])!=-1 && str_a.indexOf(arr[i][2])!=-1 && str_a.indexOf(arr[i][3])!=-1 80 && str_b.indexOf(s[i][1].toString())!=-1 && str_b.indexOf(s[i][2].toString())!=-1 && str_b.indexOf(s[i][3].toString())!=-1 && str_b.indexOf(s[i][4].toString())!=-1 ) 81 return 0; 82 break; 83 }//end switch 84 } 85 } 86 } 87 return 1; 88 }//end if 89 } 90 91 92 93 function polish() { //中缀转后缀 94 var str_p = problem[i].toString(); //中缀表达式转字符串 95 var middleArr = str_p.split(‘‘); //中缀表达式转数组 96 var opStack = []; //运算符栈 97 var outputQueue = []; //输出队列,后缀表达式 98 var pi = 0; 99 while (pi < middleArr.length) { 100 var ch = middleArr[pi].toString(); 101 var out; 102 switch (ch) { 103 case "+": 104 case "-": 105 if (opStack.length > 0) { //栈不空 106 out = opStack.pop(); //取出栈顶元素 107 if (out != "(") { //栈顶不是左括号 108 outputQueue.push(out); //栈顶元素添加到后缀表达式 109 } 110 else { //栈顶元素是左括号 111 opStack.push(out); //把刚刚的栈顶元素放回去 112 } 113 } 114 opStack.push(ch); //当前运算符进栈 115 pi++; 116 break; 117 118 case "*": 119 case "/": 120 if (opStack.length > 0) { //栈不空 121 out = opStack.pop(); //取出栈顶元素 122 if (out == "*" || out == "/") { //栈顶是乘号或除号 123 outputQueue.push(out); //栈顶元素添加到后缀表达式 124 } 125 else { //栈顶不是乘号也不是除号 126 opStack.push(out); //把刚刚的栈顶元素放回去 127 } 128 } 129 opStack.push(ch); //当前运算符进栈 130 pi++; 131 break; 132 133 case "(": 134 opStack.push(ch); 135 pi++; 136 break; 137 case ")": 138 out = opStack.pop(); //取出栈顶元素 139 while (out != null && out != "(") { //直到遇到左括号 140 outputQueue.push(out); //栈顶元素添加到后缀表达式 141 out = opStack.pop(); 142 } 143 pi++; 144 break; 145 146 default: //遇到数字 147 while ( pi < middleArr.length && (ch >= ‘0‘ && ch <= ‘9‘ ) ) { 148 outputQueue.push(ch); //直接添加到输出队列 149 pi++; 150 if (pi < middleArr.length) 151 ch = middleArr[pi]; 152 } 153 outputQueue.push(‘ ‘); //添加空格作为数值之间的分隔符 154 }//end switch 155 156 }//end while 157 158 while (opStack.length != 0){ //已遍历完中缀表达式,若运算符栈不为空 159 out = opStack.pop(); //取出栈顶元素 160 outputQueue.push(out); //添加到后缀表达式 161 } 162 163 return outputQueue; 164 165 }//end polish 166 167 168 function workPolish() { //计算后缀表达式 169 var value = ""; //用于还原运算数 170 var value2= ""; 171 var numStack = []; //运算数栈 172 // var vue = ""; 173 while (Queue.length > 0) { 174 var cur = Queue.shift(); //取队头 175 if (cur >= ‘0‘ && cur <= ‘9‘ ) { //遇到数字 176 value = ""; 177 while(cur != ‘ ‘) { //不是空格 178 value2 = cur; 179 value = value + value2; 180 cur = Queue.shift(); //继续取队头 181 } 182 numStack.push(value.toString()); //压入运算数栈 183 } 184 else if(cur != ‘ ‘){ //出现了运算符,则取出两个运算数 185 var y = numStack.pop(); 186 var x = numStack.pop(); 187 var vue = worktwo(x, y, cur); 188 numStack.push(vue); 189 } 190 }//end while 191 return numStack; //这个结果是还没化简的 192 } 193 194 195 function worktwo (fir, sec, cur) { 196 if(fir.toString().indexOf(‘/‘) == -1 && sec.toString().indexOf(‘/‘) == -1) { //两数都不是分数 197 fir = Number(fir); 198 sec = Number(sec); 199 switch(cur) { 200 case ‘+‘: return (fir + sec); 201 case ‘-‘: return (fir - sec); 202 case ‘*‘: return (fir * sec); 203 case ‘/‘: return fir + ‘/‘ + sec; 204 } 205 } 206 else if(fir.toString().indexOf(‘/‘) != -1 && sec.toString().indexOf(‘/‘) == -1){ //第一个数为分数 207 var fractional = fir.split(‘/‘); //字符串分割成数组 fractional【0】分子/fractional【1】分母 208 switch(cur) { 209 case ‘+‘: return ( Number(fractional[1]) * Number(sec) + Number(fractional[0]) ) + ‘/‘ + Number(fractional[1]); 210 case ‘-‘: return ( Number(fractional[0]) - Number(fractional[1]) * Number(sec) ) + ‘/‘ + Number(fractional[1]); 211 case ‘*‘: return ( Number(fractional[0]) * Number(sec) ) + ‘/‘ + Number(fractional[1]); 212 case ‘/‘: return Number(fractional[0]) + ‘/‘ + ( Number(fractional[1]) * Number(sec) ); 213 } 214 215 } 216 else if(fir.toString().indexOf(‘/‘) == -1 && sec.toString().indexOf(‘/‘) != -1){ //第二个数为分数 217 var fractional = sec.split(‘/‘); 218 switch(cur) { 219 case ‘+‘: return Number(fractional[1]) * Number(fir) + Number(fractional[0]) + ‘/‘ + Number(fractional[1]); 220 case ‘-‘: return ( Number(fractional[1]) * Number(fir) - Number(fractional[0]) ) + ‘/‘ + Number(fractional[1]); 221 case ‘*‘: return ( Number(fractional[0]) * Number(fir) ) + ‘/‘ + Number(fractional[1]); 222 case ‘/‘: return ( Number(fractional[1]) * Number(fir) ) + ‘/‘ + Number(fractional[0]); 223 } 224 } 225 else if(fir.toString().indexOf(‘/‘) != -1 && sec.toString().indexOf(‘/‘) != -1){ //两个数都是分数 226 var fractional1 = fir.split(‘/‘); 227 var fractional2 = sec.split(‘/‘); 228 switch(cur) { 229 case ‘+‘: return ( Number(fractional2[1]) * Number(fractional1[0]) + Number(fractional2[0]) * Number(fractional1[1]) ) + ‘/‘ + (Number(fractional1[1]) * Number(fractional2[1]) ); 230 case ‘-‘: return ( Number(fractional1[0]) * Number(fractional2[1]) - Number(fractional2[0]) * Number(fractional1[1]) ) + ‘/‘ + (Number( fractional1[1]) * Number(fractional2[1]) ); 231 case ‘*‘: return ( Number(fractional1[0]) * Number(fractional2[0]) ) + ‘/‘ + ( Number(fractional1[1]) * Number(fractional2[1]) ); 232 case ‘/‘: return ( Number(fractional1[0]) * Number(fractional2[1]) ) + ‘/‘ + ( Number(fractional1[1]) * Number(fractional2[0]) ); 233 } 234 } 235 } 236 237 238 function factor(fx, fy) { // 找最大公因数 239 var t = 0; 240 while(fy) { 241 t = fx%fy; //取余 242 fx = fy; 243 fy = t; 244 } 245 return fx; 246 } 247 248 249 function fenShu (a, b, ft) { // 分数化简 (a为分子,b为分母,mf为最大公因数) 250 if(ft == 1) { // 最大公因数是1 251 if(a > b) { // 分子大,则转化为真分式 252 return parseInt(a/b) + ‘’‘ + a%b + ‘/‘ + b; 253 } 254 else if(a < b) { // 分子小 255 return a + ‘/‘ + b; 256 } 257 //若最大公因数为1,且a==b,那么a=b=1,而b==1这种情况已经在huajian(num)里面解决了,所以这里不写 258 } 259 else { //最大公因数不是1,eg:a=12, b=18, ft=6 260 var fa = a/ft; 261 var fb = b/ft; 262 if( fb==1) { 263 return fa; 264 } 265 else { //此时最大公因数是1,回到前面部分,所以这里用递归 266 return fenShu(fa, fb, factor(fa, fb)); 267 } 268 } 269 } 270 271 272 function huajian(num) { 273 num = num.toString(); 274 if (num.indexOf(‘/‘) == -1) { //不是分数 275 if (num >= 0) return num; 276 else return "#"; //"#"用于标记无效题目 277 } 278 else { //若是分数,化简 279 var arr = num.split(‘/‘); 280 arr[0] = Number(arr[0]); //分子 281 arr[1] = Number(arr[1]); //分母 282 if (arr[0] < 0 || arr[1] <= 0) 283 return "#"; 284 if (arr[1] == 1) 285 return arr[0]; 286 else 287 return fenShu(arr[0], arr[1], factor(arr[0], arr[1])); 288 } 289 } 290 291 292 function pro(){ 293 var operatorNum = randomNum(1,3); //题目会使用多少个符号? 294 arr[i][0] = operatorNum; 295 var num = 1, op = 1; 296 while (num <= operatorNum+1 && op <= operatorNum){ 297 if (arr[i][op-1] != "/") 298 s[i][num] = randomNum(0,range); //生成运算数 299 else 300 s[i][num] = randomNum(1,range); //生成运算数 301 arr[i][op] = randomOperator(); //生成运算符 302 num++; 303 op++; 304 } 305 var brack; //控制括号 306 switch (operatorNum) {//控制括号 307 case 1: 308 problem[i] = s[i][1] + arr[i][1] + s[i][2]; 309 break; 310 case 2: 311 brack = randomNum(1,2); 312 if (brack == 1) 313 problem[i] = s[i][1] + arr[i][1] + s[i][2] + arr[i][2] +s[i][3]; 314 else 315 problem[i] = s[i][1] + arr[i][1] + "(" + s[i][2] + arr[i][2] +s[i][3] + ")"; 316 break; 317 case 3: 318 brack = randomNum(1,5) 319 if (brack == 1) 320 problem[i] = s[i][1] + arr[i][1] + s[i][2] + arr[i][2] +s[i][3] + arr[i][3] + s[i][4]; 321 else if (brack == 2) 322 problem[i] = "(" + s[i][1] + arr[i][1] + s[i][2] + ")" + arr[i][2] +s[i][3] + arr[i][3] + s[i][4]; 323 else if (brack == 3) 324 problem[i] = s[i][1] + arr[i][1] + "(" + s[i][2] + arr[i][2] +s[i][3] + ")" + arr[i][3] + s[i][4]; 325 else if (brack == 4) 326 problem[i] = s[i][1] + arr[i][1] + s[i][2] + arr[i][2] + "(" +s[i][3] + arr[i][3] + s[i][4] + ")"; 327 else 328 problem[i] = s[i][1] + arr[i][1] +"(" + s[i][2] + arr[i][2] +s[i][3] + arr[i][3] + s[i][4] + ")"; 329 break; 330 }//end switch 331 }//end pro 332 333 334 function randomNum(min,max) { 335 return Math.floor(Math.random() * (max - min + 1) + min); 336 } 337 338 339 function randomOperator() { 340 var operator; 341 operator = randomNum(1,4); 342 if (operator == 1) 343 return "+"; 344 else if (operator == 2) 345 return "-"; 346 else if (operator ==3) 347 return "*"; 348 else 349 return "/"; 350 } 351 352 353 function showAnswer(){ 354 if(sign == 0 ){alert("请先出题");return false;} 355 if(answerSign==1){alert("已输出答案,查看上方答案栏");return false;} 356 357 var j; 358 for(j = 1;j <= subject;j++) 359 { 360 answerHtmlArr += ‘<li>‘+ ‘第‘ + j +‘题:‘+ arr[j][4] +‘</li>‘; 361 } 362 document.getElementById(‘answer-text‘).innerHTML=answerHtmlArr; 363 364 answerSign=1; 365 366 367 } 368 369 370 function marking(){ 371 if(sign ==0 ){alert("请先出题");return false;} 372 var j,tureTotal,flaseTotal; 373 var userAnswer=document.getElementsByClassName("userA") 374 userAn = []; 375 trueAnswer = new Array(); 376 trueAnswer="<p>正确题号:"; 377 flaseAnswer = new Array(); 378 flaseAnswer="<p>错误题号:"; 379 tureTotal=0; 380 flaseTotal=0; 381 382 383 for(j = 1;j <= subject;j++) 384 { 385 if(userAnswer[j-1].value == arr[j][4]) 386 { trueAnswer+= j + ‘,‘;tureTotal++;} 387 else 388 { flaseAnswer += j+‘,‘;flaseTotal++;} 389 userAn[j] = userAnswer[j-1].value; 390 391 } 392 console.log(userAn); 393 console.log(tureTotal); 394 console.log(flaseTotal); 395 trueAnswer+="</p><h>共"+tureTotal+"题</h>"; 396 flaseAnswer+="</p><h>共"+flaseTotal+"题</h>"; 397 console.log(trueAnswer); 398 console.log(flaseAnswer); 399 400 document.getElementById("Right").innerHTML = trueAnswer; 401 document.getElementById("Fault").innerHTML = flaseAnswer; 402 403 } 404 405 406 function downloadQuestion(){ 407 if(sign ==0 ){alert("请先出题");return false;} 408 var question = quesitonsHtmlArr.toString(); 409 var name = "question.txt"; 410 question = question.split("<input class=‘userA‘ type=‘text‘/></li>"); 411 question = question.join(" "); 412 question = question.split("<li>"); 413 question = question.join(""); 414 415 download(name,question) 416 } 417 418 419 function donloadAnswer(){ 420 if(sign ==0 ){alert("请先出题");return false;} 421 var answer =answerHtmlArr.toString(); 422 var name = "answer.txt"; 423 answer = answer.split("</li>"); 424 answer = answer.join(" "); 425 answer = answer.split("<li>"); 426 answer = answer.join(""); 427 download(name,answer) 428 } 429 430 431 function download(filename, text) { 432 var pom = document.createElement(‘a‘); 433 pom.setAttribute(‘href‘, ‘data:text/plain;charset=utf-8,‘ + encodeURIComponent(text)); 434 pom.setAttribute(‘download‘, filename); 435 if (document.createEvent) { 436 var event = document.createEvent(‘MouseEvents‘); 437 event.initEvent(‘click‘, true, true); 438 pom.dispatchEvent(event); 439 } else { 440 pom.click(); 441 } 442 }
1 *{ 2 margin: 0; 3 padding: 0; 4 5 } 6 body{ 7 min-width:1000px; 8 background-image: linear-gradient(to bottom right ,#eaafc8,#654ea3); 9 } 10 .site-header{ 11 width:100%; 12 text-align: center; 13 background-color:#ffffff; 14 padding:1rem; 15 color: #654ea3; 16 font-weight:bold; 17 position:fixed; 18 font-family: "STCaiyun"; 19 font-size:1.5rem; 20 } 21 .box{ 22 height:3.56rem; 23 24 } 25 .premises{ 26 font-family: "楷体"; 27 background-color:#654ea3; 28 /*background-image: linear-gradient(to bottom right, #9cbdb3 , #37b8e9);*/ 29 30 } 31 32 .premises-content1{ 33 padding-top:1rem; 34 text-align:center; 35 width:20rem; 36 margin:0 auto; 37 line-height:3rem; 38 color:#ffffff; 39 } 40 .premises-content1 button{ 41 height:2rem; 42 width:5rem; 43 border-radius:5px; 44 border:none; 45 background-color:#ffffff; 46 color:#654ea3; 47 text-align:center; 48 text-decoration:none; 49 cursor:pointer; 50 font-weight:bold; 51 outline:none; 52 } 53 .premises-content1 button:hover{ 54 background-color:black; 55 color:#ffffff; 56 57 } 58 59 60 61 .premises-content1 input{ 62 border:1px solid #ccc; 63 padding:7px 0px; 64 padding-left:0.3rem; 65 border-radius:3px; 66 } 67 .content{ 68 width:60%; 69 height:38rem; 70 margin:0 auto; 71 line-height:2rem; 72 padding-top:2rem; 73 } 74 .question{ 75 float:left; 76 background-color:#ececec; 77 height:35rem; 78 width: 50%; 79 box-shadow:-2px 3px 5px 0px gray; 80 81 padding-left: 2rem; 82 overflow:auto; 83 } 84 .question input{ 85 border:none; 86 border-bottom:1px solid black; 87 background:transparent; 88 outline:medium; 89 padding-left:1rem; 90 text-align:center; 91 font-size:1.2rem; 92 width:7rem; 93 94 95 } 96 .answer{ 97 float:right; 98 background-color:#ececec; 99 height:35rem; 100 width:38%; 101 box-shadow:2px 3px 5px 0px gray; 102 padding-left:2rem; 103 overflow:auto; 104 } 105 .content ul{ 106 list-style:none; 107 } 108 .content2{ 109 width:30rem; 110 margin:0 auto; 111 height:3rem; 112 transform:translateX(25%); 113 114 } 115 .content2 button{ 116 height:2rem; 117 width:auto; 118 border-radius:5px; 119 border:none; 120 background-color:#ffffff; 121 color:#654ea3; 122 text-align:center; 123 text-decoration:none; 124 cursor:pointer; 125 font-weight:bold; 126 padding:0.5rem; 127 display:block; 128 outline:none; 129 130 } 131 .content2 button:hover{ 132 background-color:black; 133 color:#ffffff; 134 } 135 .bleft{ 136 137 float:left; 138 } 139 .bleft2{ 140 float:left; 141 margin-left:1rem; 142 } 143 .bright2{ 144 float:right; 145 margin-left:1rem; 146 } 147 148 .bright{ 149 150 float:right; 151 } 152 #Right{ 153 width:80%; 154 height:5rem; 155 margin:0 auto; 156 border:1px solid gray; 157 padding-left: 2rem; 158 padding-top:1rem; 159 overflow:auto; 160 background-color:#ffffff; 161 opacity:0.4; 162 } 163 #Fault{ 164 width:80%; 165 height:5rem; 166 margin:0 auto; 167 border:1px solid gray; 168 padding-left: 2rem; 169 padding-top:1rem; 170 background-color:#ffffff; 171 opacity:0.4; 172 margin-bottom:5rem; 173 overflow:auto; 174 175 }
6.测试运行:
界面
生成题目
批改及显示答案
下载
7.项目小结:
1.在这次项目中,我们不仅更加熟悉了html,css javascript语言的运用,还学习了逆波兰算法,同时也增加了与人合作开发的经验。
2.在完成这个项目的时候遇到了很多不懂的内容,我们提出彼此的想法,互相交流学习进度。而且结对项目让我们互相督促彼此,让两个人更有学习的动力。
以上是关于结对项目——自动生成小学四则运算的主要内容,如果未能解决你的问题,请参考以下文章
201571030303/201571030315《 小学四则运算练习软件》结对项目报告;
201571030122/201571030129 《小学生四则运算》 结对项目
201571030129/201571030122 《小学生四则运算》 结对项目