C#窗体->>随机四则运算(计算表达式)

时间:2023-03-08 17:22:30

用户需求:

程序能接收用户输入的整数答案,并判断对错
程序结束时,统计出答对、答错的题目数量。
补充说明:0——10的整数是随机生成的
用户可以选择四则运算中的一种
用户可以结束程序的运行,并显示统计结果。
在此基础上,做增量开发。

增量内容: 1)处理用户的错误输入,比如输入字母或符号等,处理除法运算中分母为0的情况,处理结果为负数的情况,保证是小学水平不出现负数,比如不能出现5-8=-3这种情况;
              2)用户可以设定倒计时;
              3)用户可以设定随机整数的范围和题目数量;
              4)用户可以选择哪种计算类型,比如加减乘除,或可选择软件随机生成四则运算中的一种;
              5)用户可以选择随机生成的题目中是否带有小括号,比如(2+3)*5,如果是gui程序,添加这个功能可以用复选框实现。
              6)保证生成过的题目不再重复出现。

设计思路:

因为是做增量啊,所以呢,我在看了5和6这两个增量之后,第一感觉是有点难度。这次和之前的运算不同的地方是:
             对于5):加了小括号,这就要考虑优先级了,并且不能再用两个文本框来生成两个数字进行运算了。所以我考虑,把两个文本框合成一个文本框,这样的话就让它来存生成的一个式子,最后只对这个式子进行运算就OK了,这不但可以生成两个数的运算表达式,还可以生成三个数的运算表达式,就看你怎么定义出题方法了。当然了,想的是很简单,毕竟生成的是一个式子而并非两个数进行计算那么简单了。所以我继续分析,就对后面的这个式子进行研究啊。首先它是一个字符串表达式,而进行计算的话肯定不能用string类型的来进行计算。所以用队列把表达式里的每一个数取出来,并定义一个栈,让取出的元素放到栈里,这样的话只对栈里元素用逆波兰式进行计算就可以了。
             1.对于实现 出题为一个字符串表达式,我用了如下这种方法:

                            n1 = ran.Next(int.Parse(textBox4.Text), int.Parse(textBox5.Text));
                            n2 = ran.Next(int.Parse(textBox4.Text), int.Parse(textBox5.Text));
                            , int.Parse(textBox5.Text));
                            textBox1.Text += "(";
                            ) textBox1.Text += "(" + n1 + ")";
                            else textBox1.Text += n1;
                            , ) == ) textBox1.Text += "+";
                            else textBox1.Text += "-";
                            ) textBox1.Text += "(" + n2 + ")";
                            else textBox1.Text += n2 + ")";
                            , ) == ) textBox1.Text += "*"+n3;
                            else textBox1.Text += "/" + n3;
                            break;

2.对于让它连续出一种运算的表达式,根据最小取值范围的字符长度,也就是截取第一个运算数后面的运算符来进行判断。如下:

                    ) == "+")
                    {
                        RandomNumjia();
                    }

3.在准备工作做好之后就是进行计算了:
C#窗体->>随机四则运算(计算表达式)

代码实现:

