「24點」是經典數學遊戲:給定 4 個數字,使用 + - * / 和括號運算得出 24。本文深度解析遊戲核心邏輯 —— 如何判斷 4 個數能否算出 24,以及 如何驗證用戶輸入表達式的合法性與計算結果。代碼採用「預計算所有可解組合 + 表達式語法分析」雙軌制,邏輯嚴密,適合算法入門與編譯原理初探。
封裝三大核心能力:
private float[] number(float[] a, int i) {
final float[] arr = new float[4];
// switch-case 硬編碼 24 種排列,i=0..23
// 例:case 0: a[0],a[1],a[2],a[3]; case 1: a[0],a[1],a[3],a[2] ...
return arr;
}
private char[][] Calculate() {
char[][] ops = new char[64][3];
int[][] idx = new int[64][3];
int t = 0;
for (int i=0;i<4;i++) for (int j=0;j<4;j++) for (int k=0;k<4;k++) {
idx[t][0]=i; idx[t][1]=j; idx[t][2]=k;
for (int l=0;l<3;l++) ops[t][l] = mapOp(idx[t][l]); // 0:+,1:-,2:*,3:/
if (++t == 64) return ops;
}
return ops;
}
對於 4 個數 a,b,c,d 和 3 個運算符 op1,op2,op3,合法括號化對應 5 種二元樹結構:
((a op1 b) op2 c) op3 d — 左傾鏈(a op1 b) op2 (c op3 d) — 平衡雙分支(a op1 (b op2 c)) op3 d — 右子樹優先a op1 ((b op2 c) op3 d) — 右側左傾a op1 (b op2 (c op3 d)) — 右傾鏈代碼中依次計算,任一結果 == 24 即返回 true 並記錄表達式字符串 outputs。
private float Run(float a, float b, char op) {
switch(op) { case '+': return a+b; case '-': return a-b; case '*': return a*b; case '/': return a/b; }
return 0;
}
採用語法分析 + 優先級計算 兩階段:
根據括號層級、乘除優先於加減,為 3 個運算符分配優先級 1/2/3,構成 3 位數編碼 abc(如 321 表示第3運算符優先級最高)。通過 switch(abc) 直接映射到 6 種計算順序(對應上述 5 種括號結構 + 1 種無括號左結合)。
// 例:優先級編碼 321 -> 計算順序對應 ((a op1 b) op2 c) op3 d
case 321: return Run(Run(Run(n[0],n[1],op[0]),n[2],op[1]),n[3],op[2]);
MsgDlg/MasgDlg:結果彈窗(成功/失敗/超時),控制「確定」「重新開始」按鈕狀態。MyTimer:Swing Timer 實現分鐘:秒 計時顯示。

| 階段 | 複雜度 | 說明 |
|---|---|---|
| 預計算可解性 | O(24 × 64 × 5) = O(7680) | 常數級,極快,僅在發牌時觸發 |
| 用戶表達式驗證 | O(L) L=表達式長度 | 單次掃描 + 常數switch,微秒級 |
優化建議:
double 替代 float 減少精度誤差(如 8/(3-8/3)=24 含循環小數)。本項目展示了「組合窮舉 + 語法分析」解決約束求解問題的經典模式: