Swift學(xué)習(xí) - 第三周知識整理

1.?第一天

字典和集合(由于他們在內(nèi)存中不是有序排序的,所以打印他們元素時時不規(guī)則顯示的)
// 哈希碼(hash code)/散列碼
// MD5 / SHA-1

1.1?字典 var dict: [String: String]

// 字典(存放鍵值對組合的容器)
// 字典中的每個元素都是由兩部分構(gòu)成的, 冒號前面是鍵,冒號后面是值
var dict: [String: String] = ["abacus": "算盤", "abnormal": "異常的", "hello" : "你好", "good": "好的"]
// 通過鍵獲取對應(yīng)的值(可空類型, 因為給的鍵有可能沒有與之對應(yīng)的值)
// key ---> value
print(dict["hello"]!)  
print(dict["abcxyz"])                 // 返回nil

// 添加元素
dict["shit"] = "狗屎"
dict["delicious"] = "好吃的"
print(dict)

// 刪除元素
// dict.removeValueForKey("hello")
dict["hello"] = nil
print(dict)
print(dict["hello"])

// 修改元素
dict["shit"] = "牛糞"
print(dict)

// 遍歷字典中所有的值
for value in dict.values {
    print(value)
}

// 遍歷字典中所有的鍵
for key in dict.keys {
    print("\(key) ---> \(dict[key])")
}

// 直接通過一個元組獲得字典中的鍵和值(原始類型)
for (key, value) in dict {
    print("\(key) ---> \(value)")
}

1.2?集合 var a: Set<Int>

var a: Set<Int> = [1, 2, 3, 1, 2, 5]
a.insert(100)           // 添加元素
a.remove(2)             // 刪除元素
print(a)
var b: Set<Int> = [3, 5, 7, 9, 11]
print(b)

print(a.intersect(b))   // 交集(a和b都有的元素)
print(a.union(b))       // 并集(a和b的所有元素)
print(a.subtract(b))    // 差集(a有b沒有的元素)

print(a == b)
print(b.isSubsetOf(a))

let c: Set<Int> = [1, 3]
print(c.isSubsetOf(a))      // 判斷c是不是a的子集
print(a.isSupersetOf(c))    // 判斷a是不是c的超集

let d: Set<Int> = [2, 1000, 10000]
print(a.isDisjointWith(d))  // 判斷兩個集合是否相交

1.3?函數(shù)

** inout - 輸入輸出參數(shù)(不僅將數(shù)據(jù)傳入函數(shù)還要從函數(shù)中取出數(shù)據(jù))
Swift中函數(shù)的參數(shù)列表可以是可變參數(shù)列表(參數(shù)的個數(shù)是任意多個)
Swift中函數(shù)的參數(shù)可以設(shè)定默認(rèn)值,如果調(diào)用函數(shù)的時候沒有給該參數(shù)賦值就直接使用默認(rèn)值
可以使用元組(tuple)讓函數(shù)一次返回多條數(shù)據(jù)**

// 函數(shù)的參數(shù)名
// 函數(shù)名(外部參數(shù)名 內(nèi)部參數(shù)名: 類型, 外部參數(shù)名 內(nèi)部參數(shù)名: 類型)
// 如果不寫外部參數(shù)名那么內(nèi)部參數(shù)名也是外部參數(shù)名
// 可以使用_來作為外部參數(shù)名表示省略外部參數(shù)名
func myMin(a x: Int, b y: Int) -> Int {
    return x < y ? x : y
}


// 調(diào)用函數(shù)的時候要寫函數(shù)的外部參數(shù)名
print(myMin(a: 3, b: 5))

// 定義函數(shù)
// func 函數(shù)名(參數(shù)列表) -> 返回類型 { 函數(shù)的執(zhí)行體 }
// Swift中函數(shù)的參數(shù)可以設(shè)定默認(rèn)值
// 如果調(diào)用函數(shù)的時候沒有給該參數(shù)賦值就直接使用默認(rèn)值
func sayHello(personName: String, alreadyGreeted: Bool = false) -> String {
    // let greeting = "Hello, " + personName + "!"
    // 如果函數(shù)的返回類型不是Void 那么函數(shù)中一定有return語句
    // return greeting
    // personName = "王小錘"   // 編譯錯誤
    if alreadyGreeted {
        return "怎么又是你, " + personName + "!"
    }
    else {
        return "你好, " + personName + "!"
    }
}

// 調(diào)用函數(shù)
// 函數(shù)名(參數(shù)值)
// 調(diào)用Swift的函數(shù)時, 在默認(rèn)情況下從第二個參數(shù)開始需要寫參數(shù)名
print(sayHello("王大錘", alreadyGreeted: true))
// 如果沒有給第二個參數(shù)賦值那么就直接使用默認(rèn)值false
let str = sayHello("Jack")
print(str)

// Swift中函數(shù)的參數(shù)列表可以是可變參數(shù)列表(參數(shù)的個數(shù)是任意多個)
func sum(nums: Int...) -> Int {
    var total = 0
    for num in nums {
        total += num
    }
    return total
}

print(sum())
print(sum(999))
print(sum(1, 2, 3))
print(sum(90, 82, 37, 68, 55, 11, 99))

