تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
[مشروع] لعبة الذاكرة مبسطة ( مع الشرح )
#1
Photo 
بسم الله الرحمن الرحيم

السلام عليكم ورحمة الله وبركاته اعضاء المنتدى الكرام

كان الاخ عبد الهادي بهاب بارك الله فيه وادام عليه نعمه قد طرح لعبة الذاكرة من تصميمه في هذا الموضوع

http://vb4arb.com/vb/showthread.php?tid=36191

ذلك جعلني افكر في ابسط طريقة يمكن عمل بها مثل هذه الالعاب البسيطة بدون تايمر او تكرار ، لذلك قمت بكتابتها بسرعة وانا مبهور من انها عملت فعلا  Big Grin

   
   
   
   

اللعبة موجودة في المرفقات ، والان الى الشرح ، يمكنك المغادرة الان وان كنت افضل ان تكمل الشرح لتفهم اسلوب العمل

شرح اسلوب العمل

قبل ان نبدأ في شرح الكود نحتاج ان نفهم ما ما المشاكل التي تنطوي عليها اللعبة وكيف نقوم بحلها ، حتى نعرف الاجرائات التي سنقوم باستدعائها عند الحاجة لتلافي التكرار ولتبسيط الامر :



الخطوة الاولى : نريد طريقة امنة لتخزين الصور بحيث يمكننا الحصول عليها عند الحاجة بسهولة



اخترت ان اخزن الصور في المرفقات حيث انها تكون متضمنه في exe المشروع ولن اقلق حيال استدعائها داخل البرنامج 

   

بعد ذلك نحصل على الصور عن طريق My.Resources._1 هكذا ،
واذا قمنا باستيراد مجال الاسماء يصبح بامكاننا استدعاء الصور باسمائها مباشرة :

كود :
Imports MemoryGame.My.Resources


الان لتسهيل التعامل مع الصور طوال عمل البرنامج قمت بتعريف List(Of Image) تحتوي الصور من الريسورسز ، تعريف عام للبرنامج كله :

كود :
   Dim ImgList As New List(Of Image)({_1, _2, _3, _4, _5, _6, _7, _8})


الخطوة الثانية : تصميم شكل اللعبة


نريد طريقة سريعة وعملية لرص مربعات الصور بجانب بعضهم البعض
قمت باضافة الاداه TableLayoutPanel1 لكي اضع بها الصور ، واضفت بها 4 صفوف و4 اعمدة ،
وبداخلها اضفت 16 مربع صور ، ثم جعلت الخاصية Dock لكل مربعات الصور = Fill :

   

طيب الان نريد ان نضع كل مربعات الصور في List(of PictureBox) حتى نتمكن من التعامل معها بسهولة لاحقا ، قمت بتعريف التالي في التعريفات العامة :

كود :
   Dim PictureBoxList As List(Of PictureBox)

طيب الان كيف نملأ هذه ال List بمربعات الصور فعلا ؟ هل نقوم باضافتها ام ان هناك فكرة افضل ؟ 

في الحقيقة لا اطيق التكرار ، وعندي قناعة ان هناك دائما طريقة ابسط لفعل الاشياء معظم الوقت 

بما اننا وضعنا مربعات الصور داخل TableLayoutPanel1 فانه يمكننا بسهولة ملئ ال list الخاصة بالصور من الادوات التي تحتويها عن طريق الدالة OfType

الكود التالي ضعه في مشيد الفورم Sub New () :

كود :
       PictureBoxList = Me.TableLayoutPanel1.Controls.OfType(Of PictureBox).ToList
لاحظ ToList السحرية التي تعيد نسخة جديدة من القائمة الى قائمتنا 


الخطوة الثالثة : تغيير ترتيب الصور عشوائيا في مربعات الصور


سنقوم بتعريف الدالة RandomizePictureBox التي تقوم باسناد الصور الى مربعات صور عشوائية 

