项目需求:

像阿超那样,花二十分钟写一个能自动生成小学四则运算题目的命令行 “软件”, 分别满足下面的各种需求。下面这些需求都可以用命令行参数的形式来指定:

a) 除了整数以外,还要支持真分数的四则运算。 (例如:  1/6 + 1/8 = 7/24)

b) 让程序能接受用户输入答案,并判定对错。 最后给出总共 对/错 的数量。

c) 逐步扩展功能和可以支持的表达式类型,最后希望能支持下面类型的题目 (最多 10 个运算符,括号的数量不限制):
         25 - 3 * 4 - 2 / 2 + 89 = ?
         1/2 + 1/3 - 1/4 = ? 
        (5 - 4 ) * (3 +28) =?

d) 一次可以批量出 100 道以上的题目,保存在文本文件中, 并且保证题目不能重复,(1+2) 和 (2+1) 是重复的题目。

我的实现:

我了解到我的同学们大多都是用前、中、后缀表达式的互相转换来实现算式计算的,这个算法在上学期的课中编写过了,所以我想用个不一样的方法实现。

我使用了C#的反射,动态生成、编译代码。这样,只要在程序中生成了中缀表达式,将其转换为String型然后插入动态代码中编译,即可直接算出结果。

代码动态创建及编译的核心代码:

 1                 // 1.CSharpCodePrivoder
 2                 CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();
 3
 4                 // 2.ICodeComplier
 5                 ICodeCompiler objICodeCompiler = objCSharpCodePrivoder.CreateCompiler();
 6
 7                 // 3.CompilerParameters
 8                 CompilerParameters objCompilerParameters = new CompilerParameters();
 9                 objCompilerParameters.ReferencedAssemblies.Add("System.dll");
10                 objCompilerParameters.GenerateExecutable = false;
11                 objCompilerParameters.GenerateInMemory = true;
12
13                 // 4.CompilerResults
14                 GenerateLines();
15                 Console.WriteLine("==========No." + (i+1).ToString() + "==========");
16                 Console.WriteLine(lines);
17
18                 CompilerResults cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters, GenerateCode());
19
20                 if (cr.Errors.HasErrors)
21                 {
22                     Console.WriteLine("编译错误:");
23                     foreach (CompilerError err in cr.Errors)
24                     {
25                         Console.WriteLine(err.ErrorText);
26                     }
27                 }
28                 else
29                 {
30                     //通过反射,调用HelloWorld的实例
31                     Assembly objAssembly = cr.CompiledAssembly;
32                     object objHelloWorld = objAssembly.CreateInstance("DynamicCodeGenerate.HelloWorld");
33                     MethodInfo objMI = objHelloWorld.GetType().GetMethod("OutPut");
34                     string re = objMI.Invoke(objHelloWorld, null).ToString();
35                 }

其中,GenerateCode()是我用来生成代码的函数,返回了一个需要被动态编译的代码,其中定义了namespace DynamicCodeGenerate,public class HelloWorld以及其下方法public string OutPut()。

代码生成函数GenerateCode()的主要功能即是生成算式。因为题目要求程序可以计算分数,所以GenerateCode()还需要能进行通分、约分的操作。

GenerateCode()函数的主要流程:生成随机数,产生一个中缀表达式;对表达式全通分(即每一项都乘上所有被除项之积),然后将得数与刚才乘上的数约分,即得到分数形式的答案。

之后接受用户输入,和标准答案比对后输出结果即可。