// 可以使用元組(tuple)讓函數(shù)一次返回多條數(shù)據(jù)
func minMax(array: [Int]) -> (min: Int, max: Int)? {
    if array.count == 0 {
        return nil
    }
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        }
        else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

if let b = minMax([23, 45, 99, 68, 72, 12, 55]) {
    print(b.min)        // print(b.0)
    print(b.max)        // print(b.1)
}
else {
    print("數(shù)組中沒有元素!!!")
}

func swap(inout a: Int, inout _ b: Int) -> Void {
    (a, b) = (b, a)
//    let temp = a
//    a = b
//    b = temp
}

var a = 300, b = 500
swap(&a, &b)
print("a = \(a)")
print("b = \(b)")

// inout - 輸入輸出參數(shù)(不僅將數(shù)據(jù)傳入函數(shù)還要從函數(shù)中取出數(shù)據(jù))
func createX(inout x: Int) {
    x = 1000
}

var x = 1
// inout類型的參數(shù)前要加上&符號
createX(&x)
print(x)


//var x = 5, y = 10
//// 函數(shù)調(diào)用傳參都是傳值
//swap(x, y)
//print("x = \(x)")
//print("y = \(y)")

1.4?練習(xí)

1.4.1?設(shè)計一個函數(shù)根據(jù)系統(tǒng)時間返回不同的問候語
func sayHello(name: String) -> String {
    let date = NSDate()
    let cal = NSCalendar.currentCalendar()
    let hour = cal.component(.Hour, fromDate: date)
    
    var greeting: String
    switch hour {
    case 0...6:         // 不同的分支可以有重疊的部分
        greeting = "怎么還沒睡呀"
        // fallthrough  // 無條件繼續(xù)執(zhí)行下一個case
    case 4...10:        // 匹配了一個分支之后不再匹配其他的分支
        greeting = "早起的鳥兒有蟲吃"
    case 11...13:
        greeting = "中午好"
    case 14...18:
        greeting = "下午好"
    default:
        greeting = "晚上好"
    }
    return name + ", " + greeting + "!"
}
print(sayHello("劉備"))

在這里主要強(qiáng)調(diào)的是如何當(dāng)前獲取時間

let date = NSDate()
let cal = NSCalendar.currentCalendar()
let hour = cal.component(.Hour, fromDate: date)

1.4?指紋支付代碼

import UIKit
import LocalAuthentication

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let errPointer = NSErrorPointer()
        let ctx = LAContext()
        // 判斷設(shè)備是否支持指紋識別
        if ctx.canEvaluatePolicy(.DeviceOwnerAuthenticationWithBiometrics, error: errPointer) {
            // z = f(x, g(y))
            // Swift中允許將一個函數(shù)作為另一個函數(shù)的參數(shù)
            // evalutePolicy方法的第三個參數(shù)是一個函數(shù)
            // 該函數(shù)有兩個參數(shù)沒有返回值
            // 給該參數(shù)傳參時可以在花括號中寫一個匿名函數(shù)傳進(jìn)去
            // 該匿名函數(shù)通常也稱之為閉包(closure)
            ctx.evaluatePolicy(.DeviceOwnerAuthenticationWithBiometrics, localizedReason: "請輸入指紋進(jìn)行支付", reply: { (isOK, err) -> Void in
                if isOK {
                    print("支付成功!!!")
                }
                else {
                    print("指紋驗證失敗, 請輸入支付密碼")
                }
            })
        }
        else {
            print("你的設(shè)備不支持指紋識別")
        }
    }
}

1.4?設(shè)計一個函數(shù),傳入年月日,返回該日期是這一年的第幾天

func isLeapYear(year: Int) -> Bool {
    return year % 4 == 0 && year % 100 != 0 || year % 400 == 0
}
func daysOfYear(year: Int, _ month: Int, _ day: Int) -> Int {
    
    let daysOfMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    
//    if isLeapYear(year) {
//        daysOfMonth[1] = 29
//    }
    
    var sum = 0
//    for days in daysOfMonth[0..<month - 1] {
//        sum += days
//    }
    for i in 0..<month - 1 {
        sum += daysOfMonth[i]
    }
    if isLeapYear(year) && month > 2 {
        sum += 1
    }
    return sum + day
//    var num = 0
//    for i in 1..<month {
//        switch i {
//        case 3, 5, 7, 8, 10: num += 31
//        case 4, 6, 9, 11: num += 30
//        case 2:
//            if isLeapYear(year) {
//                num += 29
//            }
//            else {
//                num += 28
//            }
//        default: break
//        }
//    }
//    return num + day
}
print("請輸入年,月,日:", terminator: "")
let num1 = inputInt()
let num2 = inputInt()
let num3 = inputInt()
print("這是一年中的第\(daysOfYear(num1, num2, num3))天")

1.4 函數(shù)的遞歸調(diào)用(一個函數(shù)直接或間接的調(diào)用自身)

// 1. 遞歸公式
// 2. 收斂條件

// 用遞歸計算1~n的和
func sum(n: Int) -> Int {
    if n == 1 {
        return 1
    }
    return n + sum (n - 1)
}
print(sum(100))


