python实例:解决经典扑克牌游戏 — 四张牌凑24点 (一)

python实例:解决经典扑克牌游戏 -- 四张牌凑24点 (一)[Python基础]

  Hey! Hope you are having a great day so far!

  今天想和大家讨论的是一道我从这学期cs的期末考试得到灵感的题:Get 24 Poker Game。说到 Get 24 Poker Game,也就是我们通常说的凑24点,大家可能都比较熟悉。但是因为这个游戏有很多变种,我们还是来简单说一下游戏的规则。老规矩,上Wikipedia:

The 24 Game is an arithmetical card game in which the objective is to find a way to manipulate four integers so that the end result is 24.

  简单来说,这个游戏需要玩家快速用随机抽出的四张牌上的整数通过常见的加减乘除计算来凑出24点来取得胜利(一定要用全4张,不可以弃牌)。不同于我们通常玩的斗地主,钓鱼等等扑克游戏,凑24点更考验玩家的数学反应能力(less fun but somewhat interesting:))。在这里稍稍跑一下题,因为可能会有人好奇,为什么恰恰选了24这个数字。其实答案很直白,因为这个数字最容易被凑出来:24是拥有八个除数的最小整数(1, 2, 3, 4, 6, 8, 12, and 24),使用这个数字不仅仅把游戏变得更加简单(毕竟可能没有人想花一个小时在用扑克牌凑数上),还把游戏作废(目标数字凑不出来)的几率降到最小。

  好了,希望大家对这个卡牌游戏已经有一些基础的认知了,但是在正式开始编这个游戏之前,我想先从这学期cs期末考试的一道题入手:

  It is possible to combine the numbers 1, 5, 6, 7 with arithemtic operations to get 21 as follows: 6/(1-5/7).

Part I: 

  Write a function that takes in a list of three numbers and a target number, and returns a string that contains an expression that uses all the numbers in the list once, and results in the target. Assume that the task is possible without using parentheses.

  For example, get_target_noparens([3, 1, 2], 7) can return “2*3+1” or “1+2*3” (either output would be fine).

 

Part II:

  Now, write the function get_target which returns a string that contains an expression that uses all the numbers in the list once, and results in the target. The expression can contain parentheses. Assume that the task is possible.

  For example, get_target([1, 5, 6, 7], 21) can return “6/(1-5/7)” , this will return all permutation of the list of number.

 

  这道题有两部分,第一部分的大意是写出一个函数,让其能够以列表的形式接收三个数字并试图用加减乘除的方法来凑出目标点数(注意,这里不包括括号操作)。第二部分相对于前一部分难度更高一点,要求写出函数,让其能够接受任意数量的数字,并可通过对其进行加减乘除(这里包括括号)的操作来凑出目标点数。另外,在做这道题的时候不需要考虑备选数字没有办法凑出目标点数的情况。

  我们不难看出,第二题其实和我们想要做出的卡牌游戏的解法基本上是完全重合,甚至更加简单。只需把函数的目标数字设为24,而且限制前面列表的数字数量为4,就能够做出这个游戏的解法。但第一题给考生了一个基础的思路,也就是说第一题给第二题做了很好的铺垫,能够让人更快的找到正确的逻辑,完成解题过程。所以只要解决这两道题,我们就可以很流畅的找出凑24点的最终解法(多做一道赚一道啊!)。

 

  话不多说,我们开始!(完整代码在文末)


   

  通过读题,我们可以发现第一题和第二题最主要的差别在以下两点上:

  1. 第一题只需要考虑三个数字,两个符号的排列组合,也就是说在改变运算符号时,我们只需考虑4选1,或者4选2的情况。而第二题却需要完全不同的思路,要在不确定总数字量的情况下,在每两个数字间考虑到所有排列可能。
  2. 第二题需要考虑到一个,或者多个括号的算法,在这种情况下,我们不能直接计算结果,因为没有办法确定括号的个数和位置。

  记住以上两点:)如果我们能在做第一小题时找到关于第二小题的启发,会事半功倍的!

 

  第一小题我们可以从运算式子的结构入手。正常写出的话,一个有三个运算数字的式子会长这个样子:

$1+2+3$

结构一目了然,三个数字,两个运算符号。如果想生成所有排列组合的可能性的话,我们可以用嵌套for循环很容易的用代码实现如下:

1 def get_all_comb(num_list):
2     """find all arithmatic combination using the given 3 numbers"""
3 
4     for op_1 in ["+","-","*","/"]: # 用第一个for loop来考虑所有第一个位置的运算符号的可能性
5         for op_2 in ["+","-","*","/"]: # 用第二个for loop来考虑所有第二个位置的运算符号的可能性
6             comb = str(num_list[0])+op_1+str(num_list[1])+op_2+str(num_list[2]) # 组装运算式
7             print(comb) # 打印运算式
hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » python实例:解决经典扑克牌游戏 — 四张牌凑24点 (一)