0 前言——关于IIPP
本系列博客的内容均来自《An Introduction to Interactive Programming in Python (Part 1)》(在此我简称为“IIPP”)。
这是Coursera上的一门课程,以做游戏为导向讲解python交互式编程,非常有意思。它总共有8周的课程,每周都会有一个迷你项目(mini-project),由易到难,不过即使是容易完成的内容也能在某一个小点引人思考——比方说第一周的内容仅仅是猜拳,但老师所提出的关于“模数”的想法是异常精妙的,如果没有这方面的提示当然也是可以用一种傻瓜式编程编写出来,但是将列写出全部5*5=25种可能性(程序显得憨憨傻傻),然而一旦引入了“模数”的概念,则会将程序简化又简化,会让人由衷地感慨:“这就是数学之美!”
因此我将把每一次的作业编写结果都用博客的方式记录下来,并且与此同时也整理一下我从这一次作业中得到了什么。
1 作业内容
本周的作业内容是基于“剪刀石头布”的一种扩展,在“剪刀”“石头”“布”这三张牌的基础上又增加了两种牌——“蜥蜴”和“斯波克”(虽然我并不知道斯波克是什么东西……),于是由原先的剪刀石头布“一物降一物”变成了“两物降两物”,什么意思呢?我拿一张图进行解释:
如图,箭头的两端连接的是克制者与被克制者,被箭头指的是被克制的那一方。比如绿色的球与红色的球,通过查看箭头指向,可以发现是绿色克制红色。
国产的游戏里经常出现五行相生相克这种东西(当然还有一些游戏基于五行相生相克搞出来更复杂的相生相克关系,比如《赛尔号》),所以我觉得这样理解起来不难吧?画上面那图的时候我还用的是五行中的五种颜色呢~
总而言之,五张牌中任意一张牌,会克制其中两张牌,同时被其中另外两张牌克制,这样很公平。
2 判断胜出函数“compare_player_comp”的实现
2-1 方法一
现在题目来了:让玩家出任意一张牌,然后计算机再出一张牌,比较一下看谁赢。是不是感觉简单得不得了?其实最简单的方法就是把全部的可能性都列写出来,也就是共有5*5=25种可能性。
但是在前言中也说了这种方法有点憨,Joe老师给出一个提示就是:给这五张牌按0~4进行编号,然后比较大小。编号是这样的:
0 — rock
1 — Spock
2 — paper
3 — lizard
4 — scissors
这种方法识别起来很直观,比如0<1,所以Spock赢了rock;0<2,所以paper赢了rock……
不过要注意,当给定的两个数字的差值大于2开始,就不能这样直白地比较大小了。比如0和3比较,这里0应该转为5(0和5对5的余数都是5,就像时钟里0点=12点一样,0和12对12的余数都是12),是5>3因此是rock胜。同理,0和4比较,因为|0-4|=4>2,所以要把0转为5再进行比较,是5>4所以rock胜出。
因此当给定两个数的时候,我们必须先搞清楚这两个数的差值是否大于2。分为以下三种情况:
(1)-2≤num1-num2≤2:直接令num1与num2进行比较,谁大谁赢;
(2)num1-num2<-2:让num1加5,然后再与num2比较,谁大谁赢;
(3)num1-num2>2:让num1减5,然后再与num2比较,谁大谁赢。
写成代码就是这样的:
def compare_player_comp_m1(player_number,comp_number):
diff = player_number - comp_number
if (diff>2):
player_number -= 5
elif (diff<-2):
player_number += 5
if player_number>comp_number:
winner="player"
elif player_number<comp_number:
winner="computer"
else:
winner="nobody"
print winne