چرا حلقه داریم؟
اگر بخواهی یک LED پنج بار چشمک بزند، نوشتن پنج بار کد تکراری هم طولانی است و هم احتمال اشتباه دارد. حلقه کار تکراری را کنترل میکند:
for (int i = 0; i < 5; i++) {
blinkOnce();
}
در for سه بخش داریم: مقدار شروع، شرط ادامه و تغییر شمارنده. در مثال بالا i از صفر شروع میشود، تا وقتی کمتر از ۵ است ادامه دارد و هر دور یک واحد زیاد میشود؛ پس دقیقا پنج بار اجرا میشود.
حلقه while
وقتی تعداد تکرار مشخص نیست ولی یک شرط داریم، while مفید است:
while (distanceCm > 20) {
moveForward();
distanceCm = readDistance();
}
stopMotors();
نکته مهم: چیزی داخل حلقه باید بتواند شرط را تغییر دهد. اگر distanceCm را دوباره نخوانیم، ممکن است حلقه هیچوقت تمام نشود.
تابع؛ یک اسم برای یک کار
تابع کمک میکند برنامه را به قطعههای قابل فهم تقسیم کنیم:
int clampSpeed(int value) {
if (value < 0) return 0;
if (value > 255) return 255;
return value;
}
این تابع یک مسئولیت دارد: سرعت را در محدوده ۰ تا ۲۵۵ نگه میدارد. تابع خوب را میتوان مستقل تست کرد: ورودیهای -10، 100 و 300 باید به ترتیب 0، 100 و 255 بدهند.
چرا شکستن مسئله مهم است؟
به جای یک loop() دویست خطی، میتوانیم بخشها را جدا کنیم:
void loop() {
readSensors();
decideBehavior();
updateMotors();
}
این ساختار باعث میشود وقتی موتور اشتباه رفتار کرد، بدانیم باید خواندن سنسور، منطق تصمیم یا خروجی موتور را جدا بررسی کنیم.
خطاهای رایج
- شرط حلقهای که هرگز false نمیشود.
- تغییر اشتباه شمارنده و اجرای یک دور کمتر/بیشتر (
off-by-one). - تابعی که هم سنسور میخواند، هم نمایشگر را آپدیت میکند، هم موتور را کنترل میکند؛ چنین تابعی سخت تست میشود.
- کپی کردن کد تکراری به جای ساخت تابع.
تمرین
تابعی به نام isSafeDistance(int cm) طراحی کن که اگر فاصله ۲۰ یا بیشتر بود true بدهد. بعد با یک حلقه for پنج مقدار فرضی را تست کن. برای هر ورودی، خروجی مورد انتظار را قبل از اجرا بنویس. اگر یک تست شکست خورد، فقط همان تابع را اصلاح کن، نه کل برنامه ربات را.