Към съдържанието
wannacode

Цикли

Проблем

Колко ще спестиш?

Решаваш да спестяваш: първия месец отделяш 10 €, втория 20 €, третия 30 € и все така с по 10 € повече. Колко ще имаш след 4 месеца?

int total = 0;
total += 1 * 10;
total += 2 * 10;
total += 3 * 10;
total += 4 * 10;
Console.WriteLine(total);
Изход
100

Работи. Но след 3 години ще са 36 реда, почти еднакви. А ако броят на месеците се въвежда от клавиатурата, изобщо не знаеш колко реда да напишеш. Трябва ти начин да кажеш „повтори това толкова пъти“.

Идеята

for: повтори, докато условието е вярно

Повтарящото се парче код се казва цикъл. Най-често ползваният е for. Ето числата от 1 до 10:

for (int i = 1; i <= 10; i++)
{
Console.WriteLine(i);
}
Изход
1
2
3
4
5
6
7
8
9
10

В скобите има три части, разделени с ;:

  • Начало: int i = 1. Изпълнява се веднъж, преди всичко останало. Тук се създава броячът.
  • Условие: i <= 10. Проверява се преди всеки кръг. Ако е вярно, тялото се изпълнява. Ако не е, цикълът свършва.
  • Стъпка: i++. Изпълнява се след всеки кръг.

Всяко изпълнение на тялото се казва итерация или просто кръг.

По-точно, за любопитните
  • Стъпката може да е каквато ти трябва: i += 2 (през едно), i-- (назад).
  • Броячът i съществува само вътре в цикъла. След затварящата } го няма и ако го ползваш, програмата не се компилира.
  • Често ще видиш броене от 0: for (int i = 0; i < 10; i++). Пак е 10 кръга. Защо се брои от 0, ще стане ясно в урока за масивите.

Виж го

Кръг по кръг

Това са спестяванията от първата карта, с цикъл. Следи как се сменят month и total.

int total = 0;
for (int month = 1; month <= 4; month++)
{
total += month * 10;
}
Console.WriteLine(total); // 100
Стъпка по стъпка, с думи
  1. total започва от 0.
  2. month = 1. Проверка: 1 <= 4 е вярно, влизаме в тялото.
  3. Кръг 1: total += 1 * 10, total става 10.
  4. month++ прави month 2. 2 <= 4: още един кръг, total става 30.
  5. month 3: total става 60.
  6. month 4: total става 100.
  7. month++ прави month 5. 5 <= 4 е невярно: цикълът свършва.
  8. След цикъла total е 100.

Тялото е един ред и е написано веднъж. За 36 месеца сменяш само 4 на 36. А можеш да сложиш там и променлива, прочетена от клавиатурата.

Пробвай

Обратно броене

Какво ще отпечата програмата?

for (int sec = 3; sec > 0; sec--)
{
Console.WriteLine(sec);
}
Console.WriteLine("Старт!");
Отговор

Идеята

while: докато не дойде краят

Понякога не знаеш предварително колко кръга ще има. Касата чете цени, докато касиерът не въведе 0, и тогава казва сметката. Тук for не пасва. Пасва while: само условие, без начало и стъпка.

int total = 0;
int price = int.Parse(Console.ReadLine());
while (price != 0)
{
total += price;
price = int.Parse(Console.ReadLine());
}
Console.WriteLine("Общо: " + total + " €");
Вход
12
4
7
0
Изход
Общо: 23 €

Първата цена се чете преди цикъла, за да има какво да провери условието. Следващата се чете в края на тялото. Ако първото число е 0, тялото не се изпълнява нито веднъж.

Ако искаш тялото да се изпълни поне веднъж, има do-while. Условието е отдолу и се проверява след кръга. Удобно е за въпрос, който се повтаря, докато отговорът не стане приемлив:

int count;
do
{
Console.WriteLine("Колко билета (от 1 до 10)?");
count = int.Parse(Console.ReadLine());
} while (count < 1 || count > 10);
Console.WriteLine("Запазени билети: " + count);
Вход
0
15
3
Изход
Колко билета (от 1 до 10)?
Колко билета (от 1 до 10)?
Колко билета (от 1 до 10)?
Запазени билети: 3
По-точно, за любопитните
  • Ако условието никога не стане невярно, цикълът не свършва. Това е безкраен цикъл: програмата „увисва“ и трябва да я спреш ръчно. Най-честата причина е забравена промяна на променливата в условието, например липсващо price = … в края на тялото.
  • След while (…) на do-while има ;. Без нея програмата не се компилира.
  • Всеки for може да се напише като while и обратно. Избираш този, който се чете по-ясно: for за известен брой кръгове, while за „докато нещо стане“.

Пробвай

Намери грешката

Програмата трябва да събере числата от 1 до 5: 1 + 2 + 3 + 4 + 5 = 15. Отпечатва 10. На кой ред е грешката?

Избери реда с грешката.

Идеята

break и continue

Две думи сменят обичайния ход на цикъла.

continue прескача останалото от текущия кръг и минава на следващия. Записваш часове за прегледи от 9 до 17, но в 13 е обедната почивка:

for (int hour = 9; hour <= 17; hour++)
{
if (hour == 13)
{
continue;
}
Console.WriteLine(hour + ":00");
}
Изход
9:00
10:00
11:00
12:00
14:00
15:00
16:00
17:00

break спира целия цикъл веднага. Търсиш първото число, на което 91 се дели. Щом го намериш, няма смисъл да продължаваш:

int n = 91;
for (int d = 2; d < n; d++)
{
if (n % d == 0)
{
Console.WriteLine(n + " се дели на " + d);
break;
}
}
Изход
91 се дели на 7
По-точно, за любопитните
  • break спира само цикъла, в който се намира. Ако е във вложен цикъл (следващата карта), външният продължава.
  • Често ще срещнеш while (true) с break вътре: цикъл, който свършва не от условието, а от break на подходящото място.

