在前面, 我们学会制作了一个简单的小游戏石头剪刀布, 现在我们来学习制作第二个小游戏, 那就是舒尔特表啦, 首先让我们来创建一个新的工程并且配置好storyboard:
搭建好页面之后, 一般情况下我们是需要进行UI控件关联, 但这次比较特殊一点, 我们要创建多一个Class, 并且把右边的UIVIewController和我们新创的Class关联在一起
PS: 记得, 新建的Class要继承与UIViewController, 否则无法关联.
设置完之后, 我们还需要再配置一些细节, 就是从第一个页面跳转到第二个页面:
PS: 按住control键选中UIButton, 拖到第二个页面之后放手, 然后选择modal, 然后就把两个页面进行关联.
现在我们来关联控件, 首先我们先关联第二个页面的控件.
这里有一点要注意, 这里有一个IBOutletCollection, 是用来把第二个页面的所有UIButton堆在一起, 做成一个UIButton集合, 这样子方便我们对这一堆按钮进行随机操作, 并且这里还有一个IBAction方法, 也是保存所有的按钮, 但是这里我们需要设置好UIButton的tag值.
我在这里定义了一个代理和一个协议, 代理是用来给第一个页面里面的UILabel使用的, 用来记录玩家最佳的成绩, 协议里面的方法就是用来实现该代理方法的, 接下来我们继续:
@interface GameViewController ()
{
// 用户上次点击的数字
NSInteger _lastTapNumber;
// 游戏开始的时间
NSDate *_gameStartTime;
// 游戏时间
NSTimer *_gameTimer;
}
@end- (void)viewDidLoad {
[super viewDidLoad];
NSArray *numberArray = [self createNumberArray];
for (UIButton *button in _numberButtons) {
NSString *text = [numberArray[button.tag]stringValue];
[button setTitle:text forState:UIControlStateNormal];
}
_lastTapNumber = 0;
// 设置定义时钟
// 第一个参数:多少时间会触发一次, 以秒为单位
// 第二个参数:如果看到函数的参数有target, 一般情况下都使用self
// 第三个参数:SEL, 需要调用其他的方法, 就是每次时钟被触发的时候去调用, 最多可以一个参数, 就是时钟本身
// 第四个参数:暂时不用考虑, 设置成nil
// 第五个参数:是否重复
_gameTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];
// 记录游戏开始的时间
_gameStartTime = [NSDate date];
}
#pragma mark - 私有方法
// 时间触发执行方法
- (void)updateTimer:(NSTimer *)sender
{
// 在此处设置游戏计时器标签的内容, 提示玩家当前过了多少秒
// fireDate是时钟当前触发的时间
NSInteger deltaTime = [sender.fireDate timeIntervalSinceDate:_gameStartTime];
// 将时间专成NSString
NSString *text = [NSString stringWithFormat:@"%02ld:%02ld", deltaTime / 60, deltaTime % 60];
// 设置计时器时间
[_timerLabel setText:text];
// 设置时间的字符串 00:00 mm:ss
NSLog(@"过了一秒了 %ld", deltaTime);
}
// 数组
- (NSArray *)createNumberArray
{
NSMutableArray *array = [NSMutableArray array];
for (NSInteger i = 1; i < 10; i++)
{
[array addObject:@(i)];
}
// 打乱数组的顺序
// 思路: 使用随机数, 不能重复
// 1,2,3,4,5,6,7,8,9
// 先随机出来一个位置的数字0~9 假设是5, 用位置5的数字位置和0交换
// 6,2,3,4,5,1,7,8,9
// 再随机出来一个位置的数字1~9 假设是3, 用位置1的数字位置和1交换
// 以此类推, 就可以得到一个随机顺序的数组.
for (NSInteger i = 0; i < 9; i++) {
NSInteger seed = i + arc4random_uniform(9 - (unsigned int)i);
// 交换数据
[array exchangeObjectAtIndex:i withObjectAtIndex:seed];
}
return array;
}
#pragma mark 回到主界面
- (IBAction)done {
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark 点击事件
- (IBAction)tapNumberButton:(UIButton *)sender {
NSString *text = [[sender titleLabel] text];
NSInteger number = [text integerValue];
NSLog(@"%ld", number);
if ((_lastTapNumber + 1) == number) {
_lastTapNumber++;
// 设置点击后的颜色
[sender setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
// 点击后禁用按钮
[sender setEnabled:NO];
} else {
NSLog(@"点错了");
}
NSLog(@"末次计数:%ld", _lastTapNumber);
if (_lastTapNumber == 9) {
NSLog(@"胜利了");
//关闭时钟
[_gameTimer invalidate];
// 委托代理执行方法, 如果没有设置代理, 那么这条指令就不会执行, 但也不会报错
[_delegate gameViewDidDone:_timerLabel.text];
NSString *message = [NSString stringWithFormat:@"帅呆了, 用时:%@", _timerLabel.text];
// UIAlertView是用来提示用户信息的小窗口
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
}
}
#pragma mark - AlertView代理方法
#pragma mark 回到游戏主界面
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
[self done];
}
PS: 一般我们玩游戏, 无论是赢了或者是输了, 游戏都会弹出一个对话框出来, 提示游戏结束, 并且会释放游戏页面, 但释放页面方法并不是是在游戏胜利的方法里执行, 而是在代理方法里面执行, 否则我们会见到游戏页面结束的速度会比弹出对话框的速度要快.
接下来就是ViewController文件:
最后我们来实现ViewController.m里面所有的功能:
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
// ViewController的内置方法, 所有在storyboard中的连线在推出新的视图控制器之前都会调用这个方法.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// 获得目标视图控制器
GameViewController *controller = [segue destinationViewController];
[controller setDelegate:self];
}
#pragma mark - 游戏视图代理方法
- (void)gameViewDidDone:(NSString *)timeString
{
NSLog(@"你花了%@时间",timeString);
[_socreLabel3 setText:timeString];
}
@end
最终的效果:
好了, 基础控件讲到这里就已经全部讲完了, 之后的就是讲解高级控件了~~~