السيناريو كالتالي : نعرف List بمربعات الصور التي لم يتم اسناد لها صورة بحيث تأخد نسخة اولية من List مربعات الصور
لكل صورة في List الصور نفعل ما يلي :

  1. نختار index عشوائي من List مربعات الصور عن طريق rnd.Next
  2. نضع الصورة الحالية في هذا المربع ، وكذلك ترتيب الصورة في ال Tag حتى نتمكن من مقارنتها لاحقا
  3. نمسح مربع الصور من List بمربعات الصور الفارغة 

كود :
   Sub RandomizePictureBox()
       Dim Remainig As List(Of PictureBox) = PictureBoxList.ToList
       Dim rnd As New Random()
       Dim PicIndex As Integer
       For i As Integer = 0 To ImgList.Count - 1
           PicIndex = rnd.Next(0, Remainig.Count - 1)
           Remainig(PicIndex).Tag = i
           Remainig(PicIndex).Image = ImgList(i)

           Remainig.RemoveAt(PicIndex)

           PicIndex = rnd.Next(0, Remainig.Count - 1)
           Remainig(PicIndex).Tag = i
           Remainig(PicIndex).Image = ImgList(i)

           Remainig.RemoveAt(PicIndex)
       Next
   End Sub


نكرر العملية من 1 الى 3 مرة اخرى ( كل صورة موجودة في مربعين صور عشوائيين )





الخطوة الرابعة : تجهيز لعبة جديدة:


 نعرف اجراء لبدأ لعبة جديدة

كود :
    Dim RemainingPictureBox As List(Of PictureBox)

   Sub Reset()
       RandomizePictureBox()
       RemainingPictureBox = PictureBoxList.ToList
   End Sub

تقوم بترتيب الصور عشوائيا في مربعات الصور
طيب الان نريد طريقة نعرف بها مربعات الصور التي لم يطابقها المستخدم بعد 
نعرف List للصور المتبقية دون مطابقة ونقوم بملئها من List مربعات الصور


الخطوة الخامسة : بدأ اللعبة


نضيف زر جديد لبدأ اللعبة

طيب دعنا نفكر ماذا نحتاج ان نفعله لبدأ اللعبة ؟

  1. اولا ان نعطل الزر الذي يبدأ اللعبة حتى لا يتم ضغطه مرة اخرى
  2. اخفاء جميع الصور من مربعات الصور
  3. انتظار ام يضغط المستخدم على مربعات الصور
 
نعرف الاجراء الذي يبدأ اللعبة :

كود :
   Sub Start()
       Button1.Enabled = False
       HideAllPics()
       PictureBoxList.ForEach(Sub(x) AddHandler x.Click, AddressOf PictureBox_Click)
   End Sub

في السطر الثالث نضيف الاجراء PictureBox_Click ( لم نعرفه بعد ) الى حدث Click لكل الصور 
في السطر الثاني نستدعى الاجراء الخاص باخفاء كل الصور 

كود :
   Sub HideAllPics()
       PictureBoxList.ForEach(Sub(x) x.Image = unknown)
   End Sub




الخطوة السادسة : الاستجابة للضغط على مربعات الصور


نقوم بتعريف الاجراء الذي اضفناه لحدث الضغط على كل الصور PictureBox_Click وهو عصب اللعبة الاساسي :

كود :
   Private Async Sub PictureBox_Click(sender As Object, e As EventArgs)

   End Sub

طيب الان المستخدم ضغط على الصورة ، نريد ان نعرف اي صورة ضغط عليها ومن ثم نعطل حدث الضغط لها حتى لايضغط عليها مرة اخرى  ( اجراء احترازي )

كود :
       Dim Pic As PictureBox = DirectCast(sender, PictureBox)

       RemoveHandler Pic.Click, AddressOf PictureBox_Click

بعد ذلك نريد ان نظهر الصورة التي يحملها مربع الصورة ( تذكر ان ترتيبها موجود في الخاصية tag ) :

كود :
       Pic.Image = ImgList(Pic.Tag)


طيب الان كيف نعرف هل الصورة التي ضغط عليها المستخدم هي اول صورة ام ثاني صورة ؟ 
نعرف متغير عام خارج الاجراء LastPic يمثل اخر صورة تم الضغط عليها 

