第三课没有太多的知识点,主要是完成前两节课中的一个小的纸牌游戏。因为上课的时间有限,所以课上并没有太多复杂的逻辑,主要是通过这样的一个小demo来加深对MVC架构的理解。
设计需求
- 显示多张卡牌,点击任意一张卡牌可以翻过卡牌
- 匹配两张卡牌的内容,花色或数字相同即为匹配成功,并且将按钮置于不能点击的状态,而且有不同的对应分值。若匹配不成功则将卡牌扣回
- 每次点击卡牌都会消耗分值
- 每次分值改变(翻卡牌)之后都要更新UI
结构设计
Card(卡牌)
包含公共变量三个,内容contents
,选中状态chosen
,匹配状态matched
。
|
|
一个公共方法用来判断是否匹配。这个方法比较简单粗暴,直接判断两个字符串是否相等。
|
|
Deck(牌堆)
只有一个私有变量cards
用来存放Card。
|
|
另外有三个公有方法,其中两个是添加卡牌到牌堆,还有一个是随机抽取一张卡牌。
|
|
PlayingCard(扑克牌)
继承于Card
类,是扑克牌的具体化表现。有花色和大小两个公有变量
|
|
在这里重写了父类中match:
方法,实现了需求中对花色和大小进行判断的条件。
|
|
PlayingCardDeck(扑克牌堆)
继承与Deck
,这里只是在初始化的时候生成全部52张扑克牌。
|
|
CardMatchingGame (卡牌匹配)
这是整个游戏的核心部分,完成卡牌匹配的判断工作。这里重写了初始化函数,因为简单的init
方法已经不够实现我们需要的功能,这里在初始化函数中添加了数量和牌堆的属性。
|
|
然后有一个核心匹配方法chooseCardAtIndex:
用来实现整个游戏的功能。
|
|
在这里使用了常量并且介绍了两种常量的使用方式
|
|
其中#define
只是简单的使用 2 来替换 MISMACTH_PENALTY关键字,并没有指定的类型,而static const int MISMACTH_PENALTY
有指定的类型,并不是简单的替换。
而且对于分数score
属性在共有和私有中做了不同的处理。在公有中使用了readonly
关键字来修饰,在私有中使用了readwrite
关键字来修饰。来防止外部对分数的修改。达到外部只能看到分数而不能插手干预分数的目的。
MatchingGameViewController(控制器)
作为整个应用的控制器,MatchingGameViewController
负责接受UI的事件,并告诉Model,Model根据收到的信息对自身数据进行改变后再通知控制器,控制器再根据数据更新UI。
具体实现如下:
- 控制器接收到按钮的点击事件触发
touchCardButton:
方法 - 控制器使用
CardMatchingGame
类中的chooseCardAtInde:
方法告诉Model点击的卡牌,由Model对匹配进行处理 - 使用
updateUI
方法对UI进行更新
|
|
这里使用了titleForCard:
和backgroundForCard:
提炼了对卡牌的设置
|
|
至此这个纸牌游戏的Demo就完成了,具体功能样式如下图:
其他小知识
数组中第一个元素和最后一个元素的选择
一共有三种方法来定位数组中的第一个元素
|
|
其中建议使用第一种方法,因为如果当数组为空的时候,使用第一种方法只会得到一个nil的元素,而并不会引起崩溃。但是第二第三种方法则会因为数组下标越界而引起崩溃。
总结
这一课中大的知识点并不多,主要还是强调了MVC的重要性,并且在代码编写的过程中不断强调要优雅的实现功能。而且要对自己的代码进行一些保护,增强代码的健壮性。