منتدى فيجوال بيسك لكل العرب | منتدى المبرمجين العرب
مقال- كيف نحل مشاكلنا بأنفسنا- - نسخة قابلة للطباعة

+- منتدى فيجوال بيسك لكل العرب | منتدى المبرمجين العرب (http://vb4arb.com/vb)
+-- قسم : الاقسام الاخرى (http://vb4arb.com/vb/forumdisplay.php?fid=74)
+--- قسم : قسم المقالات العام (http://vb4arb.com/vb/forumdisplay.php?fid=85)
+--- الموضوع : مقال- كيف نحل مشاكلنا بأنفسنا- (/showthread.php?tid=6720)



مقال- كيف نحل مشاكلنا بأنفسنا- - RaggiTech - 27-10-12

كاتب الموضوع : رغيد الطيب

اولاً السلام عليكم ورحمة الله وبركاته ....

وثانياً تواصلاً لمشاور السلسلة الذهبية في المواضيع العلمية سوف نناقش اليوم موضوع يهم المبتدئين بشكل اساسي وهو كيفية إستغلال معلوماتك البسيطة في تكوين فكرة عن حل المشكلة او الموضوع الذي تنوي برمجته ثم ننتقل بإذن من الله تعالى وتوفيق الى بعض الاختصارات و الافكار البرمجية البسيطة التي بالتأكيد سوف تستغلها في العديد من برامجك القادمة وذلك في الموضوع التالي من حلقات هذة السلسلة إن شاء الله تعالى ... واخص حديثي هذا بأخوتي حديثوا العهد بالبرمجة ...


الاسلوب الامثل في حل المسائل البرمجية :

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

واما الطريقة المناسبة في مواجهة المسائل المعقدة هي اولاً محاولة فهم الامر فهماً صحيحاً ثم الشروع في محاولة الاجابة بعدة طرق والبحث في جميع الادوات او الاوامر التي يمكن ان يكون لها علاقة بالموضوع وسوف اذكر بعد قليل مثال بسيط ثم نرى كيف يمكننا ان نجيب عليه باكثر من طريقة ثم انظر اي الطرق كنت ستتخذها في حال طلب منك برنامج كهذا ...

واما الطريقة الثانية فهي البحث في ملفات المساعدة عن امكانيات اللغة التي تستخدمها ( لغة البرمجة طبعاً وليست اللغة الطبيعية ) فأنت لا تعلم كم ستستفيد من هذا البحث فقد تبحث عن موضوع وتجد امثلة و دوال لم تكن تعلم بوجودها اصلاً بل انني اتذكر احياناً كثيرة كنت فيها ابحث عن موضوع معين وينتهي بي المطاف وقد نسيت الموضوع الذي كنت ابحث عنه لما اجده من الفوائد العضيمة والمواضيع الشيقة اثناء بحثي خاصة اذا كنت تتجول في مكتبة الـ MSDN ....

واما الخطوة الاخيرة فهي التي تلجأ فيها الى المساعدة من اشخاص تعرفهم ومن منتداك هذا بالطبع ... ولكن بشرط واحد هو ان تعي وتفهم الحل الذي ستجده وتحاول كتابته بنفسك بعد ان تفهمه جيداً ... (ولاتنسى ان تدعو بالخير لأخيك الذي اعانك في حل المسئلة) ...

وبعد ان تعرف حل هذة المشكلة حاول نقلها لمن تظن انهم سيستفيدون منها ....


مثال يستحق التأمل :

دعنا الان نرى كيف يمكن التعامل مع هذة المشكلة البسيطة .. لنفرض انك كنت تقوم بتصميم برنامج لتعليم الصغار الرياضيات وتريد ان تختبر الارقام الذي يدخلها الطفل ثم تساعده في معرفة العدد الفردي منها من العدد الزوجي .. !!

للقيام بمثل هذا البرنامج يجب عليك انت اولاً معرفة الرقم الفردي من الزوجي بطريقة برمجية فالنفرض انك قمت بقراءة الرقم الذي ادخله المستخدم في متغير عددي اسميته N بالطريقة التالية :

كود :
Dim N As Integer

N = InputBox("ادخل اي عدد صحيح")
والان كيف يمكن معرفة ان الرقم المخزن في المتغير N هو عدد فردي ام زوجي ؟؟؟

طبعاً اذا كنت ممن لهم باع طويل بالبرمجة اظنني اراك الان تبتسم من سذاجة السؤال - ولكن انتظر قليلاً دعنا ندرس الامر اولاً فبعد قليل سوف اطلب منك حل المسئلة باكثر من ثلاث طرق مختلفة - ..... و اما اذا كنت مبتدئاً او ممن اعتاد عدم بذل مجهود في البحث عن إجابة قد تجد ان هذا امر محير فعلاً حتى وان طلبت منك ايجاد اي حل وليس ثلاثة حلول مختلفة ...

حاول الان معي تتخيل الطرق التي يمكن ان تجيب بها على هذا السؤال البسيط قبل ان نبدء في خطوات الحال التالية ...

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


الحل الأول للمسئلة :

الامر الذي ينبغي ان تذهب اليه عقولنا جميعاً هو الرياضيات فما هي الطريقة التي نفرق فيها بين العدد الفردي والعدد الزوجي رياضياً ... طبعاً جميعنا يدرك ان الرقم الذي يقبل القسمة على اثنين بدون باقي - اي ان الباقي صفراً - فهو عدد زوجي واما الذي ينتج عنه باقي بعد قسمته على 2 فهو عدد فردي ... وهذا امر بديهي ... اذا ما يتوجب علينا التفكير فيه هو ما الامر او المعامل الذي يمكنني ان استخدمه في لغتنا الفيجوال بيسك للحصول على باقي القسمة .... اظن الجميع الان يعرف الاجابة طبعاً المعامل Mod فهو يستخدم للحصول على باقي القسمة .... واما اذا كنت لا تعرف هذا المعامل فاليك هذة الامثلة السريعة :

كود :
0 = 12 Mod 3
0 = 6 Mod 2
1 = 7 Mod 2
3 = 15 Mod 4
2 = 9 Mod 7
فالسطر الاول يدل على ان باقي قسمة 12 على 3 هو صفر لانه ينتج من القسمة 4 والباقي صفر.
واما السطر الثاني فهو ايضاً صفر لان ناتج قسمة 6 على اثنين هو ثلاثة والباقي صفر .
والثالث كان الناتج فيه هو واحد لان ناتج قسمة 7 على اثنين هو 3 والباقي واحد .
وكذلك الحال في السطر الرابع فان ناتج قسمة 15 على 4 هو 3 والباقي 3 ..
واما السطر الاخير فان ناتج قسمة 9 على 7 هو واحد والباقي 2 ...

والان من السطرين الثاني والثالث نرى بوضوح ان قسمة عدد زوجي ( 6 في السطر الثاني) على 2 يبقى صفراً ... بينما ناتج قسمة عدد فردي ( السبعة في السطر الثالث ) على اثنين فان الباقي هو واحد ...

وبالتالي فاننا يمكن ان نستغل المعامل Mod في البرنامج كالتالي :

كود :
Dim N As Integer

N = InputBox("ادخل اي عدد صحيح")

If N Mod 2 = 0 Then
MsgBox "عدد زوجي"
Else
MsgBox "عدد فردي"
End If
هذا الحل كان من المفترض ان يستخدمه الذين يعرفون المعامل Mod ....


الحال الثاني لهذة المسئلة :

لنفرض الان انك لم تكن على دراية بوجود هذا المعامل في الفيجوال بيسك فليس من الممكن ان تستخدمه مع عدم درايتك به اصلاً .... اذاً انت الان ملزم بالبحث عن بديل فليس من المعقول ايضاً ان تعيقك مثل هذة المشكلة في مثل هذا البرنامج الموجه للصغار !!

والان دعنا نفكر عن بديل طبعاً سيبقى مجال تفكيرنا رياضياً حيث ان الموضوع يتعلق بالرياضيات ( فليس من المعقول ان نبحث عن حل بين دوال الرسم مثلاً مثل Line و Circle ) ... لهذا سوف نستفيد من معاملي القسمة الذين يقدمهما لنا الفيجوال بيسك فكلنا يعلم معامل القسمة العادية وهو / .. فمثلاً :

كود :
4 = 12 / 3
3 = 6 / 2
3.5 = 7 / 2
3.75 = 15 / 4
2.25 = 9 / 4
الكل يعلم النواتج السابقة لانها عبارة عن قسمة عادية ... ولكننا سوف نستخدم الى جوار هذا المعامل معامل آخر يهمنا في حل هذة المسئلة وهو المعامل \ وهو معامل عكس معامل القسمة العادية / ... ويستخدم هذا المعامل في ايجاد ناتج القسمة بدون باقي اي اننا اذا قسمنا خمسة على 2 فان الناتج هنا سيكون 2 وليس كما اعتدنا اثنين ونصف و ذلك لان هذا المعامل يهمل الباقي ويكتفي بالناتج دون باقي ... ولمزيد من الامثلة انظر الى السطور التالية :

كود :
4 = 12 \ 3
3 = 6 \ 2
3 = 7 \ 2
2 = 9 \ 4
نرى بوضوح ان ناتج السطر الاول هو اربعة لان ناتج قسمة 12 على 3 هو 4 بدون باقي ...
وفي السطر الثاني ايضاً فأن الناتج من قسمة 6 على 2 هو 3 والباقي صفر ..
واما السطر الثالث ففيه 7 قسمة 2 هو 3.5 ولكن لان القسمة هنا هي بدون باقي فان الناتج هو 3 فقط ...
وكذلك السطر الرابع فأن ناتج قسمة 9 على 4 هو 2.25 ولكن الناتج هو بدون باقي اي انه 2 فقط ...

لهذا فننا نخرج باستنتاج ان القسمة باستخدام المعامل "/" هي قسمة عادية ..
و اما القسمة باستخدام المعامل "\" فهي قسمة بدون باقي ...

والان كيف يمكن ان نستغل هذين المعاملين في برنامجنا القديم ... الاجابة ستكون باعتماد ناتج القسمة من المعاملين على العدد الذي نريده فمثلاً اذا قمسنا عدد زوجي على 2باستخدم القسمة العادية فان الناتج سكون بدون باقي لأن العدد الزوجي يقبل القسمة على اثنين بدون باقي واما اذا قسمنا العدد الزوجي نفسه على اثنين ولكن باستخدام القسمة بدون باقي فسوف ينتج ايضاً نفس الناتج من القسمة العادية لانه لايوجد باقي اصلاً خذ مثلاً :

كود :
6 / 2 = 3 ' قسمة بباقي
6 \ 2 = 3 ' قسمة بدون باقي
لاحظ ان ناتج قسمة 6 على اثنين هو ثلاثة في الحالتين ... والان دعنا نجرب مع عدد فردي فمثلاً اذا قسمنا السبعة على 2 قسمة عادية فان الناتج هو 3.5 بالطبع ... ولكن اذا قسمنا نفس العدد - السبعة - على اثنين ولكن بدون باقي اي باستخدام المعامل "\" فان الناتج في هذة الحالة هو 3 فقط بدون باقي .. انظر المثال :

كود :
7 / 2 = 3.5 ' قسمة بباقي
7 \ 2 = 3 ' قسمة بدون باقي
من الواضح الان ان ناتج قسمة عدد زوجي على اثنين هو نفس الناتج في حال استخدمنا القسمة بباقي او القسمة بدون باقي ... واما اذا قسمنا عدد فردي على 2 فان الناتج يختلف فيما اذا كانت القسمة بباقي او بدون باقي ...

لهذا كله يمكننا الان استخدام هذة الميزة لجعل برنامجنا يبدو كالتالي :

كود :
Dim N As Integer

N = InputBox("ادخل اي عدد صحيح")

If (N \ 2) = (N / 2) Then
MsgBox "عدد زوجي"
Else
MsgBox "عدد فردي"
End If
لاحظ ان الشرط كان هو انه اذا تساوى حاصل القسمة بدون باقي مع حاصل القسمة بباقي فأن الرقم في هذة الحالة هو عدد زوجي واما اذا لم يتساوى الناتجان فان العدد هو عدد فردي ولا ريب ...

الحل السابق كان من المفترض ان يستخدموه من كانت لهم معرفة سابقة بمعاملات القسمة العادية والقسمة بدون باقي ..



الحل الثالث ( حل ثنائي ) :

لقد كان الحلان السابقان جميلان جدا و يفيان بالغرض تماماً ولكن ماذا اذا لم تكن تعرف بوجود المعاملات السابقة ( الـ Mod والقسمة بدون باقي \ ) في هذة الحالة لن تكون إجابتك مشابهه لاحدى الطريقتين السابقتين وسيكون من المفترض عليك ان تجيب على السؤال المطروح هنا وهو كيفية التفريق بين الاعداد الزوجية والفردية برمجياً ؟ ...

نعرف جميعاً ان الكمبيوتر الذي نجلس الان امامه يعمل على نظام واحد وهو النظام الثنائي ( صفر و واحد ) ... وهو امر نسلم به جميعاً وإن كنا نواجه صعوبة في فهم كيف تكون الصور التي نراها في الشاشة والاصوات التي نسمعها من السماعات هي جميعها ناتجة عن هذا النظام الثنائي ( 0010100100100) شيء غريب بالفعل .. ولكن مع تعمقك اكثر واكثر في الامور البرمجية خاصة المتعلقة منها بالبايت(Byte) والبت (Bit) سوف تبدء تشعر بتأقلم مع تقبل فكرة ان كل شيء يعمل بالفعل بهذا النظام العجيب !!

سوف نحاول هنا ان نستغل هذا النظام في الحل الذي نبحث عنه مستغليتن هنا المعاملات المنطقية وبالذات المعامل AND ... ولكن قبل هذا ينبغي ان نعرف ان لكل رقم نستخدمه في النظام العشري مايقابله في النظام الثنائي.

مايهمنا هو المعامل And وكيف يتعامل مع الارقام وهذا المعامل المنطقي يدخل ضمن عدة معاملات اخرى مثل OR و XOR و EQV وغيرها ... والجدول المنطقي المرتبط بالمعامل And هو كالتالي :

كود :
0 And 0 = 0
0 And 1 = 0
1 And 0 = 0
1 And 1 = 1
و نرى بوضوح ان الناتج دائماً هو صفر إلا في حالة واحدة هي ان يكون الرقمين الذي تتم مقارنتهما بـ And هما واحد ... وهذة المقارنة تتم على مستوى البت اي على المستوى الثنائي فمثلاً اذا قارنت الرقمين التالين بـ And :

كود :
12 And 6 = 4
الناتج هو 4 والسبب في ذلك يعود للنظام الثنائي ولكي نفهم لماذا كان الناتج هو 4 يجب اولاً ان نحظر الارقام 6 و 12 بالنظام الثنائي ...
فالـ 12 يمثل الرقم 1100 و اما الستة فرقمه هو 0110 وبالتالي فان مقارنتهما تتم بالشكل التالي :

كود :
1100 And 0110 = 0100
وذلك كما يلي
1100 = 12
0110 = 6
------------
0100 = 4
لاحظ اننا نقارن كل بت من بتات الرقم 12 مع البت الذي يماثله(تحته مباشرة) في الرقم 6 اعتماداً على المعامل And فاذا كان هناك 1 وتحته مباشرة 1 آخر فان الناتج هو 1 وغير ذلك فان الناتج هو 0 ويظهر بوضوح ان الـ 12 و 6 يشتركان في ان البت الثالث (من اليمين) هو واحد لهذا فأن الناتج سوف يكون اصفار ماعدا البت الثالث فهو واحد اي ان الرقم الناتج هو 0100 وبنظرة سريعة يمكن ان تعرف ان هذا الرقم الثنائي يمثل الرقم 4 في النظام العشري ...

والان لننتقل الى ما يهمنا في هذا كله لنفرض اننا قارنا اي رقم مع الرقم 1 والذي يمثل 0001 في النظام الثنائي فان الناتج في هذه الحالة إما صفر او واحد وهذا يعتمد على البت الاول في الرقم مثلاً اذا قارنا الرقم 7 مع الواحد :

كود :
0111 = 7
0001 = 1
---------- And
0001 = 1
ونرى بوضوح ان ناتج المقارنه كان واحد لان السبعة يحمل الرقم واحد في البت الاول له من اليمين ....

اما اذا قارنا الرقم 6 مع الواحد في الناتج في هذة الحالة هو صفر لان البت الاول من اليمين للسته هو صفر 0110 وذلك كما يلي :

كود :
0110 = 6
0001 = 1
---------- And
0000 = 0
وبهذا فان الناتج يكون صفر اذا كان الرقم يبدء من اليمن بصفر ويكون واحد اذا كان الرقم يبدء بواحد ... و بنظرة سريعة الى الجدول السابق سوف ترى بوضوح ان جميع الاعداد الزوجية تبدء بصفر والاعداد الفردية تبدء بواحد لهذا يمكن بسهولة استغلاله في برنامجنا بالشكل التالي :

كود :
Dim N As Integer

N = InputBox("ادخل اي عدد صحيح")

If (N And 1) = 0 Then
MsgBox "عدد زوجي"
Else
MsgBox "عدد فردي"
End If
لاحظ اننا استخدمنا معرفتنا السابقة بان مقارنة العدد الزوجي مع الرقم واحد ينتج عنها صفر ومقارنة العدد الفردي مع الواحد ينتج عنه واحد ...

هذا الحل لن يستخدمه إلا من كانت له دراية بالنظام الثنائي والمعاملات المنطقية ...


الحل النهائي :

لنفرض الان اني لم تكن لدي الخبرة الكافية في المعاملات السابقة جميعاً و ليس لدي غير الاشياء الاساسية في اللغة اي مثل المقارنات بـ IF و اوامر الدوران For و Until و While ... فهل يعني هذا اني لن اتمكن مع حل البرنامج وسنتهي بي المطاف بالاقلاع عن تصميم البرنامج بشكل كامل ؟ ....

الاجابة هنا هي بالطبع ... لا !!!

بل يمكن لك ان تقوم بعمل بسيط باستخدام الدوران وسوف تحصل في الاخير على ناتج مشابه و إن كانت النتيجة ستكون اقل كفائة وسرعة ... ولكنها ستكون بالتأكيد افضل من ان يتوقف البرنامج كلياً ...

وهذة الطريقة ببساطة هي ماذا لو عملنا دوران بسيط نقوم فيه في كل مرة بتنقيص الرقم الذي معنا بمقدار اثنين بحيث يتوقف الدوران عندما يصبح الرقم اقل من اثنين ... فان الناتج في هذة الحال سيكون دائماً اما واحد(في حالة الاعداد الفردية) او صفر ( في حالة الاعداد الزوجية ) ...

خذ مثلاً الرقم 5 اذا انقصنا منه 2 سوف يبقى 3 ولانه ليس اصغر من اثنين نقوم بالتنقيص مرة اخرى فيصبح لدينا الان 1 وهو رقم اصغر من اثنين الان نقارن اذا كان صفر فهو زوجي وان كان واحد كما في هذه الحالة فهو فردي ...

واذا قارنا برقم زوجي لنقل الـ 6 مثلاً فانه في المرة الاولى ننقص 2 فيبقى 4 ثم ننقص 2 فيبقى 2 ثم ننقص 2 فيبقى صفراً وهنا نتوقف عن التنقيص لان الرقم المتبقي اصغر من اثنين ( بقي صفراً ) وهذا يعني ان الرقم زوجي ...

يمكن ترجمة ماسبق بدوران بسيط ينقص 2 في كل مرة ويتوقف عندما يكون الرقم اصغر من 2 ثم نقارن بالشكل التالي :

كود :
Dim N As Integer

N = InputBox("ادخل اي عدد صحيح")

Do Until N < 2
N = N - 2
Loop

If N = 0 Then
MsgBox "عدد زوجي"
Else
MsgBox "عدد فردي"
End If
وبهذا نكون قد انهينا حل المسئلة بطرق مختلفة وطبعاً يمكن لكل شخص ان يبتكر طرق اخرى ولكني اكتفي هنا بهذا الحد ....


كلمة اخيرة لتوضيح المقصد من الموضوع ككل :

عشنا سوياً فيما سبق دقائق جميلة في محاولة حل مسئلة بسيطة وسعينا فيها الى التوضيح بان كل واحد منا قادر على ايجاد حلول وابتكارها من العدم وينبغي فقط عدم احتقار قدرات عقلولنا البشرية الذي منحنا اياها الله تعالى ... وعدم اعتمادك على الغير بقدر الامكان فقليل جداً ممن سيقرئ الموضوع سيجد انه لم يكن يعرف اياً من الحلول السابقة وآخرون سوف تجدهم يعرفون معظم المعاملات التي ذكرناها ولكن لم تخطر لهم الفكرة في استخدامها واما الباقين فسوف يشعرون بان كل ما سبق كان مضيعة للوقت وان هذة جميعها طرق بسيطة ويمكن ان تكون في رؤسهم الكثير من الطرق الافضل من هذة ... و طبعاً سيكون هذا بسبب انهم لم يركنوا عقولهم بسرعة في معظم المشاكل التي تواجههم في حياتهم البرمجية ...

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


هل توجد طريقة لعمل كذا و كذا ؟

الى الصيغة :

هل توجد طريقة افضل من هذة التي توصلت اليها لعمل كذا وكذا ؟


طبعاً لن تكون تملك الحلول لجميع المشاكل التي تواجهك وسوف تضطر في بعض المرات الى طلب المساعدة وسوف تجد في منتدانا من يسره كثيراً ان يمد يد العون لك ولكن كن متأكداً من انك قد استنفدت كل ما في جعبتك من طرق لحل المشكلة ....


والسلام عليكم ورحمة الله وبركاته ....