حلقههای تودرتو و الگوهای نجومی
رسم مثلث، مربع، لوزی، ضربدری و صلیب با ستارهها به کمک حلقههای تودرتو
فهرست این درس
- حلقه تودرتو چیست؟
- مثال ۱: مثلث راستقائم ستارهای
- چرا `endl` بیرون حلقه داخلی است؟
- مثال ۲: مثلث معکوس ستارهای
- مثال ۳: مربع توخالی با ستاره
- اشتباه جزوه: استفاده از `or` بهجای `||`
- دو شرط طلایی: `i == j` و `i + j == n + 1`
- مثال ۴: چاپ قطر اصلی و قطر فرعی (ضربدری X)
- مثال ۵: لوزی کامل
- فلوچارت رسم لوزی
- مثال ۶: ضربدری متقارن (V شکل پر شده)
- مثال ۷: صلیب یا علامت بهعلاوه (+)
- اشتباهات رایج در حلقههای تودرتو
- نکته طلایی: رسم روی کاغذ قبل از کدنویسی
- درک مفهوم حلقه تودرتو (Nested Loop) و ترتیب اجرای حلقه داخلی و خارجی
- پیادهسازی الگوهای ستارهای مثلث، مربع توخالی، لوزی و ضربدری
- استفاده از شرطهای `i==j` (قطر اصلی) و `i+j==n+1` (قطر فرعی) برای کنترل جای ستارهها
- شناخت توکنهای جایگزین `or`/`and` در C++ استاندارد و این که چرا `||`/`&&` و نوشتن `return 0;` (بهعنوان عادت خوب، نه الزام) را ترجیح میدهیم
حلقه تودرتو چیست؟
وقتی داخل بدنهی یک حلقه (معمولاً حلقه بیرونی) یک حلقهی دیگر (حلقه داخلی) قرار بگیرد، به آن حلقه تودرتو (Nested Loop) میگویند. در الگوهای نجومی، حلقه بیرونی معمولاً روی سطرها حرکت میکند و حلقه داخلی روی ستونها یا تعداد ستارههای هر سطر.
قاعده مهم: به ازای هر بار اجرای حلقه بیرونی، حلقه داخلی کاملًا از ابتدا تا انتها اجرا میشود. یعنی اگر حلقه بیرونی n بار و حلقه داخلی m بار اجرا شود، دستور داخل حلقه داخلی در مجموع n × m بار اجرا خواهد شد.
در این درس میآموزیم چطور با ترکیب دو حلقه ساده for و چند شرط هوشمندانه، شکلهای زیبایی مثل مثلث، لوزی، ضربدری و صلیب رسم کنیم.
مثال ۱: مثلث راستقائم ستارهای
سادهترین الگو، مثلثی است که در سطر i ام دقیقاً i ستاره چاپ میکند. حلقه بیرونی i از ۱ تا n حرکت میکند و حلقه داخلی j از ۱ تا i ستاره چاپ میکند.
Enter n: 4 * ** *** ****
چرا `endl` بیرون حلقه داخلی است؟
دستور cout << endl; باید پس از حلقه داخلی و داخل حلقه بیرونی نوشته شود تا در پایان هر سطر، فقط یک بار به خط جدید برویم. اگر داخل حلقه داخلی بنویسیمش، هر ستاره در یک خط جداگانه چاپ میشود و مثلث بههم میریزد.
مثال ۲: مثلث معکوس ستارهای
اگر بخواهیم مثلث برعکس شود (سطر اول n ستاره و سطر آخر ۱ ستاره)، کافی است حلقه بیرونی را نزولی بنویسیم: i از n شروع شود و تا 1 کاهش یابد؛ حلقه داخلی در هر سطر همان i ستاره را چاپ میکند.
Enter n: 3 *** ** *
مثال ۳: مربع توخالی با ستاره
برای مربع توخالی، در هر خانه از ماتریس n×n چک میکنیم: اگر روی سطر اول، سطر آخر، ستون اول یا ستون آخر باشیم، ستاره چاپ میکنیم؛ در غیر این صورت فاصله (space) چاپ میکنیم.
Enter n: 5 ***** * * * * * * *****
اشتباه جزوه: استفاده از `or` بهجای `||`
در جزوه اصلی شرط بهصورت if(i==n or j==1 or i==j) نوشته شده است. حقیقت را بدانیم: or و and در C++ استاندارد توکنهای جایگزین برای || و && هستند (از C++98) و هر کامپایلرِ منطبق بر استاندارد موظف است آنها را بپذیرد. مشکل واقعی سراغ کامپایلرهای پیشاستاندارد مثل Turbo C++ (همان محیط جزوه) میرود که این کلمات را نمیشناسد — به همین دلیل کد جزوه در آن محیط خطا میدهد. برای سازگاری با محیطهای امتحانی و خوانایی، همیشه || و && بنویسید.
دو شرط طلایی: `i == j` و `i + j == n + 1`
وقتی یک ماتریس n × n از سطرهای ۱ تا n و ستونهای ۱ تا n داریم، دو شرط جالب بهدست میآید:
- قطر اصلی (Main Diagonal): خانههایی که شماره سطر و ستونشان برابر است، یعنی
i == j. این خانهها از گوشه بالا-چپ به پایین-راست میروند. - قطر فرعی (Secondary / Anti Diagonal): خانههایی که مجموع شماره سطر و ستونشان برابر
n + 1است، یعنیi + j == n + 1. این خانهها از گوشه بالا-راست به پایین-چپ میروند.
| n=5 | j=1 | j=2 | j=3 | j=4 | j=5 |
|---|---|---|---|---|---|
| i=1 | ✓(main) | ✓(anti) | |||
| i=2 | ✓(main) | ✓(anti) | |||
| i=3 | ✓(both) | ||||
| i=4 | ✓(anti) | ✓(main) | |||
| i=5 | ✓(anti) | ✓(main) |
این دو شرط، کلید رسم لوزی، ضربدری و صلیب هستند.
مثال ۴: چاپ قطر اصلی و قطر فرعی (ضربدری X)
ترکیب دو شرط بالا، شکل ضربدری (X) میسازد. هر خانهای که روی یکی از دو قطر باشد، ستاره میگیرد.
Enter n (odd): 5 * * * * * * * * *
مثال ۵: لوزی کامل
برای رسم لوزی، فاصلهی هر سطر از مرکز را حساب میکنیم. مرکز در سطر mid = (n + 1) / 2 قرار دارد. در سطر i، تعداد فاصلهی ابتدا برابر |i - mid| و تعداد ستارهها برابر n - 2 * |i - mid| است. این روش برای هر n فردی کار میکند.
Enter n (odd): 5 * *** ***** *** *
فلوچارت رسم لوزی
گامبهگام الگوریتم رسم لوزی متقارن با n فرد:
مثال ۶: ضربدری متقارن (V شکل پر شده)
این الگو مانند یک مثلث متقارن است که در هر سطر i، ابتدا n - i فاصله، سپس i ستاره با فاصله بین آنها چاپ میشود.
Enter n: 4 * * * * * * * * * *
مثال ۷: صلیب یا علامت بهعلاوه (+)
برای رسم صلیب، باید ستارههایی چاپ کنیم که یا روی سطر وسط هستند یا روی ستون وسط. سطر و ستون وسط برابر (n + 1) / 2 است (n باید فرد باشد).
Enter n (odd): 5 * * ***** * *
اشتباهات رایج در حلقههای تودرتو
return 0;در انتهایmainالزامی نیست: از C++98 به بعد، رسیدن به انتهایmainخودش معادلreturn 0;است. نوشتنش عادت خوبی است که خروج موفق برنامه را صریح نشان میدهد — اما فراموش کردنش خطا نیست.- استفاده از
or/andبهجای||/&&— توکنهای جایگزین استانداردند، اما کامپایلرهای قدیمی (مثل Turbo C++) آنها را نمیشناسند و خطا میدهند. - قرار دادن
endlداخل حلقه داخلی که شکل را بههم میریزد. - اشتباه در مرز حلقهها مثلاً
j < iبهجایj <= iکه باعث چاپ یک ستاره کمتر میشود. - عدم مقداردهی اولیهی متغیرها مثل
midکه ممکن است در شرایط خاص مقدار زباله بگیرد.
نکته طلایی: رسم روی کاغذ قبل از کدنویسی
بهترین روش برای حل مسائل الگو، رسم شکل روی کاغذ و شمارهگذاری سطرها و ستونهاست. سپس قاعدهی هر سطر را پیدا کنید (تعداد فاصله و تعداد ستاره) و آن را به فرمول تبدیل کنید. این کار، نوشتن حلقههای تودرتو را بسیار ساده میکند.
مرور سریع مطالب
۱۴ بخش در این درس- حلقه تودرتو چیست؟
- مثال ۱: مثلث راستقائم ستارهای
- چرا `endl` بیرون حلقه داخلی است؟
- مثال ۲: مثلث معکوس ستارهای
- مثال ۳: مربع توخالی با ستاره
- اشتباه جزوه: استفاده از `or` بهجای `||`
- دو شرط طلایی: `i == j` و `i + j == n + 1`
- مثال ۴: چاپ قطر اصلی و قطر فرعی (ضربدری X)
- مثال ۵: لوزی کامل
- فلوچارت رسم لوزی
- مثال ۶: ضربدری متقارن (V شکل پر شده)
- مثال ۷: صلیب یا علامت بهعلاوه (+)
- اشتباهات رایج در حلقههای تودرتو
- نکته طلایی: رسم روی کاغذ قبل از کدنویسی
تمرینها
برنامهای بنویسید که عدد n را از ورودی بگیرد و یک مثلث عددی چاپ کند. برای n=4 خروجی باید اینگونه باشد: ``` 1 12 123 1234 ```
نمایش راهنما
برنامهای بنویسید که عدد فرد n را گرفته و یک فلش به سمت راست با ستاره چاپ کند (نصف لوزی، یعنی n سطر که ابتدا افزایشی و سپس کاهشی است).
نمایش راهنما
برنامهای بنویسید که عدد فرد n را گرفته و یک مربع توخالی با قطرهای پر چاپ کند. یعنی حاشیه و هر دو قطر اصلی و فرعی با ستاره و بقیه با فاصله.
نمایش راهنما
برنامهای بنویسید که عدد n را گرفته و جدول ضرب n×n را چاپ کند (اعداد با فاصله).
نمایش راهنما
- 01حلقه تودرتو از دو (یا چند) حلقه تشکیل میشود که حلقه داخلی بهازای هر تکرار حلقه بیرونی، کامل اجرا میشود.
- 02برای رسم الگوهای ستارهای، معمولاً حلقه بیرونی روی **سطرها** و حلقه داخلی روی **ستونها** حرکت میکند.
- 03شرط `i == j` قطر اصلی و شرط `i + j == n + 1` قطر فرعی ماتریس را مشخص میکند.
- 04برای لوزی، فاصله از مرکز را با `|i - mid|` بهدست میآوریم و تعداد ستارهها برابر `n - 2 * dist` است.
- 05`or`/`and` توکنهای جایگزین استاندارد C++ هستند، اما چون کامپایلرهای قدیمی (مثل Turbo C++) آنها را نمیشناسند، همیشه `||` و `&&` بنویسید؛ `return 0;` در انتهای `main` اجباری نیست اما نوشتنش عادت خوبی است.
تحلیلگر عدد
تسلط بر حلقهها، ارقام، اعداد اول و حلقههای تودرتو
آخرین درس این دسته را تمام کردی — وقت آن است که همهچیز را یکجا به محک بزنی. برنامهای بنویس که یک عدد صحیح مثبت n را بخواند و بعد در یک منو (با do-while) این امکانات را بدهد: ۱) جدول ضرب n، ۲) جمع ارقام و معکوس n، ۳) بررسی اول بودن n، ۴) نمایش n جملهٔ اول فیبوناچی، ۰) خروج. منو تا انتخاب صفر تکرار شود و انتخاب نامعتبر پیام بدهد.
آرایههای یکبعدی
تعریف، مقداردهی، پیمایش، یافتن ماکزیمم و شمارش تکرارها در آرایه
۴۰ دقیقهمتوسط۱۴ بخش