zoukankan      html  css  js  c++  java
  • 【结对项目总结】优化的四则运算生成器

    结对小组信息:

    13070027 郑亦然

    13070038 李芳达

    基于之前的个人项目(http://www.cnblogs.com/yuki8819/p/5305107.html),本项目将主体功能封装,并加入了新的控制模块,并且制作了GUI

    效果如图

    程序主要分为三个模块:Controller, Generator, Calculator

    Controller负责控制GUI,与后台交互

    Generator封装了生成算式的功能

    Calculator封装了计算算式的功能

    关于Calculator和Generator的设计可见http://www.cnblogs.com/yuki8819/p/5305107.html

    Generator支持参数修改:本轮生成多少算式?算式中运算数的最大数值?算式长度?

    使用主界面中的Option按钮可以进入修改参数的界面

    按下Next按钮可以生成一条算式,在输入框中输入答案后,按OK按钮可以得到结果(作对或做错,以及正确答案)

    做完规定的题数后,会得到最后的得分(即作对的题数)

    按Restart键可以重新开始一轮答题

    测试方面,由于这个程序本身在输入上不会出现非法输入(输入框有格式限制),所以我新建了一个控制台程序来测试Calculator模块,代码如下:

    1 static void Main(string[] args)
    2 {
    3     while (true)
    4     {
    5         string line = Console.ReadLine();
    6         Console.WriteLine(Calculate(line));
    7     }
    8 }

    输入算式,由CMD显示运算结果或错误提示

    输入错误测试:

    +12-34(以符号开始)

    12-34+(以符号结束)

    12++34*56(连续的运算符)

    12+34/0-56*78(0作被除数)

    12x45+56*78/23(非法字符)

    (空算式)

    12+34/56*78(正确算式)

    结果:

    这次的结对项目是我和同学李芳达一起完成的,在设计过程中,我们一起讨论了几种可行的解决方案,最后选择了上述方案。对于GUI的选择,我们使用了Unity3D的GUI系统。虽然我们都对这个引擎不很熟悉,但是我们对它很感兴趣,所以决定一起学习使用这个引擎。过程还是比较顺利的,最终结果也比较令人满意。

    全部源代码:

    PS: 源代码需要在Unity3D工程下才可以运行

    Controller

      1 using UnityEngine;
      2 using System.Collections;
      3 using UnityEngine.UI;
      4 using System;
      5 
      6 public class Controller : MonoBehaviour 
      7 {
      8     public GameObject field_Answer;
      9     public GameObject btn_Next;
     10     public GameObject btn_Restart;
     11     public GameObject btn_Options;
     12     public GameObject btn_OK;
     13     public GameObject txt_Quiz;
     14     public GameObject txt_Result;
     15 
     16     public GameObject OptionText;
     17 
     18     public GameObject field_Amount;
     19     public GameObject field_Max;
     20     public GameObject field_Operators;
     21 
     22     public Generator generator;
     23 
     24     public string result;
     25     public int count;
     26     public int correct;
     27 
     28     // Use this for initialization
     29     void Start()
     30     {
     31         generator = new Generator();
     32         field_Answer = new GameObject();
     33         btn_Next = new GameObject();
     34         btn_Restart = new GameObject();
     35         btn_Options = new GameObject();
     36         btn_OK = new GameObject();
     37         OptionText = new GameObject();
     38         txt_Quiz = new GameObject();
     39         txt_Result = new GameObject();
     40         field_Amount = new GameObject();
     41         field_Max = new GameObject("field_Max");
     42         field_Operators = new GameObject("field_Operators");
     43 
     44         field_Answer = GameObject.Find("field_Answer");
     45         btn_Next = GameObject.Find("btn_Next");
     46         btn_Restart = GameObject.Find("btn_Restart");
     47         btn_Options = GameObject.Find("btn_Options");
     48         btn_OK = GameObject.Find("btn_OK");
     49         txt_Quiz = GameObject.Find("txt_Quiz");
     50         txt_Result = GameObject.Find("txt_Result");
     51 
     52         OptionText = GameObject.Find("OptionText");
     53 
     54         field_Amount = GameObject.Find("field_Amount");
     55         field_Max = GameObject.Find("field_Max");
     56         field_Operators = GameObject.Find("field_Operators");
     57 
     58 
     59 
     60         field_Amount.SetActive(false);
     61         field_Max.SetActive(false);
     62         field_Operators.SetActive(false);
     63         txt_Result.SetActive(false);
     64 
     65         count = 0;
     66         correct = 0;
     67     }
     68 
     69     // Update is called once per frame
     70     void Update()
     71     {
     72         
     73     }
     74 
     75     public void OnNext()
     76     {
     77         generator.GenerateLines();
     78         Text txt = txt_Quiz.GetComponent<Text>();
     79         txt.text = generator.lines;
     80         result = Calculator.Calculate(generator.lines_final, generator.tf);
     81         Debug.Log(result);
     82         btn_OK.SetActive(true);
     83         InputField inf = field_Answer.GetComponent<InputField>();
     84         inf.text = "";
     85     }
     86 
     87     public void OnOK()
     88     {
     89         count++;
     90         btn_OK.SetActive(false);
     91         InputField inf = field_Answer.GetComponent<InputField>();
     92         if (inf.text == result)
     93         {
     94             correct++;
     95             Text txt = txt_Quiz.GetComponent<Text>();
     96             txt.text = "Correct!";
     97         }
     98         else
     99         {
    100             Text txt = txt_Quiz.GetComponent<Text>();
    101             txt.text = "Wrong answer! The answer should be: " + result;
    102         }
    103         if (count >= generator.rows)
    104         {
    105             txt_Result.SetActive(true);
    106             Text txt = txt_Result.GetComponent<Text>();
    107             txt.text = "Finished!
    Your Score is: " + correct + " out of " + count;
    108             btn_Next.SetActive(false);
    109         }
    110     }
    111 
    112     public void OnRestart()
    113     {
    114         btn_OK.SetActive(false);
    115         count = 0;
    116         correct = 0;
    117         Text txt = txt_Quiz.GetComponent<Text>();
    118         txt.text = "";
    119         txt_Result.SetActive(false);
    120         btn_Next.SetActive(true);
    121     }
    122 
    123     public void OnOptions()
    124     {
    125         if (!field_Amount.active)
    126         {
    127             field_Amount.SetActive(true);
    128             InputField infa = field_Amount.GetComponent<InputField>();
    129             infa.text = "" + generator.rows;
    130             field_Max.SetActive(true);
    131             InputField infm = field_Max.GetComponent<InputField>();
    132             infm.text = "" + generator.max;
    133             field_Operators.SetActive(true);
    134             InputField info = field_Operators.GetComponent<InputField>();
    135             info.text = "" + generator.operators;
    136 
    137             field_Answer.SetActive(false);
    138             btn_Next.SetActive(false);
    139             txt_Quiz.SetActive(false);
    140             btn_OK.SetActive(false);
    141             txt_Result.SetActive(false);
    142 
    143             Text txt = OptionText.GetComponent<Text>();
    144             txt.text = "Confirm";
    145         }
    146         else
    147         {
    148             field_Amount.SetActive(false);
    149             InputField infa = field_Amount.GetComponent<InputField>();
    150             generator.rows = Int32.Parse(infa.text);
    151             field_Max.SetActive(false);
    152             InputField infm = field_Max.GetComponent<InputField>();
    153             generator.max = Int32.Parse(infm.text);
    154             field_Operators.SetActive(false);
    155             InputField info = field_Operators.GetComponent<InputField>();
    156             generator.operators = Int32.Parse(info.text);
    157 
    158             field_Answer.SetActive(true);
    159             btn_Next.SetActive(true);
    160             txt_Quiz.SetActive(true);
    161             btn_OK.SetActive(false);
    162             txt_Result.SetActive(false);
    163 
    164             Text txt = OptionText.GetComponent<Text>();
    165             txt.text = "Options";
    166             OnRestart();
    167         }
    168         
    169     }
    170 }
    View Code

    Generator

      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 using UnityEngine;
     12 using System.Collections;
     13 
     14 
     15 public class Generator
     16 {
     17     public int max;//最大数值
     18     public int rows;//生成算式个数
     19     public int operators;//每行运算符个数
     20     public List<int> nums;
     21     public List<int> add_n_minus;
     22     public List<int> div;
     23     public List<int> div_nums;
     24     public int tf;//通分分母
     25     public int amount;
     26     public string lines;
     27     public string lines_tf;//通分分母字符串
     28     public string lines_final;//通分分子字符串
     29     public int count;
     30 
     31 
     32     public Generator()
     33     {
     34         max = 50;
     35         rows = 10;
     36         operators = 10;
     37     }
     38 
     39 
     40     public void GenerateLines()
     41     {
     42         tf = 1;
     43         nums = new List<int>();
     44         add_n_minus = new List<int>();
     45         div = new List<int>();
     46         div_nums = new List<int>();
     47         System.Random rnd = new System.Random(GetRandomSeed());
     48         amount = rnd.Next(1, operators + 1);
     49         lines = "";
     50         lines_tf = "";
     51         lines_final = "";
     52 
     53         int x = 0;
     54         int d = 0;
     55         for (int i = 0; i < amount; i++)
     56         {
     57             //A new number
     58             rnd = new System.Random(GetRandomSeed());
     59             nums.Add(rnd.Next(1, max));
     60             lines += nums[i];
     61             //A new operator
     62             System.Random rnd0 = new System.Random(GetRandomSeed());
     63             int key = rnd0.Next(0, 4);
     64             switch (key)
     65             {
     66                 case 0:
     67                     x = 0;
     68                     lines += "+";
     69                     add_n_minus.Add(lines.Length);
     70                     break;
     71                 case 1:
     72                     x = 0;
     73                     lines += "-";
     74                     add_n_minus.Add(lines.Length);
     75                     break;
     76                 case 2:
     77                     x++;
     78                     if (x <= 3)
     79                     {
     80                         lines += "*";
     81                         break;
     82                     }
     83                     else
     84                     {
     85                         goto case 1;
     86                     }
     87                 case 3:
     88                     x = 0;
     89                     d++;
     90                     if (d <= 3)
     91                     {
     92                         lines += "/";
     93                         div.Add(i);
     94                         break;
     95                     }
     96                     else
     97                     {
     98                         goto case 1;
     99                     }
    100                 default:
    101                     x = 0;
    102                     break;
    103             }
    104         }
    105 
    106         rnd = new System.Random(GetRandomSeed());
    107         nums.Add(rnd.Next(1, max));
    108         lines += nums[amount];
    109 
    110         for (int i = 0; i < div.Count; i++)
    111         {
    112             div_nums.Add(nums[div[i] + 1]);
    113             lines_tf += div_nums[i];
    114             lines_tf += "*";
    115             tf *= div_nums[i];
    116         }
    117 
    118         lines_final += lines_tf;
    119         lines_final += lines;
    120 
    121         if (div.Count > 0)
    122         {
    123             for (int i = 1; i <= add_n_minus.Count; i++)
    124             {
    125                 lines_final = lines_final.Insert(i * lines_tf.Length + add_n_minus[i - 1], lines_tf);
    126             }
    127         }
    128     }
    129 
    130     public int GetRandomSeed()
    131     {
    132         byte[] bytes = new byte[4];
    133         System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
    134         rng.GetBytes(bytes);
    135         return BitConverter.ToInt32(bytes, 0);
    136     }
    137 }
    View Code

    Calculator

      1 using UnityEngine;
      2 using System;
      3 using System.Reflection;
      4 using System.Globalization;
      5 using Microsoft.CSharp;
      6 using System.CodeDom;
      7 using System.CodeDom.Compiler;
      8 using System.Text;
      9 using System.Collections.Generic;
     10 using System.IO;
     11 using System.Collections;
     12 
     13 static class Calculator
     14 {
     15     public static string Calculate(string lines)
     16     {
     17         if (lines[0] < '0' || lines[0] > '9')
     18         {
     19             return "Error: the formula must be begun with a number";
     20         }
     21         if (lines[lines.Length - 1] < '0' || lines[lines.Length - 1] > '9')
     22         {
     23             return "Error: the formula must be ended with a number";
     24         }
     25         for (int i = 0; i < lines.Length; i++)
     26         {
     27             if ((lines[i] >= '0' && lines[i] <= '9') || lines[i] == '+' || lines[i] == '-' || lines[i] == '*' || lines[i] == '/')
     28             {
     29                 if (lines[i] < '0' || lines[i] > '9')
     30                 {
     31                     if (lines[i + 1] < '0' || lines[i + 1] > '9')
     32                     {
     33                         return "Error: continuous operators are not allowed";
     34                     }
     35                     if (lines[i] == '/')
     36                     {
     37                         if (lines[i + 1] == '0')
     38                         {
     39                             return "Error: 0 cannot be divided";
     40                         }
     41                     }
     42                 }
     43             }
     44             else
     45             {
     46                 return "Error: invalid characters included";
     47             }
     48         }
     49 
     50         string temp = lines;
     51         List<int> nums = new List<int>();
     52         List<int> add_n_minus = new List<int>();
     53         List<int> div = new List<int>();
     54         List<int> div_nums = new List<int>();
     55         string lines_tf = "";
     56         string lines_final = "";
     57         int tf = 1;
     58         for (int i = temp.Length; i >= 0; i--)
     59         {
     60             if (temp[i] == '+' || temp[i] == '-' || temp[i] == '*' || temp[i] == '/')
     61             {
     62                 string n = temp.Substring(i + 1, temp.Length - i);
     63                 temp = temp.Remove(i);
     64                 nums.Add(Int32.Parse(n));
     65                 if (temp[i] == '+' || temp[i] == '-')
     66                 {
     67                     add_n_minus.Add(lines.Length - i);
     68                 }
     69                 else if (temp[i] == '/')
     70                 {
     71                     div.Add(nums.Count);
     72                 }
     73             }
     74         }
     75         nums.Add(Int32.Parse(temp));
     76         nums.Reverse(0,nums.Count - 1);
     77         div.Reverse();
     78         for (int i = 0; i < div.Count; i++)
     79         {
     80             div[i] = nums.Count - div[i];
     81         }
     82         for (int i = 0; i < div.Count; i++)
     83         {
     84             div_nums.Add(nums[div[i] + 1]);
     85             lines_tf += div_nums[i];
     86             lines_tf += "*";
     87             tf *= div_nums[i];
     88         }
     89 
     90         lines_final += lines_tf;
     91         lines_final += lines;
     92 
     93         if (div.Count > 0)
     94         {
     95             for (int i = 1; i <= add_n_minus.Count; i++)
     96             {
     97                 lines_final = lines_final.Insert(i * lines_tf.Length + add_n_minus[i - 1], lines_tf);
     98             }
     99         }
    100 
    101         // 1.CSharpCodePrivoder
    102         CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();
    103 
    104         // 2.ICodeComplier
    105         ICodeCompiler objICodeCompiler = objCSharpCodePrivoder.CreateCompiler();
    106 
    107         // 3.CompilerParameters
    108         CompilerParameters objCompilerParameters = new CompilerParameters();
    109         objCompilerParameters.ReferencedAssemblies.Add("System.dll");
    110         objCompilerParameters.GenerateExecutable = false;
    111         objCompilerParameters.GenerateInMemory = true;
    112 
    113         // 4.CompilerResults
    114 
    115 
    116         CompilerResults cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters, GenerateCode(lines_final, tf));
    117 
    118         if (cr.Errors.HasErrors)
    119         {
    120             Debug.Log("编译错误:");
    121             foreach (CompilerError err in cr.Errors)
    122             {
    123                 Debug.Log(err.ErrorText);
    124             }
    125             return "Error: compiler error.";
    126         }
    127         else
    128         {
    129             //通过反射,调用HelloWorld的实例
    130             Assembly objAssembly = cr.CompiledAssembly;
    131             object objHelloWorld = objAssembly.CreateInstance("DynamicCodeGenerate.HelloWorld");
    132             MethodInfo objMI = objHelloWorld.GetType().GetMethod("OutPut");
    133             return objMI.Invoke(objHelloWorld, null).ToString();
    134         }
    135     }
    136 
    137     public static string Calculate(string lines_final, int tf)
    138     {
    139         if (tf == 0)
    140         {
    141             return "Error: 0 cannot be divided";
    142         }
    143         if (lines_final[0] < '0' || lines_final[0] > '9')
    144         {
    145             return "Error: the formula must be begun with a number";
    146         }
    147         if (lines_final[lines_final.Length - 1] < '0' || lines_final[lines_final.Length - 1] > '9')
    148         {
    149             return "Error: the formula must be ended with a number";
    150         }
    151         for (int i = 0; i < lines_final.Length; i++)
    152         {
    153             if ((lines_final[i] >= '0' && lines_final[i] <= '9') || lines_final[i] == '+' || lines_final[i] == '-' || lines_final[i] == '*' || lines_final[i] == '/')
    154             {
    155                 if (lines_final[i] < '0' || lines_final[i] > '9')
    156                 {
    157                     if (lines_final[i + 1] < '0' || lines_final[i + 1] > '9')
    158                     {
    159                         return "Error: continuous operators are not allowed";
    160                     }
    161                     if (lines_final[i] == '/')
    162                     {
    163                         if (lines_final[i + 1] == '0')
    164                         {
    165                             return "Error: 0 cannot be divided";
    166                         }
    167                     }
    168                 }
    169             }
    170             else
    171             {
    172                 return "Error: invalid characters included";
    173             }
    174         }
    175 
    176         // 1.CSharpCodePrivoder
    177         CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();
    178 
    179         // 2.ICodeComplier
    180         ICodeCompiler objICodeCompiler = objCSharpCodePrivoder.CreateCompiler();
    181 
    182         // 3.CompilerParameters
    183         CompilerParameters objCompilerParameters = new CompilerParameters();
    184         objCompilerParameters.ReferencedAssemblies.Add("System.dll");
    185         objCompilerParameters.GenerateExecutable = false;
    186         objCompilerParameters.GenerateInMemory = true;
    187 
    188         // 4.CompilerResults
    189         
    190 
    191         CompilerResults cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters, GenerateCode(lines_final, tf));
    192 
    193         if (cr.Errors.HasErrors)
    194         {
    195             Debug.Log("编译错误:");
    196             foreach (CompilerError err in cr.Errors)
    197             {
    198                 Debug.Log(err.ErrorText);
    199             }
    200             return "Error: compiler error.";
    201         }
    202         else
    203         {
    204             //通过反射,调用HelloWorld的实例
    205             Assembly objAssembly = cr.CompiledAssembly;
    206             object objHelloWorld = objAssembly.CreateInstance("DynamicCodeGenerate.HelloWorld");
    207             MethodInfo objMI = objHelloWorld.GetType().GetMethod("OutPut");
    208             return objMI.Invoke(objHelloWorld, null).ToString();
    209         }
    210     }
    211 
    212     public static string GenerateCode(string lines_final, int tf)
    213     {
    214         StringBuilder sb = new StringBuilder();
    215         sb.Append("using System;using System.IO;using System.Collections.Generic;using System.Text;");
    216         sb.Append(Environment.NewLine);
    217         sb.Append("namespace DynamicCodeGenerate");
    218         sb.Append(Environment.NewLine);
    219         sb.Append("{");
    220         sb.Append(Environment.NewLine);
    221         sb.Append("	public class HelloWorld");
    222         sb.Append(Environment.NewLine);
    223         sb.Append("	{");
    224         sb.Append(Environment.NewLine);
    225         sb.Append("	public string OutPut()");
    226         sb.Append(Environment.NewLine);
    227         sb.Append("		{");
    228         sb.Append(Environment.NewLine);
    229         sb.Append("long tf = " + tf + ";");
    230         sb.Append(Environment.NewLine);
    231         sb.Append("long re = " + lines_final + ";");
    232         sb.Append(Environment.NewLine);
    233         sb.Append("for (int i = 2; i < re || i < tf; i++){while (re % i == 0 && tf % i == 0){re = re / i;tf = tf / i;}}");
    234         sb.Append(Environment.NewLine);
    235         //sb.Append("Console.Write("Result = ");");
    236         sb.Append("		if (tf != 1){return re.ToString() + "/" + tf.ToString();} else{return re.ToString();}");
    237         sb.Append(Environment.NewLine);
    238         sb.Append(Environment.NewLine);
    239         sb.Append("		}");
    240         sb.Append(Environment.NewLine);
    241         sb.Append("	}");
    242         sb.Append(Environment.NewLine);
    243         sb.Append("}");
    244         string code = sb.ToString();
    245         return code;
    246     }
    247 }
    View Code
  • 相关阅读:
    悼念512汶川大地震遇难同胞——珍惜现在,感恩生活--hdu2191(多重背包模板)
    Gunner II--hdu5233(map&vector/二分)
    Geometric Progression---cf 567C(求组合方式,map离散)
    Guess Your Way Out! II---cf 558D (区间覆盖,c++STL map 的使用)
    Amr and Chemistry---cf558C(暴力,加技巧)
    汉诺塔IV---hdu2077
    Safe Or Unsafe--hdu2527(哈夫曼树求WPL)
    Divisibility by Eight---cf550C(被8整除 暴力)
    Charles使用技巧
    RabbitMQ-高级特性(六)
  • 原文地址:https://www.cnblogs.com/yuki8819/p/5391598.html
Copyright © 2011-2022 走看看