24点游戏破解

问题描述:

常见游戏规则:

   从扑克中每次取出4张牌。使用加减乘除,第一个能得出24者为赢。(其中,J代表11,Q代表12,K代表13,A代表1),按照要求编程解决24点游戏。

基本要求 随机生成4个代表扑克牌牌面的数字字母,程序自动列出所有可能算出24的表达式,用擅长的语言(C/C++/Java或其他均可)实现程序解决问题。

 

算法思路:

对于这道题目,通常的解法就是暴力破解,穷举出所有的可能的表达式组合,再计算每个表达式的值。如果为24则保留下来,否则舍弃。

那么在进行构造表达式的时候,先把4个数进行排列组合,对每组数先构造前两个的所有组合,再将前两个的所有组合与第三个数进行组合,再与第四个数进行组合。这样会出现重复的表达式,对于满足交换律的表达式只保留一个即可。再将得到的所有表达式进行计算,结果等于24就保留下来。

python计算表达式有一个函数eval(),可以直接计算出值。

代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : point24.py
# @Author: deng
# @Date  : 2018/9/17
# @Desc  :

import random as rd
import itertools

operator = ['+', '-', '*', '/']


def get_cards():
    """
    随机产生四张牌
    :return:
    """
    cards = [rd.randint(1, 13) for i in range(4)]
    return cards


def exp(a, b, op):
    """
    将两个数和一个操作符拼接成表达式
    :param a: 操作数1
    :param b: 操作2
    :param op: 运算符
    :return: 表达式
    """
    return '(' + str(a) + op + str(b) + ')'


def group(cards, k=None):
    """
    将一组牌进行排列组合
    :param cards: 4张扑克牌
    :param k: 每组的个数 默认:全排列
    :return: 有的组合列表
    """
    return list(itertools.permutations(cards, k))


def join(*args):
    """
    将四组数进行表达式组合
    :param args: 四组数
    :return: 表达式列表
    """
    a, b, c, d = args
    arr1 = []
    arr2 = []
    arr = []
    for op in operator:
        arr1.append(exp(a, b, op))
    for item in arr1:
        for op in operator:
            arr2.append(exp(item, c, op))
    for item in arr2:
        for op in operator:
            arr.append(exp(item, d, op)[1:-1])

    return list(set(arr))


def swap_head(g):
    old = g[2:g.find(')')]
    op = list(set(old) & set(operator))[0]
    x, y = old.split(op)
    new = y + op + x
    return old, new


def swap_tail(g):
    old = g[g.find(')') + 2:]
    temp_g = old.replace(')', '')
    opr = list(set(temp_g) & set(operator))[0]
    x, y = temp_g.split(opr)
    new = y + ')' + opr + x
    return old, new


def swap_tails(g):
    old = g[g.find(')')+1:]
    x, y = old.split(')')
    new = y + ')' + x
    return old, new


def trim(case):
    move = []
    result = case
    index = len(result)
    for i in range(index):
        g = result[i]
        old, new = swap_head(g)
        new_g = g.replace(old, new)
        if new_g in result[i:]:
            move.append(result[i])
    for i in move:
        result.remove(i)

    move = []
    index = len(result)
    for i in range(index):
        g = result[i]
        old, new = swap_tail(g)
        new_g = g.replace(old, new)
        if new_g in result[i:]:
            move.append(result[i])

    for i in move:
        result.remove(i)
    return trims(result)


def trims(case):
    """
    表达式去重
    :param case: 待去重表达式列表
    :return: 去重后的列表
    """
    move = []
    result = case
    index = len(result)
    for i in range(index):
        g = result[i]
        # old, new = swap_head(g)
        # g = g.replace(old, new)
        old, new = swap_tails(g)
        new_g = g.replace(old, new)
        if new_g in result[i:]:
            move.append(result[i])
    for i in move:
        result.remove(i)
    return result


def search24(cards):
    """
    搜索24点
    :param cards: 4张牌
    :return: 所有可能的组合
    """
    all_case = []
    result = []
    groups = group(cards=cards)
    for i in groups:
        a, b, c, d = i
        all_case += join(a, b, c, d)
    all_case = list(set(all_case))
    for j in all_case:
        if eval(j) == 24:
            result.append(j)
    return result


if __name__ == '__main__':
    card = get_cards()
    print("你获得的四张牌为: ", card)
    print("所有表达式结果为:")
    re = search24(cards=card)
    # 除去重复的表达式组合
    r = trim(re)
    # 输出表达式
    for i in r:
        print(i)

 

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值