القائمة الرئيسية

الصفحات

التعامل مع الدوال في الخوارزميات

مفهوم الدوال

دالة تعني Function أو Method في اللغة الإنجليزية. و تسمى ميثود أيضاً في العربية.


ما هي فكرة الدوال؟

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


ماذا تعني كلمة دالة؟

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


ما هي فائدة الدوال في البرامج؟

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

أنواع الدوال

إلى كم نوع تقسم الدوال؟

يمكننا تقسيم الدوال لنوعين أساسيين:

  1. دوال نوعها void أي تنفذ كود معين فقط و لا ترجع قيمة, أي لا تفعل return.

  2. دوال لها نوع معين مثل ( int أو double أو String.. ) تنفذ كود معين و ترجع قيمة , أي تفعل return.



تعريف دالة نوعها void

في المثال التالي قمنا بتعريف دالة نوعها void و إسمها DisplayMyInfo().
إنتبه: عند تعريف دالة نوعها void لا نضع الكلمة return.

الخوارزمية

كود الجافا



تعريف دالة لها نوع محدد

في المثال التالي قمنا بتعريف دالة نوعها int و إسمها getNumber().
إنتبه: عند تعريف دالة لها نوع محدد, يجب أن تفعل return لقيمة من نفس نوعها.
هنا بما أن نوع الدالة هو int, فعلنا return لقيمة نوعها int أيضاً و التي هي 50.

الخوارزمية

كود الجافا



إنتبه

عند تعريف أي دالة نوعها ليس void على الكمبيوتر, سيظهر لك أن هناك خطأ في الكود مباشرةً أثناء تعريفها.
فعلياً هذا ليس خطأ لكنه سيظل يظهر أن هناك خطأ في الكود إلى تفعل return لأي قيمة في الدالة.



طريقة إختيار نوع الدالة التي تنوي تعريفها

قبل أن تقوم بكتابة أي دالة عليك أن تسأل نفسك السؤال التالي حتى تعرف ماذا يجب أن يكون نوعها.
السؤال هو:   " لما أنا بحاجة إلى هذه الدالة؟ ".

هناك ثلاث إجابات محتلمة لهذا السؤال:

  1. تريد عرض شيء للمستخدم, هنا أنت بحاجة لأن يكون نوع الدالة void.

  2. تريد تغيير قيمة لمتغير, هنا أنت بحاجة لأن يكون نوع الدالة void.

  3. تريد إرجاع قيمة لها نوع محدد, هنا أنت بحاجة لأن يكون نوع الدالة هو النوع الذي تريد إرجاعه.

لا تقلق إذا لم تفهم كل شيء الآن لأنك ستفهم كل شيء بتفصيل لاحقاً من خلال الأمثلة.

طريقة تعريف دالة في الخوارزميات و في لغة جافا


خطوات تعريف دالة جديدة

  1. وضع public static من أجل لغة جافا فقط.

  2. تحديد نوع الدالة.

  3. إعطاء إسم للدالة.

  4. وضع قوسين ( ) من أجل الباراميترات التي يمكن وضعها للدالة (ستفهم المقصود في الدروس التالي).

  5. كتابة الأوامر التي ستتنفذ عند إستدعاء الدالة بين { }.



مكان تعريف دالة جديدة

عندما تريد أن تعرّف أي دالة, قم بتعريفها خارج حدود الدالة main() و ليس بداخلها, و عندما تحتاجها قم باستدعائها في الدالة main().
إذاً خارج حدود الدالة main() نقوم بتعريف أي دالة نريد, و عندما نريد تنفيذ أي دالة نقوم فقط باستدعائها في الدالة main() لكي يتم تنفيذها.



طريقة إستدعاء دالة معرّفة سابقاً

إستدعاء دالة تعني مناداة الدالة بإسمها حتى يتم تنفيذها.
لإستدعاء أي دالة قمت بتعريفها في الدالة main(), أكتب إسمها فقط و عندها يفهم الكمبيوتر أنك تريد تنفيذ الأوامر الموضوعة في هذه الدالة.

لا تقلق ستفهم كل شيء من خلال الأمثلة.



نقاط مهمة حول الدوال

  • عند تشغيل أي برنامج, فإن الكمبيوتر يبحث عن الدالة main(), و عندما يجدها يبدأ بتنفيذ الأوامر الموجودة فيها بالترتيب, أي لا ينتقل من أمر إلى آخر إلا إذا أنهى تنفيذ الأمر السابق.

  • لن يتم تنفيذ أي دالة أخرى غير الدالة main() ما لم تقم أنت باستدعائها بنفسك.

  • يمكنك تعريف العدد الذي تريده من الدوال في برنامجك.



مصطلحات تقنية

المصطلح بالعربية المصطلح بالإنجليزية معناها في البرمجة
إستدعاء call تعني كتابة إسم الدالة التي نريد أن يتم تنفيذ الأوامر الموضوعة فيها.
قفز jump هي مرحلة إنتقال سهم تنفيذ الأوامر إلى الدالة التي سيتم تنفيذها.
إرجاع return تعني إرجاع قيمة من نفس نوع الدالة.

لا تقلق إذا لم تفهم معنى هذه المصطلحات الآن لأنها ستمر معك في الأمثلة.

أمثلة شاملة و بسيطة تعلمك كيف تعرف دالة ثم تستدعيها

ملاحظة

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


تعريف دوال جديدة في الخوارزميات - المثال الأول

المثال التالي يعلمك طريقة بناء دالة مهمتها فقط عرض شيء للمستخدم.
الآن سنكتب دالة بسيطة إسمها DisplayMyInfo() تطبع لنا فقط بعض المعلومات عندما نقوم باستدعائها.


نتيجة التشغيل

كود الجافا

		public class Methods {

		public static void DisplayMyInfo()
		{
        System.out.print("My name is Mhamad Harmush \n");
        System.out.print("I am from Lebanon \n");
        System.out.print("I made harmash.com when I was 20 years old \n");
		}

		public static void main (String[] args)
		{
        DisplayMyInfo();
		}

		}
	  

شرح الكود


    			public static void DisplayMyInfo()
    			{
    			System.out.print("My name is Mhamad Harmush \n");
    			System.out.print("I am from Lebanon \n");
    			System.out.print("I made harmash.com when I was 20 years old \n");
    			}
    		  
  • هنا قمنا بتعريف دالة إسمها DisplayMyInfo() تحتوي على 3 أوامر طباعة.



  • 			public static void main (String[] args)
    			{
    			DisplayMyInfo();
    			}
    		  
  • هنا قمنا بإستدعاء الدالة DisplayMyInfo() حتى يتم تنفيذ جميع أوامر الطباعة الموضوعة بداخلها.

شرح عملية الإستدعاء بتفصيل



تعريف دوال جديدة في الخوارزميات - المثال الثاني

