随记(第四周Day02)

随记

1. 五子棋游戏

(1). RenjuBoard.swift
mport UIKit

/**
 棋盘交叉点的状态
 
 - Space: 空格
 - Black: 黑棋
 - White: 白棋
 */
enum PointState {
    case Space, Black, White
}

/// 棋盘
class RenjuBoard {
    var board: [[PointState]]
    var isBlackTurn = true
    var isGameOver = false
    
    init() {
        board = [[PointState]](count: 15, repeatedValue: [PointState](count: 15, repeatedValue: .Space))
    }
    
    // 索引器语法 - 可以直接对棋盘对象做下标运算来放置棋子
    subscript(row: Int, col: Int) -> Bool {
        get { return board[row][col] == .Space }
        set(isBlack) {
            if board[row][col] == .Space {
                board[row][col] = isBlack ? .Black : .White
                isBlackTurn = !isBlackTurn
            }
        }
    }
    
    func reset() {
        isGameOver = false
        isBlackTurn = true
        for i in 0..<board.count {
            for j in 0..<board[i].count {
                board[i][j] = .Space
            }
        }
    }
    
    func judge(row: Int, _ col: Int) -> Bool {
        return _judgeH(row, col) || _judgeV(row, col) || _judgeX1(row, col) || _judgeX2(row, col)
    }

    private func _judgeH(row: Int, _ col: Int) -> Bool {
        var counter = 1
        var currentCol = col - 1
        while currentCol >= 0 {
            if board[row][currentCol] == board[row][col] {
                counter += 1
                currentCol -= 1
            }
            else {
                break
            }
        }
        currentCol = col + 1
        while currentCol < board.count {
            if board[row][currentCol] == board[row][col] {
                counter += 1
                currentCol += 1
            }
            else {
                break
            }
        }
        return counter >= 5
    }
    
    private func _judgeV(row: Int, _ col: Int) -> Bool {
        var counter = 1
        var currentRow = row - 1
        while currentRow >= 0 {
            if board[currentRow][col] == board[row][col] {
                counter += 1
                currentRow -= 1
            }
            else {
                break
            }
        }
        currentRow = row + 1
        while currentRow < board.count {
            if board[currentRow][col] == board[row][col] {
                counter += 1
                currentRow += 1
            }
            else {
                break
            }
        }
        return counter >= 5
    }
    
    private func _judgeX1(row: Int, _ col: Int) -> Bool {
        var counter = 1
        var currentRow = row - 1
        var currentCol = col - 1
        while currentRow >= 0 && currentCol > 0 {
            if board[currentRow][currentCol] == board[row][col] {
                counter += 1
                currentRow -= 1
                currentCol -= 1
            }
            else {
                break
            }
        }
        currentRow = row + 1
        currentCol = col + 1
        while currentRow < board.count && currentCol < board.count {
            if board[currentRow][currentCol] == board[row][col] {
                counter += 1
                currentRow += 1
                currentCol += 1
            }
            else {
                break
            }
        }
        return counter >= 5
    }
    
    private func _judgeX2(row: Int, _ col: Int) -> Bool {
        var counter = 1
        var currentRow = row - 1
        var currentCol = col + 1
        while currentRow >= 0 && currentCol < board.count {
            if board[currentRow][currentCol] == board[row][col] {
                counter += 1
                currentRow -= 1
                currentCol += 1
            }
            else {
                break
            }
        }
        currentRow = row + 1
        currentCol = col - 1
        while currentRow < board.count && currentCol >= 0 {
            if board[currentRow][currentCol] == board[row][col] {
                counter += 1
                currentRow += 1
                currentCol -= 1
            }
            else {
                break
            }
        }
        return counter >= 5
    }
    
