(Python)簡易24點遊戲的實現步驟
題目說明:
24點遊戲是經典的紙牌益智遊戲。
常見遊戲規則:從撲克中每次取出4張牌。使用加減乘除,第一個能得出24者為贏。(其中,J代表11,Q代表12,K代表13,A代表1), 隨機生成4個代表撲克牌牌面的數字字母,程式自動列出所有可能算出24的表示式。
解題思想:
- 生成4個符合要求的隨機數
- 對4個隨機數進行全排列
- 對‘+’、‘-’、‘×’、‘÷’進行全排列
- 通過拼湊的方式構造表示式
- 計算表示式,將滿足運算結果為24的表示式打印出來
解題步驟:
1.生成4個符合要求的隨機數
對於python來說,生成隨機數一般都是通過導包來實現,在這裡需要用到的包是random
random. randrange (stop) |
|
random. randrange (start, stop[, step]) |
Return a randomly selected element from range(start, stop, step) . |
random. randint (a, b) |
Return a random integer N such that a <= N <= b . |
我所用到的是random.
randint
(a, b)函式,使用它生成4個1-14的數字作為模擬抽取的卡牌
2.對4個隨機數進行全排列
對隨機數進行全排列可以使用python自帶的包(itertools)或者自己寫一個遞迴函式實現相同功能都可以,這裡使用的是itertools進行隨機數的全排列
詳細程式碼:
def generateNumberList(numbers):
result_list = []
count = 0
# set() 用於去除重複的排列,itertools.permutations()用於生成全排列的元組
for each_tuple in set(itertools.permutations(numbers, len(numbers))):
result_list.append(list(each_tuple))
count += 1
return result_list
3.對‘+’、‘-’、‘×’、‘÷’進行全排列
對4種運算子的全排列和數字的全排列幾乎一樣,但是因為是4個數字進行計算,所以只會用到3個運算子,所以在後期處理上只需要將最後一個運算子刪除即可
詳細程式碼:
def generateOperatorList(operators):
result_list = []
count = 0
# set() 用於去除重複的排列,itertools.permutations()用於生成全排列的元組
for each_tuple in set(itertools.permutations(operators, len(operators))):
templist = list(each_tuple)
templist.pop()
result_list.append(templist)
return result_list
4.通過拼湊的方式構造表示式
對生成的數字全排列列表和預算符全排列列表只需要交替的插入即可構造一個只有數字和“+、-、×、÷”的運算表示式,但這樣構造的表示式不夠多樣,存在很多不滿足運算結果等於24的情況,所以應當引入括號運算,保證運算的多樣性。
在加入括號後可以儘可能多的產生滿足計算結果等於24的表示式,但是也會出現很多相同的表示式
例如:
4+4+8+8=24
(4+4)+8+8=24
4+(4+8)+8=24
所以為了避免出現這樣的情況,應當設定合適的條件來新增括號。如果一個表示式不是按照順序計算的,那麼在這個表示式中加入括號將有可能改變表示式最後的運算結果,為了避免加入括號後不能改變運算結果的情況,所以應當先判斷改表示式在不新增括號的情況下結果是否等於24,否在新增括號
例如:
9+2×6+3=24
9+(2×6)+3=24
5.計算表示式,將滿足運算結果為24的表示式打印出來
計算表示式可以通過兩兩計算得到結果再進行兩兩計算,但在python中提供了一種更加簡單和快捷的計算表示式結果的方法
eval
(expression, globals=None, locals=None)
The arguments are a string and optional globals and locals. If provided, globals must be a dictionary. If provided, locals can be any mapping object.
在使用eval函式進行計算表示式時,有時會遇到表示式除數為0的情況,在python中這樣的表示式是不合法的,程式會丟擲異常導致整個程式碼的執行終止,為了避免這種情況,應當在有計算表示式的程式碼出新增異常處理機制,當程式丟擲除數為0的異常時即使處理,使得整個程式碼能夠繼續執行完
詳細程式碼(構造表示式+計算表示式):
def insertParentheses(number_list, operator_list):
count = 0
expression_list = []
for each_number_list in number_list:
for each_operator_list in operator_list:
expression1 = str(each_number_list[0]) + each_operator_list[0] + str(each_number_list[1]) \
+ each_operator_list[1] + str(each_number_list[2]) + each_operator_list[2] + \
str(each_number_list[3])
try:
result = eval(expression1)
except:
result = 0
if result == 24:
expression_list.append(expression1 + '=' + str(result))
count += 1
else:
expression2 = '(' + str(each_number_list[0]) + each_operator_list[0] + str(each_number_list[1]) + ')' \
+ each_operator_list[1] + str(each_number_list[2]) + each_operator_list[2] + \
str(each_number_list[3])
try:
result = eval(expression2)
except:
result = 0
if result == 24:
expression_list.append(expression2 + '=' + str(result))
count += 1
else:
expression3 = str(each_number_list[0]) + each_operator_list[0] + '(' + str(each_number_list[1]) \
+ each_operator_list[1] + str(each_number_list[2]) + ')' + each_operator_list[2] + \
str(each_number_list[3])
try:
result = eval(expression3)
except:
result = 0
if result == 24:
expression_list.append(expression3 + '=' + str(result))
count += 1
else:
expression4 = str(each_number_list[0]) + each_operator_list[0] + str(each_number_list[1]) \
+ each_operator_list[1] + '(' + str(each_number_list[2]) + each_operator_list[2] \
+ str(each_number_list[3]) + ')'
try:
result = eval(expression4)
except:
result = 0
if result == 24:
expression_list.append(expression4 + '=' + str(result))
count += 1
for each in expression_list:
print(each)
print('一共有%d個表示式' % count)
執行截圖:
因為在處理時沒有考慮位置而引起的重複,此處預設位置不同也是不同的表示式,如果想要去掉這種重複還請自行解決