// 漢諾伊塔
var counter = 1
func hanoi(n: Int, _ a: String, _ b: String, _ c: String) {
    if n > 0 {
        hanoi(n - 1, a, c, b)
        print("\(counter): \(a)--->\(b)")
        counter += 1
        hanoi(n - 1, c, b, a)
    }
}
hanoi(1, "A", "B", "C")
counter = 1
hanoi(2, "A", "B", "C")
counter = 1
hanoi(5, "A", "B", "C")

2.?第二天

2.1?函數(shù)的擴(kuò)展

func sum(a: Int, _ b: Int) -> Int {
    return a + b
}

func mul(a: Int, _ b: Int) -> Int {
    return a * b
}

// 在Swift中函數(shù)是一種類型
// 這也就意味著函數(shù)可以作為變量或常量的類型
// 同理函數(shù)也可以作為另一個函數(shù)的參數(shù)或返回值
func foo(array: [Int], fn: (Int, Int) -> Int) -> Int {
    var sum = array[0]
    for x in array[1..<array.count] {
        sum = fn(sum, x)
    }
    return sum
}

let a = [1, 2, 3, 4, 5]
// 當(dāng)調(diào)用foo函數(shù)時第二個參數(shù)可以傳什么?
// 1. 所有自定義的(Int, Int) -> Int類型的函數(shù)
print(foo(a, fn: sum))
// 2. 傳入已有的二元運(yùn)算符: +-*/%(因為運(yùn)算符也是函數(shù))
print(foo(a, fn: +))
// 3. 傳入匿名函數(shù)(閉包)
// 3.1 完整的閉包寫法
print(foo(a, fn: { (a, b) -> Int in
    return a + b
}))
// 3.2 省略掉類型和不必要的括號
print(foo(a, fn: { a, b in a + b }))
// 3.3 省略參數(shù)名
print(foo(a, fn: { $0 + $1 }))
// 3.4 尾隨閉包
print(foo(a) { (a, b) -> Int in
    return a + b
})
print(foo(a) { $0 + $1 })
var array = ["game", "abacus", "hello", "cat", "good", "internationalization", "chaos", "dislike", "zealot", "young"]

// array.sortInPlace(>)
array.sortInPlace({ $0 > $1 })
// array.sortInPlace() { $0 > $1 }
// array.sortInPlace { $0 > $1 }
// 如果函數(shù)的最后一個參數(shù)是閉包可以寫成尾隨閉包的形式
// 也就是將閉包放到函數(shù)參數(shù)的圓括號外面寫在一對花括號中
// 如果函數(shù)后面有尾隨閉包且函數(shù)的圓括號中沒有參數(shù)
// 那么函數(shù)的圓括號也可以省略(僅限于有尾隨閉包的場景)
array.sortInPlace {
    if $0.characters.count == $1.characters.count {
        return $0 < $1
    }
    return $0.characters.count < $1.characters.count
}
print(array)

2.2?數(shù)組的三個重要方法:過濾、映射、縮減

let array = [23, 37, 96, 55, 40, 92, 68, 88]

// 1. 過濾
let newArray1 = array.filter { $0 > 50 }
print(newArray1)

let newArray2 = array.filter { $0 % 2 == 0 }
print(newArray2)

// 2. 映射
let newArray3 = array.map { $0 * $0 }
print(newArray3)
let newArray4 = array.map { sqrt(Double($0)) }
print(newArray4)

// 3. 縮減
let result1 = array.reduce(0, combine: +)
print(result1)
let result2 = array.reduce(1, combine: *)
print(result2)
let result3 = array.reduce(array[0]) {
    $1 > $0 ? $1 : $0
}
print(result3)

let strArray = ["I", "love", "you"]
let result4 = strArray.reduce("") { $0 + " " + $1 }
print(result4)

2.3?類

2.3.1?定義類
// 步驟1: 定義類(如果你要用的類蘋果已經(jīng)提供了就直接進(jìn)入第2步)
// 定義類就可以創(chuàng)建出新的類型
// 學(xué)生類
class Student {
    // 變量定義到類的外面就叫變量 - variable
    // 變量定義到類的里面就叫屬性 - property
    // 數(shù)據(jù)抽象 - 找到和學(xué)生相關(guān)的屬性(找名詞)
    var name: String
    var age: Int
    
    // 初始化方法(構(gòu)造方法/構(gòu)造器) - constructor
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    // 函數(shù)寫到類的外面就叫函數(shù) - function
    // 函數(shù)寫到類的里面就叫方法 - method
    // 行為抽象 - 找到和學(xué)生相關(guān)的方法(找動詞)
    func eat() {
        print("\(name)正在吃飯.")
    }
    
    func study(courseName: String) {
        print("\(name)正在學(xué)習(xí)\(courseName).")
    }
    
    func watchJapaneseAV() {
        if age >= 18 {
            print("\(name)正在觀看動作片.")
        }
        else {
            print("親愛的\(name), 我們推薦你觀看《熊出沒》")
        }
    }
}

// 步驟2: 創(chuàng)建對象(調(diào)用初始化方法)
let stu1 = Student(name: "劉備", age: 35)
// 步驟3: 給對象發(fā)消息(通過給對象發(fā)消息來解決問題)
stu1.eat()
stu1.study("Swift程序設(shè)計")
stu1.watchJapaneseAV()

let stu2 = Student(name: "王大錘", age: 15)
stu2.eat()
stu2.study("中國近代史")
stu2.watchJapaneseAV()
// 0. 發(fā)現(xiàn)類
//  - 在對問題的描述中找名詞和動詞
//  - 名詞會成為類或者類中的屬性 動詞會成為類中的方法

// 1. 定義類
//  - 數(shù)據(jù)抽象(屬性)
//  - 行為抽象(方法)
//  - 初始化方法

// 訪問修飾符
//  - public (公開)
//  - internal (內(nèi)部的) - 默認(rèn)
//  - private (私有)
class Circle {
    // stored property
    // 存儲屬性(保存和圓相關(guān)的數(shù)據(jù)的屬性)
    var center: Point
    var radius: Double
    
    init(center: Point, radius: Double) {
        self.center = center
        self.radius = radius
    }
    
    // 通常獲得某個計算出的值的方法都可以設(shè)計成計算屬性
    // computational property
    // 計算屬性(通過對存儲屬性做運(yùn)算得到的屬性)
    var perimeter: Double {
        // 圓的周長是一個只讀屬性
        // 所以此處只有g(shù)et{}沒有set{}
        get { return 2 * M_PI * radius }
    }
    
    var area: Double {
        get { return M_PI * radius * radius }
    }
}
2.3.1?定義一個走動的時鐘類
class Clock {
    var hour: Int
    var minute: Int
    var second: Int
    
    init() {
        let date = NSDate()
        let cal = NSCalendar.currentCalendar()
        hour = cal.component(.Hour, fromDate: date)
        minute = cal.component(.Minute, fromDate: date)
        second = cal.component(.Second, fromDate: date)
    }
    
    func showTime() -> String {
        return "\(hour):\(minute):\(second)"
    }
    
    func run() {
        second += 1
        if second == 60 {
            second = 0
            minute += 1
            if minute == 60 {
                minute = 0
                hour += 1
                if hour == 24 {
                    hour = 0
                }
            }
        }
    }
}

let clock = Clock()
while true {
    print(clock.showTime())
    sleep(1)
    clock.run()
}

3.?第三天

3.1?函數(shù)的擴(kuò)展2

3.1.1?convenience調(diào)用其他的初始化方法
??我們可以在一個類中定義多個初始化方法
??利用convenience調(diào)用其他的初始化方法來初始化方法

class Point {
    var x: Double
    var y: Double
    
    // 我們可以在一個類中定義多個初始化方法
    
    // 便利初始化方法 / 便利構(gòu)造器
    // 利用convenience調(diào)用了其他的初始化方法的初始化方法
    convenience init() {
        self.init(x: 0, y: 0)
    }
    
    convenience init(point: (Double, Double)) {
        self.init(x: point.0, y: point.1)
    }
    
    // 指派初始化方法 / 指派構(gòu)造器
    // 被其他初始化方法調(diào)用的初始化方法
    init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }
    
    func distanceTo(other: Point) -> Double {
        let dx = x - other.x
        let dy = y - other.y
        return sqrt(dx * dx + dy * dy)
    }
    
    func moveTo(x: Double, _ y: Double) {
        self.x = x
        self.y = y
    }
    
    func moveBy(dx: Double, _ dy: Double) {
        x += dx
        y += dy
    }
}

3.1.2?類擴(kuò)展(extension)
??如果在某個特定的應(yīng)用場景中你發(fā)現(xiàn)現(xiàn)有的類缺少了某項功能
??那么可以通過類擴(kuò)展(extension)的方式現(xiàn)場添加這項功能

// 如果color為nil就取??后面的值
// 如果color不為nil就直接使用color的值
(color ?? UIColor.blueColor()).set()

// 如果在某個特定的應(yīng)用場景中你發(fā)現(xiàn)現(xiàn)有的類缺少了某項功能
// 那么可以通過類擴(kuò)展(extension)的方式現(xiàn)場添加這項功能
extension Point {
    var cgPoint: CGPoint {
        get { return CGPointMake(CGFloat(x), CGFloat(y)) }
    }
}

func randomInt(min: UInt32, _ max: UInt32) -> Int {
    return Int(arc4random_uniform(max - min + 1) + min)
}

extension CGPoint {
    var myPoint: Point {
        get {
            return Point(x: Double(self.x), y: Double(self.y))
        }
    }
}

class Triangle {
    var va: Point
    var vb: Point
    var vc: Point
    var color: UIColor?
    
    init(va: Point, vb: Point, vc: Point) {
        self.va = va
        self.vb = vb
        self.vc = vc
    }
    
    var perimeter: Double {
        get {
            let ab = va.distanceTo(vb)
            let bc = vb.distanceTo(vc)
            let ca = vc.distanceTo(va)
            return ab + bc + ca
        }
    }
    
    var area: Double {
        get {
            let ab = va.distanceTo(vb)
            let bc = vb.distanceTo(vc)
            let ca = vc.distanceTo(va)
            let halfP = perimeter / 2
            return sqrt(halfP * (halfP - ab) * (halfP - bc) * (halfP - ca))
        }
    }
    
    func draw() {
        let bezierPath = UIBezierPath()
        bezierPath.moveToPoint(va.cgPoint)
        bezierPath.addLineToPoint(vb.cgPoint)
        bezierPath.addLineToPoint(vc.cgPoint)
        bezierPath.addLineToPoint(va.cgPoint)
        // bezierPath.closePath()
        // bezierPath.fill()
        // 如果color為nil就取??后面的值
        // 如果color不為nil就直接使用color的值
        (color ?? UIColor.blueColor()).set()
        bezierPath.fill()
    }
}

    var circleArray: [Circle] = []
    
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if let touch = touches.first {
            let touchPoint = touch.locationInView(self)
            let c = Circle(center: touchPoint.myPoint, radius: Double(randomInt(150, 250)))
            circleArray.append(c)
            setNeedsDisplay()
        }
    }

3.1.3? newValue為設(shè)置的值

var hp: Int {
        get { return _hp }
        set { _hp = newValue > 0 ? newValue : 0 }
    }

3.2?奧特曼打小怪獸

// 奧特曼類
func randomInt(min: UInt32, _ max: UInt32) -> Int {
    return Int(arc4random_uniform(max - min + 1) + min)
}

class UItraman {
    private var _name: String
    private var _hp: Int
    private var _mp: Int
      
    var isAlive: Bool {
        get {
            return _hp > 0
        }
    }
    
    var name: String {
        get {
            return _name
        }
    }
    
    var mp: Int {
        get {
            return _mp
        }
    }
    
    var hp: Int {
        get {
            return _hp
        }
        set {
            _hp = newValue > 0 ? newValue : 0
        }
    }
    
    init(name: String, hp: Int, mp: Int) {
        _name = name
        _hp = hp
        _mp = mp
    }
    
    func attack(monster: Monster) {
        let injury = randomInt(15, 20)
        monster.hp -= injury
        _mp = _mp + 5 > 100 ? 100 : _mp + 5
    }
    
    func hugeAttack(monster: Monster) {
        let injury = monster.hp * 3 / 4 >= 50 ? monster.hp * 3 / 4 : 50
        monster.hp -= injury
    }
    
    func magicalAttack(monster: [Monster]) -> Bool {
        if _mp >= 30 {
            for monster in monster {
                if monster.isAlive {
                    let injury = randomInt(5, 15)
                    monster.hp -= injury
                }
            }
            _mp -= 30
            return true
        }
        return false
    }
}


// 小怪獸類
class Monster {
    var name: String
    private var _hp: Int
    
    
    var isAlive: Bool {
        get {
            return _hp > 0
        }
    }
    
    var hp: Int {
        get {
            return _hp
        }
        set {
            _hp = newValue > 0 ? newValue : 0
        }
    }
    
    init(name: String, hp: Int) {
        self.name = name
        _hp = hp
    }
    
    func attack(ultraman: UItraman) {
        let injury = randomInt(5, 10)
        ultraman.hp -= injury
    }
}


// 主方法調(diào)用

// 奧特曼打小怪獸
// 從一群小怪獸中挑選一只活著的小怪獸
func pickOneMonster(mArray: [Monster]) -> Monster {
    var monster: Monster
    repeat {
        let randomIndex = randomInt(0, UInt32(mArray.count - 1))
        monster = mArray[randomIndex]
    } while !monster.isAlive
    return monster
}

// 判斷小怪獸是否全部死光
func isAllDead(mArray: [Monster]) -> Bool {
    for monster in mArray {
        if monster.isAlive {
            return false
        }
    }
    return true
}


let u = UItraman(name: "迪迦", hp: 300, mp: 80)

let mArray = [
    Monster(name: "熊丹凌", hp: 120),
    Monster(name: "歐陽堅", hp: 250),
    Monster(name: "張尼瑪", hp: 180),
    Monster(name: "王尼瑪", hp: 150)
]

var round = 1
repeat {
    print("======第\(round)回合=======")
    let m = pickOneMonster(mArray)
    let factor = randomInt(1, 10)
    switch factor {
    case 1...7:
        print("\(u.name)奧特曼使用了普通攻擊")
        u.attack(m)
        if m.isAlive {
            m.attack(u)
        }
    case 8...9:
        
        if u.magicalAttack(mArray) {
            for m in mArray {
                if m.isAlive {
                    m.attack(u)
                }
            }
            print("\(u.name)奧特曼使用了吞天噬地")
        }
        else {
            u.attack(m)
            if m.isAlive {
                m.attack(u)
            }
            print("\(u.name)奧特曼使用了普通攻擊")
        }
    default:
        print("\(u.name)奧特曼使用了動感光波")
        u.hugeAttack(m)
    }
    u.attack(m)
    if m.isAlive {
        m.attack(u)
    }
    
    print("\(u.name)奧特曼生命值:\(u.hp)")
    print("\(u.name)奧特曼魔法值:\(u.mp)")
    for m in mArray {
        print("\(m.name)小怪獸生命值:\(m.hp)")
    }
    round += 1
} while u.isAlive && !isAllDead(mArray)

if u.hp > 0 {
    print("\(u.name)奧特曼獲勝")
}
else {
    print("小怪獸獲勝")
}

4.?第四天

4.1?學(xué)生姓名隱去最后一個字符,學(xué)寫文檔

_name.characters.count獲得字符串長度
_name.substringToIndex(_name.endIndex.predecessor())去掉最后一個字


/// 學(xué)生姓名隱去最后一個字符
    public var name: String {
        get {
            let displayName = _name.substringToIndex(_name.endIndex.advancedBy(-1))
            return displayName + "*"
        }
    }

public var name: String {
        get {
            let value = _name.characters.count > 2 ? -2 : -1
            //let displayName = _name.substringToIndex(_name.endIndex.predecessor())
            //let displayName = _name.substringToIndex(_name.endIndex.advancedBy(-1))
            let displayName = _name.substringToIndex(_name.endIndex.advancedBy(value))
            return displayName + "*"
        }
    }

/**
     學(xué)習(xí)
     - parameter courseName: 課程的名稱
     - parameter hour: 學(xué)習(xí)時間
     - returns: 學(xué)會了返回true否則返回false
     */
    public func study(courseName: String, hour: Int) -> Bool {
        print("\(_name)正在學(xué)習(xí)\(courseName).")
        return hour > 180 ? true : false
    }

4.2?短除法(歐幾里得算法)

// 短除法(歐幾里得算法)
// x和y的最大公約數(shù)跟y%x和x的最大公約數(shù)是一樣的
// Greatest Common Divisor
func gcd(x: Int, _ y: Int) -> Int {
    if x > y {
        return gcd(y, x)
    }
    else if y % x != 0 {
        return gcd(y % x, x)
    }
    else {
        return x
    }
}


// 主方法調(diào)用

4.3?寫一個使用分?jǐn)?shù)進(jìn)行運(yùn)算的類

// 短除法(歐幾里得算法)
// x和y的最大公約數(shù)跟y%x和x的最大公約數(shù)是一樣的
// Greatest Common Divisor
func gcd(x: Int, _ y: Int) -> Int {
    if x > y {
        return gcd(y, x)
    }
    else if y % x != 0 {
        return gcd(y % x, x)
    }
    else {
        return x
    }
}

class Fraction {
    private var _num: Int
    private var _den: Int
    
    var info: String {
        get {
            return _num == 0 || _den == 1 ? "\(_num)" : "\(_num)/\(_den)"
        }
    }
    
    init(num: Int, den: Int) {
        _num = num
        _den = den
        simplify()
        normalize()
    }
    
    func add(other: Fraction) -> Fraction {
        return Fraction(num: _num * other._den + other._num * _den, den: _den * other._den)
    }
    
    func sub(other: Fraction) -> Fraction {
        return Fraction(num: _num * other._den - other._num * _den, den: _den * other._den)
    }
    
    func mul(other: Fraction) -> Fraction {
        return Fraction(num: _num * other._num, den: _den * other._den)
    }
    
    func div(other: Fraction) -> Fraction {
        return Fraction(num: _num * other._den, den: _den * other._num)
    }
    
    func normalize() -> Fraction {
        if _den < 0 {
            _num = -_num
            _den = -_den
        }
        return self
    }
    
    func simplify() -> Fraction {
        if _num == 0 {
            _den = 1
        }
        else {
            let x = abs(_num)
            let y = abs(_den)
            let g = gcd(x, y)
            _num /= g
            _den /= g
        }
        return self
    }
}

// 運(yùn)算符重載(為自定義的類型定義運(yùn)算符)

func +(one: Fraction, two: Fraction) -> Fraction {
    return one.add(two)
}

func -(one: Fraction, two: Fraction) -> Fraction {
    return one.sub(two)
}

func *(one: Fraction, two: Fraction) -> Fraction {
    return one.mul(two)
}

func /(one: Fraction, two: Fraction) -> Fraction {
    return one.div(two)
}


主方法調(diào)用:

let f1 = Fraction(num: 3, den: -4)
let f2 = Fraction(num: 8, den: 9)

print(f1.info)
print(f2.info)

//let f3 = f1.add(f2)
let f3 = f1 + f2
print(f3.info)
let f4 = f1 - f2
print(f4.info)
let f5 = f1 * f2
print(f5.info)
let f6 = f1 / f2
print(f6.info)

3.4?模擬撲克游戲

Card類

enum Direction: Int {
    case Up, Right, Down, Left
}

// GET: 枚舉是定義符號常量的最佳方式
// GET: 符號常量總是優(yōu)于字面常量
/**
 花色的枚舉
 
 - Spade:   黑桃
 - Heart:   紅心
 - Club:    草花
 - Diamond: 方塊
 */
enum Suite: String {
    case Spade = "??"
    case Heart = "??"
    case Club = "??"
    case Diamond = "??"
}

/// 一張牌
class Card {
    var suite: Suite
    var face: Int
    
    /**
     初始化方法
     - parameter suite: 花色
     - parameter face:  點數(shù)
     */
    init(suite: Suite, face: Int) {
        self.suite = suite
        self.face = face
    }
    
    /// 牌的信息
    var info: String {
        get {
            var str = suite.rawValue
            switch face {
            case 1: str += "A"
            case 11: str += "J"
            case 12: str += "Q"
            case 13: str += "K"
            default: str += "\(face)"
            }
            return str
        }
    }
}


Poker類

func randomInt(min: UInt32, _ max: UInt32) -> Int {
    return Int(arc4random_uniform(max - min + 1) + min)
}

