这节我们要加入一个model,里面装的数据、逻辑 算法。
新建文件GameModel.swift
import UIKit
import Foundation
前面定义协议方便控制信息传递:
protocol GameModelProtocol :class {
//协议内容现在先不用知道干啥的 一会再说
func changeScore(to score:Int)
func moveOneUnit(from: (Int,Int), to: (Int,Int), value: Int)
func moveTwoUnits(from: ((Int,Int), (Int,Int)), to: (Int,Int), value:Int)
func insertUnit(at location:(Int,Int), withValue value:Int)
}
记录一个单元上有没有小块
enum UnitEnum {
case empty
case unit(Int)
}
自定义一个结构体,定义下标(学过swift二维数组实现吧?)作用: <记录每个数字块的信息,状态是空还是有值,值为几> 。现在也不用理解,一会用的时候会想
struct SequenceGameView<T> {
var dimension :Int
var unitArray:[T]
init(dime d:Int,initValue:T) {
dimension = d
unitArray = [T](repeating:initValue,count: d*d)
它的内部有一个泛型数组保存着小块信息
}
subscript就是给结构体定义下标访问方式
subscript(row :Int , col :Int) ->T {
get{
returnunitArray[dimension*row + col]
}
set{
unitArray[dimension*row + col] = newValue
}
}
}
class GameModel :NSObject{
let dimension :Int
let delegate :GameModelProtocol
//结构体用处:声明一个实例 gameView存放数字块信息
var gameView :SequenceGameView<UnitEnum>
var score :Int =0{
didSet{
delegate.changeScore(to:score)
我们通过协议来传值,所以上面协议里第一个方法 get ✅
}
}
// 初始化
init(dimension :Int , delegate :GameModelProtocol) {
self.dimension = dimension
self.delegate = delegate
gameView =SequenceGameView(dime: dimension , initValue: .empty)
super.init()
}
在GamePanel.swift里:实现GameModelProtocol:
classGamePanel:UIViewController,GameModelProtocol{
所以这里新增为:
var game:GameView!
var scoreBoard:ScoreView!
var gameModle:GameModel?
然后构造方法要加入:
gameModle = GameModel(dimension:dimension, delegate:self)
// 肯定要实现协议方法,这里先写空的占着,以后需要的时候再补上去(实际写代码时候这些方法都是需要的时候现加的,谁都不知道还会有什么方法==再加呗)
func changeScore(to score:Int) {
scoreBoard.score = score
}
func moveOneUnit(from: (Int,Int), to: (Int,Int), value: Int) {
}
func moveTwoUnits(from: ((Int,Int), (Int,Int)), to: (Int,Int), value:Int) {
}
func insertUnit(at location: (Int,Int),withValue value:Int) {
}
好 弄点细节 单元格上数字不同 则颜色不同, 这就需要写一个协议来 管理颜色
新建文件AppearanceProvider.swift
这个类纯粹是辅助!!!!没意思!!!!看看粘贴上去就行!
import Foundation
import UIKit
提供颜色协议,具体细分到单元格颜色,数字颜色和字体:
protocol AppearanceProviderProtocol:class {
func unitColor(_ value:Int)->UIColor
func numberColor(_ value:Int)->UIColor
func fontForNumbers() ->UIFont
}
class AppearanceProvider:AppearanceProviderProtocol{
1.字体:
func fontForNumbers() ->UIFont {
if let font = UIFont(name: "HelveticaNeue-Bold", size: 20){
return font
}
returnUIFont.systemFont(ofSize:20)
}
2.数字颜色
func numberColor(_ value:Int)->UIColor {
if value==4||value==2{
returnUIColor(red:0.4, green:110/255.0,blue:100/255.0, alpha:1.0)
}
returnUIColor.white
}
3.单元格颜色:不同数字 switch
func unitColor(_ value:Int)->UIColor {
switch value {
case 2:
returnUIColor(red:238.0/255.0, green:228.0/255.0,blue:218.0/255.0, alpha:1.0)
case 4:
returnUIColor(red:237.0/255.0, green:224.0/255.0,blue:200.0/255.0, alpha:1.0)
case 8:
returnUIColor(red:242.0/255.0, green:177.0/255.0,blue:121.0/255.0, alpha:1.0)
case 16:
returnUIColor(red:245.0/255.0, green:149.0/255.0,blue:99.0/255.0, alpha:1.0)
case 32:
returnUIColor(red:246.0/255.0, green:124.0/255.0,blue:95.0/255.0, alpha:1.0)
case 64:
returnUIColor(red:246.0/255.0, green:94.0/255.0,blue:59.0/255.0, alpha:1.0)
case 128, 256, 512,1024,2048:
returnUIColor(red:237.0/255.0, green:207.0/255.0,blue:114.0/255.0, alpha:1.0)
case 4096,8192:
returnUIColor(red:0.99, green:0.2,blue:0.2, alpha:1.0)
default:
returnUIColor.white
}
}
}
颜色协议弄好啦
思考: 每个单元格上的颜色小块到底是怎么实现的? 改变某个位置的属性吗?因为涉及到移动,合并等行为,以及每个块上有自己的数字,颜色,写java的同学会情不自禁的新建一个类来管理:
新建文件UnitView.swift 是小单元格上贴的带数字的view
import Foundation
import UIKit
class UnitView:UIView{
var label:UILabel! / / 用来显示格子的值,以及根据 值的颜色协议 确定格子颜色:
var value:Int =0{
didSet{
backgroundColor =delegate.unitColor(value)
label.textColor =delegate.numberColor(value)
label.text ="\(value)"
}
}
let delegate:AppearanceProviderProtocol!
初始化
init(pos:CGPoint,wid:CGFloat,value:Int,delegated:AppearanceProviderProtocol) {
delegate = d
self.value = value
注意,任意view的frame是相对于superView的,因此:
1. label相对于这个unitview的frame:
label =UILabel(frame:CGRect(x:0, y:0, width: wid, height: wid))
label.textAlignment = .center
label.minimumScaleFactor =0.5
label.font =UIFont(name:"HelveticaNeue-Bold", size:15)
2。这个unitview相对大正方形的frame:
super.init(frame:CGRect(x: pos.x, y:pos.y, width: wid, height: wid))
label.layer.cornerRadius =6
label.clipsToBounds = true
addSubview(label)
第一篇文章里两个for循环是初始化一个外观,这里UnitView类才是真正的单元格上的动态显示内容
backgroundColor=delegate.unitColor(value)
label.textColor =delegate.numberColor(value)
label.text ="\(value)"
}
requiredinit?(coder aDecoder:NSCoder) {
fatalError("init(coder:) has not beenimplemented")
}
}
这里单元格的view弄好了,在GameView.swift里:
var dimension:Int!
var unitwidth:CGFloat!
var thinPadding:CGFloat!
var x:CGFloat!
var y:CGFloat!
多出 存储小块的字典 其中IndexPath是小块对应的位置(x,y)
var units:Dictionary<IndexPath,UnitView>
let provider=AppearanceProvider()
然后在构造函数里添加:
units = Dictionary()
UI部分基本结束了 下篇文章开始真正的操控方块