完整代码:

  1 using System;
  2 using System.Reflection;
  3 using System.Globalization;
  4 using Microsoft.CSharp;
  5 using System.CodeDom;
  6 using System.CodeDom.Compiler;
  7 using System.Text;
  8 using System.Collections.Generic;
  9 using System.IO;
 10
 11 namespace A_Boring_Project_CSharp
 12 {
 13     class Program
 14     {
 15         static int max = 50;
 16         static int rows = 10;
 17         static List<int> nums;
 18         static List<int> add_n_minus;
 19         static List<int> div;
 20         static List<int> div_nums;
 21         static int tf;
 22         static int amount;
 23         static string lines;
 24         static string lines_tf;
 25         static string lines_final;
 26         static int count;
 27
 28         static void Main(string[] args)
 29         {
 30
 31             lines = "";
 32             count = 0;
 33
 34             for (int i = 0; i < rows; i++)
 35             {
 36                 // 1.CSharpCodePrivoder
 37                 CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();
 38
 39                 // 2.ICodeComplier
 40                 ICodeCompiler objICodeCompiler = objCSharpCodePrivoder.CreateCompiler();
 41
 42                 // 3.CompilerParameters
 43                 CompilerParameters objCompilerParameters = new CompilerParameters();
 44                 objCompilerParameters.ReferencedAssemblies.Add("System.dll");
 45                 objCompilerParameters.GenerateExecutable = false;
 46                 objCompilerParameters.GenerateInMemory = true;
 47
 48                 // 4.CompilerResults
 49                 GenerateLines();
 50                 Console.WriteLine("==========No." + (i+1).ToString() + "==========");
 51                 Console.WriteLine(lines);
 52
 53                 CompilerResults cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters, GenerateCode());
 54
 55                 if (cr.Errors.HasErrors)
 56                 {
 57                     Console.WriteLine("编译错误:");
 58                     foreach (CompilerError err in cr.Errors)
 59                     {
 60                         Console.WriteLine(err.ErrorText);
 61                     }
 62                 }
 63                 else
 64                 {
 65                     //通过反射,调用HelloWorld的实例
 66                     Assembly objAssembly = cr.CompiledAssembly;
 67                     object objHelloWorld = objAssembly.CreateInstance("DynamicCodeGenerate.HelloWorld");
 68                     MethodInfo objMI = objHelloWorld.GetType().GetMethod("OutPut");
 69                     string re = objMI.Invoke(objHelloWorld, null).ToString();
 70
 71                     string answer = Console.ReadLine();
 72
 73                     if (re == answer)
 74                     {
 75                         count++;
 76                         Console.WriteLine("Correct");
 77                     }
 78                     else
 79                     {
 80                         Console.WriteLine("Wrong, the answer should be " + re.ToString());
 81                     }
 82                 }
 83             }
 84             Console.WriteLine("Your score is: " + count.ToString() + " out of " + rows.ToString());
 85             Console.ReadLine();
 86         }
 87
 88         static string GenerateCode()
 89         {
 90
 91             StringBuilder sb = new StringBuilder();
 92             sb.Append("using System;using System.IO;using System.Collections.Generic;using System.Text;");
 93             sb.Append(Environment.NewLine);
 94             sb.Append("namespace DynamicCodeGenerate");
 95             sb.Append(Environment.NewLine);
 96             sb.Append("{");
 97             sb.Append(Environment.NewLine);
 98             sb.Append("\tpublic class HelloWorld");
 99             sb.Append(Environment.NewLine);
100             sb.Append("\t{");
101             sb.Append(Environment.NewLine);
102             sb.Append("\tpublic string OutPut()");
103             sb.Append(Environment.NewLine);
104             sb.Append("\t\t{");
105             sb.Append(Environment.NewLine);
106             sb.Append("long tf = "+ tf + ";");
107             sb.Append(Environment.NewLine);
108             sb.Append("long re = " + lines_final + ";");
109             sb.Append(Environment.NewLine);
110             sb.Append("for (int i = 2; i < re || i < tf; i++){while (re % i == 0 && tf % i == 0){re = re / i;tf = tf / i;}}");
111             sb.Append(Environment.NewLine);
112             sb.Append("Console.Write(\"Result = \");");
113             sb.Append("\t\tif (tf != 1){return re.ToString() + \"/\" + tf.ToString();} else{return re.ToString();}");
114             sb.Append(Environment.NewLine);
115             sb.Append(Environment.NewLine);
116             sb.Append("\t\t}");
117             sb.Append(Environment.NewLine);
118             sb.Append("\t}");
119             sb.Append(Environment.NewLine);
120             sb.Append("}");
121
122             string code = sb.ToString();
123
124             return code;
125         }
126
127         static void GenerateLines()
128         {
129             tf = 1;
130             nums = new List<int>();
131             add_n_minus = new List<int>();
132             div = new List<int>();
133             div_nums = new List<int>();
134             System.Random rnd = new System.Random(GetRandomSeed());
135             amount = rnd.Next(1, 11);
136             lines = "";
137             lines_tf = "";
138             lines_final = "";
139
140             int x = 0;
141             int d = 0;
142             List<int> anm;
143             List<int> op;
144             anm = new List<int>();
145             op = new List<int>();
146             for (int i = 0; i < amount; i++)
147             {
148                 //A new number
149                 rnd = new System.Random(GetRandomSeed());
150                 nums.Add(rnd.Next(1, max));
151                 lines += nums[i];
152                 //A new operator
153                 System.Random rnd0 = new System.Random(GetRandomSeed());
154                 int key = rnd0.Next(0,4);
155                 op.Add(lines.Length + 1);
156                 switch (key)
157                 {
158                     case 0:
159                         anm.Add(i);
160                         x = 0;
161                         lines += "+";
162                         add_n_minus.Add(lines.Length);
163                         break;
164                     case 1:
165                         anm.Add(i);
166                         x = 0;
167                         lines += "-";
168                         add_n_minus.Add(lines.Length);
169                         break;
170                     case 2:
171                         x++;
172                         if (x <= 3)
173                         {
174                             lines += "*";
175                             break;
176                         }
177                         else
178                         {
179                             goto case 1;
180                         }
181                     case 3:
182                         x = 0;
183                         d++;
184                         if (d <= 3)
185                         {
186                             lines += "/";
187                             div.Add(i);
188                             break;
189                         }
190                         else
191                         {
192                             goto case 1;
193                         }
194                     default:
195                         x = 0;
196                         break;
197                 }
198             }
199             op.Add(lines.Length);
200
201             rnd = new System.Random(GetRandomSeed());
202             nums.Add(rnd.Next(1, max));
203             lines += nums[amount];
204
205             for (int i = 0; i < div.Count; i++)
206             {
207                 div_nums.Add(nums[div[i] + 1]);
208                 lines_tf += div_nums[i];
209                 lines_tf += "*";
210                 tf *= div_nums[i];
211             }
212
213             lines_final += lines_tf;
214             lines_final += lines;
215
216             if (div.Count > 0)
217             {
218                 for (int i = 1; i <= add_n_minus.Count; i++)
219                 {
220                     lines_final = lines_final.Insert(i * lines_tf.Length + add_n_minus[i - 1], lines_tf);
221                 }
222             }
223
224         }
225
226         static int GetRandomSeed()
227         {
228             byte[] bytes = new byte[4];
229             System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
230             rng.GetBytes(bytes);
231             return BitConverter.ToInt32(bytes, 0);
232         }
233
234     }
235 }

