24點遊戲演算法及實現(字尾表示式思想)

2021-04-29 17:58:32 字數 2962 閱讀 4099

一般而言,我理解的24點遊戲是用4個數字經過數**行,得到24. 一般推廣版的應該使用撲克的52張牌(出去大小王),a表示1,k表示13.任意4張牌看是否能夠組合得到24.

我這裡所設計的就是這樣的情況,而不是任意的4個數。(因為這裡需要用乙個辦法表示分數,而我使用了比較簡單的一種,能表示範圍較小,所以我只處理了1到13這個情況。雖然實現裡邊可以將13這個範圍向上推一段。)

4個數進行四則運算,一般的思維是四個數中間的3個空放置3個運算子,然後可能還需要在不同的地方加上括號,表示優先順序的不同。僅僅是數字和運算子好好 做,一旦要新增括號就會有點亂七八糟。前兩天看網頁突然看到字尾表示式這個東西,我一下想起來了。(網頁作者說字尾表示式可以實現無括號的優先順序運算)那 我使用字尾表示式的這種方法來做就簡單了。反正就只有4個數。

假設i、j、m、n是4個數,r、s、t是3個運算子。那麼使用字尾表示式只有如下4種情況:

1)i j r m n s t ==> (i r j) t (m s n)

2)i j r m s n t ==> ((i r j) s m) t n

3)i j m r s n t ==> (i s (j r m)) t n

4)i j m n r s t ==> i t (j s (m r n))

不理會所有的重複,上面4種情況分別有1536中可能,那麼總計就是 6144中可能情況。每種情況計算3次,也就20000次計算而已。對計算機來說這個數目是極小的。

在實現中,我沒有採用任何取巧的辦法,而是每種情況使用了7個for迴圈進行計算。唯一的取巧是前兩種的前邊4個for迴圈是一樣,我就將兩種拼起來了。

處理整數計算還有乙個問題是,計算機無法精確的表示分數,特別是那種無限小數,比如1/3這種。如果不能精確計算,最後就無法判斷是否精確等於24,這是計算機的乙個弱點,這點不如人啊。

我的方法是,每個數字都用乙個int表示,int表示為4位元組。由於最大的單個數為13,那麼即使是13的連乘也不過28561,不足兩個位元組能表示的 65536 。因此我使用乙個int的低兩個位元組表示分子或者實際的數值(沒有分母的,也就等於整個int表示的數),高兩個位元組表示分母(不存在分母則表示為0)。 在做計算時將分子統一為等分母的數,然後計算之後與分母作用得到最後的數。這樣的話4/5就表示為了0x00050004了。

由於找到一種解法就結束,所以根據輸入的資料,得到的可能與通常人們計算得到的結果有出入,比如2 2 6 6 ,人的計算結果一般為2*6+2*6,但是程式結果可能為(2+6)*(6/2),當然結果也是正確的。

另外需要注意的是,對於任何兩個數計算得到負數,我都沒有繼續啊向下計算,因為這個必須得加乙個正數或者乘以乙個輔助才可能得到24 。而既然能夠得到負數,兩個數的位置調換一下就是乙個正數了,沒有必要在數值前邊加上負號來處理。

具體實現**如下,c語言實現:

/* 24.c 計算4個1到13之間的數(包含)是否能夠通過加減乘除達到24.*/

#include

#define mask  0xffff

#define shift 16

enum ;

const char ops = "+*-/";

int test (const int nums, char *result);

int calculate (int num1, int num2, char op);

int main(int argc, char *argv)

;int i;

char *result;

if (argc != 5)

for (i = 0 ;i < 4 ;i++ )

}/*2 pairs of paren, 3 operators, 1 for null. */

len += 4 + 3 + 1;

result = (char *)malloc (len);

if (test(nums, result))

printf ("%s/n", result);

else

printf ("no matched./n");

if (result != null)

free (result);

return 0;

}/* 測試所有可能的情況,找到一種解法*/

int test (const int nums, char *result)}}

}/* second loop: i j r m s n t ==> ((i r j) s m) t n */

for (s = 0 ;s < 4 ;s++ )}}

}}}}

}/* third loop: i j m r s n t ==> (i s (j r m)) t n */

for (i = 0 ;i < 4 ;i++ )}}

}}}}

}/* forth loop: i j m n r s t ==> i t (j s (m r n)) */

for (i = 0 ;i < 4 ;i++ )}}

}}}}

}return failure;

}/* 計算兩個特定的數和操作符的結果*/

int calculate (int num1, int num2, char op)

else if (denominator_num1 > 0 && denominator_num2 == 0)

else if (denominator_num1 == 0 && denominator_num2 > 0)

else

/* 計算*/

if (op == '+')

else if (op == '-')

else if (op == '*')

else if (op == '/')

else

}if (denominator>0 && numerator%denominator == 0)

ret = (numerator<=0)?numerator:((numerator&mask) | (denominator

}

中綴表示式轉字尾表示式演算法及實現

1 23 include 4 using namespace std 56 template class mystack 7 20 2122 template void mystack init 23 26 27 template bool mystack empty 28 31 32 templa...

字尾表示式實現表示式求值

看到別人寫的乙個表示式求值程式,想到很久之前寫的乙個。中間有個字串轉數值型,可以用stringstream來實現或者c語言裡面的strtod直接得到 include include include include includeusing namespace std class data doubl...

中綴表示式轉字尾表示式及字尾表示式的計算

這裡舉個栗子手動轉換叭 ps 以下紅色括號皆為新增後的效果!中綴表示式 5 20 1 3 14 按運算子優先順序對所有運算子和它的運算數加括號 原本的括號不用加 5 20 1 3 14 把運算子移到對應的括號後 此處注意括號的變化 5 20 1 3 14 去掉括號 字尾表示式 5 20 1 3 14...