    func draw() {
        let lineBP = UIBezierPath()
        
        // 绘制15条横线和15条竖线来构造一个棋盘
        for i in 0..<board.count {
            lineBP.moveToPoint(CGPointMake(10, 10 + 50 * CGFloat(i)))
            lineBP.addLineToPoint(CGPointMake(710, 10 + 50 * CGFloat(i)))
            lineBP.moveToPoint(CGPointMake(10 + 50 * CGFloat(i), 10))
            lineBP.addLineToPoint(CGPointMake(10 + 50 * CGFloat(i), 710))
        }
        lineBP.stroke()
        
        // 绘制棋盘的边框
        let rectBP = UIBezierPath(rect: CGRectMake(3, 3, 714, 714))
        rectBP.lineWidth = 6
        rectBP.stroke()
        
        // 绘制天元和星
        let starsRectArray = [
            CGRectMake(155, 155, 10, 10),
            CGRectMake(555, 155, 10, 10),
            CGRectMake(155, 555, 10, 10),
            CGRectMake(555, 555, 10, 10),
            CGRectMake(355, 355, 10, 10)
        ]
        for starRect in starsRectArray {
            let ovalBP = UIBezierPath(ovalInRect: starRect)
            ovalBP.fill()
        }
        
        // 绘制棋盘上的棋子
        for i in 0..<board.count {
            for j in 0..<board[i].count {
                if board[i][j] != .Space {
                    let ovalBP = UIBezierPath(ovalInRect: CGRectMake(-10 + CGFloat(j) * 50, -10 + CGFloat(i) * 50, 40, 40))
                    (board[i][j] == .Black ? UIColor.blackColor() : UIColor.whiteColor()).set()
                    ovalBP.fill()
                }
            }
        }
    }
}
(2). Canvas.swift
import UIKit

// 有的时候某个对象要做某件事情但其自身又没有能力做这件事情
// 这个时候就可以使用委托回调的编程模式让别的对象来做这件事情
// 实现委托回调的编程模式有以下几个步骤:
//  1. 设计一个协议(被委托方必须要遵循协议才能给别的对象当委托)
protocol CanvasDelegate: class {
    
    // 协议里面的方法就是要委托其他对象做的事情
    func showMessage(canvas: Canvas, message: String)
}

class Canvas: UIView {
    // 2. 委托方添加一个属性其类型是遵循了协议的被委托方
    weak var delegate: CanvasDelegate?
    
    var renjuBoard = RenjuBoard()
    var isAutoMode = false
    
    func clearBoard() {
        renjuBoard.reset()
        setNeedsDisplay()
    }
    
    func randomMove() {
        let row = Int(arc4random_uniform(15))
        let col = Int(arc4random_uniform(15))
        if renjuBoard[row, col] {
            renjuBoard[row, col] = renjuBoard.isBlackTurn
            setNeedsDisplay()
        }
    }
    
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        // Swift 2中的guard大法, Swift 3中据说要废掉
        guard !isAutoMode else { return }
        // guard !renjuBoard.isGameOver else { return }
        
        if !renjuBoard.isGameOver {
            if let touch = touches.first {
                let point = touch.locationInView(self)
                let row = lround(Double(point.y - 10) / 50)
                let col = lround(Double(point.x - 10) / 50)
                if renjuBoard[row, col] {
                    renjuBoard[row, col] = renjuBoard.isBlackTurn
                    setNeedsDisplay()
                    if renjuBoard.judge(row, col) {
                        renjuBoard.isGameOver = true
                        // 3. 自己做不了的事情委托给别的对象来做
                        delegate?.showMessage(self, message: renjuBoard.isBlackTurn ? "白棋胜" : "黑棋胜")
                    }
                }
            }
        }
    }
    
    override func drawRect(rect: CGRect) {
        renjuBoard.draw()
    }

}
(3). ViewController.swift
//  4. 让视图控制器遵循协议成为被委托方(协议表能力)
class ViewController: UIViewController, CanvasDelegate {
    
    var timer: NSTimer?
    var canvas: Canvas!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        canvas = Canvas(frame: CGRectMake(0, 0, 720, 720))
        // canvas.isAutoMode = true
        //  6. 给画布对象绑定委托(self就是视图控制器对象它遵循了协议所以有充当委托的能力也就是说可以扮演被委托方的角色)
        canvas.delegate = self
        canvas.center = self.view.center
        canvas.backgroundColor = UIColor(red: 254.0 / 255.0, green: 209.0 / 255.0, blue: 46.0 / 255.0, alpha: 1)
        self.view.addSubview(canvas)
        
        // timer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: canvas, selector: "randomMove", userInfo: nil, repeats: true)
    }
    
    //  5. 遵循协议就必须要实现协议中的方法(协议表约定)
    func showMessage(canvas: Canvas, message: String) {
        let alertController = UIAlertController(title: message, message: "", preferredStyle: .Alert)
        let okAction = UIAlertAction(title: "确定", style: .Default) { action in
            // 此处通过尾随闭包来定义点击确定按钮后要做什么
            canvas.clearBoard()
        }
        alertController.addAction(okAction)
        self.presentViewController(alertController, animated: true, completion: nil)
    }
    
    // deinit在销毁对象的时候调用
    deinit {
        // 销毁计时器
        timer?.invalidate()
    }
}

结构体于类

import Foundation

class Student1 {
    var name: String
    var age: Int
    var tel: String?
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    func getOlder() {
        age += 1
    }
    
    func study(courseName: String) {
        print("\(name)正在学习.")
    }
}

struct Student2 {
    var name: String
    var age: Int
    
    func study(courseName: String) {
        print("\(name)正在学习.")
    }
    
    // 区别3: 结构中的方法在默认情况下是不允许修改结构中的属性除非加上mutating关键字
    mutating func getOlder() {
        age += 1
    }
}

// 计算机的硬件由五大部件构成:
// 运算器、控制器、存储器、输入设备、输出设备
// 运算器 + 控制器 => CPU (中央处理器)
// 存储器 => 内存 (RAM - Random Access Memory)

// 程序员可以使用的内存大致分为五块区域:
// 栈 (stack) - 我们定义的局部变量/临时变量都是放在栈上
//  - 特点: 小、快
// 堆 (heap) - 我们创建的对象都是放在堆上的
//  - 特点: 大、慢
// 静态区 (static area)
//  - 数据段 - 全局量
//  - 只读数据段 - 常量
//  - 代码段 - 函数和方法

//var a: Int = 10
//var b = a
//b = 100
//print(a)
//
//var c: Double = 100
//var d = c
//d = 1.23456
//print(c)
//
//var e: String = "Hello"
//var f = e
//f = "Good"
//print(e)
//
//var g: Array<Int> = [1, 2, 3, 4, 5]
//var h = g
//h[0] = 1000
//print(g)

// 区别1: 结构的对象是值类型, 类的对象是引用类型
// 值类型在赋值的时候会在内存中进行对象的拷贝
// 引用类型在赋值的时候不会进行对象拷贝只是增加了一个引用
// 结论: 我们自定义新类型时优先考虑使用类而不是结构除非我们要定义的是一种底层的数据结构(保存其他数据的类型)

// 引用类型的类
//let stu1 = Student1(name: "阿郎", age: 35)
//var stu3 = stu1     // 此处内存中仍然只有一个学生对象
//stu3.name = "罗小号"
//stu3.age = 18
//print(stu1.name)
//print(stu1.age)
//
// 值类型的结构
// 区别2: 结构会自动生成初始化方法
//let stu2 = Student2(name: "阿郎", age: 35)
//var stu4 = stu2     // 此处内存中会复制一个新的学生对象
//stu4.name = "王大锤"
//stu4.age = 18
//print(stu2.name)
//print(stu2.age)

// 在Swift中同名函数只要参数列表不同是可以共存的 这个叫函数的重载
func changeName(inout name: String) {
    name = "王大锤"
}

// 参数前面加var的做法在Swift 3中肯定是要废掉的
func changeName(var stu: Student2) {
    stu.name = "王大锤"
}

var name = "阿郎"
changeName(&name)
print(name)

var stu = Student2(name: "阿郎", age: 35)
changeName(stu)
print(stu.name)


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • link
    angerskon阅读 1,817评论 0 0
  • 我去过那个人的家,他有一个书柜,里面放了好多书,我就想那些书他都读过吗?那么他又喜欢那里面的那些呢,读的时候他想...
    45度向阳阅读 197评论 0 1
  • 夏天来大姨妈兼职要人命
    Ml_Zy阅读 121评论 0 0
  • 这几天百无聊奈,天天在为即将到来的各种考证做准备,上个星期刚刚完成了教师资格证的考试,四月份第一个星期又有证券,五...
    苦笑嫣然阅读 275评论 0 1