-
Notifications
You must be signed in to change notification settings - Fork 19
/
Chapter_I-8.tex
293 lines (232 loc) · 16.2 KB
/
Chapter_I-8.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
\chapter{عمل تطبيقي: "أكثر أو أقل"، لعبتك الأولى}
نصل اليوم إلى أول عمل تطبيقي. الهدف هو أن أريك أنك قادر على برمجة الكثير من الأشياء بما علّمتك إياه. لأنه في الواقع، الجانب النظري للغة أمر جيّد لكننا إن كنا لا نعرف كيف نطبّق ما تعلّمناه بشكل سلس فلا داعي لإهدار وقتنا بتعلم المزيد.
صدّق أو لا تصدّق، يسمح لك مستواك الآن ببرمجة أول برنامج ممتع. إنّه لعبة كونسول (أذكّرك بأننا سنصل للبرامج بنافذة لاحقا). مبدأ عمل اللعبة سهل للغاية، وسهل البرمجة، ولهذا اخترتها لتكون موضوع أول عمل تطبيقي لك.
\section{تجهيزات ونصائح}
\subsection{مبدأ عمل البرنامج}
قبل كلّ شيء، سأشرح عمل برنامجنا. إنّه لعبة صغيرة نسمّيها "أكثر أو أقل".
مبدأ عمل اللعبة هو التالي.
\begin{enumerate}
\item الجهاز يختار عشوائيا عددا من 1 إلى 100.
\item يطلب منك أن تخمن عددا وبالتالي ستختار بدورك عددا من 1 إلى 100.
\item يقوم الجهاز بمقارنة العدد الذي كتبته بالعدد "الغامض" الّذي حصل عليه عشوائيّا، ثم يقول لك ما إن كان العدد الغامض أصغر أو أكبر من العدد الذي اخترته أنت.
\item ثم يقوم الجهاز بإعادة طلب العدد منك.
\item ثم يقول لك ما إن كان العدد الغامض أصغر أو أكبر من العدد الذي اخترته أنت.
\item وهكذا تستمر العملية حتى تجد أنت ذلك العدد.
\end{enumerate}
و الهدف من اللعبة هو أن تجد العدد الغامض في أقل عدد ممكن من المحاولات بالطبع.
و هذه "لقطة شاشة" مما يجب أن تكون عليه اللعبة في طور التنفيذ:
\begin{Console}
What's the number ? 50
Greater !
What's the number ? 75
Greater !
What's the number ? 85
Lesser !
What's the number ? 80
Lesser !
What's the number ? 78
Greater !
What's the number ? 79
Bravo, you have found the mysterious number !!!
\end{Console}
\subsection{اختيار عدد عشوائي}
\begin{question}
لكن كيف يختار الجهاز عددا عشوائيًا؟ أنا لا أجيد فعل هذا!
\end{question}
صحيح، نحن لا نجيد كيفية توليد عدد عشوائي. ويجب القول أن طلب ذلك من الحاسوب ليس أمرًا سهلًا: هو يجيد القيام بعمليات حسابية، لكن أن يستخرج عددًا عشوائيا، هذا أمر لا يجيد فعله!
في الواقع، لـ"محاولة" الحصول على عدد عشوائيّ، يجب القيام بحسابات معقّدة للحاسوب، وهذا ما يعود في النهاية إلى القيام بحسابات!
لكي نفعل هذا، نميز حلين.
\begin{itemize}
\item إما أن نطلب من المستعمل أن يقوم باختيار عددٍ عشوائي في بداية اللعبة بواسطة الدالة
\InlineCode{scanf}.
هذا يستلزم لاعبين: واحد يقوم بإدخال العدد الغامض والآخر يحاول تخمينه بعد ذلك.
\item نجرّب طريقة ثانية لجعل الجهاز يختار وحده العدد. الشيء الجيّد هنا هي أنّك ستتمكن من لعب اللعبة لوحدك. أمّا الشيء السيّئ هو\dots أنّني مضطرّ لأن أشرح لك كيف تقوم بذلك!
\end{itemize}
طبعا سنقوم بالاختيار الثاني ولكن إن أردت تجريب الحل الأول فيما بعد فلا شيء يمنعك.
لاختيار عدد عشوائي نستعمل الدالة
\InlineCode{rand}.
و هي دالة تسمح باختيار عدد بطريقة عشوائية. لكنّنا نريد عددًا بين 1 و100 مثلا (لأننا إن لم نعرف الحدود فستصبح اللعبة معقّدة جدّا).
للقيام بذلك، سنستخدم العبارة التالية (لا يمكنني أن أطلب منك تخمينها هي أيضًا!):
\begin{Csource}
srand(time(NULL));
mysteriousNumber = (rand() % (MAX - MIN + 1)) + MIN;
\end{Csource}
السطر الأول (الذي بـه
\InlineCode{srand})
يسمح بتهيئة مولَد الأرقام العشوائية. نعم الأمر صعب قليلًا كما أخبرتك.
\InlineCode{mysteriousNumber}
هو متغير سيحمل العدد العشوائي المختار.
\begin{warning}
التعليمة
\InlineCode{srand}
لا يجب أن تشغّل إلا مرة واحدة (في بداية البرنامج). فيجب وضع
\InlineCode{srand}
مرة واحدة في البداية، ومرة واحدة فقط. \\
بعدها يمكنك استعمال القدر الذي تريده من الدالة
\InlineCode{rand}
لاختيار العدد العشوائي. ولكن
\underline{يجب ألّا}
يقرأ جهازك التعليمة
\InlineCode{srand}
مرتين، لا تنس ذلك.
\end{warning}
\InlineCode{MAX}
و
\InlineCode{MIN}
هما ثابتان، الأول هو العدد الأقصى (100) والثاني هو العدد الأدنى (1)، وأنصحك بتعريف الثابتين في بداية البرنامج هكذا:
\begin{Csource}
const int MAX = 100, MIN = 1;
\end{Csource}
\subsection{تضمين المكتبات اللازمة}
كي يشتغل برنامجك بشكل صحيح، يجب أن تقوم بتضمين المكتبات
\InlineCode{stdlib}
و
\InlineCode{stdio}
و
\InlineCode{time}
(الأخيرة تستعمل من أجل الأعداد العشوائية).\\
يجب إذن أن يبدأ برنامجك بالتالي:
\begin{Csource}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
\end{Csource}
\subsection{يكفي شرحا!}
حسنا، سأتوقف هنا لأنه لو أكملت سأعطيك الشفرة الخاصة ببرمجة اللعبة كاملة!
\begin{information}
لتوليد الأعداد العشوائية، اضطررت لإعطائك شفرة "جاهزة" دون أن أشرح كيف تعمل بالضبط. عادة، لا أحبّ فعل هذا، لكن لا يوجد خيار هنا لأنني لا أريد تعقيد الأشياء كثيرا حاليّا.\\
تأكّد أنه ستتعلم فيما يلي الكثير من المفاهيم التي ستسمح لك بفهم هذه الأشياء بنفسك.
\end{information}
باختصار، أنت تعرف الكثير. لقد شرحت لك المبدأ وأعطيتك صورة عن البرنامج لحظة التشغيل.\\
بعد كل هذا أنت قادر على كتابة البرنامج لوحدك.
حان وقت العمل! بالتوفيق!
\section{التصحيح!}
توقف! من الآن سأجمع الأوراق.
سأعطيك طريقتي الخاصة لحلّ التطبيق. بالطبع هناك طرائق جيّدة عديدة لفعل ذلك. إن كانت لديك شفرة مصدريّة تختلف عن شفرتي وكانت تشتغل، فمن المحتمل أن تكون جيّدة أيضًا.
\subsection{تصحيح "أكثر أو أقل"}
هذا هو التصحيح الذي أقترحه:
\begin{Csource}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main ( int argc, char** argv )
{
int mysteriousNumber = 0, inputNumber = 0;
const int MAX = 100, MIN = 1;
// Generation of random number
srand(time(NULL));
mysteriousNumber = (rand() % (MAX - MIN + 1)) + MIN;
do
{
// We request the number
printf("What's the number? ");
scanf("%d", &inputNumber );
// We compare between inputNumber and mysteriousNumber
if (mysteriousNumber > inputNumber )
printf("Greater !\n\n");
else if (mysteriousNumber < inputNumber )
printf("Lesser !\n\n");
else
printf ("Bravo, you have found the mysterious number !!!\n\n");
} while (inputNumber != mysteriousNumber);
return 0;
}
\end{Csource}
\subsection{الملف التنفيذي والشفرة المصدرية}
لمن يريد ذلك، اللعبة والشفرة المصدرية متوفّران للتنزيل من هنا:
\textenglish{\url{https://openclassrooms.com/uploads/fr/ftp/mateo21/plusoumoins.zip} \mbox{(7 Ko)}}
\begin{information}
الملف التنفيذي
(\InlineCode{.exe})
مترجم لـ\textenglish{Windows}، لذا إن كنت تستخدم نظام تشغيل آخر فيجب عليك إعادة ترجمة البرنامج ليشتغل عندك.
\end{information}
يوجد مجلّدان، واحد فيه الملف التنفيذي (مترجم لـ\textenglish{Windows}، أكرّر) وآخر فيه ملفات الشفرة المصدرية.
في حالة "أكثر أو أقل"، المصادر بسيطة جدّا: يوجد فقط الملف
\InlineCode{main.c}.\\
لا تفتح هذا الملفّ مباشرة، افتح أوّلا البيئة التطويرية الّتي تفضّلها، ثم أنشئ مشروعا جديدًا من نوع
\textenglish{Console}
و قم باستيراد الملف
\InlineCode{main.c}.
يمكنك ترجمة البرنامج من جديد للتجريب كما يمكنك التعديل عليه إن أردت.
\subsection{الشرح}
سأشرح الآن الشفرة المصدريّة الخاصة بي بدءً من الأعلى:
\subsubsection{توجيهات المعالج القبلي}
هي الأسطر التي تبدأ بعلامة
\InlineCode{\#}
في الأعلى. وهي تقوم بتضمين المكتبات التي نحتاج إليها.\\
أعطيتها لك جاهزة أعلاه، لذلك فإن استطعت ارتكاب خطأ هنا، فأنت قويّ جدّا!
\subsubsection{المتغيرات}
لم نحتج الكثير منها.\\
احتجنا فقط واحدا للعدد الذي يدخله المستعمل
(\InlineCode{inputNumber})
و ثانٍ لكي نسمح للجهاز بتوليد عدد عشوائي
(\InlineCode{mysteriousNumber}).
قمت بتعريف الثوابت كما ذكرت في بداية هذا الفصل. الشيء الجيد أيضًا هو إمكانية تحديد صعوبة اللعبة (بوضع أعلى قيمة هي 1000 مثلا)، يكفي أن نعدّل على هذا السطر ونعيد ترجمة البرنامج.
\subsubsection{الحلقة}
لقد اخترت الحلقة
\InlineCode{do\dots while}.
نظريّا، حلقة
\InlineCode{while}
بسيطة يمكنها أن تقوم بالمهمة أيضا، لكنّي وجدت بأن استخدام
\InlineCode{do\dots while}
منطقيّ أكثر.
لماذا؟ لأنه إن كنت تتذكر،
\InlineCode{do\dots while}
هي حلقة تسمح لنا بتشغيل التعليمات بين الحاضنتين على الأقل مرّة واحدة. ونحن سنطلب من المستعمل إدخال العدد الغامض لمرة واحدة على الأقل أيضًا (فالمستعمل غير قادر على تخمين العدد في أقل من محاولة واحدة، إلا إن كان شخصًا خارقًا!).
في كلّ دورة من الحلقة نطلب من المستعمل إدخال عدد. نقوم بتخزين القيمة في المتغير
\InlineCode{inputNumber}.\\
بعدها، نقارن المتغير السابق بالمتغير
\InlineCode{mysteriousNumber}.
هنا نجد ثلاثة احتمالات:
\begin{itemize}
\item يكون العدد الغامض أكبر من العدد الذي أدخله المستعمل وبالتالي تظهر على الشاشة العبارة
"\textenglish{Greater !}".
\item يكون العدد الغامض أصغر من العدد الذي أدخله المستعمل وبالتالي تظهر على الشاشة العبارة
"\textenglish{Lesser !}".
\item يكون العدد الغامض لا أكبر ولا أصغر من الّذي أدخله المستعمل، أي أنّه مساوٍ بالضرورة! وبالتالي تظهر على الشاشة العبارة
"\textenglish{Bravo, you have found it !}".
\end{itemize}
يجب أن تضع شرطا للحلقة. وهذا سهل للإيجاد: نعيد تشغيل الحلقة
\textbf{مادام العدد الذي تم إدخاله لا يساوي العدد الغامض}.\\
و ما إن يتم إدخال العدد المطلوب تتوقف الحلقة وبالتالي ينتهى البرنامج هنا.
\section*{أفكار للتحسين}
لم تعتقد أنّي أريد للعمل التطبيقي أن ينتهي هنا؟ أنا أصرّ على أن تقوم بتحسين البرنامج، من أجل التدريب. ولتتأكد بأنه مع التدريب ستتطور قدراتك! من يعتقد أنه يقرأ الدروس ولا يطبّق ما جاء فيها فهو مخطئ، أقولها وأكررها!
لقد عرفت أنّه لديّ خيال واسع، وحتى بكونه برنامجًا سهلًا فأنا أملك أفكارا لتطويره!
لكن احذر هذه المرة فلن أعطيك التصحيح، عليك أن تتدبّر أمرك بنفسك! فإن كانت لديك حقّا مشاكل، فيمكنك زيارة منتديات
\href{http://www.siteduzero.com/forum-81-126-langage-c.html}{\textenglish{OpenClassrooms}}
من أجل طلب المساعدة من الآخرين.
\begin{itemize}
\item \textbf{ضع عدادا للمحاولات}،
وهو متغير نقوم بزيادة قيمته في كلّ مرة عندما لا يجد المستعمل الرقم الغامض. بمعنى آخر في كل مرة يعود فيها البرنامج لتشغيل الحلقة، وعند انتهاء اللعبة تقوم بإظهار عدد المحاولات للاعب هكذا مثلا:
"\textenglish{Bravo ! you have found in 3 tries only !}".
\item في هذا البرنامج، عندما يجد اللاعب العدد الغامض يتوقف البرنامج، لماذا لا نجعل البرنامج يسأله ما إن أراد
\textbf{جولة ثانية}؟\\
إذا أردت تطبيق الفكرة فيجب عليك وضع حلقة تشمل تقريبا كل برنامجك. وهذه الحلقة تتكرر
\underline{مادام}
اللاعب لم يطلب إيقاف البرنامج، وأنصحك بإضافة متغير منطقي اسمه مثلا
\InlineCode{continuePlaying}
ذي قيمة ابتدائية مساوية لـ1. إذا طلب اللاعب إيقاف البرنامج، تُغيّر القيمة لـ0 ويتوقف البرنامج.
\item \textbf{أنشئ وضع لاعبين}!
يعني بالإضافة إلى وضع اللاعب الواحد، ضع إمكانية اشتراك لاعبين!\\
لهذا عليك بصنع قائمة
(\textenglish{menu})
في البداية لتطلب من المستخدم اختيار لاعب واحد أو لاعبين إثنين. الفرق بين الوضعين هو توليد العدد الغامض، ففي الحالة الأولى نستعمل الدالة
\InlineCode{rand}
وفي الحالة الثانية نستعمل الدالة
\InlineCode{scanf}!
\item \textbf{إنشاء مستويات مختلفة لصعوبة اللعبة}.
يمكنك وضع قائمة في البداية ليختار المستخدم فيه المستوى وهذا مثال:
\begin{itemize}
\item 1 = بين 1 و100،
\item 2 = بين 1 و1000،
\item 3 = بين 1 و10000.
\end{itemize}
لفعل هذا يجب التعديل على الثابت
\InlineCode{MAX}.
بطبيعة الحال لا يمكننا أن نسميه ثابتا إن كانت قيمته تتغير أثناء البرنامج! قم بتغيير اسم هذا المتغير إلى
\InlineCode{maximumNumber}
ولا تنس نزع الكلمة المفتاحية
\InlineCode{const}
لأنه ببقاءها يبقى ثابتا!). تتغير قيمة هذه المتغير حسب المستوى المختار.
\end{itemize}
ستساعدك هذه التحسينات على الاشتغال قليلًا. لا تتردد في إيجاد أفكار أخرى لتطوير هذه اللعبة، أعلم أنّه يوجد! ولا تنس أن المنتديات في خدمتك في حالة واجهت صعوبات.