Acest articol descrie procesul de creare a unui joc simplu de antrenament de memorie care îmi place foarte mult. Pe lângă faptul că sunt bune în sine, veți învăța puțin mai multe despre cursurile și protocoalele Swift pe măsură ce mergeți. Dar înainte de a începe, să înțelegem jocul în sine.
Amintim:pentru toți cititorii „Habr” - o reducere de 10 de ruble la înscrierea la orice curs Skillbox folosind codul promoțional „Habr”.
Jocul începe cu o demonstrație a unui set de cărți. Se întind cu fața în jos (respectiv, imaginea în jos). Când faceți clic pe oricare, imaginea se deschide pentru câteva secunde.
Sarcina jucătorului este să găsească toate cărțile cu aceleași imagini. Dacă, după deschiderea primei cărți, îl întoarceți pe al doilea și imaginile se potrivesc, ambele cărți rămân deschise. Dacă nu se potrivesc, cărțile sunt închise din nou. Scopul este de a deschide totul.
Structura proiectului
Pentru a crea o versiune simplă a acestui joc, aveți nevoie de următoarele componente:
Un controler: GameController.swift.
One View: CardCell.swift.
Două modele: MemoryGame.swift și Card.swift.
Main.storyboard pentru a se asigura că întregul set de componente este disponibil.
Începem cu cea mai simplă componentă a jocului, cărțile.
Card.swift
Modelul cardului va avea trei proprietăți: id pentru a le identifica pe fiecare, o variabilă booleană afișată pentru a specifica starea cardului (ascuns sau deschis) și artworkURL pentru imaginile de pe carduri.
class Card {
var id: String
var shown: Bool = false
var artworkURL: UIImage!
}
Veți avea nevoie și de aceste metode pentru a controla interacțiunea utilizatorului cu hărțile:
Metodă de afișare a unei imagini pe un card. Aici resetăm toate proprietățile la valorile implicite. Pentru id, generăm un id aleatoriu apelând NSUUIS().uuidString.
Al doilea model este MemoryGame, aici setăm o grilă 4*4. Modelul va avea proprietăți precum cărți (o matrice de cărți pe o grilă), o matrice cardsShown cu cărți deja deschise și o variabilă booleană isPlaying pentru a urmări starea jocului.
class MemoryGame {
var cards:[Card] = [Card]()
var cardsShown:[Card] = [Card]()
var isPlaying: Bool = false
}
De asemenea, trebuie să dezvoltăm metode pentru a controla interacțiunea utilizatorului cu rețeaua.
Această metodă citește ultimul element din matricea **cardsShown** și returnează cardul care nu se potrivește.
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 și GameController.swift
Main.storyboard arată cam așa:
Inițial, trebuie să setați noul joc ca viewDidLoad în controler, inclusiv imaginile pentru grilă. În joc, toate acestea vor fi reprezentate de 4*4 collectionView. Dacă nu sunteți încă familiarizat cu collectionView, iată-l puteți obține informațiile de care aveți nevoie.
Vom configura GameController ca controler rădăcină al aplicației. GameController va avea un collectionView pe care îl vom referi ca IBOutlet. O altă referință este la butonul IBAction onStartGame(), acesta este un UIButton, îl puteți vedea în storyboard-ul numit PLAY.
Câteva despre implementarea controlorilor:
Mai întâi, inițializam două obiecte principale - grila: game = MemoryGame() și un set de cărți: cards = [Card]().
Am setat variabilele inițiale ca viewDidLoad, aceasta este prima metodă care este apelată în timp ce jocul rulează.
collectionView este setat la ascuns deoarece toate cărțile sunt ascunse până când utilizatorul apasă pe PLAY.
De îndată ce apăsăm PLAY, pornește secțiunea IBAction onStartGame și setăm proprietatea collectionView isHidden la false, astfel încât cărțile să poată deveni vizibile.
De fiecare dată când utilizatorul selectează un card, este apelată metoda didSelectItemAt. În metoda pe care o numim didSelectCard pentru a implementa logica principală a jocului.
Acum să vorbim puțin despre protocoalele importante.
protocoale
Lucrul cu protocoale este nucleul programării Swift. Protocoalele oferă capacitatea de a defini reguli pentru o clasă, o structură sau o enumerare. Acest principiu vă permite să scrieți cod modular și extensibil. De fapt, acesta este un model pe care îl implementăm deja pentru collectionView în GameController. Acum să facem propria noastră versiune. Sintaxa va arăta astfel:
protocol MemoryGameProtocol {
//protocol definition goes here
}
Știm că un protocol ne permite să definim reguli sau instrucțiuni pentru implementarea unei clase, așa că să ne gândim la ce ar trebui să fie acestea. Ai nevoie de patru în total.
Începutul jocului: memoryGameDidStart.
Trebuie să întoarceți cardul cu fața în jos: memoryGameShowCards.
Trebuie să întoarceți cardul cu fața în jos: memoryGameHideCards.
Sfârșitul jocului: memoryGameDidEnd.
Toate cele patru metode pot fi implementate pentru clasa principală, care este GameController.
memoryGameDidStart
Când această metodă este rulată, jocul ar trebui să înceapă (utilizatorul apasă pe PLAY). Aici pur și simplu vom reîncărca conținutul apelând collectionView.reloadData(), care va amesteca cardurile.
Numim această metodă din collectionSDViewSelectItemAt. Mai întâi arată cardul selectat. Apoi verifică dacă există o carte nepotrivită în matricea cardsShown (dacă numărul de cardsShown este impar). Dacă există unul, cardul selectat este comparat cu acesta. Dacă imaginile sunt aceleași, ambele cărți sunt adăugate la cardurile afișate și rămân cu fața în sus. Dacă este diferit, cardul lasă cărțile afișate și ambele sunt întoarse cu fața în jos.
memoryGameHideCards
Dacă cardurile nu se potrivesc, această metodă este apelată și imaginile cardului sunt ascunse.
arătat = fals.
memorieGameDidEnd
Când această metodă este apelată, înseamnă că toate cărțile sunt deja dezvăluite și sunt în lista cardsShown: cardsShown.count = cards.count, deci jocul s-a terminat. Metoda este apelată în mod specific după ce am apelat endGame() pentru a seta varul isPlaying la false, după care este afișat mesajul de final de joc. De asemenea, alertController este folosit ca indicator pentru controler. viewDidDisappear este apelat și jocul este resetat.
Iată cum arată totul în GameController:
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()
}
}
De fapt, asta-i tot. Puteți folosi acest proiect pentru a vă crea propria versiune a jocului.