كود :
   Dim LastPic As PictureBox

الان  نعود للدالة ،
اذا كانت المتغير LastPic لايشير الى شيء فهذا معناه انها اول صورة يتم الضغط عليها ، وعندها كل ما علينا فعله هو ان نضع الصورة التي ارسلت حدث الضغط في LastPic ومن ثم نقوم ب Return من الاجراء :

كود :
       If LastPic Is Nothing Then
           LastPic = Pic
           Return
       End If

طيب اذا اكمل الحدث الكود بعد هذه النقطة فهذا معناه ان LastPic كانت تشير لمربع الصورة الذي تم ضغطه اولا ، وحينها تقوم بعمل متغير محلى يحمل مربع الصورة التي يشير لها LastPic ، ثم نقوم بجعل LastPic لايشير الا شيء حتى تتكرر العملية مجددا مع مربع صور جديد :

كود :
       Dim lst As PictureBox = LastPic
       LastPic = Nothing

الان نقارن بين مربع الصورة الذي تم ضغطه اولا ومربع الصورة الحالي 
اذا تساوي الخاصية tag لهما هذا يعني ان هناك  تطابق ، نستدعي الاجراء Match ، سنعرفه لاحقا

والا هنا محاولة خاطئة
ننتظر 500 ملي ثانية ثم نستدعي الاجراء NotMatch ، سنعرفه لاحقا ايضا

كود :
       If Pic.Tag = lst.Tag Then

           Match(Pic, lst)
       Else
           Await Task.Delay(500)

           NotMatch(Pic, lst)
       End If


الآن اذا كانت RemainingPictureBox فارغة هذا معناه اننا انهينا اللعبة ، نستدعي الاجراء Finished 


كود :
       If RemainingPictureBox.Count = 0 Then
           Finished()
       End If


الخطوة السابعة : ماذا نفعل في حالة حدوث تطابق او محاولة خاطئة او انتهاء اللعبة :



الاجراء Match : نمرر له مربعين صورة يمثل الصورة الاولى والثانية ، عند حدوث تطابق نريد ان نزيل المربعين من RemainingPictureBox ، 

وثم نضيف ما نريد من اكواد لزيادة متغير المحاولات الصحيحة مثلا او اظهار صوت او شيء نريده عند حدوث تطابق :

كود :
   Sub Match(CurrentPic As PictureBox, LastPic As PictureBox)
       RemainingPictureBox.Remove(CurrentPic)
       RemainingPictureBox.Remove(LastPic)

       'كود عرض زيادة النتيجة الصحيحة بعد هذا السطر كسلت اكتبها
   End Sub

الاجراء NotMatch : نمرر له مربعين صورة يمثل الصورة الاولى والثانية ، عند حدوث محاولة خاطئة نريد ان نضع الصورة unknown في مربعين الصورة الاولى والثانية ، وكذلك نضيف الاجراء الى حدث الضغط لهما ليعود كل شيء كما كان

وثم ايضا نضيف مانريد فعله عند حدوث محاولة خاطئة :

كود :
   Sub NotMatch(CurrentPic As PictureBox, LastPic As PictureBox)
       CurrentPic.Image = unknown
       LastPic.Image = unknown
       AddHandler CurrentPic.Click, AddressOf PictureBox_Click
       AddHandler LastPic.Click, AddressOf PictureBox_Click

       'كود عرض النتيجة خاطئة بعد هذا السطر ولكن كسلت اكتبها ايضا
   End Sub


الاجراء Finished : اخيرا المستخدم طابق كل الصور ، نظهر له رسالة تخبره بانه قد اتم اللعبة بنجاح ، 

ثم نبدأ لعبة جديدة عن طريق الاجراء Reset الذي عرفناه

وبعد ذلك نعيد تفعيل زر بدأ اللعبة 

كود :
   Sub Finished()
       MsgBox("مبروك لقد اتممت اللعبة بنجاح")
       Reset()
       Button1.Enabled = True
   End Sub