Form1.cs

 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Data;
 using System.Drawing;
 using System.Linq;
 using System.Text;
 using System.Windows.Forms;

 namespace _Random
 {
     public partial class Form1 : Form
     {
         public Form1()
         {
             InitializeComponent();
         }
         ;
         ;
         ;
         ;

         private void button1_Click(object sender, EventArgs e)
         {
             label2.Text = t.ToString();
             timer1.Enabled = true;
             timer1.Interval = ;
             timer1.Start();
         }

         private void RDN()
         {
             Random ran=new Random();
             int n1,n2;
             if (textBox4.Text==""&&textBox5.Text=="")
             {
                 MessageBox.Show("请输入取值范围!");
                 return;
             }
             if (checkBox1.Checked == true)
                 ;
             ; i < int.Parse(textBox6.Text); i++)
             {
                 textBox1.Clear();
                 switch (select)
                 {
                     :
                         {
                             n1 = ran.Next(int.Parse(textBox4.Text), int.Parse(textBox5.Text));
                             n2 = ran.Next(int.Parse(textBox4.Text), int.Parse(textBox5.Text));
                             , int.Parse(textBox5.Text));
                             textBox1.Text += "(";
                             ) textBox1.Text += "(" + n1 + ")";
                             else textBox1.Text += n1;
                             , ) == ) textBox1.Text += "+";
                             else textBox1.Text += "-";
                             ) textBox1.Text += "(" + n2 + ")";
                             else textBox1.Text += n2 + ")";
                             , ) == ) textBox1.Text += "*"+n3;
                             else textBox1.Text += "/" + n3;
                             break;
                         }
                 }

                 textBox3.Text = "";
             }
         }

         private void RandomNumjia()
         {
             textBox1.Clear();
             textBox3.Clear();
             if (textBox4.Text == "" && textBox5.Text == "")
             {
                 MessageBox.Show("请输入取值范围!");
                 return;
             }

             Random ran = new Random();
             int n1 = ran.Next(int.Parse(textBox4.Text), int.Parse(textBox5.Text));
             int n2 = ran.Next(int.Parse(textBox4.Text), int.Parse(textBox5.Text));
             ) textBox1.Text += "(" + n1 + ")";
             else textBox1.Text += n1;
             textBox1.Text += "+";
             ) textBox1.Text += "(" + n2 + ")";
             else textBox1.Text += n2;
         }

         private void RandomNumjian()
         {
             textBox1.Clear();
             textBox3.Clear();
             if (textBox4.Text == "" && textBox5.Text == "")
             {
                 MessageBox.Show("请输入取值范围!");
                 return;
             }

             Random ran = new Random();
             int n1 = ran.Next(int.Parse(textBox4.Text), int.Parse(textBox5.Text));
             int n2 = ran.Next(int.Parse(textBox4.Text), int.Parse(textBox5.Text));
             ) textBox1.Text += "(" + n1 + ")";
             else textBox1.Text += n1;
             textBox1.Text += "-";
             ) textBox1.Text += "(" + n2 + ")";
             else textBox1.Text += n2;
         }

         private void RandomNumcheng()
         {
             textBox1.Clear();
             textBox3.Clear();
             if (textBox4.Text == "" && textBox5.Text == "")
             {
                 MessageBox.Show("请输入取值范围!");
                 return;
             }

             Random ran = new Random();
             int n1 = ran.Next(int.Parse(textBox4.Text), int.Parse(textBox5.Text));
             int n2 = ran.Next(int.Parse(textBox4.Text), int.Parse(textBox5.Text));
             ) textBox1.Text += "(" + n1 + ")";
             else textBox1.Text += n1;
             textBox1.Text += "*";
             ) textBox1.Text += "(" + n2 + ")";
             else textBox1.Text += n2;
         }

         private void RandomNumchu()
         {
             textBox1.Clear();
             textBox3.Clear();
             if (textBox4.Text == "" && textBox5.Text == "")
             {
                 MessageBox.Show("请输入取值范围!");
                 return;
             }

             Random ran = new Random();
             int n1 = ran.Next(int.Parse(textBox4.Text), int.Parse(textBox5.Text));
             int n2 = ran.Next(int.Parse(textBox4.Text), int.Parse(textBox5.Text));
             ) textBox1.Text += "(" + n1 + ")";
             else textBox1.Text += n1;
             textBox1.Text += "/";
             ) textBox1.Text += "(" + n2 + ")";
             else textBox1.Text += n2;
         }

         private void timer1_Tick(object sender, EventArgs e)
         {
             )
             {
                 timer1.Enabled = false;
                 textBox3.Enabled = false;
                 MessageBox.Show("时间到!");
                 textBox3.Enabled = false;
                 Form2 frm2 = new Form2();
                 frm2.ShowDialog();
             }
             t = t - ;
             label2.Text = t.ToString();
         }

         private void button2_Click(object sender, EventArgs e)
         {
             timer1.Stop();
             Form2 frm2 = new Form2();
             frm2.ShowDialog();
         }

         private void button3_Click(object sender, EventArgs e)
         {
             RandomNumjia();
         }

         private void button4_Click(object sender, EventArgs e)
         {
             RandomNumjian();
         }

         private void button5_Click(object sender, EventArgs e)
         {
             RandomNumcheng();
         }

         private void button6_Click(object sender, EventArgs e)
         {
             RandomNumchu();
         }

         private void button7_Click(object sender, EventArgs e)
         {
             if (textBox4.Text == "" && textBox5.Text == "")
             {
                 MessageBox.Show("请输入取值范围!");
                 return;
             }
             else
             {
                 ; i < int.Parse(textBox6.Text);i++)
                 {
                     RDN();
                 }
             }
         }

         private void textBox3_KeyDown(object sender, KeyEventArgs e)
         {
             string result = textBox1.Text;

             if (Count == int.Parse(textBox6.Text))
             {
                 Form2 frm2 = new Form2();
                 frm2.ShowDialog();
             }

             if (e.KeyCode == Keys.Enter)
             {
                 if (textBox3.Text == Calucate(result).ToString())   //直接调用Calucate这个方法计算result的值并与输入的值进行比较
                 {
                     right++;
                     Count++;
                     MessageBox.Show("回答正确!");
                 }

                 else
                 {
                     MessageBox.Show("答题错误!");
                     Count++;
                     string s = textBox1.Text;
                     ) == "+")
                     {
                         RandomNumjia();
                     }
                     ) == "-")
                     {
                         RandomNumjian();
                     }
                     ) == "*")
                     {
                         RandomNumcheng();
                     }
                     ) == "/")
                     {
                         RandomNumchu();
                     }
                     )
                     {
                         RDN();
                     }
                 }

                 string m = textBox1.Text;
                 ) == "+")
                 {
                     RandomNumjia();
                 }
                 , ) == "-")
                 {
                     RandomNumjian();
                 }
                 , ) == "*")
                 {
                     RandomNumcheng();
                 }
                 , ) == "/")
                 {
                     RandomNumchu();
                 }
                 )
                 {
                     RDN();
                 }
             }
         }

         const string operators = "+-*/";                 //运算符
         static Dictionary<char, int> priorities = null;  //优先级

         static void Calculator()                         //添加了四种运算符以及四种运算符的优先级
         {
             priorities = new Dictionary<char, int>();
             priorities.Add();
             priorities.Add();
             priorities.Add();
             priorities.Add();
             priorities.Add();
         } 

         static int Compute(int leftNum, int rightNum, char op)  //这是一种方法,用来计算左右两个数的静态方法!
         {
             switch (op)
             {
                 case '+': return leftNum + rightNum;
                 case '-': return leftNum - rightNum;
                 case '*': return leftNum * rightNum;
                 case '/': return leftNum / rightNum;
                 ;
             }
         }

         static bool IsOperator(char op)                  //每次判断这个字符是否是运算符?
         {
             ;
         }

         static bool IsAssoc(char op)                //返回一个关联符号
         {
             return op == '+' || op == '-' || op == '*' || op == '/';
         }

         static Queue<object> QueueSort (string expression)           // 队列排序
         {
             Queue<object> result = new Queue<object>();
             Stack<char> operatorStack = new Stack<char>();           //运算符栈
             operatorStack.Push('#');
             char top, cur, tempChar;                                          //top栈顶,current最近的;
             string tempNum;
             , j; i < expression.Length; )                 //取出表达式
             {
                 cur = expression[i++];                                  //取出表达式的每个字符赋给cur
                 top = operatorStack.Peek();                             //栈顶元素赋给top此时为"#"

                 if (cur == '(')                                         //将左括号压栈,此时栈顶元素为"("
                 {
                     operatorStack.Push(cur);
                 }
                 else
                 {
                     if (IsOperator(cur))                             //如果是运算符的话
                     {
                         while (IsOperator(top) && ((IsAssoc(cur) && priorities[cur] <= priorities[top])) || (!IsAssoc(cur) && priorities[cur] < priorities[top]))
                         {
                             result.Enqueue(operatorStack.Pop());     //如果元素为运算符并且优先级小于栈顶元素优先级,出栈
                             top = operatorStack.Peek();              //继续把栈顶元素赋给top
                         }
                         operatorStack.Push(cur);                     //把数字压栈
                     }
                     else if (cur == ')')                           //将右括号添加到结尾
                     {
                          && (tempChar = operatorStack.Pop()) != '(')
                         {
                             result.Enqueue(tempChar);
                         }
                     }
                     else
                     {
                         tempNum = "" + cur;
                         j = i;
                         ')))
                         {
                             tempNum += expression[j++];
                         }
                         i = j;
                         result.Enqueue(tempNum);
                     }
                 }
             }
             )
             {
                 cur = operatorStack.Pop();
                 if (cur == '#') continue;
                 )
                 {
                     top = operatorStack.Peek();
                 }

                 result.Enqueue(cur);
             }

             return result;
         }

         static int Calucate(string expression)
         {
             try
             {
                 var rpn = QueueSort(expression);                   //rpn逆波兰表达式reverse polish notation
                 Stack<int> operandStack = new Stack<int>();
                 int left, right;
                 object cur;
                 )
                 {
                     cur = rpn.Dequeue();                           //出列
                     if (cur is char)                               //如果cur为字符的话
                     {
                         right = operandStack.Pop();                //右边的数字出栈
                         left = operandStack.Pop();                 //左边的数字出栈
                         operandStack.Push(Compute(left, right, (char)cur));    //此时调用compute方法
                     }
                     else
                     {
                         operandStack.Push(int.Parse(cur.ToString()));            //是数字就压栈
                     }
                 }
                 return operandStack.Pop();
             }
             catch
             {
                 throw new Exception("表达式格式不正确!");
             }
         }

     }
 }

