Python实现24点,包含对于A,1与14的处理

本文介绍了一种使用Python编程语言实现24点游戏的方法。通过随机生成四张扑克牌,考虑到A、1与14的特殊处理,利用递归、动态规划等编程概念,实现了对所有可能的数学运算组合进行搜索,以找到能够达到24点的算式。文章详细解释了如何生成随机牌面、处理不同数值的转换、添加运算符和括号,以及最终的计算和判断过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python实现24点,简易版本,数字[1,14],不含真实场景

# !/usr/bin/env python
# -*- coding:utf-8 -*-

'''
@author:ccc-ju
@software:PyCharm
@time: 19:11
'''
# 随机数
import random
# 从四个操作符种取3个,所有情况4 * 4 * 4 = 64
from itertools import product
# 获取两个集合中的笛卡尔积的情况
from itertools import permutations

# 1.生成四个随机数
cards = [random.randint(1, 14) for _ in range(4)]
# 2.考虑符号与数字的结合问题,一共有 4 * 4 * 4 = 64 种组合
def op_with_number(cards):
	operators = ['+', '-', '*', '/']
	car1, car2, car3, car4 = cards
	result = []
	for p in product(operators, repeat=len(cards) - 1):
		op1, op2 ,op3 = p
		result.append('{} {} {} {} {} {} {}'.format(car1, op1, car2, op2, car3, op3, car4))
	return result
# print(op_with_number(cards))

# 3.考虑数字的位置变换问题(笛卡尔积), 每四组数据都会有24种排列组合, 每次都会有 64 * 24 = 1536 种组合
def op_with_number_position_exchange(cards):
	result = []
	for p in permutations(cards):
		result += op_with_number(p)
	return result
# print(op_with_number_position_exchange(cards))

# 4.位置交换完了,符号也交换完了,但是这时候还不是很完善,缺少了括号的运算
# 这时候使用递归,把问题简化
def add_brace(cards):
	if len(cards) < 2:
		return [cards]
	if len(cards) == 2:
		return [['(' + str(cards[0])] + [str(cards[1]) + ')']]
	result = []
	for i in range(1, len(cards)):
		# 计算前半部分
		prefixs = add_brace(cards[:i])
		tails = add_brace(cards[i:])
		for p, t in product(prefixs, tails):
			with_brace_around = ['(' + p[0]] + p[1:] + t[:-1] + [t[-1] + ')']
			result.append(with_brace_around)
	return result
# print(add_brace(['1', '2', '3', '4']))

# 括号加完了,需要把运算符与括号加一起
def join_op(operators, with_brace):
	result = with_brace[0]
	for i, op in enumerate(operators):
		result += op + ' ' + with_brace[i + 1]
	return result
# print(join_op_with_numbers(['+', '/', '*'],['1', '2', '3', '4']))

# 解析表达式,比如 (((3 + 4) -1) * 4),分离出数字,与操作符
# 计算出所有的括号与数字的组合,分别进行分离,再组合
def join_op_with_numbers(expression):
	numbers = expression.split()[::2]
	operators = expression.split()[1::2]
	# 使用add_brace加括号,返回所有的可能性
	with_brace = add_brace(numbers)
	# 遍历加完括号的表达式,分别为它们加上运算符
	result = []
	for brace in with_brace:
		result.append(join_op(operators, brace))
	return result
# print(join_op_with_numbers('1 + 2 / 3 * 4'))

# 最终计算,进行判断是否为24点
def solve_problem_24_points(cards):
	TARGET = 24
	# 1.生成所有的表达式
	for exp in op_with_number_position_exchange(cards):
		# 2.遍历表达式加运算符
		for i in join_op_with_numbers(exp):
			# try一下,以防除零
			try:
				if eval(i) == TARGET:
					print(i)
			except ZeroDivisionError:
				continue
print('我抽到的牌是:\n', cards, '\n有以下的组合形式:')
solve_problem_24_points(cards)

Python实现24点,包含对于A,1与14的处理

# !/usr/bin/env python
# -*- coding:utf-8 -*-

'''
@author:ccc-ju
@software:PyCharm
@time: 20:30
编程三大概念
PKU:
	1.迭代模拟
	2.递归
	3.动态规划
'''
# 随机数
import random
# 从四个操作符种取3个,所有情况4 * 4 * 4 = 64
from itertools import product
# 获取两个集合中的笛卡尔积的情况
from itertools import permutations

def random_real_card():
	cards = '2 3 4 5 6 7 8 9 10 J Q K A'.split()
	color = '红桃 黑桃 方片 梅花'.split()
	return random.choice(color) + random.choice(cards)

#4个随机数
# cards = [random.randint(1, 13) for _ in range(4)]
cards = [random_real_card() for _ in range(4)]

# 操作符的64种情况
def op_collection_cards(cards):
	list_operators = ['+', '-', '*', '/']
	card1, card2, card3, card4 = cards
	expression = []
	for p in product(list_operators, repeat=len(cards) - 1):
		op1, op2, op3 = p
		expression.append('{} {} {} {} {} {} {}'.format(card1, op1, card2, op2, card3, op3, card4))
	return expression
# print(op_collection_cards(cards))

# 笛卡尔积(交换位置)
def op_collection_cards_xchange(cards):
	result = []
	for p in permutations(cards):
		result += op_collection_cards(p)
	return result
# print(op_collection_cards_xchange(cards))

# 采取递归方式加括号
def add_brace(cards):
	if len(cards) == 1:
		return [cards]
	if len(cards) == 2:
		return [['(' + str(cards[0])] + [str(cards[1]) + ')']]
	results = []
	for i in range(1, len(cards)):
		prefixs = add_brace(cards[:i])
		tails = add_brace(cards[i:])
		for p, t in product(prefixs, tails):
			with_brace_around = ['(' + p[0]] + p[1:] + t[:-1] + [t[-1] + ')']
			results.append(with_brace_around)
	return results
# print(add_brace('1 2 3 4'.split()))

# 括号与运算符一块运算
def brace_with_operators(with_brace,operators):
	finally_exp = with_brace[0]
	for i, op in enumerate(operators):
		finally_exp += (op + ' ' + with_brace[i+1])
	return finally_exp
# print(brace_with_operators(['(1', '(2', '(3', '4)))'], ['+', '-', '*']))

# 遍历不同组合的括号与运算符相结合
def join_brace_to_expression(expression):
	numbers = expression.split()[::2]
	operators = expression.split()[1::2]
	with_brace = add_brace(numbers)
	op_and_numbers = []
	for brace in with_brace:
		op_and_numbers.append(brace_with_operators(brace, operators))
	return op_and_numbers
# print(join_brace_to_expression('1 + 3 * 4 - 9'))

# 转换牌'A' 转换成 1 或者14
def card_change_to_number_card(cards, num):
	# print('抽到的牌为:\n',cards)
	str = ''
	for i in range(len(cards)):
		str += ' ' + cards[i][2:]
	cards_two = str.split(' ')[1:]
	size = len(cards_two)
	# print(cards_two)
	card_result1 = list()
	# 第一种情况num == 0时候把A转换成A
	if num == 0:
		print('进入的是第一种')
		# 第一种情况
		for i in range(size):
			if cards_two[i] == 'A':
				card_result1.append(1)
			elif cards_two[i] == 'J':
				card_result1.append(11)
			elif cards_two[i] == 'Q':
				card_result1.append(12)
			elif cards_two[i] == 'K':
				card_result1.append(13)
			else:
				card_result1.append(int(cards_two[i]))
	elif num == 1:
		print('进入的是第二种')
		# 第二种情况
		for i in range(size):
			if cards_two[i] == 'A':
				card_result1.append(14)
			elif cards_two[i] == 'J':
				card_result1.append(11)
			elif cards_two[i] == 'Q':
				card_result1.append(12)
			elif cards_two[i] == 'K':
				card_result1.append(13)
			else:
				card_result1.append(int(cards_two[i]))
	else:
		print('进入的是第三种')
		# 第三种情况 不含A
		for i in range(size):
			if cards_two[i] == 'J':
				card_result1.append(11)
			elif cards_two[i] == 'Q':
				card_result1.append(12)
			elif cards_two[i] == 'K':
				card_result1.append(13)
			else:
				card_result1.append(int(cards_two[i]))
	return card_result1
# card_change_to_number_card(cards)

# 最终结果
def finally_result(cards):
	str = ''
	for i in range(len(cards)):
		str += ' ' + cards[i][2:]
	cards_two = str.split(' ')[1:]
	TARGET = 24
	count = 0
	for i in range(len(cards_two)):
		# 让A先等于1进行尝试
		if cards_two[i] == 'A':
			# 调用牌的转换器
			print('走的第一种含A的情况且A为1')
			cards2 = card_change_to_number_card(cards, 0)
			for exp in op_collection_cards_xchange(cards2):
				for b in join_brace_to_expression(exp):
					try:
						if eval(b) == TARGET:
							count += 1
							print(b)
					except ZeroDivisionError:
						continue
	for i in range(len(cards_two)):
		# 走到这里说明没有值A不为1,把A = 1 改成 A = 14
		if cards_two[i] == 'A' and count == 0:
			print('走的第二种含A的情况且A为14')
			# 调用牌的转换器
			cards2 = card_change_to_number_card(cards, 1)
			for exp in op_collection_cards_xchange(cards2):
				for b in join_brace_to_expression(exp):
					try:
						if eval(b) == TARGET:
							count += 1
							print(b)
					except ZeroDivisionError:
						continue
	for i in range(len(cards_two)):
		# 走到这里说明牌里面不含A
		if cards_two[i] != 'A' and count == 0:
			print('走的第三种不含A的情况')
			# 调用牌的转换器
			cards2 = card_change_to_number_card(cards, -1)
			for exp in op_collection_cards_xchange(cards2):
				for b in join_brace_to_expression(exp):
					try:
						if eval(b) == TARGET:
							count += 1
							print(b)
					except ZeroDivisionError:
						continue
print('我抽到的牌是:\n', cards)
finally_result(cards)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值