إنتبه

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

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


المثال التالي يعلمك طريقة بناء دالة مهمتها فقط إرجاع قيمة للمستخدم.
الآن سنكتب دالة بسيطة إسمها GetNumber() ترجع لنا العدد 50 فقط عندما نقوم باستدعائها.


نتيجة التشغيل

كود الجافا

		public class Methods {

		public static int GetNumber()
		{
        return 50;
		}

		public static void main (String[] args)
		{
        GetNumber();
		}

		}
	  

شرح الكود


    			public static int GetNumber()
    			{
    			return 50;
    			}
    		  
  • هنا قمنا بتعريف دالة إسمها GetNumber() ترجع القيمة 50 عندما يتم إستدعاءها في المكان الذي تم استدعاءها منه.



  • 			public static void main (String[] args)
    			{
    			GetNumber();
    			}
    		  
  • هنا قمنا بإستدعاء الدالة GetNumber() حتى ترجع لنا القيمة 50 في المكان الذي قمنا باستدعاءها منه.

  • ملاحظة: هنا تم إرجاع القيمة 50 حقاً في المكان الذي قمنا فيه باستدعاء الدالة GetNumber() حتى لو لم يظهر أي شيء في نتيجة التشغيل.
        لو قمنا بعرض القيمة التي أرجعتها الدالة لتأكدنا من ذلك.

شرح عملية الإستدعاء بتفصيل



تعريف دوال جديدة في الخوارزميات - المثال الثالث

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

الآن سنقوم بإضافة بعض التعديلات على البرنامج السابق و استدعاء الدالة GetNumber() مرتين.

  • في المرة الأولى سنعرض فقط القيمة التي ترجعها الدالة.

  • في المرة الثانية سنخزن القيمة التي ترجعها الدالة في متغير من نفس نوع الدالة.


نتيجة التشغيل

كود الجافا

		public class Methods {

		public static int GetNumber ( )
		{
        return 50;
		}

		public static void main (String[] args)
		{
        System.out.print("The function return: " +GetNumber()+ "\n");

        int a;
        a = GetNumber();
        System.out.print("a = " +a+ "\n");
		}

		}
	  

شرح الكود


    			public static int GetNumber ( )
    			{
    			return 50;
    			}
    		  
  • هنا قمنا بتعريف دالة إسمها GetNumber() ترجع القيمة 50 عندما يتم إستدعاءها في المكان الذي تم استدعاءها منه.



  • 			System.out.print("The function return: " +GetNumber()+ "\n");
    		  
  • هنا قمنا بعرض القيمة التي ترجعها الدالة GetNumber().



  • 			int a;
    			a = GetNumber();
    			System.out.print("a = " +a+ "\n");
    		  
  • هنا قمنا بتجهيز المتغير a لأننا سنستخدمه لتخزين القيمة التي ترجعها الدالة GetNumber().

  • ثم قمنا باستدعاء الدالة GetNumber() و وضع العدد الذي سترجعه كقيمة للمتغير a.

  • في الأخير قمنا بعرض قيمة المتغير a للتأكد أنه قد تم وضع القيمة التي أرجعتها الدالة GetNumber() فيه.

مفهوم الباراميتر

باراميتر تعني Parameter في اللغة الإنجليزية. الباراميتر عبارة عن متغير من أي نوع مثل ( int أو double أو String.. ) يتم تعريفه بين أقواس الدالة.


في المثال التالي قمنا بتعريف دالة إسمها Demo(), نوعها int, تملك باراميتر واحد نوعه int و إسمه a, و ترجع القيمة 0.

مثال

public static int Demo (int a)
{
    return 0;
} 
		

هل أنت مجبر على وضع باراميتر للدالة؟

كلا أنت لست مجبر, و إنما تضع باراميتر إذا كنت بحاجة له.
لاحظ أننا قمنا بتعرف الدالة Demo() من جديد بدون إعطائها أي باراميتر.

مثال

public static int Demo ()
{
    return 0;
} 
		

هل بإمكانك أن تضع أكثر من باراميتر للدالة؟

نعم بإمكانك وضع العدد الذي تريده من الباراميترات, شرط أن تحدد نوع كل باراميتر تقوم بإضافته و أن تضع فاصلة بين كل باراميترَين.
في المثال التالي قمنا بتعريف دالة إسمها Demo(), نوعها void, و تملك الباراميترات التالية:

  • الباراميتر الأول إسمه a و نوعه int.

  • الباراميتر الثاني إسمه b و نوعه double.

  • الباراميتر الثالث إسمه c و نوعه String.

  • الباراميتر الرابع إسمه d و نوعه boolean.

مثال

public static void Demo (int a, double b, String c, boolean d)
{

} 
		

ما هي الفائدة من الباراميترات و لم قد أحتاجهم؟

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


هل يمكن وضع قيم أولية للباراميترات؟

كلا, لا يمكن وضع قيم أولية للباراميترات, لأن فكرة الباراميترات الأساسية هي أن يتم إعطائهم القيم عند الإستدعاء.

إذاً, عند تعريف الباراميتر بداخل الدالة, لا يمكن وضع قيمة أولية له.
أما عند إستدعاء الدالة, فإنه يجب تمرير قيمة مكان كل باراميتر موضوع فيها.

مثال يوضح طريقة التعامل مع الباراميترات و فائدتهم

في المثال التالي قمنا بتعريف دالة إسمها Sum(), نوعها void, تحتوي على باراميترَين نوعهما int إسمهم a و b.
مهمة هذه الدالة هي طباعة ناتج جمع أي عددين صحيحين نضعهما فيها عند إستدعائها.


نتيجة التشغيل


كود الجافا

public class Parameters {
 
    public static void Sum (int a, int b)
    {
        System.out.print("The sum is: " + (a+b) + "\n");
    }
 
    public static void main (String[] args)
    {
        Sum(3, 4);
        Sum(5, 9);
        Sum(10, 20);
    }
 
}
		

شرح الكود

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



  • 	public static void Sum (int a, int b)
    	{
    		System.out.print("The sum is: " + (a+b) + "\n");
    	}
    				
  • هنا قمنا بتعريف دالة إسمها Sum() و مهمتها طباعة ناتج جمع أي عددين صحيحين نضعهما فيها عند إستدعائها.

  • إذاً عند إستدعاء هذه الدالة يجب أن نمرر لها عددين صحيحين بين أقواسها, و عندها سيحدث التالي:

    • سيقوم الكمبيوتر بوضع هذين العددين في المتغيرَين a و b بنفس الترتيب.

    • بعدها سيقوم بتنفيذ أمر الطباعة الموضوع في الدالة و الذي يقضي بعرض ناتج جمع العددين الموجودين في المتغيرَين a و b.



    	public static void main (String[] args)
    	{
    		Sum(3, 4);
    		Sum(5, 9);
    		Sum(10, 20);
    	}
    				
  • هنا قمنا باستدعاء الدالة Sum() ثلاث مرات, و كل مرة قمنا بإعطائها عددين مختلفين, و بالتالي سيعمل الكود كالتالي:

    • أول مرة: وضعنا فيها القيمتين 3 و 4 و بالتالي سيتم عرض ناتج جمع العددين هكذا:   The sum is: 7.

    • ثاني مرة: وضعنا فيها القيمتين 5 و 9 و بالتالي سيتم عرض ناتج جمع العددين هكذا:   The sum is: 14.

    • ثالث مرة: وضعنا فيها القيمتين 10 و 20 و بالتالي سيتم عرض ناتج جمع العددين هكذا:   The sum is: 30.

