使用Python编写24点游戏
有一个叫做24的游戏,这是一款基于数学的游戏。如果你对这个游戏不太了解,可以先看看这个链接:http://en.wikipedia.org/wiki/24_Game
简单来说,这个游戏会给你四个数字(在我的例子中,数字范围是1到9),这些数字是随机选出来的。你的任务是用这四个数字,通过加、减、乘、除这四种基本运算,组合出数字24。规则很简单,你必须使用这四个数字,而且只能用这四个数字,每个数字只能用一次。这个游戏让我很感兴趣,所以我想写一个程序来模拟这个游戏。
我的目标是用Python编写这样一个程序。基本的步骤是……
- 生成4个随机数字
- 检查这些数字是否能组合成24
- 把这些数字显示给用户
- 看看用户输入的结果是否也能得到24
我最需要帮助的地方是第2步和第4步
我会使用随机模块来生成随机整数。
import random
num1 = random.randint ( 1, 9)
num2 = random.randint ( 1, 9)
num3 = random.randint ( 1, 9)
num4 = random.randint ( 1, 9)
所以,如果可以的话,请帮我一起创建这个游戏,并且给我讲解一下!谢谢。
另外,这是我第一次在Stack Overflow上提问,所以请给我一些建议,告诉我怎么能提高提问的技巧 :)
---编辑---
谢谢大家的帮助,但我终于搞明白了。我做了一些研究,整理了这个代码(如果你们想自己试试代码的话):
>
'''
The 24 Game
Given any four digits in the range 1 to 9, which may have repetitions,
Using just the +, -, *, and / operators; and the possible use of
brackets, (), show how to make an answer of 24.
An answer of "!" will generate a new set of four digits (if your stuck).
Otherwise you are repeatedly asked for an expression until it evaluates to 24
Note: you cannot form multiple digit numbers from the supplied digits,
so an answer of 12+12 when given 1, 2, 2, and 1 would not be allowed.
'''
from __future__ import division, print_function
import random, ast, re
import sys
while 1 == 1:
if sys.version_info[0] < 3: input = raw_input
def choose4():
'four random digits >0 as characters'
return [str(random.randint(1,9)) for i in range(4)]
def welcome(digits):
print (__doc__)
print ("Your four digits: " + ' '.join(digits))
def check(answer, digits):
allowed = set('() +-*/\t'+''.join(digits))
ok = all(ch in allowed for ch in answer) and \
all(digits.count(dig) == answer.count(dig) for dig in set(digits)) \
and not re.search('\d\d', answer)
if ok:
try:
ast.parse(answer)
except:
ok = False
return ok
def main():
digits = choose4()
welcome(digits)
trial = 0
answer = ''
chk = ans = False
while not (chk and ans == 24):
trial +=1
answer = input("Expression %i: " % trial)
chk = check(answer, digits)
if answer.lower() == 'q':
break
if answer == '!':
digits = choose4()
print ("New digits:", ' '.join(digits))
continue
if not chk:
print ("The input '%s' was wonky!" % answer)
else:
ans = eval(answer)
print (" = ", ans)
if ans == 24:
print ("Thats right!")
main()
(python 3.3)
1 个回答
我喜欢24点!我记得在小学的时候玩过这个游戏。
首先,我们来看看在一轮24点游戏中需要评估的所有可能组合的总数。在一轮游戏中,会用到四个数字和三个运算符。
我们可以把这四个数字排列成4!种方式,结果正好是24种,哈哈。
对于三个运算符的排列,我们可以用4p3种方式来计算(不考虑加法和乘法的顺序),结果也是4!,也就是24(这开始有点吓人了)。
编辑:如果我没记错的话,运算可以重复,所以实际上有4的3次方,也就是64种“运算组合”。这样我们就有1560种组合需要检查,这个数量还是可以接受的。
对于四个随机数字的每一种组合,可能的“24点方程”总数是24乘以24,结果是576。幸运的是,现代电脑可以在几微秒内计算出576个算式。
在你准备一个576个分支的if-else树之前,我们来用更优雅的方式解决这个问题。
作为热身,首先写一个函数,打印出四个随机数字的所有排列,传入这四个随机数字的列表作为参数。如果你搞不定,可以在网上搜索“Python 字符串的排列”。
然后写一个函数,打印出四个运算符的所有长度为3的排列(编辑:可以重复),返回一个包含64个字符串的列表,比如["aaa", "aas", ... , "amm", "amd", ... ],其中'a'代表加法,'s'代表减法,'m'代表乘法,'d'代表除法。
现在你准备好测试所有的情况了。把第一个函数的结果存储在一个列表Ns中,把第二个函数的结果存储在一个列表Ops中,然后
for ns in Ns:
for ops in Ops:
result = ns[0]
result = op24(result, ops[0], ns[1])
result = op24(result, ops[1], ns[2])
result = op24(result, ops[3], ns[3])
if result == 24:
return True
for ops in Ops:
result1 = op24(ns[0], ops[0], ns[1])
result2 = op24(ns[2], ops[1], ns[3])
result = op24(result1, ops[2], result2)
if result == 24:
return True
# none of the permutations were equal to 24
return False
编辑:如果生成并评估前缀表达式,可以简化上面内层循环之间的差异。
op24函数的实现如下
def op24 (ns1, op, ns2):
if op == 'a':
return ns1 + ns2
elif op == 's':
return ns1 - ns2
...
编辑 在计算时使用float()
,这样聪明的玩家就可以处理那些不能整除的数字的除法和乘法。
可以通过使用Python的“op”模块来避免使用“op24”函数,生成函数引用的排列,而不是“运算字符串”,但因为你看起来是个初学者,我就不在这里展开了;)。