post

#19 مواضيع متقدمة عن Classes – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : MRE

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C –  مواضيع متقدمة حول الفئات Classes

مواضيع متقدمة حول الفئات Classes :

ما هو الـ Garbage Collector ، و ما هي دلالات كلمة  new التس نستخدمها عند الاشتقاق من الكلاس الرئيسي ، ما هي الـ Static ، و ما هو الـ Constructer الدالة التي تقوم بتنفيذ أسطر برمجية عند الاستنساخ من كلاس رئيسي ؟

هذا كله سنتعرف عليه في هذا الدرس بعد الفاصل إن شاء الله .

 

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

بسم الله الرحمن الرحيم ، في الدرس الماضي تحدثنا عن مدخل إلى البرمجة كائنية التوجه OOP و التي هي اختصار لـ Object Oriented Programming ، و تعلمنا كيفية بناء Class ، و التي  أصبحنا نعلم أنه يمكن ترجمة الـ Class إلى العربية بكلمة ” الفئة ” ، و تكلمنا كيف يمكنك بناء فئات أو Classes تحوي معلومات مشتركة ، و رأينا كيف يمكننا تعريف الـ Property  و رأينا كيف يمكننا استنساخ Object من هذا الـ Class

في هذا الدرس سنتكلم إن شاء الله عن أمور و تطبيقات إضافية للـ Classes و الـ Method نفسها ، و سنتكلم عن مفهوم الـ Object نفسه ، فما هو مفهوم الـ Object عندما نقوم باشتقاقه من الـ  Class ، و كيف يتم تخزينه و استدعائه ، و ماهي حلقة الوصل بينه و بين الذاكرة ، سيتم مناقشة هذا في القسم الأول من الدرس ، و سنراجع معاً ما هو دور الـ Dot Net Runtime في عملية إدارة الذاكرة .

 

تكلمنا في البداية أن الـ Dot Net له أقسام معينة و هو مسؤول عن تحويل أمور معينة و تعرفنا على Common Language Runtime و اختصارها CLR ، حيث سنأخذ فكرةً عنها ، و كيف ستساعدنا هذه الأمور في انتاج برامج قوية قادرة على إدارة الـ Data  ، و قادرة على إدارة عمل البرنامج بشكل افضل .

و سنتكلم أيضاً عن شيء يسمّى Constructer  ؛ و هو Method خاصة يتم استدعاؤها عندما يتم استنساخ Object من الـ Class ، و سنتكلم أيضاً عن معنى كلمة Static ، و التي رافقتنا من أول درس إلى هذا الدرس .

 

كالعادة نقوم بإنشاء مشروع جديد بلغة c# من النوع Console App

في الدرس الماضي تكلمنا عن المكان المناسب لتعريف الـ Class ، حيث قلنا أنه يجب أن يكون موازياً للـ Class الرئيسي ، في المنطقة الواقعة داخل الحافظة الرئيسية namespace  ؛ و التي تحتوي على مجموعة من الكلاسات .

 

في البداية هناك قضية أودُّ التنويه لها ، و هي إمكانية كتابة Class ضمن كلاس آخر ، أو ما يعرف بالـ Nested Class ، لكننا لن نتعمق في هذا الموضوع ، و سنتعلم الـ Class بمفهومه البسيط ، و الذي يمكن استخدامه في أي مكان .

إذا لكتابة Class جديد نذهب لأي منطقة موازية لأي كلاس آخر ، و يمكن كتابة الـ Class فوق الكلاس الرئيسي أو تحته ، فلا مشكلة في هذه النقطة ، إذا سننتقل إلى السطر رقم 15 ، و أقوم بكتابة نفس الـ Class الذي تعاملنا معه في الدرس الماضي .

لاحظوا أن هذا الـ Class المسمّى Car يحتوي على 4 خصائص ، كل منها لديه نوع خاص ، فالشركة المصنعة لديها النوع string و سنة التصنيع من النوع int .

اشتقاق Object من Class معين :

و لاشتقاق Object من هذا الـ Class تعرفنا أنه يمكننا كتابة اسم الـ Class الرئيسي أولاً ، ثم نقوم بتعريف متغير جديد myCar على سبيل المثال ، ثم وضع إشارة المساواة ، ثم new ثم اسم الكلاس مرة أخرى ، مع وضع اقواس () و الفاصلة المنقوطة ، حيث قمنا هكذا بجعل هذا الـ Object مستنسخاً من الـ Class الذي اسمه Car ؛ لاحظوا في هذه الجملة قمنا بتعريف متغير نستطيع أن نقول عنه أنه Object من النوع Car ، و لاحظوا أنه عندما قمت بوضع كلمة new فهناك عمليات موجودة خلف هذه الكلمة .

 

ما معنى كلمة new ؟

عندما تقوم بعملية استنساخ أو بناء مجسم جديد ، فأنت فعلياً قمت بربط هذا المجسم و معلوماته بمكان معين في الذاكرة ، Address  معين في الـ Memory ، و هذا المكان في البداية هو مكان فارغ عندما قمنا بكتابة Car myCar ، و لكن عندما قمنا بكتابة new Car قمت بإضافة المعلومات الأساسية التي يتكون منها هذا الكائن ، فعندنا في البداية كائن قمنا بتعريفه فارغاً و لكن عندما قمنا بعملية ربطه بكلمة new قام فعلياً بعملية انشاءه و تهيئته بالشكل الذي قمنا بكتابته في الـ Class ، و سنتعرف بعد قليل على ميزة خاصة بعملية الـ new Car الموجودة هنا .

يمكن أيضا تشبيه هذا الموضوع بالبالون ، حيث نفترض بالون معين يطير في الهواء ؛ هذا البالون له خيط ، هذا الخيط هو عبارة عن الـ myCar ، و هو اسم المتغير  ، أما المعلومات الموجودة به فهي موجودة على البالون ، فالمتغير يدل على المنطقة في الذاكرة التي تحتوي المعلومات الكاملة .

 

القضية التي نودُّ شرحها هنا أنه بإمكاننا كما تعرفنا في الدرس السابق ، بإمكاننا إضافة المعلومات الموجودة بداخله ، حيث نضيف معلومات اللون و الخصائص السابقة ،

يمكننا أيضاً إضافة Object آخر من نفس النوع Car و جعله يشير إلى نفس المكان الموجود في الذاكرة ، بمعنى … سنقوم بإضافة متغير جديد باسم myOtherCar ، و لاحظوا أنني في هذه الجملة قمت بتعريف Object لكنه فارغ ، لا يشير إلى مكان في الذاكرة ، أو ليس له محتويات يشير إليها ، فإن قلت له في السطر التالي ، myOtherCar = myCar ، ففعلياً في هذا السطر جعلت الـ Object يشير إلى المكان الذي يشير إليه myCar

نعود لمفهوم البالون لتوضيح الصورة أكثر .

لدينا البالون الذي اتفقنا سابقاً أن له خيطاً و اعتبرناه myCar ، بالجملة التي كتبناها قمنا بعمل خيط آخر ، و الذي هو myOtherCar و الخيطين يشيران إلى نفس البالون ، و لاحظوا أنني لم أقم بإسناد أي قيمة للمتغير ، بل جعلته مساوياً للـ Object السابق .

بمعنى أنني إذا قمت بعمل طباعة الجملة التالية ، فعندها سيقوم بطباعة Black ، على الرغم من أنني قمت بطباعة myOtherCar  و ليس myCar ، إذا فعليا في المتغير myOtherCar قمت بالإشارة إلى نفس البالون الذي يحمله الـ myCar و لتتأكدوا أكثر أن الاثنان مرتبطان بنفس المنطقة في الذاكرة ، سأقول له
;”myOtherCar .color = “Red
أنا فعلياً هنا قمت بتغيير اللون لـ myOtherCar و ليس myCar ، و سأقوم مباشرة بطباعة myCar.color
و للتوضيح باختصار : انا قمت بتعريف متغير myCar و قمت بوضع اللون الأسود له ، ثم قمت بتعريف Object آخر من النوع Car و قمت بإسناد موقع الـ myCar إلى myOtherCar ، و قمت بتغيير myOtherCar.color ،و سأقوم بطباعة الـ myCar الأولى ، عند التشغيل سيظهر Red المعدلة و ليس Black ، لأنه كما ذكرنا أنه عبارة عن مكان موجود في الذاكرة و هناك أكثر من خيط يشير له ، فأي تعديل على أحدهما يؤثر على الآخر ، فـ myCar و myOtherCar هما عبارة عن خيوط للمكان المحجوز في الذاكرة نفسه .

 

ماذا لو أردت أن أقطع هذا الخيط ، بمعنى أريد فصل myOtherCar عن المكان الذي قمت بتعريفه في الأعلى . بمعنى أن تنفصل myOtherCar عن myCar ، فأنا أريد جعلها تشير إلى مكان آخر في الذاكرة ، فعلياً في السطر 17 أنت تعرف خيطاً فقط لا يشير إلى شيء ، و لا يوجد معلومات به ، و لا نعرف كيف سيكون و ما هي محتوياته ، لذلك يوجد جملة myOtherCar = null هذه القيمة null فعلياً فارغة ، و بذلك في السطر 20 قلت له أن يقوم بفصل myOtherCar عن أي شيء آخر ، و اجعله فارغاً لا يحوي أي شيء ، و بذلك ، و بدءاً من هذا السطر لو قمت بعملية طباعة أي معلومة من معلومات  myOtherCar فسنلاحظ أنه سيظهر مشكلة و خطأ برمجي ، و هو : myOtherCar was null  أي أنه فارغ !! و لا أعرف ما هو الـ color الذي تريده ، و لذلك لا اعرف كيفية طباعة هذه الجملة ، و بالتالي يظهر الخطأ .

إذاُ .. فعليا في السطر 20 قمت بقطع الحبل الخاص بـ myOtherCar الذي كان يربطه بالبالون ؛ و عند هذا السطر ، فقط myCar هو الذي يحتوي الوصلة للبالون .

 

إذا قمت بعد ذلك بقص الخيط الثاني  و ذلك بجعل myCar  تساوي null أيضاً ، و لاحظوا أنني هنا بعد تعريف الـ  Object و اضافته أن هناك بالون معين و يحتوي على المعلومات القيمة التي أريدها . و بعد السطرين 20 و 21 قمت بقطع الشريطين ، و طار البالون في الهواء و المعلومات فعلياً ذهبت إلى الأعلى و انفجرت !!

إذاً القضية التي أريد أن اوضحها لكم أن في هذه الخطوات هي فعلياً عملية ربط Object معين بموقع ، و عندما تقوم بفصله ، أو عندما يصل إلى نهاية الـ Block الذ تم تعريفه داخله فإنه فعلياً يصبح null  أي فارغاً بغض النظر عن السطرين 20 و 21 .

 

هنا يأتي دور Dot Net Runtime فماذا يفعل ؟؟

هناك معلومات قيمة و معلومات كثيرة ، فنحن الآن نتكلم عن كلمتين أو خمس حروف و هكذا ، و لكن ماذا عن المشاريع الكبيرة ، عندنا كم هائل من الـ  Data و هذه البيانات إذا بقيت في الذاكرة و لم يتم التحكم بها ، فسيكون هناك مشاكل كبيرة نحن بغنى عنها ، و هنا يأتي دور الـ Dot Net Runtime  و الذي قلنا سابقاً أن اختصاره هو CLR سيقوم بالتالي :

ستذهب و تبحث في جميع الأكواد التي قمنا بكتابتها في هذا البرنامج ، و ستجد أن هناك بالون فارغ لا يوجد أي وصلة له ، و تقوم بالبحث إن كان هناك خيوط مرتبطة بهذا البالون أم لا ، و فعلياً لن تجد أي وصلة له ، و تقول : ” أنت يا بالون خارج  التغطية و لا أريدك ، سأقوم بتهيئة مكانك ، قم باستخدامه لمتغير آخر استفيد منه خلال البرنامج ”

إذا هذا الموضوع الذي يقوم بحذف و إدارة الذاكرة شيء يسمى Garbage Collector ، هو شيء خاص بـ CLR ، و يقوم بالبحث عن المناطق أو الـ Object  التي تم فصل الارتباط بها ، و يقوم بتهيئتها لاستخدامها بشيء آخر ، هذا المصطلح يجب أن تكونوا على اطلاع عليه ، و نحن عندما نقول أن لغة السي شارب هي لغة managed  يعني أنه يوجد شيء وسيط بينك و بين الآلة يقوم بإدارة أمور معينة أنت في غنى عنها ، و لكن لاحظوا أننا عندما نقول عن لغة السي و السي بلس بلس هي لغة unmanaged  ، فإنك عندما تقوم بالتعامل مع هذه اللغات فأنت مضطر لمتابعة المتغيرات و الذاكرة و مواضيع أخرى ، فأنت مجبر أن تقوم يدوياً بعمل تفرغ لكل Object  قمت بالانتهاء منه ، كي لا تحدث مشاكل في الذاكرة و حجم البرامج ، و مشاكل كبيرة أنت في غنىً عنها .

لماذا اخترنا السي شارب ؟؟
لأنها لغة managed ، حيث توفر لنا إمكانيات و أدوات نحن في غنىً عن الغوص في تفاصيلها ، فنحن نريد أن نركز على فكرة التطبيق الذي نريد عمله

 

الآن في السطر رقم 13 عند تعريف Object  جديد قمت باستخدام قوسي الدالة () ، الحقيقة هنا يتم استدعاء  Method داخل الكلاس حتى و إن لم تقم بكتابتها و تعريفها ، ألا و هي دالة الـ Constructer  ، و هي دالة يتم استدعاؤها عندما تقوم بعمل initialize  للـ Object ، بمعنى أنه عندما تقوم بعمل فتح و اغلاق قوس يتم تنفيذ شيء معين ، و فعلياً هنا لأننا لم نقم بكتابة شيء ، هو قام بمناداته ، و لكنه ضمنياً فارغ .

لكي نتعامل مع هذا الموضوع و نتعرف عليه أكثر ، سنقوم الآن بالتعرف على كيفية كتابة الـ constructer  .

شكلها كالتالي :

()public Car

{
}

و اسمها طبق الأصل مع اسم الكلاس ..
هذه الأسطر من 29 إلى 32 ضمنياً موجودة ، و لكنها فارغة ، طالما قمت بكتابتها ، فالأولوية لما قمت بكتابته ، سأقوم بعمل التالي :

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

أنا فعلياً قمت بتعريف الـ Object ، و لكن لم أقم بإسناد أي قيمة ، فقط قم بطباعة الـ Make  و عندما أقوم بتنفيذ التطبيق سيقوم بطباعة كلمة Nissan  ؛ من أين أتت هذه الكلمة !!!!

هذه الكلمة أتت من الـ Constructer    و هو كما قلت يتم استدعاؤه ضمنياً عندما تقوم بعملية استنساخ Object  جديد ،

هنا أيضاً مفهوم آخر ذكرناه في الMethods و سنعيده مرة أخرى  ، ألا و هو الـ Overload ، و هو إمكانية كتابة نفس الـ Method بنفس الاسم ، لكن مع اختلاف عدد الـ Parameter الموجود بداخلها ، لاحظوا أننا تكلمنا أنه داخل الـ Method بإمكانك إضافة  Parameter معينة  يتم اسنادها من خارج الدالة و يتم التعامل معها من داخل الدالة .

سنقوم بإضافة دالة جديدة و هي عبارة عن public Car و لكن سنقوم بإضافة Parameter  من خارج الدالة ، و تسمى هذه العملية Overload ، فسأقول له مثلاً string make  و string model  و int year و string color  ، و لاحظوا أن الكلمة make  تختلف تماما عن الكلمة Make لأننا تكلمنا أن لغة سي شارب هي لغة Case sensitive  فالحرف الصغير يختلف عن الكبير ، إذا في الـ overload هذه هنا سأقوم بعمل التالي ، حيث أنني في السطر رقم 13 ثمت بتعريف Object  جديد و القوسين فارغين ، فعليا قام باستدعاء الدالة التي قمنا بكتابتها ، و لكن أريد منه أن يقوم في عملية الـ Initialization أن أسند إليه قيماً و يقوم مباشرة بوضعها داخل كيان الـ Object  للتعامل معها لاحقاً .

فمثلاً سأقول له كالتالي :

الـ Make ذات الحرف الكبير اجعلها الـ make ذات الحرف الصغير ،  و التي أرسلتها من خارج الدالة

و كذلك بالنسبة للـ Model & Year & Color ، نعود للأعلى في السطر 13 ، بمجرد فتح القوس الأول يقوم بإظهار خيارات ، و بالضغط على الأسهم الظاهرة ، ستلاحظ أنه يوجد أكثر من Method يمكن استدعاؤها ، و هنا الأولى لا تحتاج أي Parameter و التي استخدمناها في السطر السابق ، و لكن هنا أريد استخدام الثانية ، حيث أريد اسناد الشركة و الموديل و السنة و اللون في نفس السطر ، فسأقول له  BMW مثلا , و كذلك الموديل و السنة و اللون ، إذا قمت بإنشاء Object جديد و قمت باستدعاء دالة البناء التي تحتوي على Parameter .

إذا عندما أقوم بعمل طباعة لنوع الشركة ، لن يقوم بإعادة اسناد Nissan بل سيقوم بطباعة BMW لأني قمت بإسنادها في بداية انشاء التطبيق  .

فهذا هو مفهوم الـ Constructer ، و هو مميز جداً   ، و استخدامه مفيد جداً في حالات كثيرة .

 

كلمة Static :

القسم الرابع من درسنا هو كلمة Static  ، لاحظوا أننا من أول تطبيق و حتى الآن ، كانت ترافقنا كلمة static الموجودة في الـ voidMain ، فقد تكلمنا عن int و string و void و تحدثنا عن الـ Class و كيف يمكننا استخدامه  و تحدثنا عن كلمةnew و تعلمنا كيف يمكن استخدامها  .

لطن ما معنى كلمة static ، و لماذا ترافقنا دائماً ، و لماذا في درس الدوال عندما قمنا بإضافة دالة ، وضعناها أيضاً من النوع Static كي نتمكن من استخدامها داخل الـ  voidMain ؟

الحقيقة أن كلمة static هي شيء يكون standard في كل الكلاس ، فكلمة Make و Model و Year و Color هي لا تتبع للكلاس ،هذه تتبع للـ Object المستنسخ من الكلاس ، فإن قمت بكتابة Car و بعدها نقطة ، فلن أجد الـ property السابقة ، لماذا ؟؟

لأن الـ Property الموجودة هنا تكون تابعة للـ Object الذي يأتي بعد عملية الاستنساخ ، فهنا عندما قمت باستنساخ Object جديد و وضعت myCar و النقطة ، حصلت على كل الـ Property الموجودة فيه ، و لدي أيضاً دوال ستكون متاحة هنا ، لماذا؟

لأنها ليست من النوع static

أما عندما أقوم بتعريف متغير جديد من النوع static ، لاحظوا أنني قمت بتعريف Property جديدة و لكنها من النوع static ، فهي تعني أن هذه الـ Property يمكن استدعاؤها من الكلاس نفسه ، بذكر اسم الكلاس قم ارفاقه مباشرة و ارفاق اسم الـ static ، إذاً عندما أكتب Car و هي اسم الكلاس بالحرف الكبير ، و اضع النقطة ، مباشرة أصبح لدي Property يمكن استخدامها على مستوى الـ Class .

 

دعونا الآن نتعامل مع الكلمة static بشكل أكبر .

لاحظوا هنا في داخل الكلاس ، وضعت أنه عند تعريف متغير جديد سيقوم بتغيير الـ Make ، مبدئياً سأقوم بعملها جملة ملاحظة ، و سأضع ، عندما يتم انشاء Object جديد ، قم بزيادة الـ Count برقم 1 ، فإذا قمت بطباعة Car.Count ، فعملية الزيادة لا تتم في الـ Constructer الذي يقوم بإعطاء parameter ، فأنا عندما قمت بإنشاء مجسم جديد ، لم أقم باستخدام هذا الـ Constructer ، بل قمت باستخدام الثاني ، و الذي يقوم بإعطاء وParameter ، ففعلياً هنا لا يوجد زيادة ، فبالتالي تظهر القيمة 0 ، لذلك سنقوم بعمل جملة الزيادة جملة ملاحظة و وضعها في الـ  Constructer الثاني ، و نجعل السيارة الثانية فارغة تستدعي الـ Constructer الأول ، و بذلك تكون السيارة الأولى و الثالثة تستدعي الـ Constructer الثاني ، أما الثالثة ، فتقوم باستدعاء الأول ، و عندها في كل Constructer يتم زيادة القيمة بواحد ، و لدي 3 سيارات ، فعندما أقوم بطباعة الـ Count يجب أن يظهر الرقم 3 .

 

موضوع الـ static  ليس حصرياً على الـ Property بل يمكن استخدامه كذلك في الـ Method .

لاحظواً أننا طول الوقت ، و من أول سطر لم نقم باستنساخ مجسم من الـ Console Class ، لم نقل له أعطني مجسم جديد و اريد استخدام هذه الدالة .

لاحظوا أن الـ Method ذات الاسم WriteLine تابعة مباشرة لاسم الكلاس ، و ليست تابعة لـ Object يتم اشتقاقه من الكلاس .

ايضاً مر معنا في درس التاريخ و الوقت أننا قمنا بالتعامل مع هذه الـ Property المسماة Now ، و هي لا تحتاج لعملي اشتقاق من الـ Data Type المسماة DateTime ، فقد حصلت عليها مباشرة من خلال النقطة ، لأن هذه الProperty عبارة عن static .

أيضاً لو لاحظتم في درس المصفوفات ، حيث تعاملنا مع دالة Reverse ، و هي ايضاً لا تحتاج لعملية اشتقاق من الكلاس Array .

إذا بالمثل سأقوم بإنشاء Method جديدة ، هذه الدالة من النوع static  أي أنها تابعة للكلاس بشكل كامل ، و سأقوم باستدعائها بالكلاس الرئيسي ، و حيث أن هذه الدالة تقوم بطباعة Count
و لو قمت بتنفيذ التطبيق سيقوم بطباعة عدد السيارات التي قمت بإنشائها من هذا الكلاس .

 

مصطلحات الدرس :

Garbage Collector :

Static :

Constructer :

Object Oriented Programming (OOP) :

Property   :

Object :

Class :

Dot Net Runtime :

Common Language Runtime (CLR) :

namespace   :

Nested Class :

null   :

managed   :

unmanaged  :

initialize   :

Initialization :

Parameter :

Reverse :

Count :

Public  :

الأسطر البرمجية التي قمنا بتنفيذها في هذا الدرس

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ObjectLifeTime
{
    class Program
    {
        static void Main(string[] args)
        {
            //Car myCar = new Car();
            Car myCar = new Car("BMW","Z",1990,"Yellow");
            Car myCar2 = new Car();
            Car myCar3 = new Car("BMW","Z",1990,"Yellow");
            
            Car.PrintCount();
            //myCar.Color = "Black";

            //Car myOtherCar;
            //myOtherCar = myCar;
            //myOtherCar.Color = "Red";
            //myOtherCar = null;
            //myCar = null;
            
            //Console.WriteLine("{0}", Car.Count);
            Console.ReadLine();
            
        }
    }
    class Car
    {
        public Car()
        {
            //Make = "Nissan";
            Count++;
        }
        public Car(string make,string model,int year,string color)
        {
            Make = make;
            Model = model;
            Year = year;
            Color = color;
            Count++;
        }

        public static void PrintCount()
        {
            Console.WriteLine("{0}", Count);
        }

        public static int Count { get; set; }
        public string Make { get; set; }
        public string Model { get; set; }
        public int Year { get; set; }
        public string Color { get; set; }
    }
}

post

البرمجة كائنية التوجه OOP – الجزء الأول

البرمجة كائنية التوجه OOP :

السلام عليكم ورحمة الله وبركاته، عندما تم تطوير البرمجة كائنية التوجه Object Oriented Programming المعروفة بالإختصار OOP أحدثت ثورة كبيرة في علم البرمجة، فلقد قامت بحل العديد من الإشكاليات والمعضلات التي كانت تؤرق المطورين أنفسهم، سنأخذكم في جولة سريعة نشرح فيها أهم المبادئ للبرمجة كائنية التوجه ومن ثم نتطرق إلى كيفية إستخدامها داخل لغة #C مباشرة، فمن أهم مبادئها :

التغليف (Encapsulation ):

وتعني ببساطة منع الوصول إلى المتغيرات الموجودة داخل الكلاس بشكلٍ مباشر، والسماح بتعديلها أو استرجاعها من خلال دوال مخصصة لذلك، وتبرز أهمية التغليف في قدرتنا على وضع قواعد معينة للتعامل مع المتغيرات، مثلا لنفرض ان هناك متغير لتخزين عمر الشخص، لو أتحنا الوصول المباشر لهذا المتغير سنفقد أي تحكم بالقيمة التي سيدخلها الشخص الذي يستخدم هذه الفئة Class (مبرمج آخر)، ولربما لن يكون لديه معرفة كافية عن طريقة عمل هذه الفئة Class فربما سيفترض أن إدخاله للعمر 0 لن يسبب اي مشاكل، لكن هذا افتراض خاطئ، ربما في أحد دوال هذه الكلاس هناك عملية قسمة لمتغير آخر على هذا العمر، و القسمة على صفر تؤدي إلى حدوث خطأ، والمشكلة أن مثل هذه الأخطاء عادةً لا تظهر مباشرة لـ مستخدم الفئة Class، إنما يظهر الخطأ فيما بعد وربما أثناء عمل البرنامج لدى المستخدم النهائي وهي ما تعرف بإسم Run-Time Error، لكن لو قمنا بالسماح باستخدام هذا المتغير من خلال دالة فنستطيع التحكم وتنبيه المطور مباشرة عند ادخاله للرقم 0 للعمر، أو تحويل الـ 0 الى 1 او غيرها .. ولأن مطور الفئة Class يعرف آلية عملها بالتفصيل فيجب أن يحمي المتغيرات الموجودة داخلها.

الوراثة (Inheritance):

الوراثة هي عملية إنشاء كلاس جديد بنائاً على كلاس سابق، أو بمعنى آخر اشتقاق، وتبرز أهمية الوراثة في تمكيننا من إعادة استخدام أكواد مكتوبة سابقاً، وتعديل بعضها أو إضافة خصائص جديدة بدل من إعادة كتابتها كل مرة، وتسمى الفئة Class التي نرث منها بالأب Parent والتي نُورِّثُ إليها بالابن Son . لنفهم أهمية الوراثة نأخذ المثال التالي، لنفرض أن هناك فئة Class تقوم باستخدامها لإظهار زر على الشاشة، وهذه الفئة كتبها مبرمج غيرك وهي تعمل بكفائة، وداخل تطبيقك تحتاج لإضافة خصائص إضافية لهذا الزر ، أو خصائص غير موجودة حالياً، لنقل مثلاً خاصية النقر المزدوج، في هذه الحالة لديك عدة خيارات قد تستطيع القيام بها:
1 – الدخول إلى تلك الكلاس والقيام بتعديله وقد تقوم بتعطيل شيء فيها دون قصد.
2 – القيام بنسخ الكود الخاص بهذه الكلاس ولصقها ثم إجراء التعديلات واستخدام هذه الكلاس الجديدة، لكن في هذه الحالة أي شيء نقوم بتغييره او تطويره، او اصلاح بعض الاخطاء على الكلاس الأصلية يجب أن نغيره على هذه ايضاً، وهذا فيه إضاعة كبيرة للوقت.
3 – الوراثة ! عمل كلاس جديدة ترث الكلاس القديمة بكامل خصائصها، ثم تقوم بإضافة الخاصية الجديدة فقط، وبهذه الطريقة نتأكد من استمرارية عمل الكلاس القديمة بلا اي مشاكل، واي تطويرات على الكلاس القديمة ستنعكس ضمنياً على هذه الكلاس.

تعدد الأشكال (Polymorphism):

ويعني أن الكائن يمكن أن يتخذ أكثر من شكل، والفكرة ببساطة أن مجموعة كائنات ترث خصائصها من أب واحد، لكن كل منهم يقوم بتعديل هذه الخصائص لـ تقوم بأمر مختلف.
ومن أهم استخداماته هو القدرة على تمرير هذه الكائنات المختلفة إلى نفس الدالة، أي لو كان لدينا الكائنات التالية: مربع، مستطيل و مثلث، ولدينا كلاس اسمه Area للتعامل مع المساحات وفيها خاصية طباعة مساحة الشكل على الشاشة، بدون مفهوم تعدد الأشكال سيكون علينا أن نقوم بعمل ثلاث دوال لطباعة مساحة كل شكل من هذه الاشكال، مثلا PrintSquareArea و PrintTriangleArea و PrintRectangleArea لكن بتطبيق مبدأ تعدد الأشكال بإمكاننا الاكتفاء بـ دالة واحدة مثلا PrintArea وتستطيع استقبال جميع الاشكال، لانهم بالنهاية مشتقين من كائن واحد، وهذا ممكن ببساطة لان جميع الكلاسات الخاصة بهذه الاشكال يجب ان ترث من كلاس أب يمتلك الخصائص التي نحتاجها وليكن اسمه Shape مثلاً ولديه دالة CalculateArea لحساب المساحة، ثم تقوم كل كلاس ترث منه بتعديل طريقة حساب المساحة بما يناسبها، لكن المهم انها تمتلك هذه الدالة ! فتستطيع دالة الطباعة استدعاء الدالة على أي شكل يمرر لها دون الاهتمام بـ نوعه، المهم أنه يرث من اب يمتلك هذه الدالة فبالتأكيد أن الكائن الابن يمتلكها ايضاً.

تطبيق البرمجة كائنية التوجه OOP بواسطة #C

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

1 – الفئات والكائنات (Classes and Objects)

الفئة هي عبارة عن نموذج أو وصف للكائن (blueprint)، أما الكائن فهو عبارة عن نسخة من هذه الفئة (instance)، على سبيل المثال، لو كان لدينا فئة Student فإننا نقوم بإنشاء كائنات من هذه الفئة كما يلي:

Student std = new Student();

فهنا لدينا Student هي النموذج العام، ثم قمنا بإنشاء كائن Std وهو مستقل بذاته، أي إذا قمنا بانشاء 10 كائنات، فإن التعديل على خصائص أحدهما لا يؤثر في الآخر، لكن التعديل على الفئة نفسها ينعكس على جميع الكائنات المنشئة منها. وهنا طريقة إنشاء الفئة Class في لغة #C :

Class Student
{
}

تتكون الفئة Class من التالي :
الخصائص والمتغيرات (properties): وهي عبارة عن البيانات التي يتم تخزينها داخل الفئة Class
الدوال (methods): ويمكن ان نقول انها تمثل سلوك هذه الكلاس أو بعبارة أبسط المهام والأمور التي تقوم بها هذه الكلاس، مثلا دالة Max لإيجاد الأكبر بين رقمين.
الأحداث (events): والأحداث عبارة عن قنوات للتواصل بين الفئات والكائنات المختلفة.

2 – الخصائص والمتغيرات Properties & Variables

يمكن أن نقوم بإضافة متغيرات Variables للفئات Classes في لغة ال #C كما يلي :

Class Student
{ 
       public int age;
}

لكن كما تلاحظ فقد قمنا بانتهاك أحد مبادئ البرمجة كائنية التوجه، والتي تم شرحها في بداية المقالة، وهو التغليف Encapsulation ، لذلك يجب أن نحول متغير العمر الى شيء محمي ويبقى داخل الفئة وهو ما يعرف بالإسم private  كما يلي :

Class Student
{ 
      private int age;
}

هنا يأتي دور الخصائص Properties والتي تقوم بتعديل أو طباعة قيمة هذا المتغير وتحافظ عليه من أي تعديل خارجي، حيث يمكننا تعريفها داخل لغة #C كالتالي :

Class Student
{
	private int _age;
	public int Age
	{
		get {return _age;}
		set 
		{
			if(value <= 0)
				_age = 1;
			else 
				_age = value;
		}
	}
}

وكما تلاحظ هنا، فإننا نملك تحكم كامل بالقيم المدخلة أو المرتجعة من هذا المتغير، أي أننا قمنا بتغليفه، وفي حال أننا رغبنا بتمكين لغة السي شارب من العمليات الداخلية لهذا المتغير يمكن تعريفها بصيغة مختصرة جداً كالتالي :

Class Student
{
	Public int Age { get; set; };
}

3 – الدوال Methods

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

public int Method(string param)
{
// code
}

ويمكن للفئة Class امتلاك أكثر من دالة تحمل نفس الاسم، لكن بشرط اختلاف عدد المتغيرات الممررة لها Parameters او اختلاف نوعها، وهو ما يعرف ب overloading ، كالتالي :

public int Method(string param) {};
public int Method(int param) {};

4 – دوال البناء Constructors

دالة البناء هي دالة يتم استدعائها بشكل تلقائي عند إنشاء الكائن باستخدام new ويجب ألا تقوم بإرجاع أي قيمة، وان يكون اسمها نفس اسم الفئة Class، كما يمكنك انشاء اكثر من دالة بناء من خلال ال overloading وعادة تستخدم دالة البناء لتهيئة الكلاس ووضع قيم أولية لـ متغيراتها قبل البدء باستخدامه.وهذا مثال عليها

public class SampleClass 
{
	public SampleClass()
	{
	}
	public SampleClass(int age)
	{
	}
}

كما تلاحظ، قمنا بإنشاء دالتي بناء، الاولى سيتم استدعائها عندما ننشئ كائن بهذا الشكل

SampleClass sc1 = new SampleClass();

والثانية عند تمرير قيمة مثل

SampleClass sc1 = new SampleClass(22);

5 – الكلاسات المتداخلة Nested Class

بإمكاننا تعريف فئة Class داخل فئة أخرى، وتسمى nested class اي فئة داخلية أو متداخلة

class Main
{
	Class Nested
	{
	}
}

كما نلاحظ هنا الكلاس Nested موجودة داخل الكلاس Main ونستطيع استخدامها بهذا الشكل

Main.Nested nested = new Main.Nested();

6 – سماحية الوصول (Access Modifiers)

نستطيع التحكم بإمكانية الوصول إلى المتغيرات والدوال داخل الكلاس عن طريق ال Access Modifiers ، وهناك خمس أنواع :
عام (public): نستطيع الوصول إلى هذا المتغير أو الدالة من اي مكان في المشروع، او حتى من خلال مشروع آخر يعتمد على هذا المشروع.
خاص (private): نستطيع الوصول إلى هذا المتغير أو الدالة من خلال نفس الكلاس فقط، وليس من أي مكان آخر.
محمي (protected): نستطيع الوصول إلى هذا المتغير أو الدالة من نفس الكلاس او من كلاس أخرى مشتقة منها (أي ترث منها كما شرحنا سابقاً).
داخلي (internal): نستطيع الوصول إلى المتغير أو الدالة من نفس المشروع فقط، أي أن المشاريع الأخرى التي تعتمد على هذا المشروع لا تستطيع الوصول اليه.
داخلي محمي (protected internal): نستطيع الوصول إلى هذا المتغير أو الدالة من نفس المشروع أو من كلاس موجودة في مشروع آخر تشتق (ترث) من هذه الكلاس.

تم كتابة الجزء الاول من المقالة بواسطة Ward Mahmoud وترجمتها إستناداً إلى مقالة أصلية هنا، نلقاكم في الجزء الثاني قريباً إن شاء الله.

post

#18 الفئات Classes – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : IOR

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C –  التعامل مع الفئات Classes

الفئات Classes :

ما هو ال Class وكيف يمكن تعريف خصائص Properties له وكيف يمكن إستنساخ مجسمات منه للتعامل مع مشروعنا، هذا ما ستتعرف عليه في هذا الدرس إن شاء الله

كيف يمكننا تعريف متغيرات تشترك في صفات معينة ، ما هو الكلاس ، و كيف يمكننا استنساخ مجسمات منه ؟

هذا ما سوف نتعرف عليه في هذا الدرس بعد الفاصل ان شاء الله

 

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

بسم الله الرحمن الرحيم

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

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

تعريف الـ Class

الفئات هو المصطلح الذي وجدته معمماً في الدروس ، و هو المعرف على موسوعة ويكيبيديا .

فالـ Classes هو بتعريفه هو عبارة عن نوع جديد يحتوي على ميزات غير موجودة في الأنواع التقليدية و العادية

رأينا أنه في الدروس سمعنا كثيراً بمصطلح الـ Class  ، مثل الـ Console Class و استطلعنا أن نستعمل دوال منه مثل Write , Read , Clear

و تعاملنا في الدروس السابقة مع الكلمة new و التي قلنا أننا سنحاول تفصيلها لاحقاً قدر الإمكان .

الـ Class هو أهم شيء موجود في البرمجة كائنية التوجه OOP ، و استخدام الكلاس في هذا النوع من البرمجة يحتاج إلى شروحات كثيرة و طويلة ، لكن في هذا الدرس سنحاول تلخيصها و التعريف بموجز عنها ، كي نتمكن من استخدامها في مشاريعنا ، و ذلك لأنها الأساس في المشاريع الكبيرة .

 

نبدأ بإنشاء مشروع جديد كما تعلمنا سابقاً و لا ننسى التأكد من اختيار Visual سي شارب و اختيار Console App

و من باب التأكيد تكلمنا أن الدالة void Main هي الدالة التي يبدأ بها التطبيق بتنفيذ اسطره البرمجية ، و سنتعلم في المستقبل كيف يمكن تغييرها ، فليس شرطاً أن تكون هي الدالة الأساسية ، فيمكننا استدعاء دالة أخرى .

 

كما تحدثنا سابقاً ، فالكلاس يحيط بنا في كل تطبيق ، فمن أول تطبيق قمنا بكتابته في هذا السلسلة كان الكلاس موجوداً

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

طبعا فكرة الكلاس أو فكرة أن تقوم بإضافة مميزات أو خصائص معينة للـ Object كالتالي :

 

لنفرض أن لديك معرضاُ للسيارات و طلب منك أن تقوم بعمل إحصاء لسيارات معينة

و لو طلبت منك عمل هذا بمعرفتك البرمجية السابقة ، فستقوم بتعريف 3 متغيرات ( المتغير الأول يشير إلى اسم السيارة ، و المتغير الثاني سيشير إلى موديل السيارة ، و المتغير الثالث سيشير إلى السنة التي صنعت السيارة فيها )

و لاحظو أن هذه الثلاث متغيرات ستكون خاصة بالسيارة الأولى ، و بالطبع في المعرض لا يوجد سيارة واحدة .

فإن أردت أن أقوم بإضافة سيارة أخرى ، فما الذي سأقوم بإضافته ؟؟
كالمرة السابقة ، سأقوم بإضافة 3 متغيرات جديدة بنفس وظائف المتغيرات السابقة للسيارة الأولى .

و ذات الشيء لإضافة سيارة ثالثة .

لاحظوا أنني أقوم بإضافة متغيرات كثيرة ، ففي كل مرة أقوم بإضافة 3 متغيرات جديدة ، و أنا كمبرمج أحفظهم فقد قلت له car1 فهي السيارة الأولى ، ثم الشيء الموجود بعد الرقم 1 هو تابع للسيارة الواحدة .

حسناً .. نفترض أنني قمت بعملي هذا و وضعت القيم و تم الأمر بشكل صحيح

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

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

إذا لنقوم بكتابة الكلاس سنقوم بحذف الأسطر السابقة و نبدأ بكتابة الكلاس الخاص بنا ، و نلاحظ أن الكلاس يكتب خارج الكلاس السابق ، فلا يمكن كتابة الكلاس داخل كلاس اخر !

 

الآن أريد تعريف كلاس جديد في منطقة موازية للكلاس الرئيسي ، و هو في داخل الـ namespace الذي قمت بتعريفه منذ البداية .

سأقوم بكتابة الكلاس و يمكنكم الحاق بي …

هنا سأعطيكم ميزة موجودة في برنامج Visual Studio  و هي ميزة جيدة جداً .لاحظوا أنني قمت بكتابة property و هي الخاصية الرئيسية الموجودة في هذا الكلاس ، يمكنني أن أقوم بعملية نسخها لكن من باب التسريع يمكن استخدام الـ Quick Action التي تحدثا عنها سابقاً ، فتكتب prop اختصاراً لـ property ثم تضغط زر Tab مرتين ، فتجد أنه قام مباشرة بعملية إضافة الشكل الكامل للكلاس . و قد تعرفنا عليها سابقاً في درس الـ For Loop حيث قمنا بكتابة for و مباشرة نضغط على Tab مرتين ليقوم بإضافة الشكل الكامل.

إذا نلاحظ هنا أنه من خلال الزل Tab  يمكنني أن أنتقل بين الأماكن الصفراء التي تحتاجها ، و طبعاً int ليس شرطاً أن يكون int فمثلا الخاصية الثانية في السيارة هي من النوع string و ليس int  ، فلذلك سأستبدل الـ int  بـ string ، و أقوم مباشرة بالضغط على Tab للانتقال إلى myProperty  لأقوم بتعديلها إلى Model  . و عند الانتهاء أقوم بعمل Enter  مرتين . إذاً من أجل السرعة بإمكانكم استعمال هذه الميزة ، و بالطبع في البداية ستأخذ وقتاً حتى تعتادوا عليها ، لكن لاحقاً ستكون شيئاً أساسياً .

 

إذا نتابع انشاء الكلاسات المطلوبة للسنة و اللون ، و هكذا قمت بتعريف الكلاس الذي اسمه car بهذه الخطوات ، و هذا الكلاس يحتوي على 4 خصائص ، و التي هي الشركة المصنعة و الموديل و السنة و اللون الخاص بها .

الآن إذا أردت استخدام هذا النوع ، و هذا النوع يشبه قطاعة الكعك التي تحدثنا عنها قبل قليل ، فأنا لن أذهب إلى القطاعة و آكلها ! و بهذا لا يمكنني استخدام النوع في تطبيقي مباشرة ، فأنا أحتاج إلى المجسم أو الشيء الذي ينتج من استخدام هذه الأداة ،

لذلك نعود للدالة الرئيسية void Main و سنقوم الآن بعملية استنساخ أو بناء مجسم جديد من النوع car كالتالي :

لاحظوا أنني سأقوم بكتابة Car بحرف كبير و أضع هنا متغير جديد ، و بهذا السطر قمت بتعريف متغير جديد من النوع Car و اسمه myCar و تحدثنا سابقاً عن تعريف المتغيرات ، فكنا نقوم بتعريف متغيرات من النوع int  أو  string  …

أما الآن أصبحنا قادرين على إنتاج أنواع فئات خاصة بنا ، تحتوي على ميزات و خصائص نحن نقوم بكتابتها

إذا بعد أن قمت بتعريف متغير ، و لكي أقوم بإنشائه و التي هي عملية Initialization لاحظوا أنني قمت باستخدام كلمة new ، فنحن نقوم بعملية إنشاء أو استنساخ هذا المجسم من شيء كبير ، ألا و هو الكلاس .

إذاً ..قمت بعملية تعريف و عملية Initialization مباشرة .

لكي أقوم باستخدام هذا المجسم الجديد ، لاحظوا أنني أستطيع الدخول إلى كل الخصائص التي كتبتها هنا من الـ Member Access أو من خاصية الـ IntelliSense ، فإن قمت الآن بكتابة اسم المتغير ثم أضفت نقطة ، فسأحصل على الخصائص التي قمت أنا بكتابتها ، الشركة المصنعة و الموديل و اللون و السنة . هذه الخصائص عليها icon مثل المفتاح ، لتشير إلى أن هذه الخاصية قمت أنا بإضافتها

إذا سأقوم بإدراج قيم إليها ، فقد قمت بتعريف متغير ، و أريد أن اعطيه قيمة للخصائص الموجودة ،

لذلك سأقوم بوضع الشركة المصنعة BMW على سبيل المثال و الموديل و السنة و اللون .

لاحظوا في الجمل الأربع السابقة قمت بإعطاء قيم للخصائص التي قمت بكتابتها .

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

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

إذا في هذه الأسطر الأربع تكلمنا أنه قمنا بعملية وضع قيم ، الآن كيف يمكنني قراءة هذه القيم ،

الأمر بديهي و تكلمنا عنه سابقاً .

إذا قمت بتنفيذ التطبيق فسيقوم بطباعة اسم الشركة المصنعة و موديل السيارة و السنة و اللون

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

إذا هنا قمت بتعريف الكلاس و إضافة خصائص و إسنادها في البرنامج

الآن بإمكانك طالما أنك أنشأت نوع جديد ، و كما تكلمنا سابقاً إذا كان لديك Method فبإمكانك أن ترسل لها parameter لاستخدامه داخل الدالة ، ففي الدروس السابقة أرسنا قيمة int  و بناء عليها حددنا ما الذي يريد المستخدم ،

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

لاحظوا الآن سنتعامل مع نوع جديد من أنواع البيانات ، و هو decimal ، و هو نوع يشبه الـ float إلا أنه يحتوي على خانات أكبر ، و هو أدق ، و يستخدم عادة في التعاملات المالية ، لأنه يحتوي خانات أكثر من float ، فحجم الـ float  في الذاكرة 32 بت ، أما الـ decimal فحجمه تقريباً 128 بت .

لاحظوا هذه الدالة تقوم بعملية ارجاع قيمة decimal  ، لكن هنا أريد أن أقوم بعملية إعطاء أو ادخال متغير من النوع Car و نسميه أي اسم ، و هذا المتغير سأقوم باستخدامه داخل الدالة ، فإنا هنا لا أقول له myCar بل أقول له سأعطيك متغيراً من النوع Car  ، و نسميه أي شيء ؛ هنا سأسميه car بحرف صغير .

إذاً هنا قمت بتعريف متغير جديد ، و سأقوم باستخدامه في داخل الدالة ، إذا سوف أذهب و أقول له كالتالي :

نفترض أنني مبدئياً سأقوم بتعريف متغير من النوع decimal باسم carValue و أسند إليه قيمة مثلاً 1000 دولار ، لاحظوا هنا كما تعرفنا سابقاً عندما يكون لديك فاصلة ، فيجب إضافة الحرف m لتمييزه ، عن النوع float  .

إذا قمت بتعريف متغير و بماشرة سأقوم بإرجاع القيمة .

إذا هذه الـ Method تقوم بأخذ نوع Car و بناء عليه نقوم بإرجاع قيمة معينة ، و لاحظوا إن قمت بعملية طباعة الدالة MarketValue و قمت بإسناد الـ myCar الذي قمت بتعريفه قبل قليل ، و قمت بتشغيل البرنامج ، فإنه سيقوم بإرجاع القيمة الافتراضية . أنا هنا لم أحدد أبداً ، أنا فقط أرسلت المتغير ، و لم أقم باستخدام أي Property خاصة به ، فبما أنني قادر على ارسال نوع الـ Car إلى هذه الـ Method  ، فأنا سأقوم بإضافة قيمة معينة .

نكتب جملة شرطية ، إذا كانت car.Year أقل من 1980 فسعرها سيكون مثلاً 200.5  و لا ننسى الحرف m

ثم نتابع بكتابة الجملة else فالسيارة سعرها 2000.50 مثلاً ، و أيضاً لا ننسى الحرف m .

نقوم بتشغيل البرنامج ، لاحظوا أنه قام بأخذ الـ object الذي قمت تعريفه ، و تعامل مع الـ year  التي قمت بإسنادها أيضاً ، مباشرة قام بتحديد القيمة الراجعة من الـ Property التي تم تعريفها في الكلاس في الكلاس و بناء عليه قام بتحديدها .

الشيء الذي أريد توضيحه هنا في هذه الدالة ، أنه ليس فقط بإمكانك أن تقوم بكتابة الـ Property في الكلاس ، يمكنك أيضاً كتابة Method كاملة تقوم بإرجاع قيم ، فهنا يمكنني أن أقول له كالتالي :

في داخل هذا الكلاس لا اعرف ما هي القيم ، أنا أقوم فقط بأخذ الـ  Propertyو لا أعرف ما هي قيمة الـ object التي أتت لاحقاً و أخذت قيماً متغيرة ، لذلك أقول له في الفئة الخاصة بي إذا كانت السنة للسيارة أقل من قيمة ما ، فقم بإرجاع هذا المتغير ، و لاحظوا أنني قمت بوضعها public ،  و سنتكلم لاحقاً عن الفرق بين public  و private .

إذا سأعود هنا و سأقوم بعمل Comment  لهذا السطر و أقول له كالتالي :

أريد أن تطبع myCar.MarketValue و هذه دالة ترجع قيمة decimal .

في السطر السابق قمت باستدعاء Method داخل الكلاس الرئيسي (program) ، و لكن هنا في الأسفل في السطر الثاني قمت بتعريف Method خاصة داخلياً داخل الكلاس ، و إذا قمت بتطبيق البرنامج فنلاحظ أنه يعطي نفس القيمة التي توقعناها .

 

إذا الكلاس بشكل موجز عبارة عن فئة جديدة نحن  نقوم بتعريفها ، و من ثم بعد انتاجها ، نحن نقوم باستنساخ مجسمات أو Object  منها و وضعها في الذاكرة ،  و أريد أن أوضح أن الكلاس له مكان معين في الذاكرة ، لكن عندما أقوم بإنشاء مجسم أو Object جديد فإنه يقوم بوضعهم في أماكن مختلفة في الذاكرة ، و كأن هذا الـ Car هو int  أو string ، إذا أنا أقوم بعملية بناء مجسمات من هذا الكلاس و أقوم بإعطائها قيماً و التعامل معها .

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

مصطلحات الدرس :

Properties / Property  :

Class :

OOP :

Object :

namespace :

Quick Action :

Initialization :

IntelliSense :

parameter :

float :

decimal :

public :

private :

program :

 

 

الأسطر البرمجية :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SimpleClasses
{
    class Program
    {
        static void Main(string[] args)
        {
            Car myCar = new Car();
            myCar.Make = "BMW";
            myCar.Model = "Sedan";
            myCar.Year = 2017;
            myCar.Color = "Black";

            Console.WriteLine("{0} {1} {2} {3}", 
                myCar.Make, 
                myCar.Model, 
                myCar.Year, 
                myCar.Color);

            //Console.WriteLine(MarketValue(myCar));
            Console.WriteLine(myCar.MarketValue());

            Console.ReadLine();
        }

        private static decimal MarketValue(Car car)
        {
            decimal carValue = 1000.0m;
            if (car.Year < 1980)
                carValue = 200.5m;
            else
                carValue = 2000.50m;

            return carValue;
        }

    }
    class Car
    {
        public string Make { get; set; }
        public string Model { get; set; }
        public int Year { get; set; }
        public string Color { get; set; }

        public decimal MarketValue()
        {
            decimal carValue = 1000.0m;
            if (Year < 1980)
                carValue = 200.5m;
            else
                carValue = 2000.50m;

            return carValue;
        }
    }
}

post

#17 التاريخ والوقت DateTime – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : NYU

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C –  التعامل مع التاريخ والوقت DateTime

كيفَ يُمْكِنُنا التَّعامُلُ مَع التاريخ والوقت

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

إذاً كما تعلمنا سابقاً نقوم بإنشاء مشروع جديد ، تكلمنا كثيراً أن المكان المخصص لكتابة الأكواد البرمجية هو بين قوسي الدالة void Main ، و تكلمنا أنه يجب أن نستخدم الدالة ReadLine في نهاية التطبيق لنتمكن من مشاهدة النتائج قبل إنتهاء التطبيق.

لتعريف متغير من النوع تاريخ نقوم بكتابة نوع المتغير DateTime  ثم نكتب مسافة ثم اسم المتغير و ينتهي بالفاصلة المنقوطة ، و هذا مشابه لطريقة تعريف المتغيرات من الأنواع الأخرى كالنوع int  و  string ، و نلاحظ هنا  أن الكلمة DateTime التي ظهرت باللون الأزرق الفاتح هي نوع المتغير ، و هو مشابه للأنواع الأخرى ، لكن له صيغة معينة ، لاحظو أنني قمت بتعريف المتغير ، و الآن أريد أن أسند  قيمة إليه . و أفضل طريقة للإضافة تاريخ للمتغير هي إضافة التاريخ الحالي ، لذلك سأقوم بكتابة إشارة الإسناد ، ثم أكتب DateTime.Now ثم الفاصلة المنقوطة ، نلاحظ أنه بمجرد أن قمنا بكتابة النقطة بعد اسم الكلاس DateTime قمت بإضافة الكلمة Now لأخذ التاريح الحالي ، و لو قمت بطباعة المتغير ، سيطبع البرنامج التاريخ و الوقت ، الصيغة التي قام بطباعتها هنا اعتمدها عندما قمت باستدعاء DateTime.Now قام باعتماد الصيغة الموجودة على الجهاز ، و الصيغة تختلف بين بلد و بلد آخر ، فمثلاً في الولايات المتحدة الأمريكية يبدأ بكتابة الشهر بدل اليوم .

و هنا صادف أن التاريخ الحالي 8.8 ، و في هذه الحالي قد لا ندري أهذا هو الشهر أو اليوم ، و هنا في الجهاز الذي استخدمه النظام يبدأ باليوم ثم الشهر و بعده السنة ، و نلاحظ أنه قام بطباعة الساعة بنظام 24 ساعة ، و قد يختلف هذا أيضاً من بلد إلى آخر ، فهناك بلدان تتعامل بنظام 12 ساعة و يقوم بإضافة PM  و  AM  ، فهذا يعتمد على طبيعة النظام الذي تستخدمه على جهازك .

الـ Methods المستخدمة في التعامل مع التاريخ و الوقت :

الآن .. هناك Methods في هذا الكلاس يمكن أستخدمها لطباعة شكل معين من التاريخ ، فنلاحظ أنه قام بطباعة التاريخ مع الوقت ، ماذا لو أردت طباعة الوقت فقط . أو طباعة التاريخ فقط . و سنتعرف على هذه الدوال واحدة تلو الأخرى .

في السطر الذي قمنا بطباعة المتغير به ، و بمجرد وضع النقطة التي أسميناها الـ Member Access ستظهر الدوال التي يمكننا استخدامها  أو العديد من القيم التي يمكن أن تحصل عليها .

فلو قمت بوضع ToShortDateString و قمت بطباعة الناتج ، فلاحظو أنه سيعطيني التاريخ فقط و بالصيغة المختصرة ، و التي هي عبارة عن أرقام ، فنلاحظ أنه يظهر 8.8.2017 .

لكن هناك إمكانية للحصول على نسخة غير مختصرة و ذلك باستعمال الدالة ToLongDateString و قمت بطباعة المتغير ، فسيظهر التاريخ بشكل كامل و سيكتب اسم الشهر و اسم اليوم كذلك ، و يسمى هذا التاريخ الطويل ، لأنه لم يكتفِ بوضع اليوم ثم نقطة ثم الشهر ثم نقطة ثم السنة ، بل قام بوضعها بالصيغة الطويلة

و بالمثل هناك دالة يمكن استخدامها ، ألا و هي ToShortTimeString ، و هي تقوم بطباعة الساعة و الدقائق فقط بالشكل 19:13

و بالمثل إذا قمت بكتابة ToLongTimeString فسيطبع الساعة ، و الدقيقة ، و الثانية كذلك .

 

ليس هذا فحسب ، بل لديك إمكانيات كذلك بالتعامل مع إضافة ساعات أو أيام مع هذا التاريخ ، فإن قمت بإضافة Add  بعد النقطة فسيظهر لدينا AddDays و AddHours و AddMinutes و  AddSeconds  و AddYears ، فهناك عدة دوال لإضافة الشيء الذي تريده .

فمثلاً أريد إضافة 3 أيام للتاريخ الحالي ، ففي الأعلى قمنا بأخذ الوقت الحالي عند كتابة الكلمة Now . و مباشرة سأقوم بطباعة الوقت الحالي و لكن سأقوم بإضافة 3 أيام إليه ، و ذلك باستعمال الدالة AddDays(3)
و بتنفيذ التطبيق سيقوم بطباعة التاريخ بعد زيادة 3 أيام ، فتاريخ اليوم هو 8.8.2017  لكنه قام بطباعة 11.8.2017

و ذلك لأنني استخدمت الدالة ()AddDays  عندها قام بإضافة الرقم الموجود بين قوسي الدالة إلى التاريخ الحالي .

 

نلاحظ الآن أن المتغير من النوع DateTime ، و الـ Method التي استعملناها إذا قمنا بوضع الماوس عليها سنلاحظ أنها تقوم بأخذ Value و ترجع قيمة تاريخ و ليس string ، و بما أنه قام بإرجاع قيمة تاريخ ، فبإمكاني أن أطلب مرة أخرى تحويله إلى تاريخ قصير ، و ذلك بوضع النقطة مرة أخرى و استعمال الدالة ToShortDateString ، و بتشغيل التطبيق نلاحظ أنه قام بزيادة 3 أيام كما طلبنا سابقاً ، و قام بطباعة التاريخ بالصيغة المختصرة .

و هنا أود أن أوضع قضية مهمة ، و هي أنه طالما أن النوع DateTime و تقوم بعمل Method تقوم بتحويله أيضاً إلى DateTime ،فبإمكانك أن تقوم بعمل سلسلة لا نهائية من الـ Methods .

 

أي بعد أن تقوم بعمل زيادة 3 أيام ، قم بعمل زيادة 3 ساعات ، و قم أيضاً بعمل زيادة شهرين ، و هكذا … ، فهذه السلسل يمكن أن تكون لا نهائية ، و هذه الفكرة ليست حصرية في الـ DateTime ، فكل المتغيرات أو كل شيء يقوم بإعادة شيء من نفس النوع ، فبإمكانك أن تعيد استخدام الـ Method الموجودة في ذات النوع

اذاً بالمثل يمكنني أن أطلب هنا أيضاً طباعة الوقت الطويل .

و بالمثل أيضاً يمكنني إضافة قيم سالبة ، بمعنى أنه سيقوم بطرح القيم السالبة من التاريخ الحالي . حسناً .. سأقوم بطلب خصم 3 أيام ، و عندها سيقوم بطباعة 5.8.2017   . و عند طلب الخصم نختار الدالة AddDays و نضع بين قوسيها قيمة سالبة مثل (3-) .

 

أيضا يمكنك أن تتعامل مع جزء ، أو أن تقوم بطباعة جزء واحد من التاريخ فقط ، بمعنى أنه إن قمت بوضع Month بعد النقطة فنلاحظ أن القيمة الراجعة هي integer ،بمعنى أنه سيقوم بطباعة رقم الشهر ، و بتشغيل التطبيق يظهر الرقم 8 و هو رقم الشهر الحالي .

هذا إن قمنا بتعريف متغير و اسناد قيمة التاريخ الحالي إليه . لكن ماذا لو قمنا بوضع تاري نأخذه من المستخدم أو استخدام تاريخ خاص بنا ؟

استخدام تاريخ خاص ، أو استعمال تاريخ يدخله المستخدم :

لعمل ذلك نقوم بعمل التالي ،

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

هنا سأقوم بإضافة السنة في البداية ، ثم الشهر ، ثم اليوم . لاحظو أنني قمت بتعريف المتغير من النوع DateTime و قمت بإسناد قيمة قمت أنا بإدخالها و لم استخدم التاريخ الحالي .

فإن قمت بطباعة الناتج نلاحظ أنه قام بتحويل الأرقام التي كتبتها إلى صيغة كاملة ، فقام بكتابة اليوم و الشهر و السنة ، و بطبيعة الحال لأنني لم أقم بكتابة الوقت قام بطباعته 00:00:00 .

أيضاً بإمكانك أن تقوم بأخذ قيمة من المستخدم و محاولة تحويلها إلى قيمة تحاكي التاريخ و الوقت ، فكما في السابق قمنا بتعريف المتغير و وضع إشارة الاسناد ، ثم إضافة اسم الكلاس ، ثم وضع نقطة الـ Member Access ، و نستخدم الدالة Parse التي تقوم بأخذ قيمة نص و تحويلها إلى Date

الآن سأقوم بوضع قيم التاريخ بين قوسي الدالة ، نلاحظ أن القيم – الموجودة بين الأرقام يمكن أن تكون مختلفة ، هنا في هذه الـ Method ليقرب القيمة إلى أقرب صيغة تاريخ ممكن أن تقوم معرفة ، و إذا قمت بوضع قيم غير مناسبة قد تحدث مشكلة . نقوم الآن بتشغيل التطبيق ، نلاحظ أنه رغم أنني قمت بكتابة خطوط بين الأرقام ، لكنه قام بأخذ الرقم الأول و حوله إلى تاريخ ، و أخذ النص الثاني و الثالث كذلك ، و قام بتحويل الخطوط إلى نقاط . و لو قمنا بتغيير الخطوط – إلى / سيقوم بذات العمل ، و سيحولها إلى نقاط .

حساب الفترة الزمنية بين تاريخين :

ماذا لو أردنا حساب الفترة الزمنية بين تاريخين ، بمعنى أريد حساب الوقت الذي عشته من تاريخ ولادتي إلى الآن.

بمجرد أن نقول أننا  نريد التعامل مع فترة زمنية ، فهناك متغير جديد اسمه TimeSpan ، و هو يقوم بأخذ تاريخين و يحسب الفرق بينهما .

الآن سأطلب منع حساب الفرق بين الوقت الحالي عن طريق DateTime.Now و إضافة إشارة – لطرح قيمة المتغير myBirthday .

إذا قمت بطباعة المتغير myAge  ستظهر لدينا أرقام ، ما هي طبيعة هذه الأرقام ؟ و كيف نقوم بقراءتها ؟

الـ TimeSpan يقوم بإرجاع قيم تبدأ بالأيام ، ثم بالساعات ، ثم بالدقائق ثم بالثواني ، ثم أجزاء الثواني ، فالرقم الأول من الجهة اليسرى هو عدد الأيام ، و الرقم الثاني 19 هو عدد الساعات ، و الرقم الثالث 26 هو الدقائق ، و الرقم 32 هو الثواني ، و الرقم الأخير في الجهة اليمنى هو أجزاء الثانية . و نلاحظ أنه قام بحساب الساعات من 00:00:00 لأننا لم نحدد الساعة بدقة كما قمنا بالتحديد بالنسبة للتاريخ .

نلاحظ أن المتغير TimeSpan ليس من النوع DateTime ، لذلك إذا قمت بإضافة النقطة سأحصل على عدد من الدوال الخاصة به ، و من هذه الأمور هو الـ  TotalDays ، و باختياره و تنفيذ البرنامج سيظهر عدد الأيام الكلي .

تطبيق يقوم بحساب الوقت بين تاريخين :

الآن بما أننا تعلمنا كيف نقوم بأخذ فترة زمنية و نقوم بطباعة قيم معينة ، دعونا نقوم بتحويل ما تعلمناه إلى تطبيق يمكننا استخدامه ، لذلك سنقوم بعمل تطبيق يسأل المستخدم عن تاريخ ولادته ، و نحاول تجزئة التاريخ بحيث أن البرنامج سيخبر المستخدم كم عدد مجمل الأيام و الساعات و الدقائق التي مرت منذ ولادته .

 

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

الآن سأقوم بتعريف متغير من النوع  DateTime ثم إشارة الاسناد ، ثم سأستدعي الكلاس الأصلية و أقوم باستخدام الدالة Parse  لتقوم بمعالجة النص و تحويله إلى تاريخ ، و النص هو Console.ReadLine من المستخدم .
إذاً هنا قمت بطلب نص من المتسخدم ، و هذه القيمة حتماً ستكون string ، و هو في منطقة الـ Parse ، و الذي بدوره سيحاول تحويل القيمة إلى DateTime و التاريخ الذي حاول تحويله  سيقوم بإسناده إلى المتغير .

الآن سنقوم بتعريف متغير من النوع TimeSpan و سأكتب هنا الوقت الحالي و أطرح منه الوقت الذي أدخله المستخدم ، و يمكنني هنا أن أستخدم إشارة الطرح ، لكنني سأستخدم دالة جديدة ، و هي Subtract ، و هي تخبره أن يقوم بعملية طرح للتاريخ الثاني الذي سنضعه بين قوسي الدالة الجديدة ، وهو التاريخ الذي أدخله المستخدم .

و أخيراً سأقوم بطلب طباعة الوقت الكلي للوحدات الأيام ، الساعات ، و الدقائق .

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

الآن نقوم بتشغيل التطبيق و ادخال تاريخ الميلاد ، سيقوم البرنامج حينها بطباعة اجمالي الأيام و الساعات و الدقائق .

 

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

مصطلحات الدرس :

DateTime :

DateTime.Now :

Member Access :

Parse :

TimeSpan :

Hint :

Subtract :

تجد هنا الأسطر التي قمت بكتابتها خلال الدرس.

 

 

 

post

#16 التعامل مع النصوص Strings – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : KUT

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C –  التعامل مع النصوص Strings

كيفَ يُمْكِنُنا التَّعامُلُ مَع النُّصوصِ المُخْتَلِفة ، و كَيْفَ يُمْكِنُنا اقْتِباسُ جُزْءٍ مُعَيَّنٍ مِنْ نَصٍّ كامِلٍ ، و كيف يمكننا استبدال أحرف معينة في نص كامل ، و كيف يمكننا أيضاً معرفة عدد خانات الحروف في نص ما ؛ هذا ما سوف نعرفه في هذا الدرس بعد الفاصل إن شاء الله .

 

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

بسم الله الرحمن الرحيم

التعامل مع النصوص هو أمر أساسي في التطبيقات المستخدمة ، ففي كل مشروع يجب أن يكون هناك نصوص متداولة

و من خلالها يتم استخدامها في أمور معينة ، و عمل تعديلات عليها ، لذلك يجب أن يكون عندك معرفة بالأدوات و الـ Methods التي بإمكانك استخدامها للحصول على نص أو جزء من نص  ، و تعديل نص معين يمكنك استخدامه في البرنامد الخاص بك

 

نبدأ بإنشاء مشروع جديد بلغة #C من النوع Console App

في البداية سأكتب الأسطر التالية لأننا سنستخدمها بشكل أساسي

نلاحظ الآن أننا إذا قمنا بتشغيل البرنامج فلن يظهر شيء

حسناً ، إذا توجب علينا في حالة ما استخدام علامتي التنصيص في نص معين ، فإذا حاولت إضافة علامتي تنصيص فسيحدث مشكلة ، لماذا ؟

لأن الـ Compiler أخذ الجزء الأول و اعتبر العلامة الثانية في المنتصف هي نهاية النص الأول .

لذلك إذا أردت استخدامها فبإمكانك وضع Back Slash قبلها لكي تخبر الـ Compiler  أن هذه العلامة هي فعلاً رمز  سيستخدم داخل النص

نوضح الفرق بين الـ Slash و الـ Back Slash حتى لا يحصل التباس ، فالـ Slash  هي التي تكتب بالشكل (  /  )

أما الـ Back Slash فتكتب (  \  )

و نلاحظ أن الـ Slash /    لا تعمل عمل الـ Back Slash

الآن بعد إضافة الـ Back Slash و تشغيل التطبيق سنلاحظ أن البرنامج قام بطباعة علامتي التنصيص بشكل صحيح

و هذا هو أول استخدام للـ Back Slash

نقوم بتحويل الجملة السابقة إلى جملة ملاحظة .

 

الآن في هذه الجملة الجديدة أحتاج إلى النزول إلى سطر جديد … فإنني إن قمت بطباعتها فستظهر ف نفس السطر

لذلك إن أردنا النزول لسطر جديد فسنكتب   (Back Slash + n)      ، و عندها سيفهم الـ Compiler أنه عند هذه النقطة قم بالنزول إلى سطر جديد . و بتنفيذ البرنامج نرى أن المطلوب قد حدث فعلاً

 

نقوم بتحويل الجملة السابقة أيضاً إلى جملة ملاحظة .

 

الآن ماذا لو أردنا طباعة الـ Back Slash  في النص المراد طباعته ، فبوضعها مباشرة ضمن التطبيق ستظهر مشكلة في تطبيقنا ، و السبب أن الـ Compiler افترض أن هذا الـ Back Slash سيأتي بعده Character  معين لكي يقوم بعملية معينة ، لكن هنا في مثالنا الـCharacter التالي للـ Back Slash  هو مسافة فارغة

لذلك إن أردت استخدام الـ Back Slash قم بوضع Back Slash قبلها مباشرةً ، بالتالي فإن الـ Back Slash  الذي سيأتي ثانياً هو الذي سيتم طباعته ، أما المكتوب قبله مباشرة سيخبر الـ Compiler أن التالي هو عبارة عن نص وليس Back Slash escape Character

نلاحظ أننا إذا قمنا بتشغيل التطبيق سيقوم بطباعة المطلوب بشكل صحيح و دون مشاكل أو أخطاء

حسناً .. ماذا لو كان لدينا أكثر من Back Slash  في ذات النص ، فهل سأذهب إلى كل واحد منها و أضع قبله Back Slash إضافي ؟؟

بالطبع لا ، فبإمكانك الذهاب إلى ما قبل علامة التنصيص التي في بداية النص و إضافة الرمز @ ، و التي بدورها ستخبر الـ Compiler أن يعتبر كل رموز Back Slash الموجودة ضمن النص عبارة عن Character  عادي و ليس Back Slash Escape Character، و بالتالي تخبره أن يقوم بطباعة هذا الرمز

 

تكلمنا سابقاً عن :

;string myString = string.Format(“{0} = {1}” ,”First” , “Second” )

و كما تحدثنا ، إن أردت وضع قيمة معينة داخل نص فلا داعي لكتابة الجملة ثم أقوم بإنهائها ثم أضع القيمة ثم أعود لمتابعة الجملة ، بدلاً من ذلك سأقوم بوضع index  ، بحيث يقوم الصفر بأخذ أول خانة مباشرةً بعد الـ string

و الرقم 1 يقوم بأخذ الخانة رقم 2 ، و يتم فصل الخانات بفاصلة

بتشغيل التطبيق نلاحظ أنه أخذ أول قيمة بعد الـ string عند الرقم 0 ، ثم قام بأخذ القيم الثانية عند الرقم 1

و ليس من الضروري أن نقوم باستخدام 0 ثم 1 ثم 2 …. ، فبإمكاننا أخذ القيمة الأولى مرتين ، أو نقوم بطباعة القيمة الثانية ثم القيمة الأولى .

 

حسناً.. هذا المكان الموحود في الكود السابق {…}  له Format خاصة به ، من الممكن أن نقوم باستخدامها للتأثير على القيمة الموجودة هنا بطريقة معينة

نقوم بطباعة جملة جديدة و وضعنا بعد الرقم الحرف C فسيقوم بتحويل القيمة إلى الموجودة إلى قيمة عملة ، حيث سيضع قبلها علامة العملة الخاصة ببلد معين ، فإن قمت تستخدم الدولار فسيقوم بوضع العلامة $ ، و تتغير بحسب العملة المتبعة في بلدك ، لكن في جهازي أنا استخدم الليرة التركية ، فسيظهر علامة استفهام لأن رمز الليرة التركية غير معرف

 

الآن إذا كان لدينا رقم طويل بحيث يكون صعب القراءة ، كما تعلمنا في دراستنا فإن الرقم عادة يقسم بحيث يوجد فاصلة بين كل 3 خانات ، فإذا أردت أن يكون الرقم مفصولاً كذلك فيمكن أن نستخدم الحرف N ، عندها سيقوم بوضع الفواصل و النقط و عند التنفيذ نلاحظ أنه أضاف النقط بحيث يقسم كل 3 منازل ، و يضيف الفاصلة العشرية حتى لو لم تكن موجودة ، و يضيف الصفر إلى يمينها

 

ماذا لو أردنا استخدام النسبة المئوية percentage ، مثلا 20% , 30%

فيمكنك استخراجها باستخدام الحرف P و سنكتب في البداية كلمة percentage أو أي نص آخر

عندها سيقوم بتحويل الرقم  251. إلى 25.10%

 

ماذا لو أردت استخدام Format خاص بي

حيث سأقوم بإضافة الفواصل و النقاط و الشرطات بحسب رغبتي ، فيمكن عمل ذلك كما يلي،

ليكن لدي الرقم 1234567890 و اريد أن أحوله إلى رقم هاتف

لاحظو بعد النقطتين يمكننا طباعة الرقم كما نريد

فنضيف (###) ###-####)

كل إشارة من الإشارات السابقة هي عبارة عن خانة ، و بذلك قمنا بتنسيق الرقم كما أردنا ، و بتطبيق البرنامج سيطبع الرقم (123) 456-7890

و هذا يعد Format خاص

 

ماذا لو أردت التعامل مع نص حقيقي

لدي جملة و أريد أن آخذ أجزاء منها أو أقوم بعمليات عليها فماذا أفعل

سنعرف المتغير myString من النوع string  ثم أقول له

myString القديم سيصبح muString نفسه و اضع نقطة ، و بمجرد وضع النقطة ، و لأنه متغير نصي سيظهر لديك جميع الـ Methods الخاصة بـ string ، و بالطبع لكل نوع من أنواع البيانات Methods  خاصة به

يمكنني هنا أن أقوم بعملية قص عن طريق اختيار الدالة Substring التي اخترناها بعد النقطة

نفتح قوسي الدالة و نكتب 5 على سبيل المثال ، عندها سيقوم بقص أول 5 خانات و يطبع الباقي

يمكننا عن طريق إضافة فاصلة و رقم آخر إلى المثال السابق ، و عندها سيقوم بطباعة ما بين الخانة 5 و 11 ، و يقوم بحذف الباقي

 

ماذا لو أردت أن تحول كل أحرف الـ string إلى حروف كبيرة

عندها سنستخدم الدالة ToUpper بدلاً عن الدالة Substring ، و بعندها سيقوم بطباعة الخانات كلها مع تغيير حالة الحروف إلى حروف كبيرة

 

ماذا لو أردت استبدال خانة أو حرف بخانة أخرى ،

مثلا في النص السابق أريد استبدال خانة المسافة بخانة أخرى ، فعندها سنستخدم الدالة Replace ،

و هذه الدالة تحتاج إلى قيمتين ، فالأولى هي Old Character  و الثانية هي New Character

نكتب كل قيمة بين علامتي تنصيص ، و يفصل بين القيمتين بفاصلة

ندخل القيمة الأولى هي المسافة ، أما الثانية نجعلها الرمز –   ، عندها سنرى أن التطبيق استبدال المسافة بالرمز –

 

ماذا لو اردنا حذف جزء من الكلمة الموجودة ، فيمكن استخدام الدالة Remove  ، و لهذه الدالة أكثر من استخدام

فلو أدخلنا رقم واحد فقط ،  و ليكن الرقم 5 ، فسنلاحظ أنه أخذ أول 5 خانات و حذف الباقي

و لو قمنا بوضع قيمتين فسيقوم بحذف ما بين الخانة 5 و 11 و يطبع كل ما تبقى

 

استخدام الـ StringBuilder :

هناك قضية يجب أن ننوه لها ، فاستخدامك للـ string مكلف فعليا ، و نعني بذلك ، حاول قدر الإمكان التقليل من استخدامك للـ string

فاستخدامك له و تخزين Data  كبيرة داخله يحجز مساحات كبيرة في الذاكرة ، و هناك فرق شاسع بي تخزينك للـ integer  و تخزينك للـ string

لذلك حاول أن تكون حذراً و دقيقاً في استخدامه

 

لاحظ الآن سأقوم بمحاولة طباعة لـ string ضخم جداً ، و أقوم باستخدامه بطريقة غير مجدية

لاحظو هذه الطريقة في كتابة الحلقة for  ،

نكتب كلمة for و لا نكتب مسافة بعدها ، ثم نضغط Double Tab فسيقوم بوضع الهيكل الخاص بحلقة for

و هذه الميزة غير موجودة في كافة المحررات

بعد وضعه للهيكل الخاص يمكن التعديل عليه

 

سنشرح قضية هنا مهمة

لاحظو هنا القيم الموجودة قيمة integer  و في بعض الأحيان لا يقبل وضع قيمة int في متغير string

فمن الممكن تحويل أي متغير يمكن تحويله مهما كان نوعه  إلى string عن طريق الدالة ToString ،

الآن سيقوم البرنامج بعملية يأخذ القيمة الجديدة و وضعها في مكان معين ثم أخذ هذا المتغير مرة أخرى ،

و هذه العملية غير صحيحة كما تعلمنا ، فهي تقوم بعملية إضاعة

نحن هنانقوم بعملية 100 حلقة ، لكن تخيل لو كان لدينا 1000 حلقة أو مليون حلقة ، فسيكون مكلفاً جداً و سيقوم التطبيق باستهلاك مساحات كبيرة

لذلك لو كان لدينا string  كبير و يحتوي على أمور تجعلك بحاجة إلى القيام بعملية إضافة قيم له

فيفضل استخدام نوع جديد اسمه StringBuilder ، هذا النوع جداً مميز لاستخدام النصوص الكبيرة و عملية إضافة القيم إلى المتغير

لاحظو في المثال السابق كان يقوم بالإضافة بأسلوب غير مجدِ ، لذلك سنقوم بتحويل السابق إلى جمل ملاحظة

و مثلا هنا سنقوم بتعريف متغير من النوع StringBuilder باسم myString

 

لو قمنا بتطبيق البرنامج سيقوم تماما بعمل البرنامج السابق ، لكن قام بتقليل المساحة المستخدمة و لم يقم بوضعها في مكان و نقلها إلى مكان آخر ، بل قام بعمليات خاصة و مميزة للتقليل من حجم الذاكرة ،

 

إذا يفضل استخدام الـ StringBuilder إذا كان لدينا نص كبير يتم قراءته ، كملف تقوم بتخزين نصوص عليه ، و تحتاج لقراءته مرة أخرى ، يفضل وضعه بـ StringBuilder لأنه مخصص للنصوص الكبيرة

 

و إلى هنا نصل إلى نهاية درسنا :

تعلمنا طريقة استخدام الـ Back Slash Escabe Character

يمكنكم الاطلاع على  Standard Numeric Format String من شركة Microsoft

ستجدون بها جميع الخانات التي يمكن استخدامها

كان هذا درساً سريعة عن الـ string لتحصل على النتائج المطلوبة ، فقد استخدمنا الكثير من الـ Methods لنصل إلى النتيجة المطلوبة و لو حاولنا الوصول إلى النتيجة بدون هذه الدوال سيكون صعباً بل مستحيلاً

ملخص الدرس

مقدمة:

السلامُ عليكم ورحمةُ اللهِ وبركاته، وأهلاً بكمْ في الدرسِ السادس عشر من دروسِ سلسلةِ، تَعلُمِ البرمجةِ للمبتدئينَ كلياً بواسطةِ السي شارب، في هذا الدرس سنتعرف على كيفية التعامل بشكل أكبر مع النصوص، كونها شيء أساسي في كل المشاريع، سنتعلم كيف نقوم بقص جزء معين من جملة، وكيف نقوم بطباعة أرقام بهئية خاصة نقوم بتعريفها.

التعامل مع النصوص Strings :

لا يخلو تطبيق صغير أو كبير من إستخدام النصوص والتعامل معها، لذلك هناك عدد كبير من الدوال للنوع النصي String يمكنك معرفة المزيد عن الدوال التي تقوم بوظائف معينة، هنا شرح لبعضها :

رموز خاصة Escape Character : ويتم بإضافة \ وبعدها خانة مثل : n لسطر جديد ، ” لطباعة التنصيص داخل نص، \ لطباعته داخل نص، القائمة الكاملة للحروف هنا.
تهيئة النص string.Format : وذلك بإستخدام أرقام Index ويمكن إضافة تخصيص لها مثل : N لطباعة الأرقام بالفواصل ، P لطباعة قيمة مئوية، القائمة الكاملة هنا.
Substring : تقوم بعمل قص للنص.
ToUpper : تقوم بتحويل جميع الأحرف إلى أحرف كبيرة Capital letter .
Replace : إستبدال نص بنص آخر.

 

مصطلحات الدرس :

Compiler :

Back Slash :

Character :

Back Slash Escape Character :

index :

Format :

Percentage :

Substring :

ToUpper :

Replace :

StringBuilder :

Double Tab :

Standard Escape Format String :

 

تجد في الأسفل الأسطر البرمجية التي قمنا بكتابتها خلال شرح الدرس.

post

#15 الحلقة التكرارية While – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : FEZ

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C –  الحلقة التكرارية While

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

في درس اليوم بنتكلم عن الحلقة التكرارية While Loop

تأتي أهمية هذه الحلقة عندما لا يكون لديك حد معين لتنتهي دورات هذه الحلقة

أي أن دورها يكمن في تنفيذ أسطر معينة عدداً يمكن أن يكون غير معروف في البداية

 

نبدأ كما في العادة بإنشاء مشروع جديد بلغة سي شارب و اختيار Console App

كما تكلمنا عن المكان المخصص لكتابة الأسطر بين قوسي الدالة void Main  ،  و تكلمنا أيضاً عن إمكانية انشاء دوال خاصة ، و هذا الدرس سيكون ان شاء الله تركيزاً على استخدام الدوال لتنفيذ أسطر برمجية معينة

الآن في البداية سأقوم بكتابة كود ، يمكنكم اللحاق بي .

سأقوم باستدعاء هذه الدالة بكتابة اسمها و فتح و اغلاق أقواسها ، و وضع الفاصلة المنقوطة .

نشغل التطبيق … يقوم بطباعة جميع الخيارات الموجودة في لبرنامج و يطلب مني رقم من الأرقام الموجودة في البرنامج

لاحظوا أنني إن أدخلت أي رقم من الأرقام الثلاثة ، فإنه سوف يخرج من البرنامج .

و أنا لا اريد ذلك ، أريده أن يستمر في البرنامج إلى أن يقوم المستخدم بإدخال الرقم 3

لذلك سنقوم باستعمال الحلقة While  ليستمر في اظهار هذه الـ options ، إلى أن يقوم بكتابة الرقم 3

هنا سأقوم بتعريف متغير جديد من النوع bool ، و هو متغير جديد يحتوي على قيمتين إما True أو False

قمنا هنا بعملية إسناد للمتغير في نفس السطر .

اذا سأبدأ هنا بكتابة جملة While ، ماذا يحدث هنا

القيمة الأولية للمتغير displayMenu هي True

فهو يسأل في هذه الحلقة كالتالي :

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

بتشغيل البرنامج و كتابة أي قيمة سيبقى ضمن البرنامج و يطبع الخيارات ذاتها .

بما أن الحلقة ستبقى تتكرر إلى أن تصبح القيمة خاطئة ، سأقوم بوضع شرط إذا قام بوضع رقم 3 ستصبح القيمة خاطئة و بالتالي سيخرج من الحلقة

لاحظو الدالة mainMenu من النوع void  أي أنها لا ترجع أي قيمة إلى مكان استدعائها

الآن سنقوم بتغييرها من void إلى bool ، فنلاحظ ظهور خط أحمر ، و الخطأ يقول:
“not all code paths return a value”
لأنه طالما أن هذه الدالة ليست void ، فيجب أن تقوم بإرجاع قيمة

فأنا هنا مبدئيا سأقوم بجعل البرنامج برجع قيمة False إذا قام بإدخال الرقم 3

و أيضاً سأقوم بتعبئة باقي الأماكن بإرجاع قيمة True إذا قام بإدخال باقي الأرقام

إذاً إذا ضغط الرقم 3 سيقوم بإرجاع False  ، هذا الـ False  هو القيمة الراجعة من الـ mainMenu أريد اسنادها للمتغير displayMenu

إذاً أي قيمة راجعة من الـ mainMenu سيقوم بإسنادها للمتغير displayMenu

و إذا كانت False  سيكون الشرط غير محقق و سيخرج من البرنامج

و عند تشغيل البرنامج ، و الضغط على أي قيمة غير الرقم 3 سيستمر البرنامج ، أما في حال ادخال الرقم 3  سيخرج من البرنامج

لاحظوا أن الموجود بين القوسين هنا while (displayMenu == true) هو Expression ، أي أنَّ القيمة النهائية هي True of False

و طالما أن هذا المتغير الموجود هنا يمكن أن يكون True or False  فلا داعي لكتابة == true

إذاً هنا نفذ القسم الثالث ، لذا سنكمل القسمين الأول و الثاني

سنقوم بكتابة Method  جديدة ، و لاحظوا أننا نقوم بكتابة الـ Methods في منطقة ما بين أقواس الـ Class ؛ و سنتكلم عن الـ Class لاحقاً إن شاء الله

هنا قمنا باستخدام شيء جديد و هو تحويل المتغير ، فقد تكلمنا سابقاً أن القيمة الراجعة من الدالة ReadLine  هي string

و إذا قمنا بتعريف متغير من النوع int فلا يمكن تحويل مدخلات الدالة ReadLine  إلى int لذلك قمنا باستعمال هذه الدالة لتقوم بعملية التحويل من string  إلى  int

بعد أن قمنا بتعريف متغير جديد ضمن الدالة الجديدة ، تطلب من المستخدم إدخال الرقم ، و تقوم بعد ذلك بعملية طباعة الأرقام من 1 إلى الرقم الذي قام المستخدم بإدخاله

نقوم باستدعاء الدالة التي قمنا بكتابتها إلى داخل جملة الشرط رقم 1

عند تشغيل التطبيق و ادخال 2 ، سيطلب من المستخدم إدخال رقم ثم يقوم بطباعة الأرقام كما ذكرنا

 

سنقوم الآن بكتابة Method جديدة للـ Guessing Game

في هذه الـ Method سأطلب من التطبيق إعطائي رقم عشوائي ، ثم أطلب من المستخدم القيام بتخمين الرقم الذي قام البرنامج باختياره

سنقوم بتعريف متغير جديد من النوع Random ، و سنعرف متغير جديد آخر من النوع int و سأطلب منه اختيار رقم عشوائي بين 1 و 7 مثلاً

و سأقوم بتعريف متغير من النوع bool باسم incorrect  و نسند إليه القيمة true

سأقوم بوضعه ضمن حلقة ، لكن سنتعرف هنا على نوع آخر من أنواع While Loop

 

الشكل الثاني للحلقة While Loop

في الـ  Methods  السابقة رأينا أن الحلقة تقوم بالتحقق من الشرط و إذا لم تتحقق فلا يتم تنفيذ الأسطر و يخرج مباشرة

هناك نوع آخر من أنواع While Loop و هو يقوم بتنفيذ الحلقة مرة واحدة على الأقل ثم يقوم بالتحقق من الشرط

الشكل الآخر يكتب كالتالي :

نكتب الكلمة do و نفتح قوس و ننتهي بقوس آخر من النوع {    }

و بعد القوس الأخير نكتب كلمة while و نكتب الشرط بين قوسين (      )

فنلاحظ أن الشكل الأول للحلقة يتم بكتابة while ثم نفتح قوساً و ننتهي بقوس ، أما الشكل الثاني فيتم كتابة كلمة do في  البداية و نكتب كلمة while  ثم الشرط بعد القوس الأخير

فبالتالي في  الشكل الأول يقوم بالتحقق من الشرط أولا ، أما في الشكل الثاني يتم التنفيذ لمرة واحدة ثم يتم التحقق من الشرط ، و بالتالي إن تحقق الشرط سيقوم بتنفيذ الحلقة مرة أخرى ، أما إن لم يتحقق فإننا بهذه الحال تأكدنا من تنفيذ الشر مرة واحدة على الأقل

نتابع كتابة الدالة ، فبعد أن يقوم بتلقي المعلومات من المستخدم نضع شرطاً إذا كانت القيمة المدخلة result مساوية لـ randomNumber

و نلاحظ هنا أنني سأقوم بعملية تحويل القيمة التي من النوع int  إلى text .

كيف يتم ذلك ؟

بعد كتابة أي دالة إذا قمت بكتابة نقطة سيكون لدينا ToString و هي الدالة التي تقوم بالتحويل من int  إلى string

نعود إلى الشرط الذي قمنا بكتابته فإن كانت القيمة محققة و النتيجة True سيقوم بإسناد قيمة False للخروج من الحلقة

أما إن لم تكن محققة ، فسيتم الاحتفاظ بالقيمة true  ليبقى في الحلقة و يقوم بتنفيذها مرة أخرى ، كما سيتم طباعة جملة Wrong !

و نلاحظ أنه لا داعي لإسناد قيمة True لأن المتغير incorrect في الأصل تم إسناد القيمة true  إليه كقيمة ابتدائية

و بهذه الحلقة سيبقى يسأل عن الرقم حتى يتسطيع المستخدم الوصول إلى التخمين الصحيح للرقم

نقوم الآن بعملية استدعاء للدالة في الأعلى و مباشرة نقوم بتشغيل البرنامج

ندخل الرقم 2 للدخول إلى لعبة التخمين
يطلب مني ادخال رقم بين 1 و 7

نجرب الإدخال ، و في حال إدخال رقم غير مساوي للرقم المطلوب سيتم عرض “Wrong ! ”

و عند ادخال الرقم الصحيح سيعود إلى القيمة الرئيسية بسبب أرجاع قيمة False  كما ذكرنا بالنسبة للحلقة

 

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

 

سنقوم بتعريف متغير جديد في الدالة باسم Guesses  من النوع int   و نعطيه القيمة 0 كقيمة ابتدائية و كل مرة يقوم بإعادة تنفيذ الحلقة سيقوم بزيادة 1 للتغير

في النهاية سنقوم بطباعة المتغير بعد تحقق الشرط و الخروج من الحلقة

لنتأكد من ذلك

نعم تم عرض عدد المرات و الرقم هو 4

الآن في كل مرة يقوم البرنامج بتكرار السؤال!

ماذا لو اردنا أن تكون الطباعة على صفحة جديدة ، أي يقوم بمسح المعلومات السابقة

لذلك لدينا الدالة :

;()Console.Clear

تقوم هذه الدالة بمسح المعلومات السابقة و بناء صفحة جديدة

لذلك كل مرة نقوم باختيار رقم سيقوم بعمل حذف للسابق

نستخدم الدالة في أكثر من مكان حسب الحاجة

و بتشغيل التطبيق نلاحظ أنه يقوم بحذف المعلومات السابقة و يبدأ بصفحة جديدة

نقوم بتجربة لعبة التخمين فنصل للرقم الصحيح و لكن لا نرى النتيجة … لماذا ؟
لأنه قام بعمل مسح للصفحة بشكل سريع

لذلك يمكن أن نقوم بإضافة الدالة ReadLine لنتمكن من مشاهدة التائج

بإمكاننا أن نقوم بعمليات لترتيب التطبيق مثل إضافة أسطر و إلى ما هنالك ، و هي أمور فنية و تجميلية

هذه كانت فكرة الـ While Loop و كيف نقوم باستخدامها عدد مرات غير معروف في البداية

 

ملخص الدرس :

السلامُ عليكم ورحمةُ اللهِ وبركاته، وأهلاً بكمْ في الدرسِ الخامس عشر من دروسِ سلسلةِ، تَعلُمِ البرمجةِ للمبتدئينَ كلياً بواسطةِ السي شارب، في هذا الدرس سنتعرف على كيف أنه يمكننا تنفيذ حلقة تكرارية من الأسطر البرمجية مجهولة العدد، بحيث تنتهي وتخرج من وسطها بمجرد تحقيق شرط معين

الحلقة التكرارية While Loop :

تختلف هذه الحلقة عن For Loop في أنها قد تكون مجهولة عدد التكرارات في البداية، ففي مثالنا في هذا الدرس، سنجعل الحاسوب يقوم بأخذ رقم عشوائي، ونطلب من المستخدم تخمينه، وسنبقى نعطيه فرصه إلى أن يجده، بالتالي نحنا لا نعلم من أي مرة سيجده، وهنا تأتي فائدة الحلقة التكرارية While Loop .

مصطلحات الدرس :

WHILE Loop :

bool :

Class :

Guessing Game :

Random :

incorrect :

ToString :

Console.Clear :

post

#14 الدوال Methods – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : OXW

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C –  الدوال Methods

 

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

درس اليوم ” الدوال الـ Method “

و هي من أساسيات البرمجة و هي التي أعطت للمطورين إمكانية أن يقوم بتنفيذ مشروعه دون أن يقوم بتكرار الأسطر البرمجية أكثر من مرة

سابقاً لم يكن هناك دوال و كان المطور مجبراً على كتابة أسطر برمجية متتالية ، فتجد أن البرنامج عبارة عن 1000 سطر على سبيل المثال ، كلها متتالية حيث ينفذ السطر الأول ثم الثاني فالثالث و هكذا ….. مما كان يجعل الأمر صعباً

و خصوصاً في حال وجود أي خطأ في البرنامج فيجب أن يقوم بتتبع للبرنامج ليصل إلى مكان الخطأ

 

كما تعلمنا في كل الدروس السابقة نقوم بإنشاء مشروع جديد و نختار Visual C# ثم Console Application و سنكتب اسم البرنامج هذه المرة ” Methods ”
و تكلمنا أنه يجب أن نقوم بالبدء بالكتابة بين قوسي الدالة void Main

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

و الدالة يمكن شرحها بأنها قطعة برمجية  Block of Code تبدأ بقوس و تنتهي بقوس آخر ، و تحمل اسم , حيث يتم استدعاء هذا الاسم لتقوم بالعمل الخاص بها .

لاحظو الدالة الرئيسية void Main و هي الدالة التي يبدأ بها الـبرنامج

سنقوم الآن بكتابة دالة رئيسية و سنقوم بشرحها و شرح التركيبة الخاصة بها

هذه الدالة يمكن استخدامها و استدعاؤها في الدوال الأخرى كالتالي :

أخذ اسم الدالة (PrintMessage) ثم فتح القوس الخاص بها و اغلاقه و كتابة الفاصلة المنقوطة .

و لا ننسى أن نقوم بكتابة الدالة ReadLine

عند تشغيل التطبيق سيقوم بطباعة Hello World !

الفكرة من الدوال أنه يمكنك إضافة العديد من الأسطر البرمجية في وِحدة خاصة بها ، بحيث في حال الحاجة إلى تكرار الأسطر ، فيمكنك استدعاؤها عن طريق اسمها دون الحاجة لكتابة كافة الأسطر .

شرح الدالة

في البداية يجب أن تقوم بكتابة الدالة خارج الـ void Main  لأنه لا يمكن كتابة دالة داخل دالة

لذلك إذا أردت كتابة دالة فيجب كتابتها خارج الدوال الأخرى

الترتيب غير مهم هنا و هذا يعني أنه بإمكانك كتابتها قبل أو بعد الـ void Main

و عند الحاجة إليها أقوم بكتابة اسمها دون كتابة الأسطر البرمجية الموجودة بداخلها

 

فوائد الدوال :

(1) : استدعاء أسطر برمجية يتم كتابتها أكثر من مرة ، بحيث تقوم بكتابتها مرة واحدة داخل الدالة ثم تقوم باستدعاء الدالة في كل مرة تحتاج إلها .

(2) : عدم تكرار الأسطر البرمجية نفسها

(3) : تقوم بتنظيم المشروع

(4) : في حال حصول أي مشكلة يمكن تعديلها بشكل بسيط في مكان واحد دون تتبع التطبيق بشكل كامل

 

هذه القضايا سنتكلم عنها في الدروس القادمة و سنتحدث الآن عن الدالة void

 

 

الـ void هي نوع من أنواع البيانات أو أنواع الـ Data مثل integer  و  string

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

يمكننا نقل السطر ;()Console.ReadLine إلى الدالة التي قمنا بإنشائها

 

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

 

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

لدينا الآن أسطر برمجية مكررة في هذا التطبيق ، حيث يقوم بطباعة جملة ثم يقوم بمطالبة المستخدم بعملية إدخال و يكرر هذا الأمر

ثم يقوم بتعريف Array من النوع char  ثم يأمر بتحويلها إلى مصفوفة ثم يقوم بعملية عكس لهذه المصفوفة

إذا لدينا ثلاث أسئلة و لكل سؤال 4 عمليات

و بالتالي لدينا تقريباً 12 سطر

و في النهاية يقوم بتعريف متغير جديد باسم result

و يقوم باستخدام الحلقة foreach ليقوم بأخذ هذه الأحرف و يجمعها ليعطي هذه النتيجة

نلاحظ عند تشغيل التطبيق أنه أخذ كلمة كلمة و لم يعكس الجملة كاملة ، حيث قمت بإدخال Osama  ثم  Deep ثم amman

فأخذ الاسم الأول و قام بعكسه ، ثم أضاف مسافة قبل الاسم الثاني ثم تابع أخذ الاسم الثاني و المدينة ،

عندها قام بإعطاء النتيجة كالتالي

Result : amaso peed namma

لنرى كيف نكتب دالة توفر علينا هذا الكم من الكتابة ، فبدلاً من كتابة 16 سطر سنقوم بكتابة 4 اسطر فقط و استدعاء هذه الدالة

 

الآن نقوم بتعريف دالة جديدة

ثم نكتب التالي ضم قوسي الدالة {   }

كما في المثال التالي :

 

في البداية سنقوم بالتطبيق على الـ firstName فقط ، سنستدعي الدالة ليقوم بعرض الموجود داخلها .

المتغير الأول هو السؤال و المتغير الثاني هو ناتج المدخل

الآن سيقوم بطباعة السؤال و ثم يكون بعملية عكس للأحرف المدخلة في الجواب

حيث يقوم بتحويله لمجموعة من character  و اسنادها في متغير جديد ثم يقوم بعكسها باستخدام الدالة Array.Reverse

و في النهاية سيقوم بطباعة firstNameArray

الآن لدينا الجزء المتكرر في كل المراحل السابقة و قد أصبح ضمن الدالة التي قمنا بإنشائها

الآن نقوم بعملية استدعاء للدالة التي قمنا بإنشائها

عندها سيسأل عن الاسم الأول و يطلب إدخاله ، و سيأخذ القيمة من المستخدم و يدخلها في متغير نصي  و يتابع

عند تشغيل التطبيق سيسأل عن الاسم و عند ادخال osama  يقوم بطباعة osama لكن بالشكل المعكوس … أي  amaso

 

الآن لنلاحظ أن هذه الدالة هي من النوع void و تقوم بتنفيذ الاسطر الموجودة بدون ارجاع أي قيمة أخرى

لاحظوا أنه سيكون لدينا مشكلة إذا قمنا بكتابة هذه الدالة للاسم الثاني و اسم المدينة

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

نحن نريد أن يقوم بإرجاع القيمة الناتجة و استخدامها لاحقا

 

فقد تكلمنا أن الـ void لا يرجع أي قيمة ، لكن بإمكاننا استبدال هذا النوع بـ string

أي أن هذه الدالة ستقوم بعمليات معينة ثم ستعيد نصاً إلى مكان استدعائها

 

بما أن هذه الدالة أصبحت من النوع string  و ليس void  فيجب أن ترجع قيمة و بالتالي ستحتوي على return لشيء ما في نهايتها

و القيمة التي نريد ارجاعها هي النص الموجود لدينا  فيصبح السطر الأخير :

;Return string.concat(firstNameArray)

عندها سيكون هذا السطر راجعاً من الدالة DisplayResult

أي أنني في الأعلى يمكنني أن أقوم بتعريف

;()string firstName = DisplayResult

و النوع الموجود قبل إشارة المساواة من النوع string وبالتالي DisplayResult ذات الأمر ، لأن الدالة الموجودة في الأسفل من النوع string و النتيجة الراجعة من النوع string

نقوم بتشغيل التطبيق لنتأكد من صحة المعلومات و نلاحظ أنني لا اريد أن أقوم بطباعة الناتج داخل الدالة الثانية بل سأقوم بطباعته في الدالة void

 

فعلا قام التطبيق بطباعة osama  بشكل معكوس

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

 

و نتذكر أن الدوال من الممكن أن تكون int , string أو أي نوع من أنواع البيانات و يمكن أن تكون دالة لا ترجع قيمة مثل void

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

الآن أريد استخدام هذه الدالة ليس فقط لطباعة الاسم الأول
بل لطباعة الاسم الأول و الأخير و السؤال عن المدينة التي ولد فيها

إذا في الدالة يمكنك أن تقوم بإرسال قيمة
لذلك سنقوم بتعريف متغير جديد

عندما نقوم باستدعاء الدالة يجب أن نرسل قيمة يتم ارسالها إلى الدالة

 

لذلك سنقوم بحذف السؤال في الدالة و نجعله قادماً من مكان استدعائها

إذا سنأخذ المتغير question و نضعه بعد string  بين قوسي الدالة (  )

الناتج كالتالي

سنقوم باستدعاء الدالة و نرفق معها السؤال بين القوسين ، عندها سيأخذ السؤال و يقوم بطباعته مباشرة و يقوم بعمليات معينة و يقوم بإرجاع القيمة النهائية إلى هذا المكان

 

الآن قمنا بإرسال هذا النص إلى الدالة و قام بطباعته و استخدام القيمة المرسالة مع هذه الدالة

نقوم بتعريف متغير جديد اسمه lastName ، و سأسأله سؤال ” ما هو اسمك الأخير” و القيمة الراجعة من الدالة سيقوم بإسناده للمتغير lastName
ثم نسأله عن مكان الولادة

لاحظو أن هذه الثلاث أسطر هي فعليا 12 سطر
لنتأكد أن القيمة الراجعة صحيحة

ثم نقوم بطباعة الناتج النهائي

بتشغيل التطبيق سيسأل عن الاسم الأول و الأخير و المدينة ، و سيقوم بعرض ذات النتيجة التي عرضها في التجربة الأولى

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

 

نصل الآن لنهاية هذا الدرس ، ألقاك في الدرس التالي إن شاء الله

 

ملخص الدرس :

السلامُ عليكم ورحمةُ اللهِ وبركاته، وأهلاً بكمْ في الدرسِ الرابع عشر من دروسِ سلسلةِ، تَعلُمِ البرمجةِ للمبتدئينَ كلياً بواسطةِ السي شارب، في هذا الدرس سنتعرف على  الدوال Methods أو ما يسمى Function في لغات أخرى، والتي تعتبر العصب الرئيسي الذي يقوم عليه أي تطبيق ولا يخلو منها.

الدوال Methods :

يمكن تعريف الدالة على أنها قطعة برمجية Code Block تبدأ بجملة تعريفية بإسمها ونوعها سواء كانت نصية string أو رقمية int أو لا ترجع أي قيمة void أو أي نوع آخر. والدوال لها العديد من الميزات أهمها:
– تقليل عدد التكرارات الموجودة في التطبيق، وبالتالي قلة عدد الأسطر الإجمالي.
– تنظم المشروع، بحيث تكون الأسطر البرمجية الخاصة بعملية معينة في مكان واحد.
– سهولة إيجاد المشاكل المنطقية في حال وجودها لاحقاً.
و طريقة كتابة الدالة هكذا :
Method_Type Method_Name ()
}
{

خصائص الدوال :

كما ذكرنا قبل قليل، إن كانت الدالة غير النوع void ( لا ترجع أي قيمة)، أي أنها من النوع int أو string أو float أو أي نوع آخر، فيجب أن تقوم بإضافة سطر return value في نهايتها ويمكن الحصول على العائد من الدالة بعملية الإسناد، أيضاً يمكن إرسال قيم عند مناداة الدالة لإستخدامها داخل الدالة وهي ما تدعى arguments أو parameters ، وهي متغيرات يتم إستخدامها داخل الدالة للقيام بالمهمة الموكلة لها.

مصطلحات الدرس :

Methods :

Block of Code :

return :

float :

arguments :

parameters :

الأسطر البرمجية التي تم إستخدامها في الدرس :

post

وثيقة تطوير اللعبة Game Design Document

أهمية وثيقة تطوير اللعبة وكيف تقلل الوقت والجهد على فريق تطوير الألعاب

نبذة عن وثيقة تطوير اللعبة GDD :

السلام عليكم ورحمة الله وبركاته، كثر في الآونة الأخيرة إزدياد أعداد المطورين العرب، ومن المؤسف رؤية الكثير يقفز عن أهم مرحلة من مراحل تطوير اللعبة، ألا وهي المرحلة النظرية أو مرحلة كتابة مستند تطوير اللعبة المسمى Game Design Document ذو الإختصار GDD، حيث تكون في مرحلة قبل التطوير Pre-Production، فلازلنا نرى التوجه المباشر نحو محركات الألعاب، ولغات البرمجة وأدوات التصميم بشكل عشوائي وغير منظم، مما يضيع الكثير من الجهد والوقت خلال عملية تطوير الألعاب بحد ذاتها، لذلك كان لا بد من التطرق إلى مثال عملي عن هذه المرحلة، لكشف أهميتها لدى المطورين أنفسهم، ولتضفي خبرة كافية لهم لكي يقوموا بالإنتباه لها في مشاريعهم الحالية والمستقبلية.

إن كنت المسؤول عن عملية تصميم اللعبة Game Design ، فأنصحك بالإضطلاع على مهارات مصمم الألعاب عبر المقالة التالية : كيف تصبح مصمم ألعاب ناجح ، حيث تعتبر المقالة السابقة مقالة نظرية، وفي هذه المقالة سندخل تجربة تطبيق للعبة يتم تطويرها حالياً.

محتويات وثيقة تطوير اللعبة :

يمكن أن تحتوي هذه الوثيقة على خليط بين النصوص والصور والأشكال التعريفية Diagrams، أو سكيتشات أولية Concept Arts بالإضافة إلى أنها يمكن أن تحمل خوارزميات أو أسطر برمجية قياسية، أو ما يمكن تسميته Pseudocode يعطي إنطباع عن المهام الوظيفية التي ستكون داخل اللعبة، ويمكن تلخيص الأقسام الرئيسية التي تحويها كالتالي :

القصة Story : حيث يتم كتابة الفكرة الأولية للسيناريو وقصة اللعبة، ويمكن تفصيلها وتعديلها لاحقاً.
الشخصيات الرئيسية Characters : فكرة عن طبيعة شخصية اللاعب و الشخصيات المشاركة باللعبة، أو ما يعرف ب Non-Player Characters ذو الإختصار الشهير NPC.
تصميم المراحل Level/environment design : يتم وضع تصور عام عن بعض المراحل، ويمكن أن تكون عبارة عن رسومات أولية على أوراق حقيقية.
طريقة اللعبة Gameplay : وهي جوهر اللعبة لأهميتها، ويمكنك مراجعة مقالة كيف تصبح مصمم ألعاب ناجح ، للمزيد من المعلومات حول تصميم اللعبة.
الرسومات Art : السمة العامة المستخدمة داخل اللعبة، هل هي ثلاثية البعد أم ثنائية البعد، هل تصاميمها حقيقية أم كرتونية وهكذا، وتصورات مرسومة عن تفاصيل اللعبة.
الأصوات Sound and Music : نوع النمط الخاص بالصوتيات Genre ، ويمكن إرفاق ملفات أصوات سابقة مع الوثيقة.
الواجهات الرسومية User Interface : أو ما يعرف بال UI حيث يتم رسم المعلومات التي ستبقى على الشاشة خلال اللعب وماهيتها.
أزرار التحكم Game Controls : يمكن أيضاً كتابة كيفية التحكم في اللعبة، وما هي المنصة المستخدمة هل ستكون أحرف لوحة المفاتيح أم النقر كما في أجهزة الموبايل.

لعبة حرب القواعد – تطبيق عملي :

كما تعرفنا في المعلومات السابقة، أنه يمكن ضم عدد لا بأس به من الأقسام الرئيسية التي يجب أن تكون واضحة منذ بداية التطوير لكي تختصر الكثير من الوقت والجهد، في لعبة حرب القواعد تم كتابة 3 وثائق تفصيلية يمكن دمجهم معاً لتحصل على وثيقة تطوير اللعبة Game Design Document ، وهنا تم تفصيل 3 أقسام رئيسية يمكن تلخيصلهم بالشكل التالي :

1 – الوثيقة الأولية Game Concept Document :

حيث تم بروز فكرة لعبة في ذهن الأستاذ أسامة ديب ( صاحب المشروع ) لمحاكاة لعبة تحتوي على قلعتين متباعدتين، حيث يتسابقان لهدم قلعة الآخر من خلال بناء وحدات معينة، الفكرة السابقة كان لا بد من كتابتها في وثيقة ضمت المحاور التالية : شرح الفكرة، ميزات اللعبة، نوع اللعبة Genre، المنصة المستخدمة، وتطبيقات اللعبة. الوثقة تحتوي على 5 صفحات يمكن تصفحها مباشرة  هنا.

2 – الوثيقة الوظفية Functional Specification Document:

بعد الإنتهاء من الوثيقة الأولية يتم البدء بالتعمق في جوانب اللعبة التقنية ، حيث يتم تفصيل ميكانيكية اللعبة من خلال الكتابة عن نواة اللعبة وتسلسل الأحداث داخل اللعبة ، والعناصر الأساسية للعبة Game Units ، ثم التفصيل أكثر حول واجهات اللعبة الأساسية User Interface ، ومن ثم كتابة تخطيط بياني وخوارزميات لها ، إنتقالاً إلى التصاميم والرسوميات المستخدمة والسكيتشات إن وجد ذلك ، والأفلام البينية داخل اللعبة ، إنتقالاً للأصوات التي سيتم إستخدامها والموسيقى ، مروراً بسرد قصة للعبة حيث يتم إدخال اللاعب في قصة متسلسلة للعبة ككل ، والإنتقال إلى المراحل التي ستتكون منها اللعبة ، كل السابق قد تم كتابته بشكل عملي داخل هذه الوثيقة، تحتوي هذه الوثيقة على 8 صفحات يمكن تصفحها مباشرة هنا.

 

3 – الوثيقة التقنية Technical Specification Document :

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

 

  • يجدر بالذكر أن حرب القواعد تم تغيير إسمها إلى Get That Sheep ويمكن رؤية النتيجة الحالية للمشروع كما في الفيديو التالي :

post

كيف تصبح مصمم ألعاب ناجح

تعرف على مصمم الألعاب وما هي المهارات التي يجب أن يمتلكها

دور مصمم الألعاب Game Designer

السلام عليكم ورحمة الله وبركاته، يبقى الدور العام لمصمم الألعاب Game Designer هو كيفية عمل اللعبة بشكل صحيح أثناء عملية تصميمها، فهو يقوم بوضع الأهداف Objectives و القواعد Rules و الإجراءات Procedures ، ويقوم بوضع القصة وإعطاءها الحياة وهو أيضاً المسؤول عن التخطيط لكل ما يجعل اللعبة مقبولة، وهو من يقوم ببناء المرحلة Level Design سواءً بناءها على أسس الهندسة المعمارية أو رسم سكيتشات على الورق Blueprint، وهو أيضاً يقوم بتنسيق القصة (السيناريو العام) للعبة. فكل من كان يحلم في عمل مميز في هوليوود أصبح الآن بإمكانه فعل ما يريده بواسطة كتابة سيناريو القصة وإخراجها بشكل كامل، التخصصات السابقة أصبحت الآن متجزءة بشكل تخصصات كاملة، كل شخص مسؤول عن إحداها، لكن مطور الألعاب الناجح يجب أن يكون ملم بتفاصيل كل تخصص من باب تعلم شيء عن كل شيء، ولكن ما هي الأمور المطلوبة لتصبح مصمم ألعاب؟ وما هي المواهب والقدرات المطلوبة؟ وما هي أفضل طريقة لتصميم لعبة؟ هذا كله سنكتشفه من خلال هذه المقالة.

مصمم الألعاب يضع نفسه بدل اللاعب

يتمركز دور مصمم الألعاب وقبل كل شيء أن يتصرف وكأنه اللاعب، فالمصمم يجب أن يشاهد لعبته من زاوية أخرى وهي الزاوية التي يرى بها اللاعب Player هذه اللعبة، وعلى الرغم من أن هذا شيء سهل ولكنه للأسف يتم تجاهله، مما قد ينتج فجوة كبيرة في اللعبة بسبب هذا الخطأ البسيط، من البسيط أن نقوم بالتأكد أن تصميم الجرافيكس والقصة والبرمجة تسير بشكل صحيح، ولكننا نغفل عن أهم ميزة في اللعبة، وهي وجود الإثارة التي تدمج جميع ما سبق لنخرج بشيء متميز. وكمصمم ألعاب Game Designer فإن الجزء الأكبر من دورك يتمثل بالتركيز والحفاظ على تجربة اللاعب User Experience وملاحظة الأمور التي سيكتسبها من عملية اللعب، وأيضاً يجب أن لا تجعل الأمور التقنية (جرافيكس، وتأثيرات، وبرمجة) تطغى على هذا الجانب. دع كل شخص يهتم بتخصصه، فدع مسؤول الرسوميات Art Director يبدع بالتخيلات، ودع المنتج Producer يهتم بالميزانية، ودع المدير التقني Technical Director يهتم بمحرك الألعاب ومشاكله فمهمتك الأساسية هي أنه عندما يتم تسليم اللعبة للاعب يجب أن يندهش من طريقة اللعب Game play وببساطة أن يقول: !!Wow ولا يدع اللعبة في وقت قصير. وعندما نذكر مصطلح Game play يجب مباشرة أن يتبادر لذهنك الأمور التي سيكتسبها اللاعب من خلال لعبة وما هي الخبرات والأسس التي سيجدها في اللعبة.

 

مختبري اللعبة Game Testers

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

وهناك الكثير من المصممين الذي لا يدرجون الـ Game Tester بعملية تصميم اللعبة، لربما بسبب ضيق وقت العمل، أو أنه لا يريد أن يقوم المختبر بإزالة أشياء يظنها المصمم تضفي إيجابية على اللعبة، أو لربما أنهم يعتقدون أن ذلك سيكلفهم الكثير من النقود، أو أن اعتقادهم بأن عملية الاختبار تأتي ما بعد التسويق ومن خلال اللاعبين عبر العالم ولكنهم فعلياً يقومون بتضييع المزيد من الوقت والمزيد من التكلفة وأيضاً الكثير من الإبداع المتوقع من مختبري اللعبة، وذلك بسبب أن اللعبة ليست بطريق واحد للاتصال One-way بمعنى أنه ليس عليك طرح اللعبة ومن ثم إنتظار قدوم النقود!!، وليس الأمر أن يقوم المصمم بالتأكد من أن كل جزء من الأجزاء الوظيفية باللعبة تعمل بنجاح، الأمر يكمن في إيجاد الميزات التي يحب اللاعب أن تكون موجودة في لعبته المثالية Game Play وبالتأكد هذا لن تقوم بإكتشافه إلا من خلال الـ Game Tester.

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

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

 

المهارات

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

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

1 – مهارة التواصل مع مختلف الأشخاص

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

ومهارة الإتصال لا تقتصر على الكتابة وفن الخطابة، بل هي تعني أيضاً فن الإستماع والإستعداد للتناقش بوسطية ومنطقية، فإستعدادك لسماعك رأي مختبري اللعبة Game Tester ولزملائك في الفريق Teammate سينتج أفكار جديدة وباتجاهات جديدة، فما هي ردة فعلك عندما تسمع شيئاً لا تحب سماعه؟ نحن نعلم أنه من الصعب أن نقدم بعض التنازلات، ولكن هنا الأمر مختلف ويجب عليك التنازل في هذا الموضوع لأنه من هدفه زيادة الإنتاجية، وفي الحقيقة أن معظم مصممي الألعاب يعتقدون أنه لا يجب التنازل أبداً عن الرأي والأفكار التي جمعها، ولكن التنازل مطلوب في بعض الأمور فإن كان الرأي الجديد جيداً فسيقوم بإضافة أفكار من هدفها أن تعطي الإبداع للعبة. فعلى سبيل المثال، قد ترى أن بعض التأثيرات من هدفها أن تقوم بإضافة أشياء مفيدة للعبة تجعلها أجمل، ولكن من الناحية التقنية Technical، لا يمكنك فعل ذلك لأنها مكلفة على نوع الجهاز الذي ستنزل عليه اللعبة، ولربما أن الوقت غير كافي لعمل، ولكن ماذا لو قدّم المبرمج طريقة ثانوية للتأثيرات التي تريد بحيث تكون قابلة لبرمجتها وبوقت قصير وبكلفة أقل؟ هل ستحتفظ برأيك الأول في ظل هذه المعطيات؟ في النهاية يكمن هدفك في إيجاد الفكرة المناسبة التي يمكن تكييفها من كل متطلبات العمل، فيجب أن تصغي لأي رأي جديد من هدفه إنجاح المشروع.

2 – مهارة العمل ضمن فريق

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

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

3 – قادر على معالجة الأمور عند الضرورة

في أغلب الأحيان وعندما يكون عندك حط زمني معين للمشروع Deadline ، ستضطر لأخذ قرار أحياناً يؤثر سلباً على جودة اللعبة ككل أو على سير عملية التطوير، ومن شأنه أن يولد مشاكل مستقبلية تستمر بالظهور واحدة تلو الأخرى حتى تصبح اللعبة ككل مجموعة من المشاكل لا يمكن حلها!!، فالألعاب نظامها ضعيف، وكل العناصر ترتبط إرتباطاً وثيقاً ببعضها، فعند ظهور خلل في عنصر معين، سيؤثر هذا العنصر سلبياً على كل العناصر وبالتالي على كل المشروع، وهذه القضية خطيرة خصوصاً في المراحل النهائية لتصميم اللعبة، فحين ينفذ الوقت ستظهر بعض المشاكل التي لم تتمكن من حلها، وستضطر لحذف بعض المراحل وبعض العناصر للحفاظ على العناصر التي تم تصميمها بشكل سليم، إنها كارثة حقيقية، ولكنها بالنهاية تساعدنا على فهم سبب إحتواء الكثير من الألعاب على تناقضات والتي غالباً ما تميت اللعبة قبل وصولها للسوق (Dead On Arrival (D.O.A بفترة وجيزة.

4 – قادر على الإستنباط من حوله

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

إن أردت أن تصبح مصمم ألعاب مميز حاول أن تقوم بالنظر للعالم من حولك على أنه لعبة كبيرة جداً تحتوي مهمات ومستويات ومراحل مختلفة. حاول تفسير الوظائف الأساسية والمهمة في حياتك، وحاول إكتشاف القواعد التي تقوم عليها، حاول معرفة كيفية عمل الآليات والإلكترونيات، بإستنتاجك لها ستحصل على إمكانية بناء أنماط  وأفكار جديدة لم يتم التفكير بها سابقاً، كل ما عليك فعله هو كتابة ملاحظاتك وتحليلاتك ومعرفة أساساتها وستصبح بإذن لله من أنجح المصممين.
لكن لماذا لا نقوم بالنظر إلى الألعاب الموجودة في السوق على أنها مصدر للإلهام؟ فعلياً إن قمت بذلك فستقوم بعمل فكرة تم إيجادها سابقاً وبالتالي لن تحصل على ميزات الأفكار الجديدة، حاول أن تقوم بالنظر حولك وإكتشاف شيء جديد، ودائماً إجعل الحياة المحيطة بك هي مصدر لإلهامك لا ألعاب سابقة تم عملها. ومن أهم القضايا التي تلهم مصمم الألعاب بأفكار جديدة هي: العلاقات الإجتماعية، طريقة جمع النقود، البيع والشراء، المنافسة في العمل، وغير ذلك. مع ملاحظة أن كل ثقافة وبلد وطبيعة في العالم يمكن أن تغرس فيك فكرة لعبة جديدة، فيمكنك بالتالي إختيار أي فكرة تراها جيدة وتقوم بتطبيقها.
فمثلاُ في طبيعة الأرض أفكار مشعبة ومعقدة وكثيرة مثل: مستعمرات النمل، فهم منظمون إلى مجموعة من القواعد، وهم يتنافسون ويسعون لإثبات أنهم الأ فضل من خلال جمعهم الكثيف للغذاء، ويتنافسون مع مستعمرات أخرى لإثبات قدرتهم على العيش، والأمر نفسه مع كل أنظمة الحياة، من طرق إثبات القدرة على الحياة لدى الأسود الإفريقية إلى فعل ذلك لدى القطة الموجودة في أزقة الطرق.
قم بدراسة الأنظمة السابقة وقم بتقسيمهم: لعناصر objects و علاقات relationships، وسلوكيات behaviors، وإلى غير ذلك. وحاول إكتشاف كيفية التفاعل مع العناصر الأخرى، فلربما تخلق أساس لفكرة جديدة، وهذا الشيء نفسه عندما تنظر كيف يتم التعامل مع الأشخاص في مجال السياسة، وفي مجال الفن، وفي العلاقات الإجتماعية مثل الزواج، فهناك قصة لعبة في كل علاقة. من خلال إستنتاجك لجميع ما سبق، فإنك لا تكتسب زيادة المهارة في كونك مصمم ألعاب فحسب، ولكنك تفتح أفاقاً جديدة وتخيلات في ماهية لعبتك و قواعدها وطرق تصميمها.

5 – قادر على الإبداع

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

من أكبر وأشهر مصممي الألعاب Nintendo’s Shigeru Miyamoto يقول:
“دائماً ما أنظر لطفولتي ولأحلامي وهواياتي التي تتميز بالإلهام عندما كنت طفلاً، ذهبت لحديقة ووجدت بحيرة كانت لطيفة ومذهل بالنسبة لي أن أعثر عليها وعندما تجولت في البلدان بدون خريطة، حاولت شق طريقي الخاص، ووجدت أشياء مذهلة، وأدركت مدى سعادتي بمغامرة مثل هذه.”
“When I was a child, I went hiking and found a lake. It was quite a surprise for me to stumble upon it. When I traveled around the country without a map, trying to find my way, stumbling on amazing things as I went, I realized how it felt to go on an adventure like this”
وفي كثير من ألعابه قام بالإستفادة مما حلم به ورآه في طفولته.

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

 

post

#13 المصفوفات Arrays – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : YIL

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C –  المصفوفات Arrays

السلام عليكم و رحمة الله و بركاته , و أهلا بكم في درس جديد من دروس سلسلة تعلم البرمجة للمبتدئين كلياً بواسطة الـ #C

في درس اليوم سنتكلم إن شاء الله عن المصفوفات أو الـ Arrays

تعريف المصفوفات :

يمكن تعريفها على أنها وعاء يحتوي على قيم بداخلها , أو هي عبارة عن صندوق فواكه يحتوي على عدداً من التفاح على سبيل المثال , و كل تفاحة لها قيمة الخاصة  ، و الصندوق الحامل لها يسمى المصفوفة .

 

نذهب إلى File  ثم New ثم project و نتأكد من اختيار #Visual Cو نختار Console App
تكلمنا سابقاً أن المكان المخصص لكتابة الأكواد البرمجية هو بين قوسي الدالة void Main

كي لا نضيع الوقت قمت بكتابة هذه الاسطر سابقاً و سأقوم بلصقها هنا

لاحظو أنني قمت بتعريف خمسة متغيرات هنا ، و كل متغير يحتوي على قيمة معينة

نريد الآن أن نقوم بالبحث عن الرقم 16 ، عندها سأكون مجبراً على كتابة جمل شرطية if statement  لكل متغير لكي أحصل على القيمة و أقارنها بالقيمة المطلوبة

في البداية نسأل هل قيمة المتغير number1 تساوي 16

ثم ننتقل إلى الثاني … الثالث ……. الخامس و هكذا

في هذه الحالة سأكون مضطراً لكتابة كل المتغيرات و كتابة عدد كبير من جمل if statement

هنا يأتي دور المصفوفة Array

سأقوم مبدئيا بتحويل الجمل السابقة إلى جمل ملاحظات

يمكن تعريف الـ array كالتالي

;int[ ] myNumber = new int [5]

لاحظو في هذا السطر قمت بتعريف مصفوفة اسمها myNumber  من النوع integer و تحتوي على خمس قيم

قمنا بكتابة الأقواس المربعة بعد النوع مباشرةً

الآن أصبح عندي 5 عناصر أو خمس خانات استطيع التعامل معهم

كيف يمكنني أن أقوم بإدخال قيم إلى هذه العناصر ؟

يمكننا فعل ذلك كالتالي :

;myNumber[0] = 10
;myNumber[1] = 22
;myNumber[2] = 14
;myNumber[3] = 66
;myNumber[4] = 22

الخانة الموجودة بين القوسين [ ] تسمى index

لذلك عندما تريد استدعاء عنصر ضمن المصفوفة تضع اسم المصفوفة و رقمه بين الأقواس [  ] مع ملاحظة أن الخانة الأولى يجب أن تحمل الرقم 0

إذاً من خلال الأسطر السابقة قمت بإدخال قيم إلى العناصر الموجودة ضمن الـ Array

الآن ماذا لو أردت أن أقوم بعملية استدعاء للقيم ؟

سأقوم من خلال التالي بطباعة قيمة أحد العناصر في المصفوفة

;Console.WriteLine(myNumber[2] )

 و لا ننسى كتابة الدالة ReadLine لنتمكن من مشاهدة النتائج.

نقوم بتشغيل التطبيق و نلاحظ أن التطبيق قام بطباعة القيمة 14

طريقة ثانية

الآن هناك طريقة ثانية لتعريف المصفوفة و إدخال القيم بها مباشرةً .

;int [ ] myNumbes = new int [ ] {1, 5 , 3 , 4 , 66 , 55 }

و كما تكلمنا لو اردنا طباعة القيمة رقم 3 فسنكتب :

; Console.WriteLine(myNumber[2] )

 

هناك إمكانية لطباعة ” عدد العناصر الموجودة داخل المصفوفة “

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

;Console.WriteLine(myNumber.Length)

هنا قمنا بطلب أخذ الـ Length ، و هو كم عدد العناصر الموجودة ضمن المصفوفة

و لو قمنا بعمل تشغيل للتطبيق ، سنحصل على القيمة 6 ، و هو فعلاً عدد عناصر المصفوفة السابقة .

في الاسطر السابقة استعملنا النوع integer ، و بالمثل يمكننا استعمال أي نوع آخر

مثلا هنا أقوم بكتابة

;  string[] myStrings = new string[] { “Ahmad”, “Mohammad”, “Shady”, “Safaa” }

و بالمثل سنقوم بطباعة قيمة العنصر رقم 3

 

;Console.WriteLine(myStrings[2] )

و لاحظ أنه قام بطباعة شادي

 

تحدثنا في المحاضرة السابقة عن For Loop Statement  التي تقوم بعملية تكرار لأوامر معينة ، لاحظة الآن سأقوم باستخدامها لطباعة كل عناصر المصفوفة

و ذلك كالتالي :

 

لاحظو أنه قام بطباعة كل عنصر من عناصر المصفوفة و ذلك بناءً على الـى Length

لاحظو أن عدد العناصر في المصفوفة هو 4 و هذا يعني أن myStrings.Length يساوي 4

و لذلك عندما وصل إلى الرقم 3 لقيمة i  فهو فعلياً وصل إلى آخر عنصر في المصفوفة ، و عندما أصبحت i = 4 يقوم بالخروج من الحلقة و ذلك لأن 4 تساوي 4 و ليست أصغر منها طبقاً لشرط الحلقة و بالتالي بعد أن أصبح شرط الحلقة غير محقق قام بالخروج منها

حلقة foreach

هناك أيضاً حلقة يتم استخدامها بشكل كبير مع المصفوفات ، ألا و هي  foreach

شرح هذه الحلقة :

بعد إضافة foreach  نقوم بتعريف متغير من النوع الذي تم تعريف المصفوفة به
و هنا قمنا بتعربفه من النوع string  تبعاً لنوع المصفوفة myStrings و بالنسبة لاسم المتغير الجديد فهو اختياري لأننا سنقوم باستخدامه حصراً ضمن الاقواس {  }

ثم نقوم بإضافة الكلمة المحجوزة in ثثم اسم المصفوفة و ذلك بدون أقواس [  ]

عمل الحلقة :

في كل مرة سيقوم بأخذ أحد العناصر (على الترتيب) ثم يقوم بإسناده الى المتغير name و يقوم بطباعته

و لاحظ أننا لم نقم بإعطائه الـ index  الخاص بالعنصر و إنما طلبنا منه أن يقوم بجلب جميع العناصر الموجودة داخل المصفوفة

 

 

هناك أيضاً إمكانية للتعامل بشكل أكبر مع المصفوفات :

 

إذا كان لدي نص معين و أردت أن أقوم بطباعة هذا النص بالعكس ( عمليةReverse )

هناك نوع جديد من أنواع البيانات هو النوع char و تكلمنا سابقاً أنه يقبل حرفاً واحداً فقط

;’char x = ‘a

الآن لدينا التالي :

;!! string myWords = “i need to go to the hospital now

يمكنني  أن أحصل على مصفوفة من myWords عن طريق الجملة :

;()Char[ ] x = myWords.ToCharArray

من خلال هذا الجملة نقوم بفصل جميع الحروف الموجودة في النص و تحويلها إلى عناصر في المصفوفة

myWords.ToCharArray تقوم بالعودة بمصفوفة يتم اسنادها للمصفوفة x  من النوع char

و نلاحظ هنا أننا قمنا بكتابة char و ليس فقط Array في myWords.ToCharArray لأنني أريد تحويل جميع الخانات خانة خانة إلى النوع char

الآن لو قمت بوضع بكتابة الحلقة foreach كما في التالي :

لو قمت بتنفيذ التطبيق سيقوم بطباعة الجملة حرف حرف في كل سطر

و لعكس المصفوفة نقوم بكتابة التالي :

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

 

طبعاً المصفوفات لها استخدامات أكثر مما تم ذكره ، و الدروس القادمة ستكون كفيلة بصقل مهارتك باستخدام الـ Array

نصل الآن إلى نهاية هذا الدرس ، ألقاك في الدرس التالي إن شاء الله .

ملخص الدرس :

تعريف المصفوفات:

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

المصفوفة Array :

يمكن تشبيه المصفوفة أنا عبارة عن صندوق فاكهة يحتوي تفاح، حيث أن هناك عدد كبير من التفاح غير أنه غير متساوي في المواصفات، فهناك الكبير وهناك ذو الحلاوة أكثر وهناك ذو الحمرة أكثر، غير أنهم يتشاركون بصفه أنهم جميعاً من النوع الواحد ألا وهو التفاح، والمصفوفة يمكن أن تكون أي نوع من أنواع البيانات الموجودة بداخل لغة السي شارب، سواءاً كانت نصية أو رقمية أو حتى متجهات ثلاثية البعد.
ويتم حجز المصفوفة بكنابة نوعها ثم أقواس مربعة ثم إسم المصفوفة ثم إعطاءها رقم للعناصر التي ستكون بداخلها هكذا :
int[] myNumbers = new int[5];

أو كما في المثال التالي :

مصطلحات الدرس :

Arrays :

Length :

foreach :

 index  :

Zero Base :

Reverse :

char :

ToCharAray :