برای روشن کردن ترمینال، کلیک کن یا هر کلیدی را بزن

پرش به محتوای اصلی
>_
درس ۱۶متوسط

حلقه‌های تودرتو و الگوهای نجومی

رسم مثلث، مربع، لوزی، ضربدری و صلیب با ستاره‌ها به کمک حلقه‌های تودرتو

معمولی
حلقه‌ها و کنترل جریان•صفحه ۲۷•۳۵ دقیقه•۱٬۵۶۶ کلمهزمان مطالعه: ۰ دقیقه
فهرست این درس
// اهداف۴
  • درک مفهوم حلقه تودرتو (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 ستاره چاپ می‌کند.

چاپ مثلث قائم‌الزاویه با n سطرcpp
خروجی برنامه
Enter n: 4
*
**
***
****
در حال باز کردن ویرایشگر…

چرا `endl` بیرون حلقه داخلی است؟

دستور cout << endl; باید پس از حلقه داخلی و داخل حلقه بیرونی نوشته شود تا در پایان هر سطر، فقط یک بار به خط جدید برویم. اگر داخل حلقه داخلی بنویسیمش، هر ستاره در یک خط جداگانه چاپ می‌شود و مثلث به‌هم می‌ریزد.

مثال ۲: مثلث معکوس ستاره‌ای

اگر بخواهیم مثلث برعکس شود (سطر اول n ستاره و سطر آخر ۱ ستاره)، کافی است حلقه بیرونی را نزولی بنویسیم: i از n شروع شود و تا 1 کاهش یابد؛ حلقه داخلی در هر سطر همان i ستاره را چاپ می‌کند.

مثلثی که از بالا به پایین کوچک می‌شودcpp
خروجی برنامه
Enter n: 3
***
**
*
در حال باز کردن ویرایشگر…

مثال ۳: مربع توخالی با ستاره

برای مربع توخالی، در هر خانه از ماتریس n×n چک می‌کنیم: اگر روی سطر اول، سطر آخر، ستون اول یا ستون آخر باشیم، ستاره چاپ می‌کنیم؛ در غیر این صورت فاصله (space) چاپ می‌کنیم.

رسم مربع n×n که فقط حاشیه آن پر استcpp
خروجی برنامه
Enter n: 5
*****
*   *
*   *
*   *
*****
در حال باز کردن ویرایشگر…

اشتباه جزوه: استفاده از `or` به‌جای `||`

در جزوه اصلی شرط به‌صورت if(i==n or j==1 or i==j) نوشته شده است. حقیقت را بدانیم: or و and در ⁦C++⁩ استاندارد توکن‌های جایگزین برای || و && هستند (از C++98) و هر کامپایلرِ منطبق بر استاندارد موظف است آن‌ها را بپذیرد. مشکل واقعی سراغ کامپایلر‌های پیش‌استاندارد مثل Turbo ⁦C++⁩ (همان محیط جزوه) می‌رود که این کلمات را نمی‌شناسد — به همین دلیل کد جزوه در آن محیط خطا می‌دهد. برای سازگاری با محیط‌های امتحانی و خوانایی، همیشه || و && بنویسید.

نسخه اشتباه جزوه
کد دارای باگcpp
نسخه اصلاح‌شده و استاندارد
کد صحیحcpp

دو شرط طلایی: `i == j` و `i + j == n + 1`

وقتی یک ماتریس n × n از سطر‌های ۱ تا n و ستون‌های ۱ تا n داریم، دو شرط جالب به‌دست می‌آید:

  • قطر اصلی (Main Diagonal): خانه‌هایی که شماره سطر و ستونشان برابر است، یعنی i == j. این خانه‌ها از گوشه بالا-چپ به پایین-راست می‌روند.
  • قطر فرعی (Secondary / Anti Diagonal): خانه‌هایی که مجموع شماره سطر و ستونشان برابر n + 1 است، یعنی i + j == n + 1. این خانه‌ها از گوشه بالا-راست به پایین-چپ می‌روند.
n=5j=1j=2j=3j=4j=5
i=1✓(main)✓(anti)
i=2✓(main)✓(anti)
i=3✓(both)
i=4✓(anti)✓(main)
i=5✓(anti)✓(main)

این دو شرط، کلید رسم لوزی، ضربدری و صلیب هستند.

مثال ۴: چاپ قطر اصلی و قطر فرعی (ضربدری X)

ترکیب دو شرط بالا، شکل ضربدری (X) می‌سازد. هر خانه‌ای که روی یکی از دو قطر باشد، ستاره می‌گیرد.

ستاره فقط روی دو قطرcpp
خروجی برنامه
Enter n (odd): 5
*   *
 * * 
  *  
 * * 
*   *
در حال باز کردن ویرایشگر…

مثال ۵: لوزی کامل

برای رسم لوزی، فاصله‌ی هر سطر از مرکز را حساب می‌کنیم. مرکز در سطر mid = (n + 1) / 2 قرار دارد. در سطر i، تعداد فاصله‌ی ابتدا برابر |i - mid| و تعداد ستاره‌ها برابر n - 2 * |i - mid| است. این روش برای هر n فردی کار می‌کند.

لوزی متقارن با n فردcpp
خروجی برنامه
Enter n (odd): 5
  *
 ***
*****
 ***
  *
در حال باز کردن ویرایشگر…

فلوچارت رسم لوزی

گام‌به‌گام الگوریتم رسم لوزی متقارن با n فرد:

flow.svg

مثال ۶: ضربدری متقارن (V شکل پر شده)

این الگو مانند یک مثلث متقارن است که در هر سطر i، ابتدا n - i فاصله، سپس i ستاره با فاصله بین آن‌ها چاپ می‌شود.

هر سطر به‌صورت متقارن ستاره داردcpp
خروجی برنامه
Enter n: 4
   * 
  * * 
 * * * 
* * * * 
در حال باز کردن ویرایشگر…

مثال ۷: صلیب یا علامت به‌علاوه (+)

برای رسم صلیب، باید ستاره‌هایی چاپ کنیم که یا روی سطر وسط هستند یا روی ستون وسط. سطر و ستون وسط برابر (n + 1) / 2 است (n باید فرد باشد).

صلیب با حلقه بیرونی روی سطر وسط و ستون وسطcpp
خروجی برنامه
Enter n (odd): 5
  *  
  *  
*****
  *  
  *  
در حال باز کردن ویرایشگر…

اشتباهات رایج در حلقه‌های تودرتو

  • return 0; در انتهای main الزامی نیست: از C++98 به بعد، رسیدن به انتهای main خودش معادل return 0; است. نوشتنش عادت خوبی است که خروج موفق برنامه را صریح نشان می‌دهد — اما فراموش کردنش خطا نیست.
  • استفاده از or/and به‌جای ||/&& — توکن‌های جایگزین استانداردند، اما کامپایلر‌های قدیمی (مثل Turbo ⁦C++⁩) آن‌ها را نمی‌شناسند و خطا می‌دهند.
  • قرار دادن endl داخل حلقه داخلی که شکل را به‌هم می‌ریزد.
  • اشتباه در مرز حلقه‌ها مثلاً j < i به‌جای j <= i که باعث چاپ یک ستاره کمتر می‌شود.
  • عدم مقداردهی اولیه‌ی متغیر‌ها مثل mid که ممکن است در شرایط خاص مقدار زباله بگیرد.

نکته طلایی: رسم روی کاغذ قبل از کدنویسی

بهترین روش برای حل مسائل الگو، رسم شکل روی کاغذ و شماره‌گذاری سطر‌ها و ستون‌هاست. سپس قاعده‌ی هر سطر را پیدا کنید (تعداد فاصله و تعداد ستاره) و آن را به فرمول تبدیل کنید. این کار، نوشتن حلقه‌های تودرتو را بسیار ساده می‌کند.

مرور سریع مطالب

۱۴ بخش در این درس

تمرین‌ها

01
تمرین•حل کامل دارد

برنامه‌ای بنویسید که عدد n را از ورودی بگیرد و یک مثلث عددی چاپ کند. برای n=4 خروجی باید این‌گونه باشد: ``` 1 12 123 1234 ```

نمایش راهنما
به‌جای چاپ ستاره، مقدار `j` را چاپ کنید.
02
تمرین•حل کامل دارد

برنامه‌ای بنویسید که عدد فرد n را گرفته و یک فلش به سمت راست با ستاره چاپ کند (نصف لوزی، یعنی n سطر که ابتدا افزایشی و سپس کاهشی است).

نمایش راهنما
قسمت اول: از ۱ تا mid، قسمت دوم: از mid-1 تا ۱.
03
تمرین•حل کامل دارد

برنامه‌ای بنویسید که عدد فرد n را گرفته و یک مربع توخالی با قطر‌های پر چاپ کند. یعنی حاشیه و هر دو قطر اصلی و فرعی با ستاره و بقیه با فاصله.

نمایش راهنما
از شرط‌های `i==1 || i==n || j==1 || j==n || i==j || i+j==n+1` استفاده کنید.
04
تمرین•حل کامل دارد

برنامه‌ای بنویسید که عدد n را گرفته و جدول ضرب n×n را چاپ کند (اعداد با فاصله).

نمایش راهنما
در هر خانه مقدار `i * j` را چاپ کنید. برای زیبایی از `\t` استفاده کنید.
// نکات-کلیدی۵
  • 01حلقه تودرتو از دو (یا چند) حلقه تشکیل می‌شود که حلقه داخلی به‌ازای هر تکرار حلقه بیرونی، کامل اجرا می‌شود.
  • 02برای رسم الگوهای ستاره‌ای، معمولاً حلقه بیرونی روی **سطر‌ها** و حلقه داخلی روی **ستون‌ها** حرکت می‌کند.
  • 03شرط `i == j` قطر اصلی و شرط `i + j == n + 1` قطر فرعی ماتریس را مشخص می‌کند.
  • 04برای لوزی، فاصله از مرکز را با `|i - mid|` به‌دست می‌آوریم و تعداد ستاره‌ها برابر `n - 2 * dist` است.
  • 05`or`/`and` توکن‌های جایگزین استاندارد ⁦C++⁩ هستند، اما چون کامپایلر‌های قدیمی (مثل Turbo ⁦C++⁩) آن‌ها را نمی‌شناسند، همیشه `||` و `&&` بنویسید؛ `return 0;` در انتهای `main` اجباری نیست اما نوشتنش عادت خوبی است.
./project-loopsپروژهٔ پایانی این دسته

تحلیل‌گر عدد

تسلط بر حلقه‌ها، ارقام، اعداد اول و حلقه‌های تودرتو

آخرین درس این دسته را تمام کردی — وقت آن است که همه‌چیز را یک‌جا به محک بزنی. برنامه‌ای بنویس که یک عدد صحیح مثبت n را بخواند و بعد در یک منو (با do-while) این امکانات را بدهد: ۱) جدول ضرب n، ۲) جمع ارقام و معکوس n، ۳) بررسی اول بودن n، ۴) نمایش n جملهٔ اول فیبوناچی، ۰) خروج. منو تا انتخاب صفر تکرار شود و انتخاب نامعتبر پیام بدهد.

⏱ ۶۰ تا ۹۰ دقیقه۶ نیازمندی — هر کدام به یک درس لینک است
شرح کامل پروژه
گام بعدی پیشنهادی

آرایه‌های یک‌بعدی

تعریف، مقداردهی، پیمایش، یافتن ماکزیمم و شمارش تکرار‌ها در آرایه

۴۰ دقیقهمتوسط۱۴ بخش

شروع درس

جستجوی سریع در درس‌ها

نام درس، موضوع یا کلمه کلیدی را بنویسید و با Enter به آن بروید