شرح عملية الإستدعاء بتفصيل

هكذا كان يتم تمرير الأعداد التي كنا نضعها بين أقواس الدالة Sum().


إنتبه

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

الفرق بين الكلمتين Parameter و Argument

أثناء تعريف الدالة, المتغيرات التي نقوم بتعريفها بين أقواسها تسمى Parameters.
بينما عندما نقوم باستدعاء الدالة و نعطيها قيم مكان كل باراميتر موضوع فيها, هذه القيم تسمى Arguments.


مثال


  • هنا المتغيرين a و b يعتبروا Parameters بالنسبة للدالة.

  • public static void Sum (int a, int b)
    {
        System.out.print("The sum is: " + (a+b) + "\n");
    } 
    				


  • هنا القيمتين 3 و 4 يعتبروا Arguments بالنسبة للدالة.

  • public static void main (String[] args)
    {
        Sum(3, 4);
    } 
    				

تمارين شاملة حول التعامل مع الباراميترات


التعامل مع الباراميترات في الخوارزميات - التمرين الأول

المطلوب

أكتب دالة إسمها Sum تعطيها عددين صحيحين عند إستدعاءها, فتقوم بطباعة ناتج جمع هذين العددين فقط.
بعدها أطلب من المستخدم إدخال عددين, ثم قم باستدعائها لطباعة ناتج جمع هذين العددين.


النتيجة المطلوبة

لنفترض أن المستخدم قام بإدخال العددين 8 و 14.

التعامل مع الباراميترات في الخوارزميات - التمرين الأول

الخوارزمية

كود الجافا

		import java.util.Scanner;

		public class Parameters {

		/* ------------------------------- هنا قمنا بتعريف الدالة ------------------------------ */

		public static void Sum (int a, int b)
		{
        System.out.print("The sum is: " + (a+b) + "\n");
		}

		/* --------------------------- من هنا يبدأ البرنامج بالتنفيذ --------------------------- */

		public static void main (String[] args)
		{

        Scanner input = new Scanner(System.in);

        int num1;
        int num2;

        System.out.print("Enter first number: ");
        num1 = input.nextInt();

        System.out.print("Enter second number: ");
        num2 = input.nextInt();

        Sum(num1, num2);

		}

		}
	  

شرح الكود


    			public static void Sum (int a, int b)
    			{
    			System.out.print("The sum is: " + (a+b) + "\n");
    			}
    		  
  • هنا أنشأنا الدالة Sum() و حددنا أن نوعها void لأننا لا نريدها أن ترجع قيمة, و وضعنا لها باراميترين a و b.

  • إذاً عند إستدعاء هذه الدالة, يجب أن نمرر لها قيمتين نوعهما int فتقوم بعرض ناتج جمع هاتين القيمتين فقط.



  • 			public static void main (String[] args)
    			{
    
    			Scanner input = new Scanner(System.in);
    
    			int num1;
    			int num2;
    
    			System.out.print("Enter first number: ");
    			num1 = input.nextInt();
    
    			System.out.print("Enter second number: ");
    			num2 = input.nextInt();
    
    			Sum(num1, num2);
    
    			}
    		  
  • بما أن الدالة main() تمثل نقطة البداية بالنسبة للكمبيوتر, فهذا يعني أنه عند تشغيل البرنامج سيبدأ بتنفيذ الأوامر الموضوعة فيها.

  • في السطرين 19 و 20 قمنا بتجهيز المتغير num1 لتخزين أول عدد سيدخله المستخدم لاحقاً. و المتغير num2 لتخزين ثاني عدد سيدخله المستخدم.

  • من السطر 22 إلى السطر 26 سيطلب من المستخدم إدخال عددين, و سيتم تخزينهما في المتغيرين num1 و num2.

  • في السطر 28 سيتم استدعاء الدالة Sum() و تمرير القيم التي أدخلها المستخدم لها. عندها سيتم عرض ناتج جمع القيمتين اللتين أدخلهما المستخدم.



التعامل مع الباراميترات في الخوارزميات - التمرين الثاني

المطلوب

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

ملاحظة: سبق أن شرحنا مبادئ المقارنة, لكننا الآن سنعلمك كيف تضع الكود في دالة و تستدعيه متى شئت.


النتيجة المطلوبة

لنفترض أن المستخدم أدخل القيمتين " 7 " و " 9 ".

التعامل مع الباراميترات في الخوارزميات - التمرين الثاني

الخوارزمية

كود الجافا

		import java.util.Scanner;

		public class Parameters {

		/* ------------------------------- هنا قمنا بتعريف الدالة ------------------------------ */

		public static int Maximum (int a, int b)
		{

        if ( a > b )
        {
		return a;
        }
        else
        {
		return b;
        }

		}

		/* --------------------------- من هنا يبدأ البرنامج بالتنفيذ --------------------------- */

		public static void main (String[] args)
		{

        Scanner input = new Scanner(System.in);

        int num1;
        int num2;

        System.out.print("Enter first number: ");
        num1 = input.nextInt();

        System.out.print("Enter second number: ");
        num2 = input.nextInt();

        System.out.print("The max is: "+ Maximum(num1, num2) +"\n");

		}

		}
	  

شرح الكود


    			public static int Maximum (int a, int b)
    			{
    
    			if ( a > b )
    			{
    			return a;
    			}
    			else
    			{
    			return b;
    			}
    
    			}
    		  
  • هنا أنشأنا الدالة Maximum() و حددنا أن نوعها int لأننا نريدها أن ترجع عدد صحيح, و وضعنا لها باراميترين a و b.

  • إذاً, عند إستدعاء هذه الدالة يجب أن نمرر لها عددين نوعهما int و عندها ستقوم بمقارنة هذين العددين و ترجع العدد الأكبر بينهما إلى المكان الذي تم إستدعاءها منه.



  • 			public static void main (String[] args)
    			{
    
    			Scanner input = new Scanner(System.in);
    
    			int num1;
    			int num2;
    
    			System.out.print("Enter first number: ");
    			num1 = input.nextInt();
    
    			System.out.print("Enter second number: ");
    			num2 = input.nextInt();
    
    			System.out.print("The max is: "+ Maximum(num1, num2) +"\n");
    
    			}
    		  
  • بما أن الدالة main() تمثل نقطة البداية بالنسبة للكمبيوتر, فهذا يعني أنه عند تشغيل البرنامج سيبدأ بتنفيذ الأوامر الموضوعة فيها.

  • في السطرين 28 و 29 قمنا بتجهيز المتغير num1 لتخزين أول عدد سيدخله المستخدم لاحقاً. و المتغير num2 لتخزين ثاني عدد سيدخله المستخدم.

  • من السطر 31 إلى السطر 35 سيطلب من المستخدم إدخال عددين, و سيتم تخزينهما في المتغيرين num1 و num2.

  • في السطر 37 قمنا باستدعاء الدالة Maximum() بداخل دالة الطباعة System.out.print() لطباعة العدد الأكبر بين العددين اللذين أدخلهما المستخدم.



التعامل مع الباراميترات في الخوارزميات - التمرين الثالث

المطلوب

أكتب دالة إسمها Average, يعطيها المستخدم علاماته المدرسية, فتحسب له معدله, ثم تطبع له نتيجته كالتالي:
- إذا كان معدله بين 10 و 20 ستطبع أنه ناجح.
- إذا كان معدله بين 0 و 9 ستطبع أنه راسب.
- إذا لم يكن معدله بين 0 و 20 ستطبع أن هناك خطأ في العلامات المدخلة.

في البرنامج, قم بتخزين أسماء المواد في مصفوفة إسمها Methods.
ثم أطلب من المستخدم إدخال علامة بين 0 و 20 لكل مادة و خزّن العلامات التي سيدخلها المستخدم في مصفوفة إسمها Notes.
في الأخير قم باستدعاء الدالة Average لطباعة معدل و نتيجة المستخدم.


إرشادات

لنفترض أن المستخدم عنده 5 مواد (Algorithm, Java, Android, Linux, Networks) و سيدخل علامة لكل مادة منهم كالتالي.

التعامل مع الباراميترات في الخوارزميات - التمرين الثالث

تذكر: أسماء المواد يجب أن يتم وضعها في المصفوفة Methods و علامة كل مادة يجب أن يتم تخزينها في المصفوفة Notes.


النتيجة المطلوبة

لنفترض أن المستخدم أدخل نفس القيم السابقة

الخوارزمية

كود الجافا

		import java.util.Scanner;

		public class Parameters {

		/* ------------------------------- هنا قمنا بتعريف الدالة ------------------------------ */

		public static void Average (double[] a)
		{

        double S = 0;

        for(int i=0; i<a.length; i++)
        {
		S = S + a[i];
        }

        S = S/a.length;

        System.out.print("Your average is: " +S+ "\n");

        if( S >= 10 && S  <= 20 )
        {
		System.out.print("Congratulations you have succeeded \n");
        }
        else if( S >= 0 && S < 10 )
        {
		System.out.print("Sorry you failed");
        }
        else
        {
		System.out.print("Impossible result! Please enter notes between 0 and 20 \n");
        }

		}

		/* --------------------------- من هنا يبدأ البرنامج بالتنفيذ --------------------------- */

		public static void main(String[] args)
		{

        Scanner input = new Scanner(System.in);

        double[] Notes = new double[5];
        String[] Methods = {"Algorithm", "Java", "Android", "Linux", "Networks"};

        for( int i=0; i<Notes.length; i++ )
        {
		do
		{
		System.out.print(Methods[i] + ": ");
		Notes[i] = input.nextDouble();
		}
		while( Notes[i] < 0 || Notes[i] > 20 );
        }

        System.out.print("------------------------- \n");
        Average(Notes);

		}

		}
	  

شرح الكود


    			public static void Average (double[] a)
    			{
    
    			double S = 0;
    
    			for(int i=0; i<a.length; i++)
    			{
    			S = S + a[i];
    			}
    
    			S = S/a.length;
    
    			System.out.print("Your average is: " +S+ "\n");
    
    			if( S >= 10 && S  <= 20 )
    			{
    			System.out.print("Congratulations you have succeeded \n");
    			}
    			else if( S >= 0 && S < 10 )
    			{
    			System.out.print("Sorry you failed");
    			}
    			else
    			{
    			System.out.print("Impossible result! Please enter notes between 0 and 20 \n");
    			}
    
    			}
    		  
  • هنا أنشأنا الدالة Average() و حددنا أن نوعها void لأننا لا نريدها أن ترجع قيمة, و وضعنا لها باراميتر عبارة عن مصفوفة نوعها double.

  • إذاً, عند إستدعاء هذه الدالة يجب أن نمرر لها مصفوفة ذات بعد واحد نوعها double.

  • في السطر 10, قمنا بتجهيز المتغير S و أعطينها القيمة 0 لأننا سنستخدمه لتخزين المعدل النهائي لقيم المصفوفة a.

  • من السطر 12 إلى السطر 15, أنشأنا الحلقة for للوصول إلى جميع قيم عناصر المصفوفة a.
        في كل دورة من دورات هذه الحلقة سيتم إضافة قيمة عنصر من عناصر المصفوفة a على قيمة المتغير S.

  • في السطر 17, قسمنا قيمة المتغير S على عدد عناصر المصفوفة a. إذاً, هنا أصبحت قيمة المتغير S تمثل معدل القيم الموجودة في المصفوفة a.

  • في السطر 19, سيتم عرض المعدل المخزن في المتغير S.

  • من السطر 21 إلى السطر 32, سيتم فحص المعدل المخزن في المتغير S كالتالي:

    • إذا كان المعدل بين 10 و 20 ( مثل 13.5) سيتم طباعة الجملة congartulation you did it !!!.

    • إذا كان المعدل أكبر من 0 و أصغر من 10 ( أي حتى و لو كان 9.9 ) سيتم طباعة الجملة sorry you failed.

    • إذا كان المعدل ليس بين 0 و 20 ( مثل 5- أو 38 ) سيتم طباعة الجملة you didn't enter your note correctly, please try again.
          لأنه من المستحيل أن يكون معدله عبارة عن عدد سلبي أو أكبر من أعلى معدل ممكن ( أي أكبر من 20 ).
      ملاحظة: في المنطق هذا الخطأ لا يمكن أن يحدث في جميع الأحوال عند إستدعاء هذه الدالة من الدالة main() لأننا في الدالة main() تأكدنا من كل علامة قام بإدخالها المستخدم قبل إستدعاء هذه الدالة.



    			public static void main(String[] args)
    			{
    
    			Scanner input = new Scanner(System.in);
    
    			double[] Notes = new double[5];
    			String[] Methods = {"Algorithm", "Java", "Android", "Linux", "Networks"};
    
    			for( int i=0; i<Notes.length; i++ )
    			{
    			do
    			{
    			System.out.print(Methods[i] + ": ");
    			Notes[i] = input.nextDouble();
    			}
    			while( Notes[i] < 0 || Notes[i] > 20 );
    			}
    
    			System.out.print("------------------------- \n");
    			Average(Notes);
    
    			}
    		  
  • في السطر 43, قمنا بتجهيز المصفوفة Notes لتخزين العلامات التي سيدخلها المستخدم و حددنا أنها تتألف من 5 عناصر لأننا سندخل فيها فقط 5 قيم, و حددنا نوعها double لأننا نريد الأخذ بعين الإعتبار الأرقام الموجود بعد الفاصلة.

  • في السطر 44, قمنا بتجهيز المصفوفة Methods لتخزين أسماء المواد التي سيطلب من المستخدم إدخال علامتها.

  • من السطر 46 إلى السطر 54, قمنا بإنشاء حلقتين متداخلتين يعملان كالتالي:

    • بما أن أسماء المواد موجودة في المصفوفة Methods و المصفوفة Notes مجهزة لتخزين علامات المستخدم, أنشأنا الحلقة i للمرور على قيم المصفوفتين بشكل متوازي, بحيث في كل دورة سيطلب من المستخدم إدخال علامة لمادة موجودة في عنصر من عناصر المصفوفة Methods و القيمة التي يدخلها المستخدم ستخزن في نفس index العنصر الموجود في المصفوفة Methods.

    • إذاً بواسطة الحلقة for سيتم المرور على عناصر المصفوفتين Methods و Notes بشكل متوازي.

    • و بواسطة الحلقة do while سيستمر الكمبيوتر في الطلب من المستخدم بإدخال علامة مادة معينة من المواد طالما أن العلامة التي يدخلها ليست بين 0 و 20.

  • في السطر 57, قمنا باستدعاء الدالة Average() و مررنا لها المصفوفة التي تحتوي على العلامات التي أدخلها المستخدم و التي تم تخزينها في المصفوفة Notes حتى يتم طباعة معدل المستخدم.



التعامل مع الباراميترات في الخوارزميات - التمرين الرابع

المطلوب

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

في البرنامج, قم بإنشاء مصفوفة ذات بعد واحد إسمها Numbers تحتوي على قيم أولية.
ثم أطلب من المستخدم إدخال أي عدد.
في الأخير قم باستدعاء الدالة FindFirst() لطباعة ما إذا كان الرقم الذي أدخله المستخدم موجود في المصفوفة أم لا.


إرشادات

إفترض أن المصفوفة Numbers تحتوي على القيم و أن المستخدم حاول البحث عن القيمة 5 فيها.

التعامل مع الباراميترات في الخوارزميات - التمرين الرابع


النتيجة المطلوبة

إذا إفترضنا أن المصفوفة تحتوي على نفس القيم الموضوعة في الصورة السابقة, و بحثنا عن العدد 16.

إذا إفترضنا أن المصفوفة تحتوي على نفس القيم الموضوعة في الصورة السابقة, و بحثنا عن العدد 5.

الخوارزمية

كود الجافا

		import java.util.Scanner;

		public class Parameters {

		/* ------------------------------- هنا قمنا بتعريف الدالة ------------------------------ */

		public static void FindFirst (int[] a, int b)
		{

        boolean stopSearch = false;
        int i = 0;

        while ( stopSearch == false && i<a.length )
        {
		if ( a[i] == b )
		{
		System.out.print(b+ " is exist at index number: " +i+ "\n");
		stopSearch = true;
		}
		i++;
        }

        if( stopSearch == false )
        {
		System.out.print(b+ " is not exist \n");
        }

		}

		/* --------------------------- من هنا يبدأ البرنامج بالتنفيذ --------------------------- */

		public static void main(String[] args)
		{

        Scanner input = new Scanner(System.in);

        int[] Numbers = {2, 7, 5, 6, 9, 14, 0, 5, 12, 5};
        int x;

        System.out.print("Find: ");
        x = input.nextInt();

        FindFirst(Numbers, x);

		}

		}
	  

شرح الكود


    			public static void FindFirst (int[] a, int b)
    			{
    
    			boolean stopSearch = false;
    			int i = 0;
    
    			while ( stopSearch == false && i<a.length )
    			{
    			if ( a[i] == b )
    			{
    			System.out.print(b+ " is exist at index number: " +i+ "\n");
    			stopSearch = true;
    			}
    			i++;
    			}
    
    			if( stopSearch == false )
    			{
    			System.out.print(b+ " is not exist \n");
    			}
    
    			}
    		  
  • هنا أنشأنا الدالة FindFirst() و حددنا أن نوعها void لأنها لن ترجع قيمة, و وضعنا لها باراميترين, الأول مصفوفة نوعها int و الثاني متغير نوعه int.

  • إذاً, عند إستدعاء هذه الدالة يجب أن نمرر لها مصفوفة و قيمة من النوع int.

  • في السطر 10, قمنا بتجهيز المتغير stopSearch لأننا سنستخدمه لإيقاف الحلقة while مباشرةً إذا تم إيجاد القيمة المراد البحث عنها في المصفوفة

  • في السطر 11, قمنا بتجهيز المتغير i لأننا سنستخدمه كعداد في الحلقة while.

  • من السطر 13 إلى السطر 21, أنشأنا الحلقة while للمرور على جميع عناصر المصفوفة طالما أن القيمة المراد البحث عنها في المصفوفة لم يتم إيجادها بعد.

    • في كل دورة من دورات الحلقة while سيتم مقارنة قيمة عنصر من عناصر المصفوفة مع قيمة المتغير b المراد البحث عنها.

    • في حال وجود عنصر في المصفوفة يملك نفس قيمة المتغير b, سيتم طباعة رقم index العنصر, ثم وضع القيمة true في المتغير stopSearch لجعل الحلقة while تتوقف.

  • من السطر 23 إلى السطر 26, سيتم فحص قيمة المتغير stopSearch, في حال بقيت false فهذا يعني أنه لم يتم إيجاد القيمة التي تم البحث عنها في المصفوفة, لذلك سيتم طباعة أنه لم يتم إيجاد القيمة المراد البحث عنها.



  • 			public static void main(String[] args)
    			{
    
    			Scanner input = new Scanner(System.in);
    
    			int[] Numbers = {2, 7, 5, 6, 9, 14, 0, 5, 12, 5};
    			int x;
    
    			System.out.print("Find: ");
    			x = input.nextInt();
    
    			FindFirst(Numbers, x);
    
    			}
    		  
  • في السطر 37, قمنا بإنشاء المصفوفة Numbers و حددنا نوعها int و أعطيناها قيم عشوائية مباشرةً عند إنشائها.

  • في السطر 38, قمنا بتعريف المتغير x لتخزين العدد الذي سيدخله المستخدم.

  • في السطرين 40 و 41, طلبنا من المستخدم إدخال العدد الذي يريد البحث عنه في المصفوفة و وضعناه في المتغير x.

  • في السطر 43, قمنا باستدعاء الدالة FindFirst() و مررنا لها المصفوفة التي تحتوي على الأعداد العشوائية و العدد الذي أدخله المستخدم حتى تبحث عن العدد الذي أدخله المستخدم في المصفوفة, ثم تطبع له نتيجة البحث.



