專案架構
- 目標:基礎四則運算 (加減乘除)、小數點、清除 (AC)、等號 (=)。
- 介面:
TextBox 顯示輸入/結果 (右對齊、唯讀) + 16 個 Button (0-9, ., +, -, *, /, =, AC)。
- 核心變數:
_acc (累積值/運算元 A)、_sec (當前輸入/運算元 B)、_oper (待執行運算子)、_clearNext (下一輸入是否清空顯示)、_firstOp (是否為第一個運算子)。
關鍵邏輯流程
數字/小數點按鈕 (btn_clk)
private void btn_clk(object sender, EventArgs e)
{
if (_clearNext) { txtDisplay.Text = ""; _clearNext = false; }
var btn = (Button)sender;
txtDisplay.Text += btn.Text;
// 處理單獨按下 "." -> 顯示 "0."
if (txtDisplay.Text == ".") txtDisplay.Text = "0.";
_sec = Convert.ToDouble(txtDisplay.Text);
}
運算子按鈕 (+, -, *, /) (btn_Oper)
private void btn_Oper(object sender, EventArgs e)
{
var btn = (Button)sender;
_oper = btn.Text; // 記錄新運算子
if (_firstOp)
{
_acc = _sec; // 第一個運算子:直接將當前值存入累積值
_firstOp = false;
}
else
{
Calculate(); // 非第一個:先執行上一個待執行運算
}
_clearNext = true; // 下一個數字輸入時清空顯示
}
等號按鈕 (=) (btn_equ)
private void btn_equ(object sender, EventArgs e) => Calculate();
計算核心 (Calculate)
private void Calculate()
{
switch (_oper)
{
case "+": _acc += _sec; break;
case "-": _acc -= _sec; break;
case "*": _acc *= _sec; break;
case "/":
if (_sec == 0) { MessageBox.Show("除數不能為零"); return; }
_acc /= _sec; break;
}
_oper = "="; // 標記已完成
_firstOp = true; // 下一個運算子視為第一個
txtDisplay.Text = _acc.ToString();
_sec = _acc; // 結果作為下一輪運算元 A
}
清除按鈕 (AC) (btn_clr)
private void btn_clr(object sender, EventArgs e) => Clear();
private void Clear()
{
_acc = 0; _sec = 0; _firstOp = true;
txtDisplay.Text = "";
txtDisplay.Focus();
}
完整程式碼 (單一檔案版)
using System;
using System.Windows.Forms;
namespace WinCalc
{
public class CalcForm : Form
{
// UI 控制項
private TextBox txtDisplay;
private Button[] _numButtons = new Button[10];
private Button btnDot, btnAdd, btnSub, btnMul, btnDiv, btnEqu, btnClr;
// 狀態
double _acc, _sec;
string _oper = "=";
bool _clearNext, _firstOp = true;
public CalcForm()
{
InitializeUI();
Clear();
}
private void InitializeUI()
{
Text = "計算機"; ClientSize = new Size(256, 261);
txtDisplay = new TextBox { Location = new Point(16,24), Size = new Size(224,21), ReadOnly = true, RightToLeft = RightToLeft.Yes };
Controls.Add(txtDisplay);
// 建立按鈕網格 (簡化:手動定位)
Action addBtn = (txt, loc, handler) =>
{
var b = new Button { Text = txt, Location = loc, Size = new Size(32,32) };
b.Click += handler; Controls.Add(b);
};
// 數字鍵 1-9
string[] nums = {"7","8","9","4","5","6","1","2","3"};
for (int i = 0; i < 9; i++)
addBtn(nums[i], new Point(16 + (i%3)*48, 64 + (i/3)*48), btn_clk);
// 0 (寬雙倍)
var b0 = new Button { Text = "0", Location = new Point(16, 208), Size = new Size(80,32) };
b0.Click += btn_clk; Controls.Add(b0);
// 小數點
addBtn(".", new Point(112, 208), btn_clk);
// 運算子
addBtn("+", new Point(208, 64), btn_Oper); // 佔兩行高需調整
addBtn("-", new Point(160, 64), btn_Oper);
addBtn("*", new Point(160, 112), btn_Oper);
addBtn("/", new Point(160, 160), btn_Oper);
// 等號 (寬雙倍)
var beq = new Button { Text = "=", Location = new Point(160, 208), Size = new Size(80,32) };
beq.Click += btn_equ; Controls.Add(beq);
// 清除
addBtn("AC", new Point(208, 112), btn_clr);
}
// ... 此處插入上述 btn_clk, btn_Oper, btn_equ, Calculate, Clear 方法 ...
[STAThread]
static void Main() => Application.Run(new CalcForm());
}
}
擴充建議
- 錯誤處理:除零、溢位、非數字輸入。
- 進階功能:百分比、開根號、倒數、記憶體 (M+/M-/MR/MC)。
- 運算優先序:目前為連續即時運算 (如 1+2*3=9),若需標準優先序需引入運算子堆疊 (Shunting-yard 演算法)。
- 鍵盤支援:覆寫
ProcessCmdKey 處理數字鍵、Enter、Escape。
- MVVM 重構:將計算邏輯抽離為獨立
CalculatorEngine 類別,方便單元測試與 WPF/UWP 遷移。