在前面, 我们学会制作了一个简单的小游戏石头剪刀布, 现在我们来学习制作第二个小游戏, 那就是舒尔特表啦, 首先让我们来创建一个新的工程并且配置好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
最终的效果:
好了, 基础控件讲到这里就已经全部讲完了, 之后的就是讲解高级控件了~~~