问题描述:
常见游戏规则:
从扑克中每次取出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)
运行结果: