السلام عليكم ورحمة الله وبركاته
بالنظر في البرنامجيين الاوليين rtaWithoutOOP1 و rtaWithOOP1 .... لاحظ من التسمية بأن البرنامج بدون Without استخدام مفاهيم الـ OOP والآخر ... بإستخدام With مفاهيم الـ OOP.
ستجد اول الملاحظات السريعة هي طول وتعقيد الكود في مثال الـ OOP ... فمثلا في البرنامج بدون OOP فأن الكود في الفورم الرئيسية لايعدو الأربعون سطر برمجي تقريباً ... فهو بالكامل كالتالي :
Public Class Form1 Private CircleBounds As Rectangle 'لتخزين احداثيات الكرة Private rand As New Random ' لتوليد ارقام عشوائية لاحقا Private dX, dY As Integer ' لتخزين اتجاهات الحركة الحالية Private Speed As Integer ' متغير لخزن سرعة الحركة Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load CircleBounds = New Rectangle(0, 0, 30, 30) ' حجم الكرة سيكون في حدود هذا المربع CircleBounds.X = rand.Next(0, Me.ClientSize.Width) ' توليد قيمة عشوائية في حدود عرض الفورم CircleBounds.Y = rand.Next(0, Me.ClientSize.Height) ' توليد قيمة عشوائية في حدود ارتفاع الفورم Speed = 3 ' اختيار السرعة ثلاثة ويمكن تغييريها بما يناسبك dX = (1 - 2 * rand.Next(0, 2)) * Speed ' توليد رقم اما سالب او موجب ثلاثة dY = (1 - 2 * rand.Next(0, 2)) * Speed ' توليد رقم اما سالب او موجب ثلاثة tmr.Start() ' تشغيل التايمر المسئول عن الحركة End Sub Private Sub tmr_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmr.Tick CircleBounds.X += dX ' تحريك الدائرة على المحور س CircleBounds.Y += dY ' تحريكها على المحور ص ' التأكد من كونها لم تتجاوز حدود الفورم وإلا نقوم بعكس الاتجاهات If CircleBounds.X > Me.ClientSize.Width - CircleBounds.Width OrElse CircleBounds.X < 0 Then dX = -dX If CircleBounds.Y > Me.ClientSize.Height - CircleBounds.Height OrElse CircleBounds.Y < 0 Then dY = -dY ' واخيراً رسم الدائرة على الفورم Using g As Graphics = Me.CreateGraphics g.Clear(Me.BackColor) g.FillEllipse(Brushes.Blue, CircleBounds) g.DrawEllipse(Pens.Black, CircleBounds) End Using End Sub End Class
بينما نجد في مثال الـ OOP انه انقسم الى قسمين قسم معرف في كود الفورم الرئيسية ( في حدود الـعشرون سطر برمجي) .... كالتالي :
Public Class Form1 Private Ball As Circle Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Ball = New Circle(Me.ClientSize.Width, Me.ClientSize.Height) tmr.Start() End Sub Private Sub tmr_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmr.Tick Ball.Move() Using g As Graphics = Me.CreateGraphics g.Clear(Me.BackColor) Ball.Draw(g) End Using End Sub End Class
والقسم الآخر يكمن في كود الفئة Circle التي اضفناها في برنامج الـ OOP الأول :
Public Class Circle Private Width, Height As Integer Private rand As New Random Private dX, dY As Integer Sub New(ByVal FormWidth As Integer, ByVal FormHeight As Integer) Width = FormWidth Height = FormHeight _Bounds.X = rand.Next(0, Width) _Bounds.Y = rand.Next(0, Height) Me.Speed = 3 dX = (1 - 2 * rand.Next(0, 2)) * Me.Speed dY = (1 - 2 * rand.Next(0, 2)) * Me.Speed End Sub Private _Bounds As New Rectangle(0, 0, 30, 30) Public Property Bounds() As Rectangle Get Return _Bounds End Get Set(ByVal value As Rectangle) _Bounds = value End Set End Property Private _Speed As Integer Public Property Speed() As Integer Get Return _Speed End Get Set(ByVal value As Integer) _Speed = value End Set End Property Private _Color As Color = Drawing.Color.Red Public Property Color() As Color Get Return _Color End Get Set(ByVal value As Color) _Color = value End Set End Property Sub Move() _Bounds.X += dX _Bounds.Y += dY If _Bounds.X > Width - _Bounds.Width OrElse _Bounds.X < 0 Then dX = -dX If _Bounds.Y > Height - _Bounds.Height OrElse _Bounds.Y < 0 Then dY = -dY End Sub Sub Draw(ByVal g As Graphics) g.FillEllipse(New SolidBrush(Me.Color), _Bounds) g.DrawEllipse(Pens.Black, _Bounds) End Sub End Class
وهو كود بطول الستين سطر برمجي تقريباً اي بإجمالي تقريبي مقداره ثمانون سطر برمجي في برنامج الـ OOP و اربعون بدونه ... إضافة الى تقسيم الكود في مكانان منفصلان (الفورم و الفئة Circle) بينما في مثال البرمجة العادية (كود قصير واضح في مكان واحد!).
----------------------------------------------------------------------------------------------------------------------------------------------------------
وجب التنويه الى هذه الملاحظة مبدئياً قبل الانتقال الى الخطوة التالية ... وهي فرض كوننا نريد تعديل البرنامجين لكي يحتويا على عشر كرات تسير في نفس الوقت .
-------------------------------------------------------- برنامج العشر كرات بدون OOP ---------------------------------------------------------------
في الحالة السابقة (حالة الكرة الواحدة) احتجنا الى تعريف بعض المتغيرات في الفورم لحفظ احداثيات و معلومات حركة كرتنا الوحيدة ... متغيرات مثل : CircleBounds , dx , dy و Speed ... لجعل الأمر نفسه يعمل لأكثر من كرة فسنحتاج الى تغيير هذه المتغيرات الى مصفوفات فمثلا :
Dim Speed As Integer Speed = 3
يمكن تغييره الى
Dim Speed(9) As Integer Speed(0) = 3 Speed(1) = 2 Speed(2) = 5 . . .
في الكود السابق غيرنا تعريف المتغير Speed من متغير عددي واحد الى مصفوفة بعشرة عناصر(من 0 الى 9) وعليه فيمكن ان نحفظ الان في هذه المصفوفة عشر سرعات مختلفة لعشر كرات مختلفة ... كما في المثال السابق فالكرة الاولى سرعتها 3 و الثانية 2 .... وهكذا ...
وبذا يمكن تعديل البرنامج ليصبح بالكود
Public Class Form1 Private CircleBounds(9) As Rectangle 'لتخزين احداثيات الكرة Private rand As New Random ' لتوليد ارقام عشوائية لاحقا Private dX(9) As Integer Private dY(9) As Integer Private Speed(9) As Integer Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load For I As Integer = 0 To 9 CircleBounds(I) = New Rectangle(0, 0, 30, 30) ' حجم الكرة سيكون في حدود هذا المربع CircleBounds(I).X = rand.Next(0, Me.ClientSize.Width) ' توليد قيمة عشوائية في حدود عرض الفورم CircleBounds(I).Y = rand.Next(0, Me.ClientSize.Height) ' توليد قيمة عشوائية في حدود ارتفاع الفورم Speed(I) = 3 ' اختيار السرعة ثلاثة ويمكن تغييريها بما يناسبك dX(I) = (1 - 2 * rand.Next(0, 2)) * Speed(I) ' توليد رقم اما سالب او موجب ثلاثة dY(I) = (1 - 2 * rand.Next(0, 2)) * Speed(I) ' توليد رقم اما سالب او موجب ثلاثة Next tmr.Start() ' تشغيل التايمر المسئول عن الحركة End Sub Private Sub tmr_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmr.Tick Using g As Graphics = Me.CreateGraphics g.Clear(Me.BackColor) For I As Integer = 0 To 9 CircleBounds(I).X += dX(I) ' تحريك الدائرة على المحور س CircleBounds(I).Y += dY(I) ' تحريكها على المحور ص ' التأكد من كونها لم تتجاوز حدود الفورم وإلا نقوم بعكس الاتجاهات If CircleBounds(I).X > Me.ClientSize.Width - CircleBounds(I).Width OrElse CircleBounds(I).X < 0 Then dX(I) = -dX(I) If CircleBounds(I).Y > Me.ClientSize.Height - CircleBounds(I).Height OrElse CircleBounds(I).Y < 0 Then dY(I) = -dY(I) g.FillEllipse(Brushes.Blue, CircleBounds(I)) g.DrawEllipse(Pens.Black, CircleBounds(I)) Next End Using End Sub End Class
اذا امعنت النظر في الكود السابق فأن التعديلات الطفيفة في الكود قد اضافت الى البرنامج الاصلي 10 سطور برمجية ليصبح طول البرنامج مايقارب الـ 50 سطر برمجي.
يمكن الاطلاع على الكود المرفق.
-------------------------------------------------------- برنامج العشر كرات مع OOP ---------------------------------------------------------------
لتعديل برنامجنا الأول (برنامج الكرة واحدة بإستخدام الـ OOP) فإننا لن نحتاج الى المساس بالفئة Circle كون الكرات العشر على اختلافها جميعها من نفس الصنف وتحمل نفس الخصائص Properties و الطرق Methods و لكنها تختلف في قيم هذه الخصائص فلكل كرة موقعها ولونها .... وخلافه ....
وما سيلزمنا هو نفس التعديل الذي قمنا فيه في (برنامج العشر كرات بدون OOP) وهو استخدام المصفوفات لخزن عشر كرات بدلا من كرة واحدة ... بكلام آخر :
Dim Balls(9) As Cricle
كما يمكن ان نسخدم List Of للتسهيل وهي ايضا يمكن اعتبارها مصفوفة من عنصر معين (وهو الفئة Circle) في برنامجنا :
Dim Balls As List(Of Circle)
وعليه فيمكن ان يحتوي المتغير Balls على اي عدد من الكرات بإستخدام الامر Add لإضافة كرة جديدة
على العموم سواءً استخدمت المصفوفة العادية او المجموعات List Of فالناتج واحد ... والجزء الذي سيتم تغييره هو الكود الموجود في الفورم الرئيسية ... ليصبح بشكل مشابه للتالي :
Public Class Form1 Private Balls As New List(Of Circle) Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim Ball As Circle For I As Integer = 1 To 10 Ball = New Circle(Me.ClientSize.Width, Me.ClientSize.Height) Balls.Add(Ball) Next tmr.Start() End Sub Private Sub tmr_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmr.Tick Using g As Graphics = Me.CreateGraphics g.Clear(Me.BackColor) For Each Ball As Circle In Balls Ball.Move() Ball.Draw(g) Next End Using End Sub End Class
وعليه فإن تعديل ... البرنامج من كرة واحدة الى متعدد كرات بإستخدام الـ OOP .... ايضا كلفنا اضافة ما يقارب العشرة اسطر برمجية ليصبح البرنامج كاملا بمجموع التسعون سطر برمجي.
---------------------------------------------------------------------------------------------------------------------------------------
ارجو الاطلاع على البرامج المرفقة للتحليل rtaWithoutOOP2 و rtaWithOOP2 ... و سوف احاول بسرعة الانتقال الى الجزء التالي في تغييرات كلا البرنامجين ... ربما نناقشه في الغد بإذن الله تعالى.
ملاحظة مهمة آخيرة :
-------------------------
عندما تقوم بتشغيل كلا المثالين المرفقين قد يفاجئك وجود بعض الكرات الملتصقة بأحد اطراف الفورم ولا تستطيع الخروج منه ... وهو خطأ برمجي متعمد وجوده على أساس ان المبرمج لم يفطن اليه عند هذه المرحلة من تطوير البرنامج وعليه سنرجي مناقشته لخطوات متقدمة بإذن الله تعالى.
سأحاول الاسراع في وثيرة المناقشة بقدر استطاعتي كوني على سفر في بداية الاسبوع القادم بإذن الله... فنحاول التقدم سريعا قدر المستطاع ثم نكمل لاحقا إن شاء سبحانه.
تحياتي
السلام عليكم ورحمة الله و بركاتة
مواضيع برمجية تقنية جديدة
----------------------------------------------------------------------------------------------------------------------------------------------
• إستغلال خدمة الـ RSS في برامجنا ومواقعنا ! (VB.NET)
----------------------------------------------------------------------------------------------------------------------------------------------
• برنامج للبحث في الملفات ومحتواياتها (VB.NET)
----------------------------------------------------------------------------------------------------------------------------------------------
• فئة للتراسل بين برنامجين في جهاز واحد ! (VB.NET)
----------------------------------------------------------------------------------------------------------------------------------------------
مواضيع برمجية تقنية قديمة
----------------------------------------------------------------------------------------------------------------------------------------------
• إستغلال رسائل البالونات Balloons في الوينذوز أكس بي(VB.NET)
----------------------------------------------------------------------------------------------------------------------------------------------
• مقالة : لماذا يجب ان نعتني بشفرات برامجنا !؟- (VB6.0)
----------------------------------------------------------------------------------------------------------------------------------------------
• لمطوري البرامج و مواقع الويب - برنامج تركيب ألوان - (VB6.0)
----------------------------------------------------------------------------------------------------------------------------------------------
• برنامج : بسيط للتحكم بالنظام, عن طريق الريجستري - (VB6.0)
----------------------------------------------------------------------------------------------------------------------------------------------
• برنامج : لتقييد و منع تشغيل البرامج الاخرى - (VB6.0)
----------------------------------------------------------------------------------------------------------------------------------------------
• النوافذ المنبثقة و طريقة لإستغلالها في برامجنا -(VB.NET)
----------------------------------------------------------------------------------------------------------------------------------------------
• تقنية الإستدعاء الذاتي - (VB.NET , VB6.0)
----------------------------------------------------------------------------------------------------------------------------------------------
• مصفوفات الأدوات Control Arrays افكار وتلميحات ! - (VB.NET)
----------------------------------------------------------------------------------------------------------------------------------------------
• أفكار و تلميحات[ المعنى الحقيقي للـ True و False ] - أمثلة (VB.NETVB6.0)
----------------------------------------------------------------------------------------------------------------------------------------------
• دوال الـ APIs و مايقابلها في الدوت نت ! - (VB.NET)
----------------------------------------------------------------------------------------------------------------------------------------------