經典趣味24點游戲程序設計(python)


一、游戲玩法介紹:

    24點游戲是兒時玩的主要益智類游戲之一,玩法為:從一副撲克中抽取4張牌,對4張牌使用加減乘除中的任何方法,使計算結果為24。例如,2,3,4,6,通過( ( ( 4 + 6 ) - 2 ) * 3 )  = 24,最快算出24者剩。

 

二、設計思路:

    由於設計到了表達式,很自然的想到了是否可以使用表達式樹來設計程序。本程序的確使用了表達式樹,也是程序最關鍵的環節。簡要概括為:先列出所有表達式的可能性,然后運用表達式樹計算表達式的值。程序中大量的運用了遞歸,各個遞歸式不是很復雜,大家耐心看看,應該是能看懂的

    

    表達式樹:

        表達式樹的所有葉子節點均為操作數(operand),其他節點為運算符(operator)。由於本例中都是二元運算,所以表達式樹是二叉樹。下圖就是一個表達式樹

  

    具體步驟:

    1、遍歷所有表達式的可能情況

    遍歷分為兩部分,一部分遍歷出操作數的所有可能,然后是運算符的所有可能。全排列的計算采用了遞歸的思想

    

#返回一個列表的全排列的列表集合
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

 

 2、根據傳入的表達式的值,構造表達式樹

  由於表達式樹的特點,所有操作數均為葉子節點,操作符為非葉子節點,而一個表達式(例如( ( ( 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

 

 

3、計算表達式樹的值

  也運用了遞歸

  

#根據兩個數和一個符號,計算值
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)

 

4、輸出所有可能的表達式

  還是運用了遞歸

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)),

 

5、輸出結果

三、所有源碼

  

#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])
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM