各位好,第五课代码上新了
第五课:主要讲述string字符串和array数组的用法,也讲述了使用数组筛选器filter和字符串的index方法获取对应位置的字符
下面上详细代码
//
// ViewController.swift
// stanford_test_one
//
// Created by 王@@ on 2021/1/26.
//
import UIKit
class ViewController: UIViewController
{
//第四课讲述成员变量使用权限
private lazy var game = Concentration(numberOfPairsOfCards: numberOfPairsOfCards)
//第四课使用get、set方法传值s
var numberOfPairsOfCards:Int{
return (cardButtons.count + 1) / 2
}
private(set) var filpCount = 0
{
didSet{
undateFilpCountLabl()
}
}
private func undateFilpCountLabl(){
//第五课讲述使用NSAttributedString设置富文本显示样式string为要显示的文本,attributes为显示样式
let attributes : [NSAttributedString.Key : Any] = [
.strokeWidth : 5.0,
.strokeColor : #colorLiteral(red: 1, green: 0.5763723254, blue: 0, alpha: 1)
]
let attributeString = NSAttributedString(string: "Flip: \(filpCount)", attributes: attributes)
flipCountLable.attributedText = attributeString
}
@IBOutlet private weak var flipCountLable: UILabel!{
didSet{
undateFilpCountLabl()
}
}
@IBOutlet private var cardButtons: [UIButton]!
@IBAction private func touchCard(_ sender: UIButton) {
filpCount += 1
if let cardNumber = cardButtons.firstIndex(of: sender) {
//print("cardNumber = \(cardNumber)")
game.chooseCard(at: cardNumber)
updateViewFromMoudel()
}else{
print("choose cardNumber")
}
}
private func updateViewFromMoudel(){
for index in cardButtons.indices{
let button = cardButtons[index]
let card = game.cards[index]
if card.isFaceUP{
button.setTitle(emoji(for: card), for: UIControl.State.normal)
button.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
}else{
button.setTitle("", for: UIControl.State.normal)
button.backgroundColor = card.isMatched ? #colorLiteral(red: 1, green: 0.5763723254, blue: 0, alpha: 0) : #colorLiteral(red: 1, green: 0.5763723254, blue: 0, alpha: 1)
}
}
}
//第五课讲述String使用方法
//private var emojiChoise = ["👻","🦇","🙀","🎃","🍬", "🍭","🍎","😈","😱"]
private var emojiChoise = "👻🦇🙀🎃🍬🍭🍎😈😱"
//var emoji = Dictionary<Int,String>()
//第五课
private var emoji = [Card:String]()
private func emoji(for card: Card)-> String{
// if emoji[card.identifier] != nil∫∫{
// return emoji[card.identifier]!
// }else{
// return "?"
// }
//等价
//第五课讲述,使用emojiChoise,String进行操作,randomStringIndex代表从第一个字符到字符串长度的,第一个字符startIndex,offsetBy偏移到一个数值位,
//但不会超过这个数值,然后将此数值对应的字符返回给randomStringIndex,并在emojiChoise中移除randomStringIndex。
if emoji[card] == nil, emojiChoise.count > 0{
let randomStringIndex = emojiChoise.index(emojiChoise.startIndex, offsetBy: emojiChoise.count.arc4random)
emoji[card] = String(emojiChoise.remove(at: randomStringIndex))
}
return emoji[card] ?? "?"
}
}
//第四课讲述使用拓展的方法
extension Int{
var arc4random :Int{
if self > 0{
return Int(arc4random_uniform(UInt32(self)))
}else if self < 0{
return -Int(arc4random_uniform(UInt32(self)))
}else{
return 0
}
}
}
//
// Concentration.swift
// stanford_test_one
//
// Created by 王@@ on 2021/1/27.
//
import Foundation
//第五节,主要讲述struct的用法
struct Concentration
{
private(set) var cards = [Card]()
private var indexOfOneAndOnlyFaceUpCard : Int?{
//第四课使用get、set方法
get{
//第五课讲述数组筛选器filter的用法,在cards.indices筛选判断出唯一的正面朝上的卡牌,是的话初始化indexOfOneAndOnlyFaceUpCard 为1,不是的话初始化indexOfOneAndOnlyFaceUpCard 为nil
//let faceUpCardIndices = cards.indices.filter{cards[$0].isFaceUP}
return cards.indices.filter{cards[$0].isFaceUP}.oneAndOnly
//return faceUpCardIndices.count == 1 ? faceUpCardIndices.first: nil
// var foundIngex :Int?
// for index in cards.indices{
// if cards[index].isFaceUP{
// if foundIngex == nil{
// foundIngex = index
// }else{
// return nil
// }
// }
// }
// return foundIngex
}
set{
for index in cards.indices{
cards[index].isFaceUP = (index == newValue)
}
}
}
//第五课讲述mutating 是为了能在func方法中修改,struct或者enum的变量
mutating func chooseCard (at index: Int){
//第四课讲述断言的使用方法
assert(cards.indices.contains(index),"Concentration.chooseCard (at: \(index)) : choosen index not in the cards ")
if !cards[index].isMatched{
if let matchIndex = indexOfOneAndOnlyFaceUpCard,matchIndex != index{
//这里不再使用cards[matchIndex].identifier == cards[index].identifier 去匹配,因为,identifier 被设置成private数据不能直接访问
if cards[matchIndex] == cards[index]{
cards[matchIndex].isMatched = true
cards[index].isMatched = true
}
cards[index].isFaceUP = true
//indexOfOneAndOnlyFaceUpCard = nil
}
else{
// for filpDownIndex in cards.indices{
//
// cards[filpDownIndex].isFaceUP = false
// }
// cards[index].isFaceUP = true
indexOfOneAndOnlyFaceUpCard = index
}
}
//翻牌测试
// if cards[index].isFaceUP {
// cards[index].isFaceUP = false
// }else{
// cards[index].isFaceUP = true
// }
//
}
init(numberOfPairsOfCards:Int) {
assert(numberOfPairsOfCards > 0,"Concentration.init (at: \(numberOfPairsOfCards)) : you must have an least one pairs of cards ")
for _ in 1...numberOfPairsOfCards{
//card是个结构体
let card = Card()
//将结构体赋值,即复制给matchingCard
//let matchingCard = card
// cards.append(card)
// cards.append(card)
//或者
cards += [card, card]
}
}
}
//第五课拓展Collection 协议的使用
extension Collection {
var oneAndOnly : Element?{
return count == 1 ? first: nil
}
}
//
// Card.swift
// stanford_test_one
//
// Created by 王@@ on 2021/1/27.
//
import Foundation
//第五课讲述使用Hashable协议,
struct Card : Hashable
{
var hashValue: Int{return identifier}
func hash(into hasher: inout Hasher) {
}
static func ==(lhs: Card,rhs: Card)->Bool{
return lhs.identifier == rhs.identifier
}
var isFaceUP = false
var isMatched = false
private var identifier :Int
private static var indentifierFactory = 0
private static func getUniqueIndentifier()-> Int{
indentifierFactory += 1
return indentifierFactory
}
init() {
self.identifier = Card.getUniqueIndentifier()
}
}