1、遊戲玩法介紹:node
24點遊戲是兒時玩的主要益智類遊戲之一,玩法爲:從一副撲克中抽取4張牌,對4張牌使用加減乘除中的任何方法,使計算結果爲24。例如,2,3,4,6,經過( ( ( 4 + 6 ) - 2 ) * 3 ) = 24,最快算出24者剩。express
2、設計思路:app
因爲設計到了表達式,很天然的想到了是否可使用表達式樹來設計程序。本程序的確使用了表達式樹,也是程序最關鍵的環節。簡要歸納爲:先列出全部表達式的可能性,而後運用表達式樹計算表達式的值。程序中大量的運用了遞歸,各個遞歸式不是很複雜,你們耐心看看,應該是能看懂的ide
表達式樹:spa
表達式樹的全部葉子節點均爲操做數(operand),其餘節點爲運算符(operator)。因爲本例中都是二元運算,因此表達式樹是二叉樹。下圖就是一個表達式樹設計
具體步驟:3d
一、遍歷全部表達式的可能狀況code
遍歷分爲兩部分,一部分遍歷出操做數的全部可能,而後是運算符的全部可能。全排列的計算採用了遞歸的思想blog
#返回一個列表的全排列的列表集合 def list_result(l): if len(l) == 1: return [l] all_result = [] for index,item in enumerate(l): r = list_result(l[0:index] + l[index+1:]) map(lambda x : x.append(item),r) all_result.extend(r) return all_result
二、根據傳入的表達式的值,構造表達式樹遞歸
因爲表達式樹的特色,全部操做數均爲葉子節點,操做符爲非葉子節點,而一個表達式(例如( ( ( 6 + 4 ) - 2 ) * 3 ) = 24) 只有3個運算符,即一顆表達式樹只有3個非葉子節點。因此樹的形狀只有兩種可能,就直接寫死了
#樹節點 class Node: def __init__(self, val): self.val = val self.left = None self.right = None
def one_expression_tree(operators, operands): root_node = Node(operators[0]) operator1 = Node(operators[1]) operator2 = Node(operators[2]) operand0 = Node(operands[0]) operand1 = Node(operands[1]) operand2 = Node(operands[2]) operand3 = Node(operands[3]) root_node.left = operator1 root_node.right =operand0 operator1.left = operator2 operator1.right = operand1 operator2.left = operand2 operator2.right = operand3 return root_node def two_expression_tree(operators, operands): root_node = Node(operators[0]) operator1 = Node(operators[1]) operator2 = Node(operators[2]) operand0 = Node(operands[0]) operand1 = Node(operands[1]) operand2 = Node(operands[2]) operand3 = Node(operands[3]) root_node.left = operator1 root_node.right =operator2 operator1.left = operand0 operator1.right = operand1 operator2.left = operand2 operator2.right = operand3 return root_node
三、計算表達式樹的值
也運用了遞歸
#根據兩個數和一個符號,計算值 def cal(a, b, operator): return operator == '+' and float(a) + float(b) or operator == '-' and float(a) - float(b) or operator == '*' and float(a) * float(b) or operator == '÷' and float(a)/float(b) def cal_tree(node): if node.left is None: return node.val return cal(cal_tree(node.left), cal_tree(node.right), node.val)
四、輸出全部可能的表達式
仍是運用了遞歸
def print_expression_tree(root): print_node(root) print ' = 24' def print_node(node): if node is None : return if node.left is None and node.right is None: print node.val, else: print '(', print_node(node.left) print node.val, print_node(node.right) print ')', #print ' ( %s %s %s ) ' % (print_node(node.left), node.val, print_node(node.right)),
五、輸出結果
3、全部源碼
#coding:utf-8 from __future__ import division from Node import Node def calculate(nums): nums_possible = list_result(nums) operators_possible = list_result(['+','-','*','÷']) goods_noods = [] for nums in nums_possible: for op in operators_possible: node = one_expression_tree(op, nums) if cal_tree(node) == 24: goods_noods.append(node) node = two_expression_tree(op, nums) if cal_tree(node) == 24: goods_noods.append(node) map(lambda node: print_expression_tree(node), goods_noods) def cal_tree(node): if node.left is None: return node.val return cal(cal_tree(node.left), cal_tree(node.right), node.val) #根據兩個數和一個符號,計算值 def cal(a, b, operator): return operator == '+' and float(a) + float(b) or operator == '-' and float(a) - float(b) or operator == '*' and float(a) * float(b) or operator == '÷' and float(a)/float(b) def one_expression_tree(operators, operands): root_node = Node(operators[0]) operator1 = Node(operators[1]) operator2 = Node(operators[2]) operand0 = Node(operands[0]) operand1 = Node(operands[1]) operand2 = Node(operands[2]) operand3 = Node(operands[3]) root_node.left = operator1 root_node.right =operand0 operator1.left = operator2 operator1.right = operand1 operator2.left = operand2 operator2.right = operand3 return root_node def two_expression_tree(operators, operands): root_node = Node(operators[0]) operator1 = Node(operators[1]) operator2 = Node(operators[2]) operand0 = Node(operands[0]) operand1 = Node(operands[1]) operand2 = Node(operands[2]) operand3 = Node(operands[3]) root_node.left = operator1 root_node.right =operator2 operator1.left = operand0 operator1.right = operand1 operator2.left = operand2 operator2.right = operand3 return root_node #返回一個列表的全排列的列表集合 def list_result(l): if len(l) == 1: return [l] all_result = [] for index,item in enumerate(l): r = list_result(l[0:index] + l[index+1:]) map(lambda x : x.append(item),r) all_result.extend(r) return all_result def print_expression_tree(root): print_node(root) print ' = 24' def print_node(node): if node is None : return if node.left is None and node.right is None: print node.val, else: print '(', print_node(node.left) print node.val, print_node(node.right) print ')', if __name__ == '__main__': calculate([2,3,4,6])