/// 一副牌
class Poker {
    var cardsArray: [Card] = []
    
    init() {
        reset()
    }
    
    /**
     重置所有的牌
     */
    func reset() {
        // 移除數(shù)組中剩下的牌
        cardsArray.removeAll()
        // 將52張牌按照黑紅梅方的順序放到數(shù)組中
        let suitesArray = [Suite.Spade, .Heart, .Club, .Diamond]
        for suite in suitesArray {
            for face in 1...13 {
                let card = Card(suite: suite, face: face)
                cardsArray.append(card)
            }
        }
    }
    
    /**
     洗牌
     */
    func shuffle() {
        // 洗牌之前先重置所有的牌
        reset()
        // 通過隨機(jī)亂序的方式打亂牌的位置
        for i in 0..<cardsArray.count {
            let j = randomInt(0, UInt32(cardsArray.count - 1))
            (cardsArray[i], cardsArray[j]) = (cardsArray[j], cardsArray[i])
        }
    }
    
    /**
     發(fā)牌
     - returns: 當(dāng)前剩下牌中的第一張牌或nil
     */
    func deal() -> Card? {
        if hasMoreCards {
            return cardsArray.removeFirst()
        }
        return nil
    }
    
    /// 還有沒有更多的牌
    var hasMoreCards: Bool {
        get { return cardsArray.count > 0 }
    }
}


Player類

func <(one: Card, two: Card) -> Bool {
    return one.face < two.face
}

class Player {
    var nickname: String
    var cardsOnHand: [Card] = []
    
    init(nickname: String) {
        self.nickname = nickname
    }
    
    func getOneCard(card: Card) {
        cardsOnHand.append(card)
    }
    
    func sortCards() {
        cardsOnHand.sortInPlace(<)
    }
}


主方法調(diào)用

func showPlayerCards(player: Player) {
    print("\(player.nickname)", terminator: ": ")
    player.sortCards()
    for card in player.cardsOnHand {
        print(card.info, terminator: " ")
    }
    print("")
}

// 撲克游戲
let p = Poker()
p.shuffle()
let playersArray = [
    Player(nickname: "張尼瑪"),
    Player(nickname: "王尼瑪"),
    Player(nickname: "李尼瑪"),
    Player(nickname: "劉尼瑪")
]

for _ in 1...3 {
    for player in playersArray {
        if p.hasMoreCards {
            player.getOneCard(p.deal()!)
        }
    }
}

for player in playersArray {
    showPlayerCards(player)
}

5.?第五天?繼承和多態(tài)

5.1?繼承

// 繼承: 從已有的類創(chuàng)建新類的過程
// 提供繼承信息的稱為父類(超類/基類)
// 得到繼承信息的稱為子類(派生類/衍生類)
// 通常子類除了得到父類的繼承信息還會增加一些自己特有的東西
// 所以子類的能力一定比父類更強(qiáng)大
// 繼承的意義在于子類可以復(fù)用父類的代碼并且增強(qiáng)系統(tǒng)現(xiàn)有的功能

?
子類繼承父類時,增加了自己屬性時,若需初始化方法,需先給自己賦值,再調(diào)用父類;若沒增加屬性,要初始化方法,需重寫初始化方法用override

enum Gender {
    case Male
    case Female
}

class Person {
    var name: String
    var age: Int
    var gender: Gender
    
    init(name: String, age: Int, gender: Gender) {
        self.name = name
        self.age = age
        self.gender = gender
    }
    
    func eat() {
        print("\(name)正在吃飯.")
    }
}

// 老師類繼承Person類
class Teacher: Person {
    var title: String
    
    init(name: String, age: Int, gender: Gender, title: String) {
        self.title = title
        super.init(name: name, age: age, gender: gender)
    }
    
    func teach(courseName: String) {
        print("\(name)\(title)正在教\(courseName).")
    }
}


主方法調(diào)用

let p1 = Person(name: "王大錘", age: 25, gender: .Male)
p1.eat()

// 可以將子類型的對象賦值給父類型的變量(因為子類跟父類之間是IS-A關(guān)系)
// Person和Pet之間是HAS-A(關(guān)聯(lián))
// 學(xué)生是人, 老師是人, 所以學(xué)生和老師的對象可以賦值給人類型的變量
let p2: Person = Student(name: "張尼瑪", age: 18, gender: .Female, major: "計算機(jī)科學(xué)與技術(shù)")
p2.eat()
// 如果要將父類型的變量轉(zhuǎn)換成子類型需要用as運(yùn)算符進(jìn)行類型轉(zhuǎn)換
// 如果能夠確認(rèn)父類型的變量中就是某種子類型的對象可以用as!進(jìn)行轉(zhuǎn)換
// 如果不確定父類型的變量中是哪種子類型可以用as?嘗試轉(zhuǎn)換
(p2 as! Student).study("Swift程序設(shè)計")
if let temp = p2 as? Teacher {
    temp.teach("Java")
}
else {
    print("\(p2.name)不是老師!!!")
}


let p3: Person = Teacher(name: "駱昊", age: 35, gender: .Male, title: "叫獸")

p3.eat()
// p3.teach("HTML網(wǎng)頁設(shè)計")

// 終極原則: 高內(nèi)聚, 低耦合
// 面向?qū)ο笃咴瓌t:
// 1. 單一職責(zé)原則(SRP)
// 2. 開閉原則(OCP)
// 3. 依賴倒轉(zhuǎn)原則(面向抽象編程, DIP)
// 愛人, 待周愛人而后為愛人
// 《墨子·取周》
// 定義方法參數(shù)類型的時候盡可能使用父類型(抽象類型)
// 因為如果用父類型的參數(shù)調(diào)用方法時可以傳入任意子類型對象
// 4. 里氏替換原則(LSP) - 能用父類型的地方就一定可以使用子類型
// 白馬, 馬也, 乘白馬, 乘馬也
// 黑馬, 馬也, 乘黑馬, 乘馬也
// 娣, 美人也, 愛娣非愛美人也
// 盜, 人也, 惡盜非惡人也
// 《墨子·小取》
// 5. 接口隔離原則(ISP)
// 6. 合成聚合復(fù)用原則(CARP)
// 7. 迪米特法則(LoD)
// GoF(四人幫)設(shè)計模式 - 23種設(shè)計模式

var name: String
    var pet: Pet?       // Person和Pet之間是HAS-A(關(guān)聯(lián))
    
    init(name: String) {
        self.name = name
    }

func adopt(pet: Pet) {
        print("\(name)領(lǐng)養(yǎng)了\(pet.nickname).")
        self.pet = pet              // 賦值
    }
    
    func strike() {
        if let pet = pet {
            print("\(name)正在毆打\(pet.nickname).")
            pet.shout()
        }
        else {
            print("\(name)正在自虐.")
        }
    }

5.2?多態(tài)

// 同樣的對象類型(Pet類型)接收相同的消息(調(diào)用相同的方法)
// 但是做了不同的事情 這就是多態(tài)(polymorphism)
// 實現(xiàn)多態(tài)的關(guān)鍵步驟:
// 1. 方法重寫(子類在繼承父類的過程中對父類已有的方法進(jìn)行重寫, 而且不同的子類給出各自不同的實現(xiàn)版本)
// 2. 對象造型(將子類對象當(dāng)成父類型來使用)

for pet in petsArray {
    pet.eat()
    pet.play()
    // 同樣的對象類型(Pet類型)接收相同的消息(調(diào)用相同的方法)
    // 但是做了不同的事情 這就是多態(tài)(polymorphism)
    // 實現(xiàn)多態(tài)的關(guān)鍵步驟: 
    // 1. 方法重寫(子類在繼承父類的過程中對父類已有的方法進(jìn)行重寫, 而且不同的子類給出各自不同的實現(xiàn)版本)
    // 2. 對象造型(將子類對象當(dāng)成父類型來使用)
    pet.shout()
    // 可以通過if+as?將父類型安全的轉(zhuǎn)換成子類型然后再調(diào)用子類特有方法
    if let dog = pet as? Dog {
        dog.keepTheDoor()
    }
    else if let cat = pet as? Cat {
        cat.catchTheMouse()
    }
    else if let mis = pet as? Mistress {
        mis.makeTrouble()
    }
}
let empsArray = [
    Manager(name: "王大錘"),
    Programmer(name: "駱昊"),
    Programmer(name: "余婷"),
    Salesman(name: "廣告莎"),
    Salesman(name: "歐陽堅"),
    Programmer(name: "周鴻祎")
]

for emp in empsArray {
    if let worker = emp as? Programmer {
        print("請輸入\(worker.name)本月工作時間: ", terminator: "")
        worker.workingHour = inputInt()
    }
    else if let worker = emp as? Salesman {
        print("請輸入\(worker.name)本月銷售額: ", terminator: "")
        worker.sales = inputDouble()
    }
    // 員工工資的計算屬性是重寫過的多態(tài)行為
    print("\(emp.name)本月工資為: ¥\(emp.salary)元")
}

通用隨機(jī)函數(shù)

func randomInt(min: UInt32, _ max: UInt32) -> Int {
    return Int(arc4random_uniform(max - min + 1) + min)
}

三角形面積公式(海倫公式)

// halfP為: 周長/2
sqrt(halfP * (halfP - ab) * (halfP - bc) * (halfP - ca))

面向?qū)ο笃叽蠼K極原則:

☆面向?qū)ο蟮钠叽笤瓌t: 
1) 開閉原則;------面向擴(kuò)展開放,面向修改關(guān)閉。 
2) 里氏轉(zhuǎn)換原則;———超類存在的地方,子類是可以替換的。
3) 依賴倒轉(zhuǎn)原則;------實現(xiàn)盡量依賴抽象,不依賴具體實現(xiàn)。 
4) 接口隔離原則;------應(yīng)當(dāng)為客戶端提供盡可能小的單獨(dú)的接口,而不是提供大的總的接口。 
5) 組合/聚合復(fù)用原則;------盡量使用合成/聚合達(dá)到復(fù)用,盡量少用繼承。原則:一個類中有另一個類的對象。 
6) “迪米特”法則;------又叫最少知識原則,一個軟件實體應(yīng)當(dāng)盡可能少的與其他實體發(fā)生相互作用。 
7) 單一職責(zé)原則。-----每一個類應(yīng)該專注于做一件事情。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容