Идеята

Цикъл в цикъл

Залата на киното има 3 реда по 4 места. Искаш да отпечаташ всички места. За всеки ред минаваш през всички места в него:

for (int row = 1; row <= 3; row++)
{
for (int seat = 1; seat <= 4; seat++)
{
Console.Write("[" + row + "-" + seat + "]");
}
Console.WriteLine();
}
Изход
[1-1][1-2][1-3][1-4]
[2-1][2-2][2-3][2-4]
[3-1][3-2][3-3][3-4]

Това се казва вложени цикли. Вътрешният цикъл минава целия си път при всеки кръг на външния: 3 реда · 4 места = 12 отпечатвания. Write оставя местата на един ред, а празното WriteLine() след вътрешния цикъл слиза на нов ред.

Пробвай

Стълбичка

На първия ред трябва да има една звездичка, на втория две, на четвъртия четири. Какво трябва да пише на празното място?

for (int row = 1; row <= 4; row++)
{
    for (int star = 1; star <= ; star++)
    {
        Console.Write("*");
    }
    Console.WriteLine();
}

Идеята

Случайни числа за игрите

За игра на зарове трябва число, което програмата не знае предварително. Дава го Random:

Random random = new Random();
int dice = random.Next(1, 7);
Console.WriteLine("Хвърли " + dice);

Random е обект, затова се създава с new. Какво е обект, ще разберем в модул „Класове и обекти“. Засега го ползвай така: създаваш го веднъж и после искаш от него числа колкото ти трябват.

random.Next(1, 7) дава число от 1 до 6: долната граница влиза, горната не.

Всяко пускане дава различно число, затова тук няма изход. Ето и цикъл, който хвърля, докато не се падне шестица:

Random random = new Random();
int rolls = 0;
int dice;
do
{
dice = random.Next(1, 7);
rolls++;
} while (dice != 6);
Console.WriteLine("Шестица след " + rolls + " хвърляния");
По-точно, за любопитните
  • Ако дадеш на Random начално число (new Random(42)), всяко пускане дава една и съща поредица. Това помага при тестване. Java и C# дават различни поредици от едно и също начално число.
  • Числата не са истински случайни: смятат се по формула. За игри стигат, за пароли и сигурност не.

Упражнение

Задачи с цикли

Реши задачите в редактора си. За всяка има примерен вход и изход, с който да сравниш своя. Числото се чете както в урока „Вход и изход“.

1. Таблица за умножение. Прочети число и отпечатай произведенията му с числата от 1 до 10.

Вход
7
Изход
7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63
7 x 10 = 70

2. Просто число. Едно число е просто, ако се дели само на 1 и на себе си: 2, 3, 5, 7, 11… Прочети число и кажи дали е просто. Подсказка: опитай делителите от 2 нагоре и спри с break при първия.

Вход
91
Изход
91 не е просто

За 11 изходът е „11 е просто“.

3. Цифрите на число. Прочети цяло положително число. Отпечатай го наобратно и сумата на цифрите му. Подсказка: n % 10 е последната цифра, а n / 10 маха последната цифра. Повтаряй, докато числото не стане 0.

Вход
2024
Изход
Обратно: 4202
Сума на цифрите: 8

4. Познай числото. Компютърът „намисля“ число от 1 до 100, а ти го търсиш. След всеки опит програмата казва „По-малко е.“ или „По-голямо е.“, а накрая колко опита ти е отнело. Първо го напиши с тайно число 37, за да провериш с примера:

Вход
50
25
37
Изход
По-малко е.
По-голямо е.
Позна от 3 опита!

Когато работи, смени 37 със случайно число от 1 до 100. Вече и ти не знаеш отговора.

Още задачи

  • От 1 до N. Прочети N и отпечатай числата от 1 до N на един ред. За 5: 1 2 3 4 5.
  • Факториел. N! = 1 · 2 · 3 · … · N. За 5: 120. Ползвай long: int стига само до 12!, а long до 20! (2432902008176640000).
  • Прости числа до N. Отпечатай всички прости числа до N. За 20: 2 3 5 7 11 13 17 19. Проверката от задача 2 отива вътре в цикъл по числата: вложени цикли.
  • Фибоначи. Всяко число е сумата на предишните две: 0, 1, 1, 2, 3, 5, 8… Прочети N и отпечатай първите N числа. За 10: 0 1 1 2 3 5 8 13 21 34.
  • Квадрат от звездички. Прочети N и отпечатай квадрат N × N. За 3:
Изход
* * *
* * *
* * *
  • Триъгълник от звездички. Същото, но на всеки ред толкова звездички, колкото е номерът му. За 3:
Изход
*
* *
* * *
  • Хвърляне на монета. Прочети N, хвърли монета N пъти със случайно число (0 е ези, 1 е тура) и отпечатай колко пъти се е паднало всяко. Колкото по-голямо е N, толкова по-близо са двете числа до N / 2.
  • Камък, ножица, хартия. Играч срещу компютър. Играчът въвежда избора си, компютърът избира случайно, програмата казва кой печели. С do-while пита „Още една игра? (да/не)“ и накрая отпечатва резултата.

Тест

Провери се

1. Колко пъти се изпълнява тялото на for (int i = 0; i < 5; i++)?
2. Каква е разликата между while и do-while?
3. Какво прави continue?
4. Външният цикъл се върти 3 пъти, вътрешният 4 пъти. Колко пъти се изпълнява тялото на вътрешния?
5. Кой ред дава случайно число от 1 до 6?

Създаден от Иво Гергов като част от кампанията на Evo Tech за достъпно обучение по програмиране ·