التعامل مع الباراميترات في الخوارزميات - التمرين الخامس

المطلوب

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

في البرنامج, قم بإنشاء مصفوفة ذات بعد واحد إسمها Numbers تحتوي على قيم أولية.
ثم أطلب من المستخدم إدخال أي عدد.
في الأخير قم باستدعاء الدالة FindAll لطباعة index كل عنصر في المصفوفة يحتوي على نفس قيمة هذا العدد.


إرشادات

التعامل مع الباراميترات في الخوارزميات - التمرين الخامس


النتيجة المطلوبة

لنفترض أن المصفوفة تحتوي على نفس القيم الموضوعة في الصورة السابقة, و بحثنا عن العدد 1.

لنفترض أن المصفوفة تحتوي على نفس القيم الموضوعة في الصورة السابقة, و بحثنا عن العدد 5.

الخوارزمية

كود الجافا

		import java.util.Scanner;

		public class Parameters {

		/* ------------------------------- هنا قمنا بتعريف الدالة ------------------------------ */

		public static void FindAll (int[] a, int b)
		{

        int found = 0;

        for ( int i=0; i<a.length; i++ )
        {
		if ( a[i] == b )
		{
		System.out.print(b+ " is exist at index number: " +i+ "\n");
		found++;
		}
        }

        if( found == 0 )
        {
		System.out.print(b+ " is not exist \n");
        }

		}

		/* --------------------------- من هنا يبدأ البرنامج بالتنفيذ --------------------------- */

		public static void main(String[] args)
		{

        Scanner input = new Scanner(System.in);

        int[] Numbers = {2, 7, 5, 6, 9, 14, 0, 5, 12, 5};
        int x;

        System.out.print("Find all: ");
        x = input.nextInt();

        FindAll(Numbers, x);

		}

		}
	  

شرح الكود


    			public static void FindAll (int[] a, int b)
    			{
    
    			int found = 0;
    
    			for ( int i=0; i<a.length; i++ )
    			{
    			if ( a[i] == b )
    			{
    			System.out.print(b+ " is exist at index number: " +i+ "\n");
    			found++;
    			}
    			}
    
    			if( found == 0 )
    			{
    			System.out.print(b+ " is not exist \n");
    			}
    
    			}
    		  
  • هنا أنشأنا الدالة FindAll() و حددنا أن نوعها void لأنها لن ترجع قيمة, و وضعنا لها باراميترين, الأول مصفوفة نوعها int و الثاني متغير نوعه int.

  • إذاً, عند إستدعاء هذه الدالة يجب أن نمرر لها مصفوفة و قيمة من النوع int.

  • في السطر 10, قمنا بتجهيز المتغير found و أعطيناه القيمة 0 كقيمة أولية لأننا سنستخدمه لتخزين عدد المرات التي تم فيها إيجاد قيمة المتغير b بداخل المصفوفة a.

  • من السطر 12 إلى السطر 19, أنشأنا الحلقة for للمرور على جميع عناصر المصفوفة كالتالي:

    • في كل دورة من دورات الحلقة سيتم مقارنة قيمة عنصر من عناصر المصفوفة مع قيمة المتغير b المراد البحث عنها.

    • في حال وجود عنصر في المصفوفة يملك نفس قيمة المتغير b, سيتم طباعة رقم index العنصر, ثم إضافة 1 على قيمة المتغير found.

  • من السطر 21 إلى السطر 24, سيتم فحص قيمة المتغير found, في حال بقيت 0 فهذا يعني أنه لم يتم إيجاد القيمة التي تم البحث عنها في المصفوفة, لذلك سيتم طباعة أنه لم يتم إيجاد القيمة المراد البحث عنها.



  • 			public static void main(String[] args)
    			{
    
    			Scanner input = new Scanner(System.in);
    
    			int[] Numbers = {2, 7, 5, 6, 9, 14, 0, 5, 12, 5};
    			int x;
    
    			System.out.print("Find all: ");
    			x = input.nextInt();
    
    			FindAll(Numbers, x);
    
    			}
    		  
  • في السطر 35, قمنا بإنشاء المصفوفة Numbers و حددنا نوعها int و أعطيناها قيم عشوائية مباشرةً عند إنشائها.

  • في السطر 36, قمنا بتعريف المتغير x لتخزين العدد الذي سيدخله المستخدم.

  • في السطرين 38 و 39, طلبنا من المستخدم إدخال العدد الذي يريد البحث عنه في المصفوفة و وضعناه في المتغير x.

  • في السطر 41, قمنا باستدعاء الدالة FindAll() و مررنا لها المصفوفة التي تحتوي على الأعداد العشوائية و العدد الذي أدخله المستخدم حتى تبحث عن العدد الذي أدخله المستخدم في المصفوفة, ثم تطبع له نتيجة البحث.

مفهوم الـ Recursive Function

Recursion: تعني العودة إلى نفس المكان, أي تكرار نفس الشيئ.

Recursive Function: تعني دالة تفعل return لنفسها. أي تعيد إستدعاء نفسها بنفسها.

طريقة تعريف Recursive Function

عليك إعتماد الخطوات التالية عند تعريف أي دالة تستدعي نفسها:

  1. وضع نوع الدالة int أو أي نوع لا يقبل الفاصلة مثل النوع long.

  2. وضع باراميتر نوعه int, لأنه سيكون بمثابة عداد لتكرار عملية استدعاء الدالة.

  3. وضع شرط يحدد كم مرة ستقوم الدالة باستدعاء نفسها, أي كم مرة ستفعل return لنفسها.

  4. بما أن الدالة نوعها في الأساس int, علينا أن نجعلها ترجع أي قيمة نوعها int عندما تنتهي من تكرار نفسها إلى الدالة الأساسية main().
        أي يجب أن نفعل return لأي قيمة نوعها int ( مثل 0 ) حتى لا يظهر أخطاء في الكود.

  5. يجب على الأقل أن تحتوي على 2 return.



معلومة تقنية

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

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

الأخطاء المنطقية التي قد تواجه المبرمج عند تعريف Recursive Function

الآن سنكتب دالة بسيطة تستدعي نفسها لإعطاءك فكرة عامة حول شكل الـ Recursive Function و جعلك تعرف طبيعة المشكلة التي قد تحدث في حال لم تجعل الدالة تتوقف عن استدعاء نفسها و بالتالي معرفة أهمية وضع شرط عند كتابة Recursive Function.

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