الخطوة الأخيرة : تعريف حدث Load للفورم وحدث Click على زر بدأ اللعب:


في حدث Form1_Load : نقوم ببدأ لعبة جديدة Reset :

كود :
   Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
       Reset()
   End Sub


في حدث Button1_Click : نقوم ببدأ اللعب Start :


كود :
   Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
       Start()
   End Sub


هذا كل شيء تقريبا  Big Grin 



اتمنى اكون قد وصلت الفكرة والهدف وراء كل ذلك هو التفكير المنطقى وتقسيم المشكلة الكبيرة الى مشاكل صغيرة وحل كل جزئية على حده ومن ثم تجميع الاجزاء لبناء برنامج قوي، والاهم هو عدم كتابة نفس الكود اكثر من مرة في اكثر من مكان ، وذلك لتسهيل تتبع الكود بعد ذلك وتسهيل التعديل عليه


اتمنى التوفيق للجميع


الملفات المرفقة
.zip   MemoryGameVB.zip (الحجم : 462.38 ك ب / التحميلات : 9)
الرد
#2
ما شاء الله
حقيقة محترف .......... شرح واف و فيه من المعلومات اكثر مما تتوقعه
لا تحرمنا من هذه الشروحات

جزاك الله خيرا
 لعل الكلمة التي تنفعني لم أكتبها بعد
عبد الله بن المبارك
الرد
تم الشكر بواسطة: Anas Mahmoud , asemshahen5
#3
(24-08-20, 10:05 PM)عبد الهادي بهاب كتب : ما شاء الله
حقيقة محترف .......... شرح واف و فيه من المعلومات اكثر مما تتوقعه
لا تحرمنا من هذه الشروحات

جزاك الله خيرا

العفو اخي عبد الهادي

ولك بمثله ان شاء الله
الرد
تم الشكر بواسطة: asemshahen5
#4
بالتوفيق استاذ انس ..

واصل عطائك يالمتميز جزاك الله خير .
يا رحمن الدنيا والآخرة ورحيمهما
الرد
تم الشكر بواسطة: Anas Mahmoud , Anas Mahmoud , asemshahen5


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
Big Grin [مشروع] سورس كود مع الشرح بالفيديو لانشاء فورم تسجيل الدخول ahmadpal 1 1,397 10-09-20, 03:12 PM
آخر رد: 7001605497
  [مشروع] تصميم لعبة السلم و الافعى عبد الهادي بهاب 0 107 05-09-20, 07:04 PM
آخر رد: عبد الهادي بهاب
  [مشروع] تصميم لعبة المربعات squaresgame عبد الهادي بهاب 0 110 04-09-20, 02:13 PM
آخر رد: عبد الهادي بهاب
  [مشروع] تصميم لعبة الدبناصور لمتصفح كروم T- rex runner عبد الهادي بهاب 0 129 03-09-20, 04:09 AM
آخر رد: عبد الهادي بهاب
  [مشروع] تصميم لعبة الذاكرة عبد الهادي بهاب 0 134 23-08-20, 08:11 PM
آخر رد: عبد الهادي بهاب
  [مشروع] تصميم برنامج تربوي اكتشف الكلمة ..لعبة المشنقة عبد الهادي بهاب 1 195 23-08-20, 05:54 PM
آخر رد: عبد الهادي بهاب
Photo قديم : لعبة تركيب الصور Anas Mahmoud 1 172 20-08-20, 02:44 AM
آخر رد: عبد الهادي بهاب
  [مشروع] تصميم لعبة ذكاء اعواد الثقاب عبد الهادي بهاب 6 285 19-08-20, 02:07 AM
آخر رد: عبد الهادي بهاب
  لعبة تعليمية بسحب الصور واسقاطها على اسمها @@أبورائد@@ 25 11,487 15-08-20, 03:22 AM
آخر رد: عبد الهادي بهاب
  [مشروع] ملف مفتوح ..تصميم لعبة ذكاء خاصة بالارقام عبد الهادي بهاب 3 242 15-08-20, 02:35 AM
آخر رد: عبد الهادي بهاب

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم