特殊時期,女兒的數學老師布置的口算作業,讓家長自己每天出口算題,於是就有了本文;
思路:
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; }
基本程序,就這樣了,懶得每天出題,看下效果: