隨記(第四周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)


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,255評論 4 61
  • link
    angerskon閱讀 1,825評論 0 0
  • 我去過那個人的家,他有一個書柜,里面放了好多書,我就想那些書他都讀過嗎?那么他又喜歡那里面的那些呢,讀的時候他想...
    45度向陽閱讀 212評論 0 1
  • 夏天來大姨媽兼職要人命
    Ml_Zy閱讀 125評論 0 0
  • 這幾天百無聊奈,天天在為即將到來的各種考證做準備,上個星期剛剛完成了教師資格證的考試,四月份第一個星期又有證券,五...
    苦笑嫣然閱讀 285評論 0 1