IIPP迷你项目(一)“Rock-paper-scissor-lizard-Spock”
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 winner + " wins!"
其中传递进来的两个参数分别为“玩家出的牌对应的数字”和“计算机出的牌对应的数字”。
2-2 方法二
这种方法不得不承认我一开始是没有想到的,它是在课程的《Code Clinic Tips》页面下给出的一个提示。
如图所示,是将这全部5*5=25种情况列些出来的一个表格,表格中每个单元格的左上角是“player_number - comp_number”的差值,而右下角则是该差值对5取模所得。
通过这样一个表格,我们可以很直观地观察到当右下角的值为1或2时,是玩家胜出(蓝色字体标明是玩家胜出),当右下角的值为3或4时,是计算机胜出(红色字体标明是计算机胜出),右下角的值为0时,没有人胜出(黄色字体标明打平手)。
这样一来程序就更好写了:
def compare_player_comp_m2(player_number,comp_number):
diff = player_number - comp_number
diff_module = diff % 5
if (diff_module==1) or (diff_module==2):
winner="player"
elif (diff_module==3) or (diff_module==4):
winner="computer"
else:
winner="nobody"
print winner + " wins!"
3 其余helper函数以及主函数的实现
1、本程序的helper函数有以下三个:
(1)name_to_number(name):将牌名转为对应的数字0~4。
def name_to_number(name):
number=-1 #init
if name=="rock": #convert
number=0
elif name=="Spock":
number=1
elif name=="paper":
number=2
elif name=="lizard":
number=3
elif name=="scissors":
number=4
if number==-1: #return
err="no choice named "+ "\"" +name + "\"."
return err
else:
return number
(2)number_to_name(number):将数字转为对应的牌名“rock”~“scissors”。
def number_to_name(number):
name="none" #init
if number==0: #convert
name="rock"
elif number==1:
name="Spock"
elif number==2:
name="paper"
elif number==3:
name="lizard"
elif number==4:
name="scissors"
if name=="none": #return
err="the number \""+ str(number) + "\" is not a valid input."
return err
else:
return name
(3)compare_player_comp(player_number,comp_number):即上一节中实现的函数,我给出了两种实现方法,用m1和m2区分。
2、主函数rpsls(player_choice):在rpsls函数中,除过完成让电脑出拳这一步之外,它还负责将上面这些helper函数串在一起以实现猜拳功能。
import random def rpsls(player_choice):
print "Player chooses " + player_choice # rpsls part1
player_number=name_to_number(player_choice)
if str(player_number).isdigit()==True: #只有player_number是数字,才能说明输入无误,方可往下继续走
comp_number= random.randrange(0,5,1) # rpsls part2
comp_choice=number_to_name(comp_number)
print "Computer chooses " + comp_choice
compare_player_comp_m2(player_number,comp_number) #rpsls part3
print " "
else:
print player_number
4 全部程序清单
### helper function ###
def name_to_number(name):
number=-1 #init
if name=="rock": #convert
number=0
elif name=="Spock":
number=1
elif name=="paper":
number=2
elif name=="lizard":
number=3
elif name=="scissors":
number=4
if number==-1: #return
err="no choice named "+ "\"" +name + "\"."
return err
else:
return number def number_to_name(number):
name="none" #init
if number==0: #convert
name="rock"
elif number==1:
name="Spock"
elif number==2:
name="paper"
elif number==3:
name="lizard"
elif number==4:
name="scissors"
if name=="none": #return
err="the number \""+ str(number) + "\" is not a valid input."
return err
else:
return name 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 winner + " wins!" def compare_player_comp_m2(player_number,comp_number):
diff = player_number - comp_number
diff_module = diff % 5
if (diff_module==1) or (diff_module==2):
winner="player"
elif (diff_module==3) or (diff_module==4):
winner="computer"
else:
winner="nobody"
print winner + " wins!" ### main function ###
import random def rpsls(player_choice):
print "Player chooses " + player_choice # rpsls part1
player_number=name_to_number(player_choice)
if str(player_number).isdigit()==True: #只有player_number是数字,才能说明输入无误,方可往下继续走
comp_number= random.randrange(0,5,1) # rpsls part2
comp_choice=number_to_name(comp_number)
print "Computer chooses " + comp_choice
compare_player_comp_m2(player_number,comp_number) #rpsls part3
print " "
else:
print player_number ### display ###
rpsls("rock")
2016.5.29
by 悠望南山
IIPP迷你项目(一)“Rock-paper-scissor-lizard-Spock”的更多相关文章
- 2018 ACM-ICPC 中国大学生程序设计竞赛线上赛 H题 Rock Paper Scissors Lizard Spock.(FFT字符串匹配)
2018 ACM-ICPC 中国大学生程序设计竞赛线上赛:https://www.jisuanke.com/contest/1227 题目链接:https://nanti.jisuanke.com/t ...
- IIPP迷你项目(三)“Stopwatch: The Game”
0 本周项目说明 这一次博客是Coursera的IIPP课程第三周迷你项目的实现,基础要求是做一个秒表,能start能stop能reset,更高的要求是在此秒表的基础上完成两个小游戏,但是鉴于第二个小 ...
- IIPP迷你项目(四)"Pong"
1 小球在墙面的反弹 1-1 让小球在画布上匀速运动 在这一步中,首先应该明确小球是如何匀速运动的.它的方法是规定一个列表v,Scott老师说这代表着“速度(Velocity)”,但是我觉得也可以拿“ ...
- IIPP迷你项目(二)"Guess the Number!"
本来这个程序是早就编完了的,一直没时间发布博客.时至今日已时隔多天,也算是复习一下事件驱动型编程的过程吧. 1 事件驱动型编程 本质上这次的作业是披着猜数字皮的图形化界面编程,好在 simplegui ...
- 摸鱼人常备5个Python迷你项目,玩一整天不是问题(附源码)
大家好鸭,我是小熊猫 在使用Python的过程中,我最喜欢的就是Python的各种第三方库,能够完成很多操作. 下面就给大家介绍5个通过Python构建的项目,以此来学习Python编程. 一.石头剪 ...
- 洛谷 P3609 [USACO17JAN]Hoof, Paper, Scissor蹄子剪刀…
P3609 [USACO17JAN]Hoof, Paper, Scissor蹄子剪刀… 题目背景 欢迎提供翻译,请直接在讨论区发帖,感谢你的贡献. 题目描述 You have probably hea ...
- HDOJ(HDU) 2164 Rock, Paper, or Scissors?
Problem Description Rock, Paper, Scissors is a two player game, where each player simultaneously cho ...
- HDU 2164 Rock, Paper, or Scissors?
http://acm.hdu.edu.cn/showproblem.php?pid=2164 Problem Description Rock, Paper, Scissors is a two pl ...
- SDUT 3568 Rock Paper Scissors 状压统计
就是改成把一个字符串改成三进制状压,然后分成前5位,后5位统计, 然后直接统计 f[i][j][k]代表,后5局状压为k的,前5局比和j状态比输了5局的有多少个人 复杂度是O(T*30000*25*m ...
随机推荐
- win8.1休眠状态下不能进入系统
win8.1下进入睡眠状态出现的问题: 1.合上盖子或者是点击睡眠状态后唤醒进入锁屏界面.可是仅仅能鼠标移动,键盘全然输入不了,出现假死现象,仅仅能强制重新启动. 2.合上盖子再打开无法唤醒屏幕,必须 ...
- 字符编码简介:ASCII,Unicode,UTF-8,GB2312
字符编码简介:ASCII,Unicode,UTF-8,GB2312 1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和 1两种状态,因 ...
- LoadRunner测试Google Suggest
Google的搜索框是典型的AJAX应用,用户在输入关键字的同时,前端页面通过xmlhttp与后台服务器动态交互,根据用户输入的关键字查找匹配的内容,向用户提示建议的搜索项,也就是所谓的“google ...
- Photoshop | 快速抠头发(调整边缘/选择并遮住)
———————————————————————————————————————————— Photoshop快速抠头发(CS6中调整边缘功能,CC2017中更名为选择并遮住) - - - - - - ...
- 简单模拟javaScript面向对象
<html> <head> <script type="text/javascript"> if (!Object.create) { Obje ...
- 转:EMQ(emqttd) 2.x 安装和使用(物联网传输控制协议的Broker)
支持下国产开源. MQTT物联网传输控制协议:<MQTT-3.1.1-CN.pdf> 下载:emqttd-centos64-v2.0-rc.2-20161019.zip 安装: $ unz ...
- YII2 学习
下载地址: http://www.yiiframework.com/download/ http://www.yiichina.com/download 直接选择basic模板下载即可 下载之后解压到 ...
- Django中ORM介绍和字段参数
Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据 ...
- java-FileDemo
关于file类的使用:文件的增删查 package com.example; import java.io.File; import java.io.IOException; public class ...
- CentOS 7 安装以及配置桌面环境
一.安装 GNOME 桌面 1.安装命令: yum groupinstall "GNOME Desktop" "X Window System" " ...