剪刀石头布
该项目为ifLab的iOS方向新生练习项目之一,为接触了Objective-C语言后的第一个UI小练习。
主要涉及的内容有:
Objective-C语言初等语法实践;
StoryBoard基本功能使用;
Xcode基本功能使用。
这是最终完成图:
玩家选择要本局游戏是出“拳”、“布”还是“剪刀”,点击“开始”按钮后,电脑(以下简称AI)自动算出要出的子,最后进行游戏输赢判断。
如果你是第一次接触iOS开发UI方面的东西,或许会对其产生疑惑,怎么就把之前写的“黑框框”程序变成了带有UI元素的App了呢?其实我们可以把App分为三层,其中负责写“剪刀石头布”逻辑代码的部分,我们称之为Model层,Model层主要负责的事情就是输出数据,每次我们访问一次Model层的相关方法都能获得数据。
而显示出的UI,比如上图中所示的emoji和蓝色的按钮,这一白色背景上的东西我们可以称之为View层,在这一层上,主要负责UI控件的布局及更新,比如我们选择了“剪刀、石头、布”三者之一,就会给其套上一个边框,继续选择其它两个该边框会“移动”过去,这就是View层的更新操作。
但是我们怎么把从Model层获取到的数据放到View层中去呢?我们还需要一个管理者,也即Controller层,它的主要责任就是决定何时何地把Model层获取到的数据更新到View层中。
关于Xcode的介绍和简单使用,大家可以参考这篇文章。
创建工程
打开Xcode -> "create a new Xcode project" -> "Single View App" -> 填写相关信息。
此时点击Xcode左上角类似播放的按钮(下文简称"run"),此时Xcode将会编译该工程,且运行起一个模拟器,如果发现并没有模拟器运行起来,可以选择run按钮右边项目工程名字边上的设备下拉框,选择一个你所喜欢模拟器,再次run即可。
你会看到模拟器运行起来是一片空白,对,它就应该是一片空白,如果我们此时想要对它做些改变,在Xcode的左边栏的文件目录下,找到并点击一个名为Main.storyboard的文件。
没错,它就是导致了模拟器运行起来一片空白的原因。打开Xcode的右侧边栏,在右侧边栏的最下边找到一个类似铜钱的按钮,如下所示,
点击这个类似铜钱的按钮,在其中随意拖拽一个控件(按钮鼠标或者触控板)到刚才看到的空白页面上即可,如下所示,
现在再次run工程,模拟器跑起来后,你会发现上边多了刚才你所拖拽进去的控件。现在你已经会进行拖拽控件了,我们要做本文开始之前的页面,这个页面就是用拖拽控件的方式进行搭建的。
想要完成本文开始的页面(以下简称首页),我们需要UIButton、UILabel、UIProgressView这这种控件,“剪刀、石头、布”以及“开始”按钮都是UIButton类型,位于“开始”按钮之下的提示语控件类型为UILabel,而位于头部和底部用于记录双方各自得分的控件为UIProgressView。
界面搭建
在对UIButton类型控件的自定义时,注意下图所示要点:
搭建完的界面属于View层,而我们想要对View层的数据进行修改,必须要拿到这个控件,因此,接下里我们需要把这些位于View层上的控件拖拽到对应的Controller层中供后续的Model层数据源刷新后View层的刷新。
我们来尝试拖拽第一个View层上的控件,如果你是第一次进行拖拽控件,肯定会出问题🙂,具体操作如下图所示,
我们要把拖拽的文件丢入哪个文件呢?单针对Objective-C来说,我们一般把控件拖拽在@interface ...... @end之间,如果你的这个控件想要被外部类访问,那就放在.h文件中,如果这个控件你只要被该类内部自己使用,那就拖拽到.m文件的@interface ...... @end之间。针对“剪刀石头布”这个项目,因为我们只有一个Controller文件,还没涉及到分层,并且View层和Model层都混在Controller层中,因此,我们选择拖拽到ViewController.m的@interface ...... @end之间。
如果发现按照上图的操作并不能自动的帮你定位到相关文件,可以按照如下图所示操作进行资源定位,
现在,相信你已经完全的把所有控件都拖拽好了。是的,我们需要把所有控件都拖拽到对应文件中。现在ViewController.m文件的@interface ...... @end之间看起来应该差不多是这个样子的,
逻辑部分
现在,让我们再一起来梳理一遍“剪刀石头布”的游戏逻辑。不确定大家是否有自己编写过相关代码,再次就先当大家都不知道吧,简单的来说一说.
我们分别给“剪刀”、“石头”、“布”三个子设置标签(以下简称为tag),且假设剪刀tag为V,石头tag为O,布tag为W,对于玩家来说,在这三个tag中选一个就好,但是对AI来说,它需要随机的自动选择一个对应的tag。
重点就在这个随机上,如果大家有过C语言的基础,就一定知道如如何取随机数,而对于这个简单的“石头剪刀布”项目来说,我们只需要对取出的随机数对3求余即可。最后拿到AI随机出来的tag和玩家选择好的tag进行正常的游戏规则匹配即可。为了标识出玩家和AI各自选择的tag,对玩家和AI我分别设置了_kUserStr和_kMachineStr这两个NSString类型对象,记录下双方所选择tag。
对于AI部分的随机取数逻辑可以为这样:
- (void)machineMethon {
switch (arc4random() % 3) {
case 0:
_kMachineStr = @"✊️";
break;
case 1:
_kMachineStr = @"🖐";
break;
case 2:
_kMachineStr = @"✌️";
break;
}
}
而对于玩家来说,有三个按钮“剪刀”、“石头”、“布”可供选择,而且这三个按钮的方法逻辑是一样的。我们来给这三个按钮绑定同样的点击方法,
[_ManRockBtn addTarget:self action:@selector(ManBtnClick:) forControlEvents:UIControlEventTouchUpInside];
[_ManPaperBtn addTarget:self action:@selector(ManBtnClick:) forControlEvents:UIControlEventTouchUpInside];
[_ManScissorsBtn addTarget:self action:@selector(ManBtnClick:) forControlEvents:UIControlEventTouchUpInside];
而AI和玩家的判赢方法,主要被“开始”按钮触发,
- (void)judgeMethonWithUserAndMachine {
[self machineMethon];
if ([_kUserStr isEqualToString:_kMachineStr]) {
_statusLabel.text = @"平局";
} else if ([_kUserStr isEqualToString:@"✊️"] && [_kMachineStr isEqualToString:@"✌️"]) {
_statusLabel.text = @"你赢了";
[self progressViewUpdate];
} else if ([_kUserStr isEqualToString:@"✊️"] && [_kMachineStr isEqualToString:@"🖐"]) {
_statusLabel.text = @"你输了";
[self machineProgressUpdate];
} else if ([_kUserStr isEqualToString:@"✌️"] && [_kMachineStr isEqualToString:@"🖐"]) {
_statusLabel.text = @"你赢了";
[self progressViewUpdate];
} else if ([_kUserStr isEqualToString:@"✌️"] && [_kMachineStr isEqualToString:@"✊️"]) {
_statusLabel.text = @"你输了";
[self machineProgressUpdate];
} else if ([_kUserStr isEqualToString:@"🖐"] && [_kMachineStr isEqualToString:@"✌️"]) {
_statusLabel.text = @"你输了";
[self machineProgressUpdate];
} else if ([_kUserStr isEqualToString:@"🖐"] && [_kMachineStr isEqualToString:@"✊️"]) {
_statusLabel.text = @"你赢了";
[self progressViewUpdate];
}
[_MachineBtn setTitle:_kMachineStr forState:UIControlStateNormal];
for (UIButton *btn in _kBtnArr) {
btn.layer.borderColor = [UIColor whiteColor].CGColor;
}
isBegin = false;
}
在判赢方法中你会发现我们多了一个数组_kBtnArr,而且还遍历了这个数组的中的内容,给该数组的对象设置了边框颜色。这是怎么一回事呢?
为了标识出玩家到底选择了“剪刀”、“石头”、“布”三个按钮中的哪一个,我们使用了UIButton类型控件的一个边框属性,当用户点击到对应的按钮,就给该按钮设置一个边框,并且其他未选中的按钮边框选中效果清空(clear颜色)
因此,我们的按钮点击方法可以这么写,
- (void)ManBtnClick:(UIButton *)sender {
sender.layer.borderColor = [UIColor blueColor].CGColor;
sender.layer.borderWidth = 2.f;
if ([sender.titleLabel.text isEqualToString:@"✊️"]) {
_kUserStr = @"✊️";
} else if ([sender.titleLabel.text isEqualToString:@"🖐"]) {
_kUserStr = @"🖐";
} else {
_kUserStr = @"✌️";
}
for (UIButton *btn in _kBtnArr) {
if ([btn isEqual:sender]) {
continue;
} else {
btn.layer.borderColor = [UIColor whiteColor].CGColor;
}
}
// 点击了按钮即可认为游戏开始
isBegin = true;
}
以上就是“剪刀石头布”项目的核心代码,注意!是核心代码,不是完整代码,如果你对本项目感兴趣,可以在文末原项目链接down下后进行研究。再次说明该项目为ifLab的iOS方向新生练习项目之一,为接触了Objective-C语言后的第一个UI小练习,同时也适用于刚接触iOS开发的同学。