الخوارزمية

شرح طريقة عمل الخوارزمية بدقة

كود الجافا

public class Recursion {
 
/* ------------------------------- هنا قمنا بتعريف الدالة ------------------------------ */
 
    public static int RecursiveFunction ()
    {
        return RecursiveFunction();
    }
 
/* --------------------------- من هنا يبدأ البرنامج بالتنفيذ --------------------------- */
 
    public static void main (String[] args)
    {
        RecursiveFunction();
    }
 
}
		

شرح الكود

  • عند تشغيل البرنامج, سيتم تنفيذ الأوامر الموجودة في الدالة main() في البداية, و بالتالي سيتم إستدعاء الدالة RecursiveFunction().

  • عند إستدعاء الدالة RecursiveFunction() ستظل تفعل return إلى نفسها بدون توقف, أي أنها في كل مرة تتنفذ سترجع إلى نفسها و تتنفذ من جديد.

  • في الواقع, هنا كأننا قلنا لها أن ترجع و تنفذ نفسها كلما نفذت نفسها!

  • إذاً ستبقى الدالة RecursiveFunction() ترجع إلى نفسها و تنفذ نفسها بدل أن ترجع إلى الدالة main() إلى اللانهاية كما في الصورة في التالية.


الأخطاء المنطقية في الكود السابق

  • الخطأ الأول: لم نضع شرط في الدالة RecursiveFunction() لكي نجعلها تتوقف بعد استدعائها لنفسها عدة مرات.

  • الخطأ الثاني: الدالة RecursiveFunction() لم ترجع قيمة إلى الدالة main() حيث تم إستدعاءها.

تمارين شاملة حول التعامل مع الباراميترات


تعريف دوال تستدعي نفسها في الخوارزميات - التمرين الأول

المطلوب

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

في البرنامج, قم باستدعاء الدالة CountFromTo لتجربتها.


النتيجة المطلوبة

إذا قمنا باستدعاء الدالة CountFromTo() و أعطيناها القيم 1 و 3, ستطبع لنا جميع الأعداد من 1 إلى 3 كالتالي.

الخوارزمية

شرح طريقة عمل الخوارزمية بدقة

كود الجافا

		public class Recursion {

		/* ------------------------------- هنا قمنا بتعريف الدالة ------------------------------ */

		public static int CountFromTo ( int start, int end ) {

        if ( start <= end )
        {
		System.out.print("counter = " +start+ "\n");
		return CountFromTo( start + 1, end );
        }

        return 0;

		}

		/* --------------------------- من هنا يبدأ البرنامج بالتنفيذ --------------------------- */

		public static void main (String[] args) {

        CountFromTo(1, 3);

		}

		}
	  

شرح الكود


    			public static int CountFromTo ( int start, int end ) {
    
    			if ( start <= end )
    			{
    			System.out.print("counter = " +start+ "\n");
    			return CountFromTo( start + 1, end );
    			}
    
    			return 0;
    
    			}
    		  
  • هنا أنشأنا الدالة CountFromTo() و حددنا أن نوعها int و وضعنا لها باراميترين start و end, هذان المتغيران يحددان كم مرة ستقوم الدالة باستدعاء نفسها.
        المتغير start يحدد من أي عدد ستبدأ عملية إستدعاء الدالة لنفسها, فعلياً سنستخدمه كعداد أيضاً حيث أننا سنضيف عليه 1 كلما استدعت الدالة CountFromTo() نفسها.
        المتغير end يحدد عند أي عدد ستتوقف الدالة عن إستدعاء نفسها من جديد.

  • إذاً, عند إستدعاء هذه الدالة يجب أن نمرر لها عددين من النوع int.

  • في السطر 7 إلى السطر 11, وضعنا شرط لمقارنة قيمة المتغيرين start و end.
        في هذا الشرط قلنا أنه إذا كانت قيمة المتغير start أصغر أو تساوي قيمة المتغير end سيحدث التالي:

    • أولاً سيتم عرض قيمة المتغير start.

    • بعدها سيتم إستدعاء CountFromTo() من جديد ( أي ستفعل return لنفسها ) مع زيادة قيمة العداد start واحداً.

    • إذاً في كل مرة تقوم الدالة CountFromTo() باستدعاء نفسها ستأخذ ( قيمة العداد start السابقة زائد 1 ) و قيمة المتغير endالثابتة كـ Arguments.

    • عندما تصبح قيمة المتغير start أكبر من قيمة المتغير end ستتوقف الدالة CountFromTo() عن إستدعاء نفسها.

  • في السطر 13, قلنا أنه بعد تتوقف الدالة CountFromTo() عن إستدعاء نفسها, سيتم إرجاع القيمة 0 إلى الدالة main() حيث تم إستدعاءها من الأساس.

  • ملاحظة: لو لم نضع الأمر return 0; في نهاية الدالة, كان سيظهر لك خطأ في البرنامج و السبب أن نوع الدالة في الأساس int, إذاً يجب أن ترجع أي قيمة نوعها int إلى المكان الذي تم استدعائها منه حتى لا يحدث خطأ.



  • 			public static void main (String[] args) {
    
    			CountFromTo(1, 3);
    
    			}
    		  
  • هنا قمنا باستدعاء الدالة CountFromTo() و مررنا لها القيمتين 1 و 3, بالتالي سيتم طباعة جميع الأعداد الصحيحة من 1 إلى 3.

  • إذاً أول قيمة للعداد start ستكون 1, و آخر قيمة ستكون 4, لأنها عندما تصبح أكبر من قيمة المتغير end ستتوقف عن استدعاء نفسها.



تعريف دوال تستدعي نفسها في الخوارزميات - التمرين الثاني

المطلوب

أكتب دالة تستدعي نفسها, إسمها CountRecursively, تعطيها عدد صحيح أكبر من 0, فتقوم بطباعة جميع الأعداد الصحيحة الموجودة من هذا العدد وصولاً إلى 1 بشكل تنازلي.

في البرنامج, قم باستدعاء الدالة CountRecursively لتجربتها.


النتيجة المطلوبة

الخوارزمية

شرح طريقة عمل الخوارزمية بدقة

كود الجافا

		public class Recursion {

		/* ------------------------------- هنا قمنا بتعريف الدالة ------------------------------ */

		public static int CountRecursively ( int counter ) {

        if ( counter != 0 )
        {
		System.out.print("counter = " +counter+ "\n");
		return CountRecursively( counter - 1 );
        }

        return 0;

		}

		/* --------------------------- من هنا يبدأ البرنامج بالتنفيذ --------------------------- */

		public static void main (String[] args) {

        CountRecursively(3);

		}

		}
	  

شرح الكود


    			public static int CountRecursively ( int counter ) {
    
    			if ( counter != 0 )
    			{
    			System.out.print("counter = " +counter+ "\n");
    			return CountRecursively( counter - 1 );
    			}
    
    			return 0;
    
    			}
    		  
  • هنا أنشأنا الدالة countRecursively() و حددنا أن نوعها int و وضعنا لها الباراميتر counter و نوعه int أيضاً.

  • إذاً, عند إستدعاء هذه الدالة يجب أن نمرر لها أي عدد من النوع int.

  • المتغير counter سيمثل العداد الذي يحدد كم مرة ستقوم الدالة باستدعاء نفسها حيث أنه سيتم إنقاص 1 من قيمته كلما استدعت الدالة نفسها.

  • الشرط الموضوع فيها يعني أنه إذا لم تكن قيمة المتغير counter تساوي 0, سيتم عرض قيمة المتغير counter, ثم إستدعاء الدالة من جديد مع إنقاص 1 من قيمة المتغير counter.

  • إذاً هذه الدالة تستمر في إستدعاء نفسها طالما أن قيمة المتغير counter لا تساوي 0 بعد.

  • في الأخير و بعد أن تتوقف الدالة عن إستدعاء نفسها, سيتم إرجاع القيمة 0 إلى الدالة main() حيث تم إستدعاءها من الأساس.

  • ملاحظة: لو لم نضع الأمر return 0; في نهاية الدالة, كان سيظهر لك خطأ في البرنامج و السبب أن نوع الدالة في الأساس int, إذاً يجب أن ترجع أي قيمة نوعها int إلى المكان الذي تم استدعائها منه حتى لا يحدث خطأ.



  • 			public static void main (String[] args) {
    
    			CountRecursively(3);
    
    			}
    		  
  • هنا قمنا باستدعاء الدالة CountRecursively() و مررنا لها القيمة 3.

  • إذاً أول قيمة للعداد counter ستكون 3, و آخر قيمة له ستكون 0.



تعريف دوال تستدعي نفسها في الخوارزميات - التمرين الثالث

المطلوب

أكتب دالة تستدعي نفسها إسمها Factorial, تعطيها عدد صحيح, فترجع الـ Factorial لهذا العدد.

في البرنامج, قم باستدعاء الدالة Factorial لتجربتها.


إرشادات

قيمة الـ Factorial لأي عدد صحيح تساوي ضرب جميع الأعداد الصحيحة من 1 إلى هذه العدد.
مع الإشارة إلى أننا شرحنا مبدأ الـ Factorial في دروس سابقة.


النتيجة المطلوبة

لنفترض أننا أعطينا الدالة Factorial القيمة " 4 " عند إستدعائها.

الخوارزمية

شرح طريقة عمل الخوارزمية بدقة

كود الجافا

		public class Recursion {

		/* ------------------------------- هنا قمنا بتعريف الدالة ------------------------------ */

		public static int Factorial (int n) {

        if ( n > 0 )
        {
		return n * Factorial( n - 1 );
        }

        return 1;

		}

		/* --------------------------- من هنا يبدأ البرنامج بالتنفيذ --------------------------- */

		public static void main (String[] args) {

        System.out.print(Factorial(4) +"\n");

		}

		}
	  

ملاحظة

يمكن التلاعب بالشرط الموضوع في الدالة Factorial() و الحصول على نفس النتيجة.
فمثلاً يمكنك تبديل الشرط if ( n > 0 ) بالشرط if ( n != 0 ) أو if ( n > 1 ).

الفائدة من تقليص حجم الكود

لما يجب دائماً أن تحاول جعل حجم الكود أصغر؟

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


كيف يمكنك جعل حجم الكود أصغر؟

يمكنك ذلك بثلاث طرق:

  1. باستخدام الحلقات و الدول لعدم تكرار الكود.

  2. بعدم كتابة أي كود يمكن الإستغناء عنه.

  3. أسلوب المبرمج و براعته في التحليل.

تقليص حجم الكود باستخدام الحلقات

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


أسلوب كتابة الكود التالي يعتبر سيء جداً.

مثال

System.out.print("Hello Algorithm");
System.out.print("Hello Algorithm");
System.out.print("Hello Algorithm");
System.out.print("Hello Algorithm");
System.out.print("Hello Algorithm");
System.out.print("Hello Algorithm");
System.out.print("Hello Algorithm");
System.out.print("Hello Algorithm");
System.out.print("Hello Algorithm");
System.out.print("Hello Algorithm"); 
		

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

مثال

for( int i=0; i<10; i++ )
{
    System.out.print("Hello Algorithm");
} 
		

الآن سنكتبه كله على سطر واحد بداخل حلقة أيضاً, و نجعله يتكرر على قدر ما نحتاج.
أسلوب كتابة الكود التالي يعتبر سيء جداً بالنسبة للمبرمج لأن تصحيحه و التعديل عليه مستقبلاً سيكون متعب جداً.

مثال

for( int i=0; i<10; i++ ) { System.out.print("Hello Algorithm"); } 
		

إنتبه

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

تقليص حجم الكود بعدم كتابة أي كود يمكن الإستغناء عنه

في أغلب لغات البرمجة, يمكنك أن لا تضع أقواس البداية و النهاية { } مع الحلقات و الشروط إذا كنت قد وضعت بداخلهم أمر واحد فقط.
السبب في ذلك أنك بالمنطق تستخدم الحلقة لتكرار عملية واحدة على الأقل, و تضع شرط لكي تنفذ عملية واحدة على الأقل.
بمعنى آخر, عندما تستخدم حلقة أو شرط يتوقع منك البرنامج أن تضع فيهم على الأقل أمر واحد, لذلك إذا كنت تريد وضع أمر واحد بداخل الحلقة أو الشرط لا تضع أقواس البداية و النهاية لأنك لا تحتاجهم.



كتابة كود الحلقة بأفضل طريقة ممكنة

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

مثال

for( int i=0; i<10; i++ )
    System.out.print("Hello Algorithm"); 
		


كتابة كود الشروط بأفضل طريقة ممكنة

الآن سنرى كيف نستطيع التخلي عن أقواس البداية و النهاية في الشروط.
لنفترض أنه عندنا متغير عادي نريد إختبار قيمته.

مثال

int x = 5;

if( x > 0 )
{
    System.out.print( x+ " is positive.");
}
else if( x < 0 )
{
    System.out.print( x+ " is negative.");
}
else
{
    System.out.print( x+ " is zero.");
}
		

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

مثال

int x = 5;

if( x > 0 )
    System.out.print( x+ " is positive.");

else if( x < 0 )
    System.out.print( x+ " is negative.");

else
    System.out.print( x+ " is zero."); 
		

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

تقليص حجم الكود حسب أسلوب المبرمج و براعته في التحليل

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

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