рд╣рд╛ рд▓реЗрдЦ рдПрдХ рд╕рд╛рдзрд╛ рдореЗрдорд░реА рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдЧреЗрдо рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рдЪреНрдпрд╛ рдкреНрд░рдХреНрд░рд┐рдпреЗрдЪреЗ рд╡рд░реНрдгрди рдХрд░рддреЛ рдЬреНрдпрд╛рдЪрд╛ рдорд▓рд╛ рдЦрд░реЛрдЦрд░ рдЖрдирдВрдж рд╣реЛрддреЛ. рд╕реНрд╡рддрдГ рдЪрд╛рдВрдЧрд▓реЗ рдЕрд╕рдгреНрдпрд╛рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, рддреБрдореНрд╣реА рдЬрд╛рддрд╛рдирд╛ рд╕реНрд╡рд┐рдлреНрдЯ рдХреНрд▓рд╛рд╕реЗрд╕ рдЖрдгрд┐ рдкреНрд░реЛрдЯреЛрдХреЙрд▓рдмрджреНрджрд▓ рдереЛрдбреЗ рдЕрдзрд┐рдХ рдЬрд╛рдгреВрди рдШреНрдпрд╛рд▓. рдкрдг рдЖрдкрдг рд╕реБрд░реВ рдХрд░рдгреНрдпрд╛рдкреВрд░реНрд╡реА, рдЦреЗрд│ рд╕реНрд╡рддрдГ рд╕рдордЬреВрди рдШреЗрдК.
рдЖрдореНрд╣реА рдЖрдард╡рдг рдХрд░реВрди рджреЗрддреЛ: рд╕рд░реНрд╡ Habr рд╡рд╛рдЪрдХрд╛рдВрд╕рд╛рдареА - Habr рдкреНрд░реЛрдореЛ рдХреЛрдб рд╡рд╛рдкрд░реВрди рдХреЛрдгрддреНрдпрд╛рд╣реА рд╕реНрдХрд┐рд▓рдмреЙрдХреНрд╕ рдХреЛрд░реНрд╕рдордзреНрдпреЗ рдирд╛рд╡рдиреЛрдВрджрдгреА рдХрд░рддрд╛рдирд╛ 10 рд░реВрдмрд▓ рд╕рд╡рд▓рдд.
рд╕реНрдХрд┐рд▓рдмреЙрдХреНрд╕ рд╢рд┐рдлрд╛рд░рд╕ рдХрд░рддреЛ: рд╢реИрдХреНрд╖рдгрд┐рдХ рдСрдирд▓рд╛рдЗрди рдЕрднреНрдпрд╛рд╕рдХреНрд░рдо
"рдкреНрд░реЛрдлреЗрд╢рди рдЬрд╛рд╡рд╛ рдбреЗрд╡реНрд╣рд▓рдкрд░" .
рдореЗрдорд░реА рдХрд╛рд░реНрдб рдХрд╕реЗ рдЦреЗрд│рд╛рдпрдЪреЗ
рдЦреЗрд│рд╛рдЪреА рд╕реБрд░реБрд╡рд╛рдд рдкрддреНрддреНрдпрд╛рдВрдЪреНрдпрд╛ рд╕рдВрдЪрд╛рдЪреНрдпрд╛ рдкреНрд░рд╛рддреНрдпрдХреНрд╖рд┐рдХрд╛рдиреЗ рд╣реЛрддреЗ. рддреЗ рддреЛрдВрдб рдХрд░реВрди рдЭреЛрдкрддрд╛рдд (рдЕрдиреБрдХреНрд░рдореЗ, рдкреНрд░рддрд┐рдорд╛ рдЦрд╛рд▓реА). рдЬреЗрд╡реНрд╣рд╛ рддреБрдореНрд╣реА рдХреЛрдгрддреНрдпрд╛рд╣реА рдПрдХрд╛рд╡рд░ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рддреЗрд╡реНрд╣рд╛ рдкреНрд░рддрд┐рдорд╛ рдХрд╛рд╣реА рд╕реЗрдХрдВрджрд╛рдВрд╕рд╛рдареА рдЙрдШрдбрддреЗ.
рдЦреЗрд│рд╛рдбреВрдЪреЗ рдХрд╛рд░реНрдп рд╕рдорд╛рди рдЪрд┐рддреНрд░рд╛рдВрд╕рд╣ рд╕рд░реНрд╡ рдХрд╛рд░реНрдбреЗ рд╢реЛрдзрдгреЗ рдЖрд╣реЗ. рдЬрд░, рдкрд╣рд┐рд▓реЗ рдХрд╛рд░реНрдб рдЙрдШрдбрд▓реНрдпрд╛рдирдВрддрд░, рддреБрдореНрд╣реА рджреБрд╕рд░реЗ рдХрд╛рд░реНрдб рдЙрд▓рдЯрд▓реЗ рдЖрдгрд┐ рдЪрд┐рддреНрд░реЗ рдЬреБрд│рд▓реА, рддрд░ рджреЛрдиреНрд╣реА рдХрд╛рд░реНрдбреЗ рдЙрдШрдбреА рд░рд╛рд╣рддреАрд▓. рддреЗ рдЬреБрд│рдд рдирд╕рд▓реНрдпрд╛рд╕, рдХрд╛рд░реНрдбреЗ рдкреБрдиреНрд╣рд╛ рдмрдВрдж рдХреЗрд▓реА рдЬрд╛рддрд╛рдд. рд╕рд░реНрд╡ рдХрд╛рд╣реА рдЙрдШрдбрдгреНрдпрд╛рдЪреЗ рдзреНрдпреЗрдп рдЖрд╣реЗ.
рдкреНрд░рдХрд▓реНрдк рд░рдЪрдирд╛
рдпрд╛ рдЧреЗрдордЪреА рд╕реЛрдкреА рдЖрд╡реГрддреНрддреА рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рддреБрдореНрд╣рд╛рд▓рд╛ рдЦрд╛рд▓реАрд▓ рдШрдЯрдХрд╛рдВрдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЖрд╣реЗ:
- рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ: GameController.swift.
- рдПрдХ рджреГрд╢реНрдп: CardCell.swift.
- рджреЛрди рдореЙрдбреЗрд▓: MemoryGame.swift рдЖрдгрд┐ Card.swift.
- рдШрдЯрдХрд╛рдВрдЪрд╛ рд╕рдВрдкреВрд░реНрдг рд╕рдВрдЪ рдЙрдкрд▓рдмреНрдз рдЕрд╕рд▓реНрдпрд╛рдЪреА рдЦрд╛рддреНрд░реА рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА Main.storyboard.
рдЖрдореНрд╣реА рдЦреЗрд│рд╛рдЪреНрдпрд╛ рд╕рд░реНрд╡рд╛рдд рд╕реЛрдкреНрдпрд╛ рдШрдЯрдХрд╛рдкрд╛рд╕реВрди рд╕реБрд░реБрд╡рд╛рдд рдХрд░рддреЛ, рдХрд╛рд░реНрдбреНрд╕.
рдХрд╛рд░реНрдб.рд╕реНрд╡рд┐рдлреНрдЯ
рдХрд╛рд░реНрдб рдореЙрдбреЗрд▓рдордзреНрдпреЗ рддреАрди рдЧреБрдгрдзрд░реНрдо рдЕрд╕рддреАрд▓: рдкреНрд░рддреНрдпреЗрдХ рдУрд│рдЦрдгреНрдпрд╛рд╕рд╛рдареА рдЖрдпрдбреА, рдХрд╛рд░реНрдбрдЪреА рд╕реНрдерд┐рддреА (рд▓рдкрд▓реЗрд▓реЗ рдХрд┐рдВрд╡рд╛ рдЙрдШрдбреЗ) рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рджрд░реНрд╢рд╡рд┐рд▓реЗрд▓реЗ рдмреБрд▓рд┐рдпрди рд╡реНрд╣реЗрд░рд┐рдПрдмрд▓ рдЖрдгрд┐ рдХрд╛рд░реНрдбрд╡рд░реАрд▓ рдкреНрд░рддрд┐рдорд╛рдВрд╕рд╛рдареА рдЖрд░реНрдЯрд╡рд░реНрдХ URL.
class Card {
var id: String
var shown: Bool = false
var artworkURL: UIImage!
}
рдирдХрд╛рд╢рд╛рдВрд╕рд╣ рд╡рд╛рдкрд░рдХрд░реНрддрд╛ рдкрд░рд╕реНрдкрд░рд╕рдВрд╡рд╛рдж рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рддреБрдореНрд╣рд╛рд▓рд╛ рдпрд╛ рдкрджреНрдзрддреАрдВрдЪреА рджреЗрдЦреАрд▓ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЕрд╕реЗрд▓:
рдХрд╛рд░реНрдбрд╡рд░ рдкреНрд░рддрд┐рдорд╛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдгреНрдпрд╛рдЪреА рдкрджреНрдзрдд. рдпреЗрдереЗ рдЖрдореНрд╣реА рд╕рд░реНрд╡ рдЧреБрдгрдзрд░реНрдо рдбреАрдлреЙрд▓реНрдЯрд╡рд░ рд░реАрд╕реЗрдЯ рдХрд░рддреЛ. рдЖрдпрдбреАрд╕рд╛рдареА, рдЖрдореНрд╣реА NSUUIS().uuidString рд╡рд░ рдХреЙрд▓ рдХрд░реВрди рдПрдХ рд░рдБрдбрдо рдЖрдпрдбреА рддрдпрд╛рд░ рдХрд░рддреЛ.
init(image: UIImage) {
self.id = NSUUID().uuidString
self.shown = false
self.artworkURL = image
}
рдУрд│рдЦрдкрддреНрд░рд╛рдВрдЪреА рддреБрд▓рдирд╛ рдХрд░рдгреНрдпрд╛рдЪреА рдкрджреНрдзрдд.
func equals(_ card: Card) -> Bool {
return (card.id == id)
}
рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд░реНрдбрд╛рдЪреА рдкреНрд░рдд рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рдЪреА рдкрджреНрдзрдд - рдПрдХрд╕рд╛рд░рдЦреНрдпрд╛ рдореЛрдареНрдпрд╛ рд╕рдВрдЦреНрдпреЗрдиреЗ рдорд┐рд│рд╡рд┐рдгреНрдпрд╛рд╕рд╛рдареА. рд╣реА рдкрджреНрдзрдд рд╕рдорд╛рди рдореВрд▓реНрдпрд╛рдВрд╕рд╣ рдХрд╛рд░реНрдб рдкрд░рдд рдХрд░реЗрд▓.
func copy() -> Card {
return Card(card: self)
}
init(card: Card) {
self.id = card.id
self.shown = card.shown
self.artworkURL = card.artworkURL
}
рдЖрдгрд┐ рд╕реБрд░реБрд╡рд╛рддреАрд▓рд╛ рдХрд╛рд░реНрдбреНрд╕ рд╢рдлрд▓ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдгрдЦреА рдПрдХ рдкрджреНрдзрдд рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ. рдЖрдореНрд╣реА рддреЗ рдЕреЕрд░реЗ рд╡рд░реНрдЧрд╛рдЪрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░реВ.
extension Array {
mutating func shuffle() {
for _ in 0...self.count {
sort { (_,_) in arc4random() < arc4random() }
}
}
}
рдЖрдгрд┐ рдпреЗрдереЗ рд╕рд░реНрд╡ рдЧреБрдгрдзрд░реНрдо рдЖрдгрд┐ рдкрджреНрдзрддреАрдВрд╕рд╣ рдХрд╛рд░реНрдб рдореЙрдбреЗрд▓рд╕рд╛рдареА рдХреЛрдбрдЪреА рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдЖрд╣реЗ.
class Card {
var id: String
var shown: Bool = false
var artworkURL: UIImage!
static var allCards = [Card]()
init(card: Card) {
self.id = card.id
self.shown = card.shown
self.artworkURL = card.artworkURL
}
init(image: UIImage) {
self.id = NSUUID().uuidString
self.shown = false
self.artworkURL = image
}
func equals(_ card: Card) -> Bool {
return (card.id == id)
}
func copy() -> Card {
return Card(card: self)
}
}
extension Array {
mutating func shuffle() {
for _ in 0...self.count {
sort { (_,_) in arc4random() < arc4random() }
}
}
}
рдкреБрдвреЗ рдЬрд╛.
рджреБрд╕рд░реЗ рдореЙрдбреЗрд▓ MemoryGame рдЖрд╣реЗ, рдпреЗрдереЗ рдЖрдореНрд╣реА 4*4 рдЧреНрд░рд┐рдб рд╕реЗрдЯ рдХрд░рддреЛ. рдореЙрдбреЗрд▓рдордзреНрдпреЗ рдХрд╛рд░реНрдб (рдЧреНрд░рд┐рдбрд╡рд░реАрд▓ рдХрд╛рд░реНрдбреНрд╕рдЪрд╛ рдЕреЕрд░реЗ), рдХрд╛рд░реНрдбреНрд╕ рдЖрдзреАрдЪ рдЙрдШрдбрд▓реЗрд▓реЗ рдХрд╛рд░реНрдб рджрд╛рдЦрд╡рд▓реЗрд▓реЗ рдЕреЕрд░реЗ рдЖрдгрд┐ рдЧреЗрдордЪреНрдпрд╛ рд╕реНрдерд┐рддреАрдЪрд╛ рдорд╛рдЧреЛрд╡рд╛ рдШреЗрдгреНрдпрд╛рд╕рд╛рдареА рдПрдХ рдмреБрд▓рд┐рдпрди рд╡реНрд╣реЗрд░рд┐рдПрдмрд▓ рдкреНрд▓реЗрдЗрдВрдЧ рд╕рд╛рд░рдЦреЗ рдЧреБрдгрдзрд░реНрдо рдЕрд╕рддреАрд▓.
class MemoryGame {
var cards:[Card] = [Card]()
var cardsShown:[Card] = [Card]()
var isPlaying: Bool = false
}
рдЖрдореНрд╣рд╛рд▓рд╛ рдЧреНрд░реАрдбрд╕рд╣ рд╡рд╛рдкрд░рдХрд░реНрддрд╛ рдкрд░рд╕реНрдкрд░рд╕рдВрд╡рд╛рдж рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдкрджреНрдзрддреА рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдгреНрдпрд╛рдЪреА рджреЗрдЦреАрд▓ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЖрд╣реЗ.
рдЧреНрд░рд┐рдбрдордзреНрдпреЗ рдХрд╛рд░реНрдбреНрд╕ рд╢рдлрд▓ рдХрд░рдгрд╛рд░реА рдкрджреНрдзрдд.
func shuffleCards(cards:[Card]) -> [Card] {
var randomCards = cards
randomCards.shuffle()
return randomCards
}
рдирд╡реАрди рдЧреЗрдо рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рдЪреА рдкрджреНрдзрдд. рдпреЗрдереЗ рдЖрдореНрд╣реА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд▓реЗрдЖрдЙрдЯ рд╕реБрд░реВ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдгрд┐ isPlaying рд╡реНрд╣реЗрд░рд┐рдПрдмрд▓рд▓рд╛ true рдордзреНрдпреЗ рдкреНрд░рд╛рд░рдВрдн рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдкрд╣рд┐рд▓реА рдкрджреНрдзрдд рдХреЙрд▓ рдХрд░рддреЛ.
func newGame(cardsArray:[Card]) -> [Card] {
cards = shuffleCards(cards: cardsArray)
isPlaying = true
return cards
}
рдЖрдореНрд╣рд╛рд▓рд╛ рдЦреЗрд│ рдкреБрдиреНрд╣рд╛ рд╕реБрд░реВ рдХрд░рд╛рдпрдЪрд╛ рдЕрд╕реЗрд▓ рддрд░, рдирдВрддрд░ рдЖрдореНрд╣реА isPlaying рд╡реНрд╣реЗрд░рд┐рдПрдмрд▓ рдЕрд╕рддреНрдп рд╡рд░ рд╕реЗрдЯ рдХрд░рддреЛ рдЖрдгрд┐ рдХрд╛рд░реНрдбреНрд╕рдЪрд╛ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд▓реЗрдЖрдЙрдЯ рдХрд╛рдвреВрди рдЯрд╛рдХрддреЛ.
func restartGame() {
isPlaying = false
cards.removeAll()
cardsShown.removeAll()
}
рдХреНрд▓рд┐рдХ рдХреЗрд▓реЗрд▓реНрдпрд╛ рдХрд╛рд░реНрдбрд╛рдВрдЪреА рдкрдбрддрд╛рд│рдгреА рдХрд░рдгреНрдпрд╛рдЪреА рдкрджреНрдзрдд. рддреНрдпрд╛рдЪреНрдпрд╛рдмрджреНрджрд▓ рдирдВрддрд░ рдЕрдзрд┐рдХ.
func cardAtIndex(_ index: Int) -> Card? {
if cards.count > index {
return cards[index]
} else {
return nil
}
}
рдПрдХ рдкрджреНрдзрдд рдЬреА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдбрдЪреА рд╕реНрдерд┐рддреА рдкрд░рдд рдХрд░рддреЗ.
func indexForCard(_ card: Card) -> Int? {
for index in 0...cards.count-1 {
if card === cards[index] {
return index
}
}
return nil
}
рдорд╛рдирдХрд╛рдВрд╕рд╣ рдирд┐рд╡рдбрд▓реЗрд▓реНрдпрд╛ рдХрд╛рд░реНрдбрдЪреЗ рдЕрдиреБрдкрд╛рд▓рди рддрдкрд╛рд╕рдд рдЖрд╣реЗ.
func unmatchedCardShown() -> Bool {
return cardsShown.count % 2 != 0
}
рд╣реА рдкрджреНрдзрдд **рдХрд╛рд░реНрдб рджрд╛рдЦрд╡рд▓реЗрд▓реНрдпрд╛** рдЕреЕрд░реЗрдордзреАрд▓ рд╢реЗрд╡рдЯрдЪрд╛ рдШрдЯрдХ рд╡рд╛рдЪрддреЗ рдЖрдгрд┐ рди рдЬреБрд│рдгрд╛рд░реЗ рдХрд╛рд░реНрдб рдкрд░рдд рдХрд░рддреЗ.
func didSelectCard(_ card: Card?) {
guard let card = card else { return }
if unmatchedCardShown() {
let unmatched = unmatchedCard()!
if card.equals(unmatched) {
cardsShown.append(card)
} else {
let secondCard = cardsShown.removeLast()
}
} else {
cardsShown.append(card)
}
if cardsShown.count == cards.count {
endGame()
}
}
Main.storyboard рдЖрдгрд┐ GameController.swift
Main.storyboard рдЕрд╕реЗ рдХрд╛рд╣реАрддрд░реА рджрд┐рд╕рддреЗ:
рд╕реБрд░реБрд╡рд╛рддреАрд▓рд╛, рддреБрдореНрд╣рд╛рд▓рд╛ рдЧреНрд░рд┐рдбрд╕рд╛рдареАрдЪреНрдпрд╛ рдкреНрд░рддрд┐рдорд╛рдВрд╕рд╣, рдХрдВрдЯреНрд░реЛрд▓рд░рдордзреНрдпреЗ viewDidLoad рдореНрд╣рдгреВрди рдирд╡реАрди рдЧреЗрдо рд╕реЗрдЯ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ. рдЧреЗрдордордзреНрдпреЗ, рд╣реЗ рд╕рд░реНрд╡ 4*4 рдХрд▓реЗрдХреНрд╢рди рд╡реНрд╣реНрдпреВрджреНрд╡рд╛рд░реЗ рджрд░реНрд╢рд╡рд┐рд▓реЗ рдЬрд╛рдИрд▓. рдЖрдкрдг рдЕрджреНрдпрд╛рдк рдХрд▓реЗрдХреНрд╢рди рд╡реНрд╣реНрдпреВрд╢реА рдкрд░рд┐рдЪрд┐рдд рдирд╕рд▓реНрдпрд╛рд╕, рддреЗ рдпреЗрдереЗ рдЖрд╣реЗ
рдЖрдореНрд╣реА рдЧреЗрдордХрдВрдЯреНрд░реЛрд▓рд░рд▓рд╛ рдНрдкреНрд▓рд┐рдХреЗрд╢рдирдЪрд╛ рд░реВрдЯ рдХрдВрдЯреНрд░реЛрд▓рд░ рдореНрд╣рдгреВрди рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░реВ. рдЧреЗрдордХрдВрдЯреНрд░реЛрд▓рд░рдХрдбреЗ рдПрдХ рдХрд▓реЗрдХреНрд╢рди рд╡реНрд╣реНрдпреВ рдЕрд╕реЗрд▓ рдЬреНрдпрд╛рдЪрд╛ рдЖрдореНрд╣реА IBOutlet рдореНрд╣рдгреВрди рд╕рдВрджрд░реНрдн рджреЗрдК. рджреБрд╕рд░рд╛ рд╕рдВрджрд░реНрдн IBAction onStartGame() рдмрдЯрдгрд╛рдЪрд╛ рдЖрд╣реЗ, рд╣реЗ UIButton рдЖрд╣реЗ, рддреБрдореНрд╣реА рддреЗ PLAY рдирд╛рд╡рд╛рдЪреНрдпрд╛ рд╕реНрдЯреЛрд░реАрдмреЛрд░реНрдбрдордзреНрдпреЗ рдкрд╛рд╣реВ рд╢рдХрддрд╛.
рдирд┐рдпрдВрддреНрд░рдХрд╛рдВрдЪреНрдпрд╛ рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреАрдмрджреНрджрд▓ рдереЛрдбреЗрд╕реЗ:
- рдкреНрд░рдердо, рдЖрдореНрд╣реА рджреЛрди рдореБрдЦреНрдп рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рд╕реБрд░реВ рдХрд░рддреЛ - рдЧреНрд░рд┐рдб: рдЧреЗрдо = рдореЗрдорд░реА рдЧреЗрдо(), рдЖрдгрд┐ рдХрд╛рд░реНрдбреНрд╕рдЪрд╛ рд╕рдВрдЪ: рдХрд╛рд░реНрдбреНрд╕ = [рдХрд╛рд░реНрдб]().
- рдЖрдореНрд╣реА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╡реНрд╣реЗрд░рд┐рдПрдмрд▓реНрд╕ viewDidLoad рдореНрд╣рдгреВрди рд╕реЗрдЯ рдХрд░рддреЛ, рд╣реА рдкрд╣рд┐рд▓реА рдкрджреНрдзрдд рдЖрд╣реЗ рдЬреА рдЧреЗрдо рдЪрд╛рд▓реВ рдЕрд╕рддрд╛рдирд╛ рдХреЙрд▓ рдХреЗрд▓реА рдЬрд╛рддреЗ.
- рд╕рдВрдЧреНрд░рд╣ рджреГрд╢реНрдп рд▓рдкрд╡рд┐рд▓реЗрд▓реЗ рд╡рд░ рд╕реЗрдЯ рдХреЗрд▓реЗ рдЖрд╣реЗ рдХрд╛рд░рдг рд╡рд╛рдкрд░рдХрд░реНрддрд╛ рдкреНрд▓реЗ рджрд╛рдмреЗрдкрд░реНрдпрдВрдд рд╕рд░реНрд╡ рдХрд╛рд░реНрдб рд▓рдкрд╡рд▓реЗ рдЬрд╛рддрд╛рдд.
- рдЖрдореНрд╣реА PLAY рджрд╛рдмрддрд╛рдЪ, onStartGame IBAction рд╡рд┐рднрд╛рдЧ рд╕реБрд░реВ рд╣реЛрддреЛ рдЖрдгрд┐ рдЖрдореНрд╣реА collectionView isHidden рдкреНрд░реЙрдкрд░реНрдЯреА рдЦреЛрдЯреНрдпрд╛рд╡рд░ рд╕реЗрдЯ рдХрд░рддреЛ рдЬреЗрдгреЗрдХрд░реВрди рдХрд╛рд░реНрдб рджреГрд╢реНрдпрдорд╛рди рд╣реЛрддреАрд▓.
- рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд│реА рд╡рд╛рдкрд░рдХрд░реНрддрд╛ рдХрд╛рд░реНрдб рдирд┐рд╡рдбрддреЛ рддреЗрд╡реНрд╣рд╛ didSelectItemAt рдкрджреНрдзрдд рдХреЙрд▓ рдХреЗрд▓реА рдЬрд╛рддреЗ. рдореБрдЦреНрдп рдЧреЗрдо рд▓реЙрдЬрд┐рдХ рд▓рд╛рдЧреВ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдореНрд╣реА didSelectCard рдореНрд╣рдгрддреЛ рддреНрдпрд╛ рдкрджреНрдзрддреАрдордзреНрдпреЗ.
рдпреЗрдереЗ рдЕрдВрддрд┐рдо рдЧреЗрдордХрдВрдЯреНрд░реЛрд▓рд░ рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдЖрд╣реЗ:
class GameController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
let game = MemoryGame()
var cards = [Card]()
override func viewDidLoad() {
super.viewDidLoad()
game.delegate = self
collectionView.dataSource = self
collectionView.delegate = self
collectionView.isHidden = true
APIClient.shared.getCardImages { (cardsArray, error) in
if let _ = error {
// show alert
}
self.cards = cardsArray!
self.setupNewGame()
}
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if game.isPlaying {
resetGame()
}
}
func setupNewGame() {
cards = game.newGame(cardsArray: self.cards)
collectionView.reloadData()
}
func resetGame() {
game.restartGame()
setupNewGame()
}
@IBAction func onStartGame(_ sender: Any) {
collectionView.isHidden = false
}
}
// MARK: - CollectionView Delegate Methods
extension GameController: UICollectionViewDelegate, UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return cards.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CardCell", for: indexPath) as! CardCell
cell.showCard(false, animted: false)
guard let card = game.cardAtIndex(indexPath.item) else { return cell }
cell.card = card
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! CardCell
if cell.shown { return }
game.didSelectCard(cell.card)
collectionView.deselectItem(at: indexPath, animated:true)
}
}
рдЖрддрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреНрдпрд╛ рдкреНрд░реЛрдЯреЛрдХреЙрд▓рдмрджреНрджрд▓ рдереЛрдбреЗ рдмреЛрд▓реВрдпрд╛.
рдкреНрд░реЛрдЯреЛрдХреЙрд▓
рдкреНрд░реЛрдЯреЛрдХреЙрд▓рд╕рд╣ рдХрд╛рд░реНрдп рдХрд░рдгреЗ рд╣рд╛ рд╕реНрд╡рд┐рдлреНрдЯ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧрдЪрд╛ рдореБрдЦреНрдп рднрд╛рдЧ рдЖрд╣реЗ. рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╡рд░реНрдЧ, рд░рдЪрдирд╛ рдХрд┐рдВрд╡рд╛ рдЧрдгрдиреЗрд╕рд╛рдареА рдирд┐рдпрдо рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдгреНрдпрд╛рдЪреА рдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛рдд. рд╣реЗ рддрддреНрддреНрд╡ рддреБрдореНрд╣рд╛рд▓рд╛ рдореЙрдбреНрдпреВрд▓рд░ рдЖрдгрд┐ рдПрдХреНрд╕реНрдЯреЗрдВрд╕рд┐рдмрд▓ рдХреЛрдб рд▓рд┐рд╣рд┐рдгреНрдпрд╛рдЪреА рдкрд░рд╡рд╛рдирдЧреА рджреЗрддреЗ. рдЦрд░рдВ рддрд░, рд╣рд╛ рдПрдХ рдирдореБрдирд╛ рдЖрд╣реЗ рдЬреЛ рдЖрдореНрд╣реА рдЖрдзреАрдЪ GameController рдордзреНрдпреЗ collectionView рд╕рд╛рдареА рд▓рд╛рдЧреВ рдХрд░рдд рдЖрд╣реЛрдд. рдЖрддрд╛ рдЖрдкрд▓реА рд╕реНрд╡рддрдГрдЪреА рдЖрд╡реГрддреНрддреА рдмрдирд╡реВрдпрд╛. рд╡рд╛рдХреНрдпрд░рдЪрдирд╛ рдЕрд╕реЗ рджрд┐рд╕реЗрд▓:
protocol MemoryGameProtocol {
//protocol definition goes here
}
рдЖрдореНрд╣рд╛рд▓рд╛ рдорд╛рд╣рд┐рдд рдЖрд╣реЗ рдХреА рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдЖрдореНрд╣рд╛рд▓рд╛ рд╡рд░реНрдЧ рд▓рд╛рдЧреВ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдирд┐рдпрдо рдХрд┐рдВрд╡рд╛ рд╕реВрдЪрдирд╛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдгреНрдпрд╛рдЪреА рдкрд░рд╡рд╛рдирдЧреА рджреЗрддреЛ, рдореНрд╣рдгреВрди рддреЗ рдХрд╛рдп рдЕрд╕рд╛рд╡реЗрдд рдпрд╛рдЪрд╛ рд╡рд┐рдЪрд╛рд░ рдХрд░реВрдпрд╛. рддреБрдореНрд╣рд╛рд▓рд╛ рдПрдХреВрдг рдЪрд╛рд░рдЪреА рдЧрд░рдЬ рдЖрд╣реЗ.
- рдЧреЗрдо рдкреНрд░рд╛рд░рдВрдн: memoryGameDidStart.
- рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рд░реНрдбрдЪрд╛ рдЪреЗрд╣рд░рд╛ рдЦрд╛рд▓реА рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ: memoryGameShowCards.
- рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рд░реНрдбрдЪрд╛ рдЪреЗрд╣рд░рд╛ рдЦрд╛рд▓реА рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ: memoryGameHideCards.
- рдЧреЗрдордЪрд╛ рд╢реЗрд╡рдЯ: memoryGameDidEnd.
рд╕рд░реНрд╡ рдЪрд╛рд░ рдкрджреНрдзрддреА рдореБрдЦреНрдп рд╡рд░реНрдЧрд╛рд╕рд╛рдареА рд▓рд╛рдЧреВ рдХреЗрд▓реНрдпрд╛ рдЬрд╛рдК рд╢рдХрддрд╛рдд, рдЬреЗ рдЧреЗрдордХрдВрдЯреНрд░реЛрд▓рд░ рдЖрд╣реЗ.
рдореЗрдорд░реАрдЧреЗрдордбрд┐рдбрд╕реНрдЯрд╛рд░реНрдЯ
рдЬреЗрд╡реНрд╣рд╛ рд╣реА рдкрджреНрдзрдд рдЪрд╛рд▓рд╡рд▓реА рдЬрд╛рддреЗ, рддреЗрд╡реНрд╣рд╛ рдЧреЗрдо рд╕реБрд░реВ рдЭрд╛рд▓рд╛ рдкрд╛рд╣рд┐рдЬреЗ (рд╡рд╛рдкрд░рдХрд░реНрддрд╛ рдкреНрд▓реЗ рджрд╛рдмрддреЛ). рдпреЗрдереЗ рдЖрдореНрд╣реА рдлрдХреНрдд collectionView.reloadData() рд╡рд░ рдХреЙрд▓ рдХрд░реВрди рд╕рд╛рдордЧреНрд░реА рд░реАрд▓реЛрдб рдХрд░реВ, рдЬреЗ рдХрд╛рд░реНрдбреНрд╕ рд╢рдлрд▓ рдХрд░реЗрд▓.
func memoryGameDidStart(_ game: MemoryGame) {
collectionView.reloadData()
}
рдореЗрдорд░реАрдЧреЗрдорд╢реЛрдХрд╛рд░реНрдбреНрд╕
рдЖрдореНрд╣реА рдпрд╛ рдкрджреНрдзрддреАрд▓рд╛ рд╕рдВрдЧреНрд░рд╣ SDViewSelectItemAt рд╡рд░реВрди рдХреЙрд▓ рдХрд░рддреЛ. рдкреНрд░рдердо рддреЗ рдирд┐рд╡рдбрд▓реЗрд▓реЗ рдХрд╛рд░реНрдб рджрд╛рдЦрд╡рддреЗ. рдирдВрддрд░ рдХрд╛рд░реНрдб рджрд╛рдЦрд╡рд▓реЗрд▓реНрдпрд╛ рдЕреЕрд░реЗрдордзреНрдпреЗ рди рдЬреБрд│рдгрд╛рд░реЗ рдХрд╛рд░реНрдб рдЖрд╣реЗ рдХрд╛ рддреЗ рддрдкрд╛рд╕рд╛ (рдХрд╛рд░реНрдбрд╛рдВрдЪреА рд╕рдВрдЦреНрдпрд╛ рд╡рд┐рд╖рдо рдЕрд╕рд▓реНрдпрд╛рд╕) рдПрдХ рдЕрд╕рд▓реНрдпрд╛рд╕, рдирд┐рд╡рдбрд▓реЗрд▓реНрдпрд╛ рдХрд╛рд░реНрдбрдЪреА рддреНрдпрд╛рдЪреНрдпрд╛рд╢реА рддреБрд▓рдирд╛ рдХреЗрд▓реА рдЬрд╛рддреЗ. рдЬрд░ рдЪрд┐рддреНрд░реЗ рд╕рд╛рд░рдЦреА рдЕрд╕рддреАрд▓, рддрд░ рджреЛрдиреНрд╣реА рдХрд╛рд░реНрдбреЗ рдХрд╛рд░реНрдбреНрд╕рдордзреНрдпреЗ рдЬреЛрдбрд▓реА рдЬрд╛рддрд╛рдд рдЖрдгрд┐ рд╕рдореЛрд░рд╛рд╕рдореЛрд░ рд░рд╛рд╣рддрд╛рдд. рднрд┐рдиреНрди рдЕрд╕рд▓реНрдпрд╛рд╕, рдХрд╛рд░реНрдб рд╕реЛрдбрд▓реЗ рдХрд╛рд░реНрдб рджрд╛рдЦрд╡рд▓реЗ рдЖрдгрд┐ рджреЛрдиреНрд╣реА рддреЛрдВрдб рдЦрд╛рд▓реА рдХреЗрд▓реЗ.
рдореЗрдорд░реАрдЧреЗрдорд╣рд╛рдЗрдбрдХрд╛рд░реНрдбреНрд╕
рдХрд╛рд░реНрдб рдЬреБрд│рдд рдирд╕рд▓реНрдпрд╛рд╕, рд╣реА рдкрджреНрдзрдд рдХреЙрд▓ рдХреЗрд▓реА рдЬрд╛рддреЗ рдЖрдгрд┐ рдХрд╛рд░реНрдб рдкреНрд░рддрд┐рдорд╛ рд▓рдкрд╡рд▓реНрдпрд╛ рдЬрд╛рддрд╛рдд.
рджрд░реНрд╢рд╡рд┐рд▓реЗрд▓реЗ = рдЦреЛрдЯреЗ.
memoryGameDidEnd
рдЬреЗрд╡реНрд╣рд╛ рд╣реА рдкрджреНрдзрдд рдХреЙрд▓ рдХреЗрд▓реА рдЬрд╛рддреЗ, рддреЗрд╡реНрд╣рд╛ рдпрд╛рдЪрд╛ рдЕрд░реНрде рдЕрд╕рд╛ рд╣реЛрддреЛ рдХреА рд╕рд░реНрд╡ рдХрд╛рд░реНрдб рдЖрдзреАрдЪ рдЙрдШрдб рдЭрд╛рд▓реЗ рдЖрд╣реЗрдд рдЖрдгрд┐ рдХрд╛рд░реНрдб рджрд░реНрд╢рд╡рд┐рд▓реЗрд▓реНрдпрд╛ рд╕реВрдЪреАрдордзреНрдпреЗ рдЖрд╣реЗрдд: cardsShown.count = cards.count, рддреНрдпрд╛рдореБрд│реЗ рдЧреЗрдо рд╕рдВрдкрд▓рд╛ рдЖрд╣реЗ. isPlaying var рдЦреЛрдЯреНрдпрд╛рд╡рд░ рд╕реЗрдЯ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдореНрд╣реА endGame() рд▓рд╛ рдХреЙрд▓ рдХреЗрд▓реНрдпрд╛рдирдВрддрд░ рд╣реА рдкрджреНрдзрдд рд╡рд┐рд╢реЗрд╖рддрдГ рдХреЙрд▓ рдХреЗрд▓реА рдЬрд╛рддреЗ, рддреНрдпрд╛рдирдВрддрд░ рдЧреЗрдо рд╕рдорд╛рдкреНрддреАрдЪрд╛ рд╕рдВрджреЗрд╢ рджрд░реНрд╢рд╡рд┐рд▓рд╛ рдЬрд╛рддреЛ. рддрд╕реЗрдЪ alertController рдЪрд╛ рд╡рд╛рдкрд░ рдирд┐рдпрдВрддреНрд░рдХрд╛рд╕рд╛рдареА рд╕реВрдЪрдХ рдореНрд╣рдгреВрди рдХреЗрд▓рд╛ рдЬрд╛рддреЛ. viewDidDisappear рдореНрд╣рдгрддрд╛рдд рдЖрдгрд┐ рдЧреЗрдо рд░реАрд╕реЗрдЯ рдХреЗрд▓рд╛ рдЬрд╛рддреЛ.
рдЧреЗрдордХрдВрдЯреНрд░реЛрд▓рд░рдордзреНрдпреЗ рд╣реЗ рд╕рд░реНрд╡ рдХрд╕реЗ рджрд┐рд╕рддреЗ рддреЗ рдпреЗрдереЗ рдЖрд╣реЗ:
extension GameController: MemoryGameProtocol {
func memoryGameDidStart(_ game: MemoryGame) {
collectionView.reloadData()
}
func memoryGame(_ game: MemoryGame, showCards cards: [Card]) {
for card in cards {
guard let index = game.indexForCard(card)
else { continue
}
let cell = collectionView.cellForItem(
at: IndexPath(item: index, section:0)
) as! CardCell
cell.showCard(true, animted: true)
}
}
func memoryGame(_ game: MemoryGame, hideCards cards: [Card]) {
for card in cards {
guard let index = game.indexForCard(card)
else { continue
}
let cell = collectionView.cellForItem(
at: IndexPath(item: index, section:0)
) as! CardCell
cell.showCard(false, animted: true)
}
}
func memoryGameDidEnd(_ game: MemoryGame) {
let alertController = UIAlertController(
title: defaultAlertTitle,
message: defaultAlertMessage,
preferredStyle: .alert
)
let cancelAction = UIAlertAction(
title: "Nah", style: .cancel) {
[weak self] (action) in
self?.collectionView.isHidden = true
}
let playAgainAction = UIAlertAction(
title: "Dale!", style: .default) {
[weak self] (action) in
self?.collectionView.isHidden = true
self?.resetGame()
}
alertController.addAction(cancelAction)
alertController.addAction(playAgainAction)
self.present(alertController, animated: true) { }
resetGame()
}
}
рд╡рд╛рд╕реНрддрд╡рд┐рдХ, рддреЗ рд╕рд░реНрд╡ рдЖрд╣реЗ. рддреБрдореНрд╣реА рдЧреЗрдордЪреА рддреБрдордЪреА рд╕реНрд╡рддрдГрдЪреА рдЖрд╡реГрддреНрддреА рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рд╣рд╛ рдкреНрд░рдХрд▓реНрдк рд╡рд╛рдкрд░реВ рд╢рдХрддрд╛.
рдЖрдирдВрджреА рдХреЛрдбрд┐рдВрдЧ!
рд╕реНрдХрд┐рд▓рдмреЙрдХреНрд╕ рд╢рд┐рдлрд╛рд░рд╕ рдХрд░рддреЛ:
- рдкреНрд░реЕрдХреНрдЯрд┐рдХрд▓ рдХреЛрд░реНрд╕
"рдореЛрдмрд╛рдЗрд▓ рдбреЗрд╡реНрд╣рд▓рдкрд░ рдкреНрд░реЛ" .- рдСрдирд▓рд╛рдИрди рдХреЛрд░реНрд╕ рд▓рд╛рдЧреВ рдХреЗрд▓рд╛
"рдкрд╛рдпрдерди рдбреЗрдЯрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ" .- рджреЛрди рд╡рд░реНрд╖рд╛рдВрдЪрд╛ рдкреНрд░реЕрдХреНрдЯрд┐рдХрд▓ рдХреЛрд░реНрд╕
"рдореА рдкреНрд░реЛ рд╡реЗрдм рдбреЗрд╡реНрд╣рд▓рдкрд░ рдЖрд╣реЗ" .
рд╕реНрддреНрд░реЛрдд: www.habr.com