Swift Playgrounds 猜拳游戏的二次开发
目录 (Table of Contents)
1. 项目简介
这是一个用Swift语言编写的由猜拳延伸出的一个小游戏,可以在mac或ipad的Swift Playgrounds中直接运行。
源代码是在 中国大学MOOC / Swift创新导论 这门课程第二次开课时课程中下载的。
2. 项目分析
游戏规则详解
1)背景
在去往西天取经的路上,有这样4种角色:
- 👨🦲 唐僧
- 🐒 悟空
- 🐷 八戒
- 👻 妖精
我们(左边)可以派出3种角色:
- 👨🦲 唐僧
- 🐒 悟空
- 🐷 八戒
迎战电脑(pc)(右边)。
2)胜负
- 妖精能抓住唐僧, 👻 > 👨🦲
- 悟空和八戒都能打败妖精,🐒 > 👻 , 🐷 > 👻
- 悟空的实力强于八戒,🐒 > 🐷
- 悟空听唐僧的 👨🦲 > 🐒
虽然规则比猜拳复杂,不过套进西游记故事里还挺直观的
3)计分
- 胜利:格子变绿🟩,+1 Score
- 平局:格子变黄🟨,+0 Score
- 失败:格子变白⬜️,-1 Score
如图,进行多次点按骰子:
其实这样一来,我们的选择和电脑的选择,都是电脑随机决定的 啊(
函数功能详解
1)battle()函数
battle(between a: String, and b: String) -> String
这个函数用来判断单独一组游戏(1个左vs.1个右)胜负。
也就是复述一遍刚刚的「胜负」规则嘛~
具体实现函数如下:
//注意:Swift中,emoji是一种字符串
//字符串可以作为参数直接传入函数,返回值也可以是字符串;
//双方比较胜负后,返回胜利的一方的字符串
func battle(between a: String, and b: String) -> String {
if a == "👨🦲" && b == "🐒" {
return "👨🦲"
} else if a == "👨🦲" && b == "👻" {
return "👻"
} else if a == "🐒" && b == "👨🦲" {
return "👨🦲"
} else if a == "🐒" && b == "🐷" {
return "🐒"
} else if a == "🐒" && b == "👻" {
return "🐒"
} else if a == "🐷" && b == "🐒" {
return "🐒"
} else if a == "🐷" && b == "👻" {
return "🐷"
} else if a == "👻" && b == "👨🦲" {
return "👻"
} else if a == "👻" && b == "🐒" {
return "🐒"
} else if a == "👻" && b == "🐷" {
return "🐷"
} else {
return ""
}
}
2)didSet的使用
如果定义变量score时用到了didSet,那么score就是类似于一种加了监视器的变量:
var score = 0 {
didSet {
self.gameScoreLabel.text = "Score: \(self.score)"
}
}
每当score值发生变化时,都会调用一次didSet中的代码。
此处的didSet,即刷新score值。
3)setupPCChoiceLabel() 函数的功能
字面意思,就是更新pc(右边)方框的背景色、角色
func setupPCChoiceLabel(for label: UILabel, with index: Int) {
//更新角色
label.text = pcChoices[index]
label.textColor = .black
label.textAlignment = .center
//获得上述battle函数的返回值,用来更新颜色和分数;
//分数的更新,是PC和My二者中选一个写进去,不是都写进去。
let battleResult = battle(between: myChoices[index], and: pcChoices[index])
if pcChoices[index] == battleResult {
score -= 1
label.backgroundColor = 绿
} else if battleResult == "" {
label.backgroundColor = 黄
} else {
score += 1
label.backgroundColor = 白
}
//背景框的圆角、大小等细节
label.clipsToBounds = true
label.layer.cornerRadius = 8.0
label.font = UIFont.systemFont(ofSize: 40)
}
注 : “绿、黄、白”本应通过代码表示,为便于观看,这里写了中文。
例如:“绿”->"#colorLiteral(red: 0.7155902982, green: 0.8722988963, blue: 0.5982006788, alpha: 1)"
setupMyChoiceLabel()函数与setupPCChoiceLabel()除了提到的score变量的处理之外,其他相同,不再赘述了。
下方不远处👇 4) ② 代码将调用此二函数。
4)🎲按钮
🎲按钮的工作可以划分为两块,一是点击触发,二是随机选出角色。
①点击触发:
shuffleButton.addTarget(self, action: #selector(shuffle), for: .touchUpInside)
②随机选出角色:
这里是在Swift语言中使用object-c语法,所以函数前加上@objc
@objc func shuffle() {
//清空pc方的选择
pcChoices.removeAll()
score = 0
//随机生成pc方的选择
for _ in 0..<myChoices.count {
pcChoices.append(allCharactors.randomElement()!)
}
//更新pc(左边)方框的背景色、角色
for index in 0..<pcChoices.count {
let pcChoiceLabel = pcChoiceLabels[index]
setupPCChoiceLabel(for: pcChoiceLabel, with: index)
}
//更新我们(右边)方框的背景色、角色
for index in 0..<myChoices.count {
let myChoiceLabel = myChoiceLabels[index]
setupMyChoiceLabel(for: myChoiceLabel, with: index)
}
}
3. 改进思路
- 优化玩家游戏体验:
添加一个总分积分器。 - 增加玩家掌控感:
点按己方角色,可以改变自己出的角色;点按shuffle只会变化电脑方的角色。(待续)
4. 改进
积分器
每一局游戏结束后,score不清零,还可以继续游戏。
首先,在代码前段注释掉didSet
然后,在shuffle()函数中添加更新score的语句
另外,这样改动后,经过一些尝试,总得分还是负分多,或许可以推测这个游戏规则并不平衡?貌似玩家拿负分的概率更大?
5. 最终效果
6. 感想
通过这次博客的撰写,一是复习了(本就没什么基础的)Swift语言,(许许多多)以前被略过的语法点,通过这一次的二次开发理解了(一部分)。
二来,也对markdown语法更加熟悉了。虽说是md是同一种语法规则,但在不同的编辑器上美观程度相差很大。
我之前觉得,网上开源的代码就是接近完美的,因为有这么多人维护嘛,也更别说公开课的示例代码了。但是,如果从新的角度思考问题,我发现不管什么东西,只要不从原先的角度思考问题,总是有改动的空间的。
在做开发时,把自己当成软件的用户,就是一种变更思考角度的方法。
用时:
确定做什么(2h)+理解代码(6h)+确定改进的思路(1h)+改进代码(2h)+总结(1h)+打扮博客、摸索markdown(6h)
工具:
Xcode, GIPHY CAPTURE, 一个比较好看的markdownd, 优雅地从markdown加图片,
live2d(待续)