小结:

在写GenerateCode()函数时,没有预先设计好控制、变量等等的具体实现,所以最终导致代码有点混乱,下次应该多加注意。

转载于:https://www.cnblogs.com/yuki8819/p/5305107.html

【个人项目总结】四则运算生成器相关推荐

  1. 作业五—个人项目-小学四则运算 “软件”之升级版1

    作业五-个人项目-小学四则运算 "软件"之升级版 作业要求来源:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/21 ...

  2. 小学四则运算生成器(Java实现)

    跳转详细介绍的博客:小学四则运算生成器(Java实现) 实现效果图: 开始运行程序 未输入生成题目数量及数值范围 输入数值 随机生成题目 用户输入并提交答案,后台将用户答案与正确答案进行校正,统计正确 ...

  3. 【软件工程基础】结对项目之四则运算题目生成

    [软件工程基础]结对项目之四则运算题目生成 一,项目介绍 项目的github地址:https://github.com/qqqqqianru/sizeyunsuantimushengcheng 二.项 ...

  4. 2017202110104-高级软件工程第二次作业个人项目之-四则运算生成程序

    GitHub项目地址 https://github.com/Cynnn/Arithmatic PSP2.1表格 PSP2.1 Personal Software Process Stages 预估耗时 ...

  5. 第三次作业:个人项目-小学四则运算 “软件”之初版

    本次作业要求来自于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2166 我的项目GitHub远程仓库地址:https://gith ...

  6. 高级软件工程2017第2次作业—— 个人项目:四则运算题目生成程序(基于控制台)...

    Deadline:2017-09-27(周三) 21:00pm (注:以下内容参考 福大软工作业 和集大个人作业 ) 0.前言 很多童鞋在本课程的目标和规划中,都表示希望能提高自己的实践能力. Pra ...

  7. 作业四 | 个人项目-小学四则运算 “软件”之初版

    作业要求来自于https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2186 GitHub远程仓库的地址https://github.com/ ...

  8. 【结对编程】四则运算生成器

    结对项目报告 源码及接口说明地址:https://github.com/hzphzp/ArithmeticCore/tree/master/ArithmeticCore 一.功能实现 按照用户设置的要 ...

  9. react小项目 - canvas海报生成器

    1.背景   之前做过一个营销类移动端h5项目-海报生成器,上传用户本地图片合成海报并支持下载,这次有时间了整理整理. 2.几个重点 上传本地图片并支持预览 处理ios照片翻转 使用canvas对图片 ...

最新文章

  1. 用 Python 写 3D 游戏,太赞了
  2. 常用计算机主要硬件设备,个人计算机常用的输出设备41.计算机硬件的组成部分主要包括:...
  3. 微信小程序——添加按钮格式
  4. RoFormerV2:自然语言理解的极限探索
  5. sql server 2012远程链接的方法及步骤
  6. Node.js中事件的循环
  7. Linux---信号及其使用简单讲解
  8. css_selector定位总结
  9. uBLAS——Boost 线性代数基础程序库
  10. jquery系列教程8-jquery插件大全
  11. node 连接mysql 中间件_如何在node.js里连接和使用mysql
  12. oracle12c集群安装—grid安装
  13. 硬件第二节 MOS管电路工作原理及详解
  14. python2 之 DataFrame
  15. 面试:Android应用的崩溃率
  16. 计算机电脑用英语单词怎么读,计算器 英语
  17. 同步时序逻辑电路功能分析之同步五进制加法计数器
  18. Python生信练习——hg38每条染色体基因,转录本的分布
  19. ora-29861: 域索引标记为loading/failed/unusable
  20. 图解Topo拓扑排序

热门文章

  1. php cms选择,php cms 选择哪个好?
  2. 无法支持python程序的编辑运行和调试_解决pycharm的Python console不能调试当前程序的问题...
  3. 初始化 数组 java_如何用Java初始化数组
  4. objective-c教程_Objective-C Hello世界教程
  5. 斯威夫特山地车_斯威夫特枚举
  6. java se面试题_Java SE 8面试问答(第2部分)
  7. Spring @Service批注
  8. hadoop和hdfs命令_Hadoop 1.x和2.x HDFS基本开发人员命令,“ hadoop”命令
  9. Sobel边缘检测算法及OpenCV函数实现
  10. 解决ubuntu下arduino IDE的Serial Port无法选择问题