特殊时期,女儿的数学老师布置的口算作业,让家长自己每天出口算题,于是就有了本文;
思路:
1、定义基础信息:题目数量,算式符号等;
2、第一、二元素,由Random 随机生成;
3、一道算式分由四部分组成:算式(Label)、填写的答案(TextBox),正确的答案(用数组来存储)、判断答案(正确显示√,错误显示×);
4、通过选择出题数,程序自动生成相应的算式;
5、算式结果填写完后,点核对按钮显示最终成绩。
界面设定:
只说一点,用FlowOutPannel(根据控件大小可自动排序)来显示算式,如果用pnnel来显示多行多列算式会很麻烦。
局域于二年级,所以,程序中算法有以下设定:
1、加减法,即算式的第一,二元素(估且这么叫吧),小于100,当然和、差也局域于100以内;
2、乘法:局域于1-9以内;
3,除法:女儿还未学习,所以程序未设定,不过,可以后续可以增加、扩展;
程序难点:
1、自动生成的算式后,需把算式的答案存储在一个数组;
2、判断填写的答案是否正确:通过控件的ID来查找。
代码说明 :
1、基础信息:(算式符号可用类或者枚举替代,我这里偷懒)
Random rand = new Random(unchecked((int)DateTime.Now.Ticks)); /// <summary> /// 定义 +、-、* 符号 /// </summary> private string Symbol=null; /// <summary> /// 运算符加法1,减法2,乘法3 /// </summary> private int symbol { get { return rand.Next(3)+1; } } /// <summary> /// 题目数量 /// </summary> private int countItem { get { if (!string.IsNullOrEmpty(ItemCb.Text)) { return Int32.Parse(ItemCb.Text); } else { return 0; } } } /// <summary> /// 定义算式中第一、二元素 /// 正确或者错误题数,最终成绩 /// </summary> private int firstNum = 0; private int secondNum = 0; private int rightNum = 0; private int errorNum = 0; /// <summary> /// 成绩,满分100 /// 公式:(100/题数)*正确答案题数 /// </summary> private int score { get { return (100 / countItem) * rightNum; } set { value= (100 / countItem) * rightNum; } } /// <summary> /// 定义计算结果存储在一个数组中 /// C#数组是静态的,可通过list泛型转换 /// </summary> private List<int> answerList = new List<int>(); private int[] answerArray { get { return answerList.ToArray(); } }
2、自动生成算式所用到的控件方法(其实也就Label 和TextBox)
需要注意的是坐标的设定,其它可根据算式用到的控件,自己放到界面上,再根据对应属性值,大概计算出其X,Y坐标
private Label NewLabel(int x) { Label label = new Label(); label.Size = new Size(56,16); label.Location = new Point(3+120*x,30*x); label.Name = "lblExpress" + x; label.Font=new Font("宋体",12); return label; } private TextBox NewTextBox(int x) { TextBox textBox = new TextBox(); textBox.Size = new Size(50,50); textBox.Location = new Point(65 + 120 * x, 30 * x); textBox.Name="tbResult"+x; textBox.KeyPress += new KeyPressEventHandler(textBox_KeyPress); return textBox; } /// <summary> /// 限定输入框只能输入数字 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void textBox_KeyPress(object sender, KeyPressEventArgs e) { if (!(Char.IsNumber(e.KeyChar) || e.KeyChar ==\'\b\')) { e.Handled = true; } }
3、计算方法和算式表达式的设定(没有优化代码,随便了)
减法说明 :当发现第一元素,小于第二元素时,直接把算式第一、二元素调换下,总之就是被减数必需大于减数;
乘法说明:重定义第一、二元素在1-9内
/// <summary> /// 返回计算结果所有数据 /// </summary> /// <param name="i">题数,也作为控件的ID索引</param> /// <param name="labelExpress">算式表达式</param> /// <param name="labelResult">结果:对,错</param> /// <param name="tb">填写算式答案</param> private void resultStr(int i,out Label labelExpress,out Label labelResult,out TextBox tb) { labelExpress = NewLabel(i); labelResult = NewLabel(i); labelResult.Name = "lblResult" + i; tb = NewTextBox(i); labelResult.Size = new Size(12, 12); firstNum = rand.Next(1, 100); secondNum = rand.Next(1, 100 - firstNum); switch (symbol) { case 1://加法 answerList.Add(firstNum + secondNum); Symbol = "+"; labelExpress.Text = firstNum.ToString() + Symbol + secondNum.ToString() + "="; break; case 2://减法,当中发现第一元素,小于第二元素时,直接把算式第一、二元素调换下,总之就是被减数必需大于减数 Symbol = "-"; if (firstNum > secondNum) { answerList.Add(firstNum - secondNum); labelExpress.Text = firstNum.ToString() + Symbol + secondNum.ToString() + "="; } else { answerList.Add(secondNum-firstNum); labelExpress.Text = secondNum.ToString() + Symbol + firstNum.ToString() + "="; } break; case 3://乘法,需重定义第一、二元素,保证其值在1-9 firstNum = rand.Next(1,9); secondNum = rand.Next(1,9); answerList.Add(firstNum * secondNum); Symbol = "*"; labelExpress.Text = secondNum.ToString() + Symbol + firstNum.ToString() + "="; break; } }
3、出题
private void CreateBtn_Click(object sender, EventArgs e) { //每次出题前,先清除flowloutpanel中的控件 ShowFlp.Controls.Clear(); clearAll(); if (countItem == 0) { MessageBox.Show("请选择出题数!"); } for (int i = 0; i < countItem; i++) { Label labelExpress; Label labelResult ; TextBox textValue; resultStr(i, out labelExpress, out labelResult, out textValue); labelResult.Size = new Size(16,16); ShowFlp.Controls.Add(labelExpress); ShowFlp.Controls.Add(textValue); ShowFlp.Controls.Add(labelResult); } }
4、批改
未填写答案,默认为错题
private void ModifyBtn_Click(object sender, EventArgs e) { clearAll(true); for (int i = 0; i <countItem; i++) { Label labelExpress=(Label)ShowFlp.Controls.Find("lblExpress"+i,true)[0]; Label labelResult =(Label)ShowFlp.Controls.Find("lblResult" + i, true)[0]; TextBox textValue = (TextBox)ShowFlp.Controls.Find("tbResult" + i, true)[0]; int fillValue =0; if (textValue.Text == "") { labelResult.Text = "×"; labelResult.ForeColor = Color.Blue; errorNum++; } else { fillValue=int.Parse(textValue.Text); if (fillValue == answerArray[i]) { labelResult.Text = "√"; labelResult.ForeColor = Color.Red; rightNum++; } else { labelResult.Text = "×"; labelResult.ForeColor = Color.Blue; errorNum++; } } //测试结果: rightLab.Text =rightNum.ToString(); errorLab.Text = errorNum.ToString(); //正确题数=总出题数,即为满分,用于100/总出题数,余为非整数时的判断 scoreLab.Text=(rightNum==countItem?100:score).ToString(); preform(); } }
5、出题或者批改前需要清空一些基础信息
注意:只有重新出题时,才要清空,而批改时,不能清空原来存储的答案(也就是批改后,发现错误,可以重新填写,再批改)
void clearAll(bool isModify=false) { firstNum=secondNum= rightNum = errorNum = score = 0; if (!isModify) {//只有重新出题时,才要清空,而批改时,不能清空原来存储的答案; answerList = new List<int>(); } }
6、附加的简单成绩表现语句
/// <summary> /// 成绩表现语 /// </summary> private void preform() { string pre = string.Empty; if (score >= 90 && score <= 100) { pre = "成绩优秀,真棒!"; preformLab.Image = Image.FromFile("Images/right.png"); } else if (score >= 60 && score < 90) { pre = "成绩良好,很不错!"; preformLab.Image = Image.FromFile("Images/heart.png"); } else { pre = "还需努力,加油!"; preformLab.Image = Image.FromFile("Images/enjory.png"); } preformLab.Text = pre; }
基本程序,就这样了,懒得每天出题,看下效果:
请发表评论