代码编写过程:

C#窗体->>随机四则运算(计算表达式)

Form2.cs

 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Data;
 using System.Drawing;
 using System.Linq;
 using System.Text;
 using System.Windows.Forms;

 namespace _Random
 {
     public partial class Form2 : Form
     {
         public Form2()
         {
             InitializeComponent();
         }

         private void Form2_Load(object sender, EventArgs e)
         {
             textBox1.Text = Form1.Count.ToString();
             textBox2.Text = Form1.right.ToString();
             textBox3.Text = (Form1.Count - Form1.right).ToString();
         }

     }
 }

 运行过程:

答题的时候给出取值范围,和预想答题数目,然后点击随机,这时程序就会生成一个式子。
当我在输入答案并回车的时候会对生成的式子进行计算,并与输入的答案进行比较。

C#窗体->>随机四则运算(计算表达式)

 当时间用完,或者点击结束运算的时候,会弹出测试结果并提示时间到。

C#窗体->>随机四则运算(计算表达式)

 PSP耗时分析:
C#窗体->>随机四则运算(计算表达式)

结对编程总结:

说明:我们一起做了1个增量

5)用户可以选择随机生成的题目中是否带有小括号,比如(2+3)*5。
这次结对编程呢,还是和李燕燕一块的。总体来说,这次作业对我们来说确实有难度,因为那个逆波兰式我之前根本没有听说过,等到用到的时候才发现自己学到的知识真是太少了。我之前是觉得只要学到老师教的东西就行了,其实并不是,老师教的东西远远不够,想要使自己的编程能力提高,还是要靠我们自己学习。我们学了一种语言C#,没人会再教我们第二种语言,那么这第二种、第三种语言...需要我们自己来学了。比如这次逆波兰式我不会了,我就上网查啊查,折腾着,也想过要放弃不做了,但是我是那种看到别人能做出来相信自己也能做出来的人。所以我先是编写了一个控制台的小程序,一点一点测试,慢慢再加入到窗体,直到最后测试通过。才发现原来我是可以的!我觉得这种自主学习的方式我一定要坚持下去!通过这次结对编程,我认为:自主学习比较重要!!!