توضح هذه المقالة عملية إنشاء لعبة بسيطة لتدريب الذاكرة والتي أحبها حقًا. إلى جانب كونها جيدة في حد ذاتها، ستتعلم المزيد عن فئات وبروتوكولات Swift أثناء تقدمك. ولكن قبل أن نبدأ، دعونا نفهم اللعبة نفسها.
نذكر:لجميع قراء "Habr" - خصم 10 روبل عند التسجيل في أي دورة Skillbox باستخدام رمز "Habr" الترويجي.
يوصي Skillbox بما يلي: دورة تعليمية عبر الإنترنت "مهنة مطور جافا".
كيفية تشغيل بطاقة الذاكرة
تبدأ اللعبة بعرض مجموعة من البطاقات. إنهم يرقدون ووجههم لأسفل (على التوالي، الصورة لأسفل). عند النقر على أي واحد، يتم فتح الصورة لبضع ثوان.
مهمة اللاعب هي العثور على جميع البطاقات التي تحتوي على نفس الصور. إذا قمت، بعد فتح البطاقة الأولى، بقلب الثانية وتطابقت الصور، تظل كلتا البطاقتين مفتوحتين. إذا لم تكن متطابقة، يتم إغلاق البطاقات مرة أخرى. الهدف هو فتح كل شيء.
هيكل المشروع
لإنشاء نسخة بسيطة من هذه اللعبة، تحتاج إلى المكونات التالية:
وحدة تحكم واحدة: 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.
النموذج الثاني هو MemoryGame، وهنا قمنا بتعيين شبكة 4*4. سيحتوي النموذج على خصائص مثل البطاقات (مصفوفة من البطاقات على الشبكة)، ومصفوفة البطاقات المعروضة مع البطاقات المفتوحة بالفعل، والمتغير المنطقي قيد التشغيل لتتبع حالة اللعبة.
class MemoryGame {
var cards:[Card] = [Card]()
var cardsShown:[Card] = [Card]()
var isPlaying: Bool = false
}
نحتاج أيضًا إلى تطوير طرق للتحكم في تفاعل المستخدم مع الشبكة.
تقرأ هذه الطريقة العنصر الأخير في مصفوفة **cardsShown** وترجع البطاقة غير المطابقة.
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. إذا لم تكن على دراية بـ CollectionView بعد، فها هو يمكنك الحصول على المعلومات التي تحتاجها.
سنقوم بتكوين وحدة التحكم GameController لتكون وحدة التحكم الجذرية للتطبيق. سيكون لدى GameController عرض مجموعة سنشير إليه باعتباره IBOutlet. مرجع آخر هو زر IBAction onStartGame()، وهو زر UIButton، يمكنك رؤيته في لوحة العمل التي تسمى PLAY.
قليلا عن تنفيذ وحدات التحكم:
أولاً، نقوم بتهيئة كائنين رئيسيين - الشبكة: اللعبة = MemoryGame()، ومجموعة من البطاقات: البطاقات = [Card]().
قمنا بتعيين المتغيرات الأولية على أنها viewDidLoad، وهذه هي الطريقة الأولى التي يتم استدعاؤها أثناء تشغيل اللعبة.
تم تعيين CollectionView على مخفي لأن جميع البطاقات مخفية حتى يضغط المستخدم على PLAY.
بمجرد الضغط على PLAY، يبدأ قسم onStartGame IBAction، وقمنا بتعيين خاصية CollectionView isHidden على false حتى تصبح البطاقات مرئية.
في كل مرة يقوم المستخدم بتحديد بطاقة، يتم استدعاء الأسلوب didSelectItemAt. في الطريقة نسميها didSelectCard لتنفيذ منطق اللعبة الرئيسي.
العمل مع البروتوكولات هو جوهر برمجة Swift. توفر البروتوكولات القدرة على تحديد قواعد للفئة أو البنية أو التعداد. يتيح لك هذا المبدأ كتابة تعليمات برمجية معيارية وقابلة للتوسيع. في الواقع، هذا هو النمط الذي قمنا بتنفيذه بالفعل لـ CollectionView في GameController. الآن دعونا نصنع نسختنا الخاصة. سيبدو بناء الجملة كما يلي:
protocol MemoryGameProtocol {
//protocol definition goes here
}
نحن نعلم أن البروتوكول يسمح لنا بتحديد القواعد أو التعليمات لتنفيذ الفصل الدراسي، لذلك دعونا نفكر فيما ينبغي أن تكون عليه. أنت بحاجة إلى أربعة في المجموع.
بداية اللعبة: MemoryGameDidStart.
تحتاج إلى قلب البطاقة ووجهها لأسفل: MemoryGameShowCards.
تحتاج إلى قلب البطاقة ووجهها لأسفل: MemoryGameHideCards.
نهاية اللعبة: MemoryGameDidEnd.
يمكن تنفيذ جميع الطرق الأربع للفئة الرئيسية، وهي GameController.
MemoryGameDidStart
عند تشغيل هذه الطريقة، يجب أن تبدأ اللعبة (يضغط المستخدم على PLAY). هنا سنقوم ببساطة بإعادة تحميل المحتوى عن طريق استدعاء CollectionView.reloadData()، والذي سيعمل على خلط البطاقات.
نحن نسمي هذه الطريقة من المجموعةSDViewSelectItemAt. أولا يظهر البطاقة المحددة. ثم يتحقق لمعرفة ما إذا كانت هناك بطاقة غير متطابقة في مصفوفة البطاقات المعروضة (إذا كان عدد البطاقات المعروضة فرديًا). إذا كان هناك واحدة، تتم مقارنة البطاقة المحددة معها. إذا كانت الصور هي نفسها، تتم إضافة كلا البطاقتين إلى البطاقات المعروضة وتبقى مكشوفة. إذا كانت مختلفة، فستترك البطاقة البطاقات المعروضة ويتم قلب كليهما لأسفل.
MemoryGameHideCards
إذا كانت البطاقات غير متطابقة، يتم استدعاء هذه الطريقة ويتم إخفاء صور البطاقة.
مبين = خطأ.
MemoryGameDidEnd
عندما يتم استدعاء هذه الطريقة، فهذا يعني أن جميع البطاقات قد تم الكشف عنها بالفعل وهي موجودة في قائمة البطاقات المعروضة: CardShown.count =cards.count، وبالتالي تنتهي اللعبة. يتم استدعاء الطريقة على وجه التحديد بعد أن قمنا باستدعاء endGame() لتعيين قيمة isPlaying var إلى false، وبعد ذلك تظهر رسالة نهاية اللعبة. كما يتم استخدام تنبيه وحدة التحكم كمؤشر لوحدة التحكم. يتم استدعاء viewDidDisappear ويتم إعادة ضبط اللعبة.
إليك ما يبدو عليه كل شيء في 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()
}
}
في الواقع، هذا كل شيء. يمكنك استخدام هذا المشروع لإنشاء نسختك الخاصة من اللعبة.