مقدمة
قبل أن نكتب أمرا واحدا نسأل: ما الذي يعمله الحاسوب أصلا، وكيف نكلّمه؟ في هذا الفصل نتعرف إلى هندسة الحاسوب، نحلّل مهمة بسيطة، نشغّل أول برنامج، ثم نلتقي بأول كائن: سلحفاة ترسم على الشاشة بالأوامر التي نعطيها لها.
- نرى كيف يحل الحاسوب مشكلات من مجالات مختلفة، وما الذي يجعل المشكلة تحديا حسابيا.
- نحلّل مهمة بسيطة: المعطى، المطلوب والخطوات، ونكتب لها خوارزمية.
- نكتب برنامجا ونشغّله، نفحصه ونصلح أخطاءه، في بيئة تطوير حقيقية.
- نميّز بين الفئة والكائن، ونقرأ واجهة فئة جاهزة.
- نرسم في المستوى بالفئة
Turtle، وننشئ منها أكثر من كائن واحد.
1.1 هندسة الحاسوب وتحديات حسابية – הנדסת מחשבים ואתגרים חישוביים
الحاسوب ليس فقط الجهاز الذي على الطاولة: يوجد حاسوب صغير في الهاتف، في السيارة، في الغسالة وفي إشارة المرور. نقول إن أمامنا تحديا حسابيا (אתגר חישובי) عندما يكون الحساب نفسه هو العقبة: المعطيات كثيرة جدا، أو الوقت قصير جدا، أو الإمكانات أكثر من أن يجرّبها إنسان. هكذا يدخل الحاسوب إلى مجالات لا علاقة لها في الظاهر بالإلكترونيات:
| المجال | التحدي | ما يحسبه الحاسوب |
|---|---|---|
| الطب | مراقبة قلب مريض طوال اليوم | يحلّل الإشارة عيّنة بعد عيّنة، وينذر عند اضطراب النبض |
| النقل | أسرع طريق في مدينة مزدحمة | يقارن بين عدد هائل من الطرق، ويعيد الحساب كلما تغيّر الازدحام |
| الطاقة | شبكة كهرباء فيها ألواح شمسية | يوازن لحظة بلحظة بين ما يُنتَج وما يُستهلَك |
| الصناعة | فحص كل قطعة على خط إنتاج | يقارن صورة كل قطعة بالنموذج خلال جزء من الثانية |
لا يستطيع طبيب أن ينظر إلى هذا العدد من القيم. البرنامج يمر عليها كلها، ويعرض عليه فقط اللحظات التي فيها شيء غير عادي. الطبيب يقرّر، والحاسوب يوفّر له ما يحتاج إليه كي يقرّر.
1.2 مهام حسابية بسيطة – משימות חישוביות פשוטות
لا نبدأ بالشيفرة، بل بثلاثة أسئلة: ما المعطى؟ ما المطلوب؟ ما الخطوات التي توصلنا من المعطى إلى المطلوب؟ الإجابة عن السؤالين الأولين هي تحليل المهمة (ניתוח המשימה)، والإجابة عن الثالث هي صياغة الحل.
| أسود | بنّي | أحمر | برتقالي | أصفر | أخضر | أزرق | بنفسجي | رمادي | أبيض |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
المعطى: ثلاثة ألوان، وجدول يحوّل كل لون إلى رقم. المطلوب: قيمة المقاومة بالأوم. الخطوات:
- نحوّل لون الشريط الأول إلى رقم. هذا رقم العشرات.
- نحوّل لون الشريط الثاني إلى رقم. هذا رقم الآحاد.
- نحوّل لون الشريط الثالث إلى رقم، ونسميه n.
- نضرب العدد الذي حصلنا عليه من الشريطين الأولين في 10n. الناتج هو القيمة بالأوم.
بنّي يعني 1، أسود يعني 0، فالعدد هو 10. أحمر يعني n = 2:
قد تكون للمهمة نفسها أكثر من خوارزمية صحيحة، وبعضها أفضل من بعض.
المعطى: 16 مصباحا، والمقطع الذي فيه المصباح المحترق لا يوصل. المطلوب: المصباح المحترق. نقارن بين خوارزميتين:
| الخوارزمية | الخطوات | الفحوص في أسوأ حالة |
|---|---|---|
| واحدا بعد واحد | نفحص المصباح الأول، ثم الثاني، وهكذا، حتى نجد الذي لا يوصل | 15، فإذا سلمت الخمسة عشر فالأخير هو المحترق |
| التنصيف | نفحص نصف السلسلة. إذا وصل فالمحترق في النصف الآخر، وإلا فهو في هذا النصف. ثم ننصّف ما بقي، حتى يبقى مصباح واحد | 4: من 16 إلى 8، إلى 4، إلى 2، إلى 1 |
الخوارزميتان صحيحتان، لكن الثانية أوفر بكثير، وكلما طالت السلسلة زاد الفرق. سنعود إلى النجاعة (יעילות) في الفصل 4.
1.3 لغة البرمجة – שפת תכנות
المعالج لا يفهم إلا أوامر بسيطة جدا مكتوبة بأصفار وآحاد، ونحن لا نستطيع أن نكتب برامج طويلة بهذه الطريقة. كما أن العربية والعبرية لا تصلحان، لأن الجملة فيهما قد تحتمل أكثر من معنى. لغة البرمجة هي الحل الوسط بينهما.
نكتب في هذا الكتاب بلغة بايثون Python. برنامج يسمى المفسّر (מפרש) يقرأ ما كتبنا، يفحص أولا صحة الكتابة، ثم ينفّذ الأوامر واحدا بعد واحد:
لكل لغة كلماتها، لكن الفكرة واحدة. هذا الأمر نفسه، طباعة جملة على الشاشة، في ثلاث لغات:
| اللغة | أين نلتقيها | الأمر |
|---|---|---|
| Python | هذا الكتاب، تحليل المعطيات، الاتصال بالأجهزة | print("Power on") |
| C++ | لوحة أردوينو | Serial.println("Power on"); |
| C# | تطبيقات الحاسوب | Console.WriteLine("Power on"); |
print وPrint كلمتان مختلفتان، لأن الحروف الكبيرة والصغيرة مختلفة.(أ)
print("Ready")(ب)
Print("Ready")(ج)
print("Ready(د)
print "Ready"1.4 البرنامج: قراءة، كتابة، تشغيل، فحص وتصحيح – התוכנית: קריאה, כתיבה, הרצה, בדיקה ותיקון
العمل على برنامج ليس كتابة مرة واحدة ثم انتهينا، بل دورة نكررها حتى يصبح صحيحا. ونادرا ما يعمل البرنامج بشكل صحيح من المرة الأولى، وهذا عادي:
القراءة. نقرأ البرنامج من الأعلى إلى الأسفل، ونتوقع ماذا سيفعل قبل أن نشغّله. الدالة print تطبع على الشاشة ما بين القوسين. والسطر الذي يبدأ بالإشارة # هو تعليق (הערה): كتبناه لمن يقرأ، والمفسّر يتجاهله. والترتيب هو البرنامج: الأوامر نفسها بترتيب آخر تعطي مُخرَجا آخر.
print("Sensor test")
print("Reading:", 25)
# the next line runs last
print("Done")Sensor test Reading: 25 Done
print("Done")
print("Sensor test")
print("Reading:", 25)Done Sensor test Reading: 25
الكتابة. نكتب أمرا واحدا في كل سطر، ونحفظ البرنامج في ملف نهاية اسمه .py.
print("Start")
print("End")IndentationError: unexpected indent
التشغيل. نطلب من المفسّر أن ينفّذ البرنامج، وما يطبعه هو المُخرَج (פלט). الفحص. نقارن المُخرَج بما توقعناه. التصحيح. إذا اختلفا نبحث عن السبب، نصلحه، ونشغّل من جديد.
المحاولة الأولى: نسينا علامة الاقتباس التي تغلق الجملة، فرفض المفسّر البرنامج كله، ولم يُطبع حتى السطر الأول. المحاولة الثانية: أغلقنا الجملة، لكننا كتبنا حرفا كبيرا. هذه المرة نُفّذ السطر الأول، وتوقف البرنامج عند الخطأ.
print("Battery check")
print("Voltage: 9 V)SyntaxError: unterminated string literal (detected at line 2)
print("Battery check")
Print("Voltage: 9 V")Battery check NameError: name 'Print' is not defined
المحاولة الثالثة: لا رسالة خطأ. لكن هل المُخرَج صحيح؟ تيار يزيد على 200 A من بطارية صغيرة؟ مستحيل. الحاسوب قسم 9 على 100 أولا ثم أضاف 200، ونحن نريد أن يجمع المقاومتين قبل القسمة. نضيف قوسين، فنحصل على البرنامج الثاني:
print("Battery check")
print("Voltage: 9 V")
print("Current:", 9 / 100 + 200, "A")Battery check Voltage: 9 V Current: 200.09 A
print("Battery check")
print("Voltage: 9 V")
print("Current:", 9 / (100 + 200), "A")Battery check Voltage: 9 V Current: 0.03 A
الآن المُخرَج معقول، ويطابق ما نحسبه بأيدينا: 9 مقسومة على 300. وسنتعلم المعاملات الحسابية بالتفصيل في الفصل 2.
print("A")
print()
print("B", "C")
print(2 + 3)
print("2 + 3")1.5 بيئة التطوير وأول برنامج – סביבת הפיתוח ותוכנית ראשונה
توصي خطة التعليم بأن نتعرف إلى بيئتين: بيئة على الإنترنت، وبيئة نثبّتها على الحاسوب. نتعرف هنا إلى Google Colab وإلى IDLE. توجد بيئات أخرى مثل Visual Studio Code وPyCharm، والبرنامج نفسه يعمل فيها كلها.
| Google Colab | IDLE | |
|---|---|---|
| أين يعمل | في المتصفح، والبرنامج يعمل على خادم بعيد | على حاسوبنا |
| ما نحتاج إليه | حساب Google واتصال بالإنترنت | تثبيت بايثون من الموقع python.org، وIDLE يأتي معه |
| أين يُحفظ العمل | دفتر في Google Drive | ملف .py على الحاسوب |
| Turtle | لا يعمل، فالخادم البعيد لا شاشة له | يعمل، وتُفتح له نافذة |
في Google Colab:
- ندخل إلى
colab.research.google.comونختار دفترا جديدا. - نكتب البرنامج في المربع الذي يظهر، وهو الخلية.
- نضغط زر التشغيل بجانب الخلية، أو
Shift+Enter، فيظهر المُخرَج تحتها.
في IDLE:
- نفتح
IDLE، فتظهر نافذةShell. - نختار
File > New File، ونكتب البرنامج في النافذة الجديدة. - نحفظ بواسطة
File > Saveباسم مثلfirst.py. - نضغط
F5، فيظهر المُخرَج في نافذةShell.
أول برنامج لنا سطر واحد. الدالة print تطبع ما بين القوسين، وتنتقل إلى السطر التالي. والنص بين علامتي الاقتباس يُطبع حرفا بحرف. وإذا لم يكن بين القوسين شيء طُبع سطر فارغ، كما في البرنامج الثاني:
print("Hello from the lab")Hello from the lab
print("Measuring station")
print("Power on")
print()
print("Ready")Measuring station Power on Ready
ما بين علامتي الاقتباس يُطبع كما هو، وما ليس بينهما يُحسب أولا. وعندما نفصل بين القيم بفاصلة، تطبعها print في السطر نفسه مع مسافة بينها.
print("7 * 6")
print(7 * 6)
print("Seconds:", 24 * 60 * 60)7 * 6 42 Seconds: 86400
print(“Power on”)
SyntaxError: invalid character '“' (U+201C)
Solar panel ، Battery ، Gauge1.6 الكائن نسخة من فئة – העצם כמופע של מחלקה
نفتح خزانة المختبر فنجد اثني عشر مقياسا متعددا من الطراز نفسه. لها كلها الأزرار نفسها والقدرات نفسها، لأنها صُنعت حسب تصميم واحد. لكن كل مقياس شيء مستقل: هذا على مجال 20 V ويقرأ 11.9، وذاك مطفأ.
ما يحمله الكائن يسمى الصفات (תכונות)، وما يستطيع أن يفعله يسمى العمليّات (פעולות). الكائنات تشترك في أسماء الصفات وفي العمليّات، أما قيم الصفات فلكل كائن قيمه:
| الفئة | كائنان منها | صفات | عمليّات |
|---|---|---|---|
| ثنائي باعث للضوء | الأحمر الذي على اللوحة، والأخضر بجانبه | اللون، مضاء أم لا | إضاءة، إطفاء |
| بطارية | بطارية السيارة، وبطارية جهاز الإنذار | الجهد، السعة | شحن، تفريغ |
| هاتف | هاتفي، وهاتف صديقي | الرقم، الشحن | اتصال، إرسال رسالة |
1.7 فئة جاهزة: Turtle – מחלקה קיימת: Turtle
تأتي مع بايثون فئات جاهزة كثيرة. نبدأ بفئة نرى عملها بأعيننا: Turtle، أي السلحفاة. نتخيل سلحفاة صغيرة تمشي على الشاشة وتجرّ قلما، فترسم خطا حيث تمشي. كائن من هذه الفئة يظهر كسهم صغير، ونعطيه الأوامر فيتحرك.
نافذة Turtle هي مستوى ثنائي الأبعاد (מישור דו-ממדי) له محوران. النقطة (0, 0) في وسط النافذة، x يكبر نحو اليمين، وy يكبر نحو الأعلى. كل نقطة تُكتب (x, y)، وx أولا دائما. يولد الكائن في (0, 0) واتجاهه نحو اليمين. الأمران forward وbackward يحرّكانه في اتجاهه الحالي، والأمران right وleft يديرانه في مكانه، بالدرجات.
برنامج Turtle الأول:
import turtle pen = turtle.Turtle() pen.forward(100) print(pen.position()) turtle.done()
(100.00,0.00)
import turtleيجلب الوحدة الجاهزة، ونكتبه مرة واحدة في بداية البرنامج.pen = turtle.Turtle()ينشئ كائنا جديدا من الفئةTurtle، ويعطيه الاسمpen. الاسم من اختيارنا.turtleبحرف صغير هي الوحدة، وTurtleبحرف كبير هي الفئة التي في داخلها.pen.forward(100)نعطي بها الكائن أمرا: اسم الكائن، نقطة، اسم العمليّة، وبين القوسين ما تحتاج إليه. هنا يتقدم الكائن 100 خطوة.print(pen.position())نسأل الكائن أين هو، ونطبع الجواب.turtle.done()يبقي النافذة مفتوحة حتى نغلقها. من دونه قد تُغلق النافذة، في بعض البيئات، فور انتهاء البرنامج ولا نلحق أن نرى الرسم.
turtle.py: عندها يجد import turtle ملفنا نحن بدل الوحدة الجاهزة، ويتوقف البرنامج. نسميه مثلا draw1.py. ولا نجرّب Turtle في Google Colab، بل نستعمل IDLE أو بيئة أخرى على الحاسوب.الحركة والدوران:
الدوران نفسه لا يرسم شيئا ولا يغيّر الموقع: left تغيّر الاتجاه فقط، والتقدم بعدها يكون في الاتجاه الجديد. والأمر backward يعيد الكائن إلى الخلف على الخط نفسه من دون أن يدور، ولذلك يبقى السهم متجها نحو الأعلى:
import turtle pen = turtle.Turtle() pen.forward(100) pen.left(90) pen.forward(50) pen.backward(20) print(pen.position()) turtle.done()
(100.00,30.00)
right وleft هما بالنسبة إلى السهم، لا بالنسبة إلى الصفحة. إذا كان السهم متجها نحو الأسفل، فإن right(90) تديره نحو اليسار في الصفحة.نتقدم وندور، أربع مرات:
import turtle pen = turtle.Turtle() pen.forward(100) pen.right(90) pen.forward(100) pen.right(90) pen.forward(100) pen.right(90) pen.forward(100) pen.right(90) turtle.done()
هذا يعمل، لكننا كتبنا الزوج نفسه من الأوامر أربع مرات. ماذا لو أردنا شكلا له 20 ضلعا؟ في الفصل 4 نتعلم الحلقة، أي أن نقول للحاسوب «كرّر هذا»، فنكتب زوج الأوامر مرة واحدة فقط.
رفع القلم واللون:
الأمر penup يرفع القلم، فيتحرك الكائن بعده من دون أن يرسم، والأمر pendown يعيده إلى الورقة. ولهما اسمان أقصر: up وdown. والأمر color يغيّر لون القلم، واسم اللون جملة نصية بالإنجليزية بين علامتي اقتباس، ويسري على كل ما يُرسم بعده. نرسم بها تدريجا بلونين:
import turtle
pen = turtle.Turtle()
pen.color("green")
pen.forward(80)
pen.penup()
pen.forward(15)
pen.pendown()
pen.color("red")
pen.forward(40)
pen.up()
pen.forward(15)
pen.down()
pen.forward(40)
turtle.done()الانتقال إلى نقطة:
الأمر goto(x, y) ينقل الكائن مباشرة إلى النقطة (x, y) في خط مستقيم، من دون أن يغيّر اتجاهه. وهو مريح عندما نعرف الإحداثيات، إذ لا نحتاج إلى حساب أي زاوية:
import turtle pen = turtle.Turtle() pen.goto(50, 50) pen.goto(100, 0) pen.goto(150, 50) pen.goto(200, 0) print(pen.position()) turtle.done()
(200.00,0.00)
goto يرسم خطا في الطريق. وإذا أردنا الانتقال إلى مكان آخر بلا خط، نرفع القلم قبله ونعيده بعده.import turtle pen = turtle.Turtle() pen.forward(50) pen.left(90) pen.forward(30) pen.backward(10) print(pen.position()) turtle.done()
1.8 قراءة واجهة بسيطة لفئة – קריאת ממשק פשוט של מחלקה
كي نستعمل المقياس المتعدد لا نحتاج إلى أن نعرف ما في داخله. يكفي أن نعرف الأزرار والمآخذ. وهكذا الفئة الجاهزة.
ما تحتاج إليه العمليّة بين القوسين يسمى الوسيط (פרמטר)، ونحن نكتب هناك القيمة التي نعطيها له. هذه واجهة ما تعلمناه حتى الآن من الفئة Turtle:
| العمليّة | الوسائط | عملها |
|---|---|---|
| Turtle() | لا شيء | تنشئ كائنا جديدا في (0, 0)، واتجاهه نحو اليمين |
| forward(d) | عدد: مسافة | يتقدم d في اتجاهه الحالي |
| backward(d) | عدد: مسافة | يتراجع d من دون أن يدور |
| right(a) | عدد: زاوية بالدرجات | يدور في مكانه إلى يمينه |
| left(a) | عدد: زاوية بالدرجات | يدور في مكانه إلى يساره |
| penup() , up() | لا شيء | يرفع القلم |
| pendown() , down() | لا شيء | يعيد القلم إلى الورقة |
| color(name) | جملة نصية: اسم اللون | يغيّر لون القلم |
| goto(x, y) | عددان: إحداثيان | ينتقل إلى النقطة، ويرسم إذا كان القلم نازلا |
| position() | لا شيء | تعيد الموقع الحالي ولا تطبعه |
نقرأ كل سطر بثلاثة أسئلة. كم وسيطا تحتاج العمليّة؟ من أي نوع؟ وهل تفعل شيئا أم تعيد قيمة؟ العمليّة forward تحرّك الكائن ولا تعيد لنا شيئا. والعمليّة position لا تحرّك شيئا، بل تعيد قيمة، وإذا لم نستعمل هذه القيمة ضاعت. لذلك لا يطبع السطر الرابع في البرنامج الأول أدناه شيئا، والذي يطبع هو الخامس.
import turtle pen = turtle.Turtle() pen.forward(80) pen.position() print(pen.position()) turtle.done()
(80.00,0.00)
import turtle pen = turtle.Turtle() pen.forward print(pen.position()) turtle.done()
(0.00,0.00)
واسم مختلف بحرف واحد، أو قيمة من نوع آخر نعطيها للوسيط، يوقفان البرنامج. العمليّة تطلب عددا، والجملة النصية "100" ليست عددا، ولذلك تبدأ رسالة الخطأ الثانية بالكلمة TypeError، أي خطأ في نوع القيمة، وبقيتها تصف الحساب الداخلي الذي فشل:
import turtle pen = turtle.Turtle() pen.Forward(100)
AttributeError: 'Turtle' object has no attribute 'Forward'. Did you mean: 'forward'?
import turtle
pen = turtle.Turtle()
pen.forward("100")TypeError: can't multiply sequence by non-int of type 'float'
الفائدة الحقيقية من قراءة الواجهة أننا نستطيع أن نستعمل عمليّة لم نرها من قبل. هذه عمليّات أخرى من الواجهة نفسها:
| العمليّة | الوسائط | عملها |
|---|---|---|
| circle(r) | عدد: نصف قطر | يرسم دائرة، مركزها على بعد r إلى يسار السهم، ويعود إلى نقطة البداية |
| dot(size, color) | عدد وجملة نصية | يرسم نقطة ممتلئة بالقطر واللون المطلوبين، حتى لو كان القلم مرفوعا |
| pensize(w) | عدد: سماكة | يغيّر سماكة الخط |
| write(text) | جملة نصية | يكتب النص عند الموقع الحالي |
| hideturtle() | لا شيء | يخفي السهم، ويبقى الرسم |
نقرأ في الواجهة أن مركز circle(40) على بعد 40 إلى يسار السهم. السهم متجه نحو اليمين، إذن المركز هو (0, 40). نقاط الخطين نحسبها حول هذا المركز، ونرفع القلم قبل كل انتقال:
import turtle
pen = turtle.Turtle()
pen.pensize(2)
pen.circle(40)
pen.up()
pen.goto(-28, 12)
pen.down()
pen.goto(28, 68)
pen.up()
pen.goto(-28, 68)
pen.down()
pen.goto(28, 12)
pen.up()
pen.goto(50, 30)
pen.write("Lamp")
pen.hideturtle()
turtle.done()docs.python.org، وفيها عمليّات كثيرة. ويمكن أن نكتب في نافذة Shell الأمر help(turtle.Turtle.forward) بعد import turtle، فتظهر هناك واجهة هذه العمليّة.on() بلا وسائط، off() بلا وسائط، brightness(percent) بوسيط عددي من 0 إلى 100، وis_on() تعيد True أو False. عندنا كائن اسمه led. نكتب أوامر تشغّله بنصف الإضاءة، ثم تطبع هل هو مضاء.1.9 إنشاء كائنات جديدة – יצירת עצמים חדשים
في كل مرة نستدعي turtle.Turtle() تولد نسخة جديدة. ولكل كائن موقعه واتجاهه ولونه، فالأمر الذي نعطيه لكائن لا يؤثر في غيره. اسم الكائن قبل النقطة هو الذي يحدد من ينفّذ:
import turtle
pen_a = turtle.Turtle()
pen_b = turtle.Turtle()
pen_a.color("red")
pen_b.color("blue")
pen_a.forward(100)
pen_b.left(90)
pen_b.forward(60)
print(pen_a.position())
print(pen_b.position())
turtle.done()(100.00,0.00) (0.00,60.00)
ننشئ الكائن clock، نرفع قلمه، نكتب الاسم، ثم نرسم بواسطة goto. ثم ننشئ data ونفعل مثل ذلك:
import turtle
clock = turtle.Turtle()
clock.color("blue")
clock.up()
clock.goto(4, 68)
clock.write("CLK")
clock.goto(0, 60)
clock.down()
clock.goto(0, 90)
clock.goto(40, 90)
clock.goto(40, 60)
clock.goto(80, 60)
clock.goto(80, 90)
clock.goto(120, 90)
clock.goto(120, 60)
clock.goto(160, 60)
clock.hideturtle()
data = turtle.Turtle()
data.color("red")
data.up()
data.goto(4, 6)
data.write("DATA")
data.goto(0, 0)
data.down()
data.goto(80, 0)
data.goto(80, 30)
data.goto(160, 30)
data.hideturtle()
turtle.done()pen_b = pen_a لا يُنشئ كائنا: لا يوجد هنا Turtle()، بل اسمان لكائن واحد. لذلك يوجد في الرسم سهم واحد، وما نفعله بأحد الاسمين يحدث للكائن نفسه:import turtle pen_a = turtle.Turtle() pen_b = pen_a pen_a.forward(100) pen_b.left(90) pen_b.forward(50) print(pen_a.position()) print(pen_b.position()) turtle.done()
(100.00,50.00) (100.00,50.00)
goto لا يغيّر اتجاه الكائن.import turtle pen_a = turtle.Turtle() pen_b = turtle.Turtle() pen_a.goto(40, 40) pen_b.backward(30) pen_a.forward(10) print(pen_a.position()) print(pen_b.position()) turtle.done()
يرافقنا في هذا الكتاب مشروع واحد ينمو من فصل إلى فصل: محطة قياس تعمل ببطارية ولوح شمسي. في الفصل 2 تقرأ قياساتها، وفي الفصل 3 تقرّر، وفي الفصل 6 تتذكّر، وفي الفصل 10 تتصل بلوحة أردوينو حقيقية. نبدأ بما نستطيعه الآن: نرسم مخططها، وفيه اللوح الشمسي، البطارية والمبيّن. لكل جزء كائن خاص به، ولكل كائن لونه.
import turtle
panel = turtle.Turtle()
panel.color("blue")
panel.pensize(2)
panel.up()
panel.goto(-200, 125)
panel.write("PANEL")
panel.goto(-200, 60)
panel.down()
panel.goto(-100, 60)
panel.goto(-100, 120)
panel.goto(-200, 120)
panel.goto(-200, 60)
panel.up()
panel.goto(-150, 60)
panel.down()
panel.goto(-150, 120)
panel.hideturtle()
wire = turtle.Turtle()
wire.up()
wire.goto(-100, 90)
wire.down()
wire.goto(120, 90)
wire.up()
wire.goto(-150, 60)
wire.down()
wire.goto(-150, -30)
wire.goto(150, -30)
wire.goto(150, 60)
wire.up()
wire.goto(0, 90)
wire.dot(8)
wire.down()
wire.goto(0, 35)
wire.up()
wire.goto(0, -30)
wire.dot(8)
wire.down()
wire.goto(0, 25)
wire.hideturtle()
cell = turtle.Turtle()
cell.color("red")
cell.pensize(3)
cell.up()
cell.goto(-25, 35)
cell.down()
cell.goto(25, 35)
cell.up()
cell.goto(-12, 25)
cell.down()
cell.goto(12, 25)
cell.up()
cell.goto(32, 24)
cell.write("BATTERY")
cell.hideturtle()
gauge = turtle.Turtle()
gauge.color("green")
gauge.pensize(2)
gauge.up()
gauge.goto(150, 60)
gauge.down()
gauge.circle(30)
gauge.up()
gauge.goto(150, 90)
gauge.down()
gauge.goto(168, 110)
gauge.up()
gauge.goto(125, 126)
gauge.write("GAUGE")
gauge.hideturtle()
turtle.done()البرنامج طويل، لأننا نكرر الأوامر نفسها مرة بعد مرة. لا بأس: في الفصلين 4 و7 نتعلم كيف نختصره. نجرّب بأنفسنا: نضيف إلى الخط السفلي مقاومة حمل على شكل مستطيل صغير، ونسأل: أين يجب أن نرفع القلم؟
أهمّ أفكار الفصل:
- الحاسوب ينفّذ أوامر بسيطة بسرعة هائلة وبلا فهم، والتفكير في الحل علينا.
- نحلّل المهمة قبل الشيفرة: المعطى، المطلوب، ثم خطوات لا تحتمل معنيين.
- العمل على برنامج دورة: كتابة، تشغيل، فحص وتصحيح. البرنامج الذي لا يشكو ليس بالضرورة صحيحا.
- الفئة وصف عام، والكائن نسخة محددة منها لها قيم صفاتها.
- الواجهة تقول لنا كيف نستعمل فئة من دون أن نعرف ما في داخلها.
- كل استدعاء
turtle.Turtle()يولد كائنا جديدا مستقلا.
ملخّص أوامر الفصل:
| الأمر | عمله |
|---|---|
| print("text", 2 + 3) | الطباعة على الشاشة |
| # comment | تعليق يتجاهله المفسّر |
| import turtle | جلب الوحدة الجاهزة |
| pen = turtle.Turtle() | إنشاء كائن جديد واسمه pen |
| pen.forward(d) pen.backward(d) | الحركة في الاتجاه الحالي |
| pen.right(a) pen.left(a) | الدوران في المكان |
| pen.penup() pen.pendown() | رفع القلم وإنزاله |
| pen.up() pen.down() | اسمان أقصر للأمرين السابقين |
| pen.color("red") | لون القلم |
| pen.goto(x, y) | الانتقال إلى نقطة |
| pen.position() | الموقع الحالي، قيمة تعود إلينا |
| turtle.done() | إبقاء النافذة مفتوحة |
قاموس المصطلحات – מילון מונחים:
| بالعربية | بالعبرية (كما تظهر في الامتحان) | English |
|---|---|---|
| هندسة الحاسوب | הנדסת מחשבים | Computer engineering |
| تحدٍّ حسابي | אתגר חישובי | Computational challenge |
| الخوارزمية | אלגוריתם | Algorithm |
| تحليل المهمة | ניתוח המשימה | Task analysis |
| لغة البرمجة | שפת תכנות | Programming language |
| النحو | תחביר | Syntax |
| المفسّر | מפרש | Interpreter |
| البرنامج | תוכנית | Program |
| التعليق | הערה | Comment |
| المُخرَج | פלט | Output |
| بيئة التطوير | סביבת פיתוח | Development environment (IDE) |
| الفئة | מחלקה | Class |
| الكائن | עצם | Object |
| النسخة | מופע | Instance |
| الصفة | תכונה | Attribute |
| العمليّة | פעולה | Method |
| الوسيط | פרמטר | Parameter |
| الواجهة | ממשק | Interface |
35040 قراءة من كل عدّاد. وعندما يكون في المدينة مئات آلاف العدّادات لا يستطيع إنسان أن يقرأها، أما البرنامج فيجمعها ويكشف الأعطال والاستهلاك غير العادي.A ، سطر فارغ ، B C , 5 , 2 + 3print("Solar panel")
print("Battery")
print("Gauge")(50.00,20.00)led.on() ، led.brightness(50) ، print(led.is_on())(50.00,40.00) , (-30.00,0.00)أسئلة للتمرين:
print("9 * 9")
print(9 * 9)
print()
print("Done", 9 + 9)9 * 9 , 81 ، سطر فارغ ، Done 18Print("Lab 3")
print("Voltage: 5 V)
print("End")Print، لأن هذا لا يُكتشف إلا عند التنفيذ.print("Lab 3")
print("Voltage: 5 V")
print("End")import turtle pen = turtle.Turtle() pen.forward(80) pen.left(90) pen.forward(40) pen.right(90) pen.forward(80) pen.right(90) pen.forward(40) print(pen.position()) turtle.done()
(160.00,0.00).forward وleft فقط.import turtle pen = turtle.Turtle() pen.forward(120) pen.left(90) pen.forward(60) pen.left(90) pen.forward(120) pen.left(90) pen.forward(60) turtle.done()
47000 أوم.import turtle pen = turtle.Turtle() pen.left(90) pen.forward(30) pen.up() pen.forward(20) pen.down() pen.forward(30) pen.up() pen.forward(20) pen.down() pen.forward(30) print(pen.position()) turtle.done()
(0.00,130.00)import turtle pen = turtle.Turtle() pen.up() pen.dot(30, "red") pen.forward(50) pen.dot(30, "orange") pen.forward(50) pen.dot(30, "green") pen.hideturtle() turtle.done()
plus يبدأ من (0, 40)، ويصل إلى (120, 25). والسلك الأسود minus يبدأ من (0, 0)، ويصل إلى (120, 15). نرسم السلكين بكائنين، بزوايا قائمة فقط، ونطبع موقع النهاية لكل منهما.import turtle
plus = turtle.Turtle()
minus = turtle.Turtle()
plus.color("red")
minus.color("black")
plus.up()
plus.goto(0, 40)
plus.down()
plus.goto(120, 40)
plus.goto(120, 25)
minus.goto(120, 0)
minus.goto(120, 15)
print(plus.position())
print(minus.position())
turtle.done()(120.00,25.00) , (120.00,15.00)import turtle pen = turtle.Turtle() pen.pensize(4) pen.up() pen.goto(0, 100) pen.down() pen.goto(50, 100) pen.goto(50, 50) pen.goto(0, 50) pen.goto(0, 0) pen.goto(50, 0) pen.hideturtle() turtle.done()
60 درجة، ونحتاج إلى 12 أمرا: أمرين لكل ضلع. ولمضلع له 100 ضلع نحتاج إلى 200 أمر، ولذلك نحتاج إلى الحلقة في الفصل 4.import turtle pen = turtle.Turtle() pen.forward(60) pen.left(60) pen.forward(60) pen.left(60) pen.forward(60) pen.left(60) pen.forward(60) pen.left(60) pen.forward(60) pen.left(60) pen.forward(60) pen.left(60) turtle.done()