В настоящата глава ще се запознаем с конструкциите за повторение на група команди, известни в програмирането с понятието "цикли". Ще напишем няколко цикъла с използване на оператора for
в най-простата му форма. Накрая ще решим няколко практически задачи, изискващи повторение на поредица от действия, като използваме цикли.
В програмирането често пъти се налага да изпълним блок с команди няколко пъти. За целта се използват т.нар. цикли. Нека разгледаме един пример за for
цикъл, който преминава последователно през числата от 1 до 10 и ги отпечатва:
Цикълът започва с оператора for
и преминава през всички стойности за дадена променлива в даден интервал, например всички числа от 1 до 10 включително, и за всяка стойност изпълнява поредица от команди.
В декларацията на цикъла се задава начална стойност и крайна стойност. Тялото на цикъла се огражда с къдрави скоби { }
и представлява блок с една или няколко команди. На фигурата по-долу е показана структурата на един for
цикъл:
В повечето случаи един for
цикъл се завърта от 1
до n
(например от 1 до 10). Целта на цикъла е да се премине последователно през числата 1, 2, 3, …, n и за всяко от тях да се изпълни някакво действие. В примера по-горе променливата i
приема стойности от 1 до 10 и в тялото на цикъла се отпечатва текущата стойност. Цикълът се повтаря 10 пъти и всяко от тези повторения се нарича "итерация".
Да се напише програма, която печата числата от 1 до 100. Програмата не приема вход и отпечатва числата от 1 до 100 едно след друго, по едно на ред.
Можем да решим задачата с for
цикъл , с който преминаваме с променливата i
през числата от 1 до 100 и ги печатаме в тялото на цикъла:
Стартираме програмата с [Shift+F10] и я тестваме:
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/655#0.
Трябва да получите 100 точки (напълно коректно решение).
Докато програмираме, постоянно се налага да пишем цикли, десетки пъти всеки ден. Затова в повечето среди за разработка (IDE) има шаблони за код (code snippets) за писане на цикли. Един такъв шаблон е шаблонът за for
цикъл в IntelliJ IDEA. Напишете fori
в редактора за Java код в IntelliJ IDEA и натиснете [Enter]. IntelliJ IDEA ще разгъне за вас шаблон и ще напише цялостен for
цикъл, единствено трябва да добавите крайната стойност:
Опитайте сами, за да усвоите умението да ползвате шаблона за код за for
цикъл в IntelliJ IDEA.
Да се напише програма, която намира всички числа в интервала [1 … 1000], които завършват на 7.
Задачата можем да решим като комбинираме for
цикъл за преминаваме през числата от 1 до 1000 и проверка за всяко число дали завършва на 7. Има и други решения, разбира се, но нека решим задачата чрез завъртане на цикъл + проверка:
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/655#1.
Да се напише програма, която отпечатва буквите от латинската азбука: a, b, c, …, z.
Полезно е да се знае, че for
циклите не работят само с числа. Може да решим задачата като завъртим for
цикъл, който преминава последователно през всички букви от латинската азбука:
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/655#2.
Да се напише програма, която въвежда n
цели числа и ги сумира.
- От първия ред на входа се въвежда броят числа
n
. - От следващите
n
реда се въвежда по едно число. - Числата се сумират и накрая се отпечатва резултатът.
Вход | Изход |
---|---|
2 10 20 |
30 |
3 -10 -20 -30 |
-60 |
4 45 -20 7 11 |
43 |
1 999 |
999 |
0 | 0 |
Можем да решим задачата за сумиране на числа по следния начин:
- Четем входното число
n
. - Започваме първоначално със сума
sum = 0
. - Въртим цикъл от 1 до
n
. На всяка стъпка от цикъла четем числоnum
и го добавяме към суматаsum
. - Накрая отпечатваме получената сума
sum
.
Ето и сорс кодa на решението:
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/655#3.
Да се напише програма, която въвежда n цели числа (n > 0) и намира най-голямото измежду тях. На първия ред на входа се въвежда броят числа n. След това се въвеждат самите числа, по едно на ред. Примери:
Вход | Изход |
---|---|
2 100 99 |
100 |
3 -10 20 -30 |
20 |
4 45 -20 7 99 |
99 |
1 999 |
999 |
2 -1 -2 |
-1 |
Първо въвеждаме едно число n
(броят числа, които предстои да бъдат въведени). Задаваме на текущия максимум max
първоначална неутрална стойност, например -10000000000000 (или Integer.MIN_VALUE
). С помощта на for
цикъл, чрез който итерираме n-1 пъти, прочитаме по едно цяло число num
. Ако прочетеното число num
е по-голямо от текущия максимум max
, присвояваме стойността на num
в променливата max
. Накрая, в max
трябва да се е запазило най-голямото число. Отпечатваме го на конзолата.
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/655#4.
Да се напише програма, която въвежда n цели числа (n > 0) и намира най-малкото измежду тях. Първо се въвежда броя числа n, след тях още n числа по едно на ред.
Вход | Изход |
---|---|
2 100 99 |
99 |
3 -10 20 -30 |
-30 |
4 45 -20 7 99 |
-20 |
Задачата е абсолютно аналогична с предходната, само че започване с друга неутрална начална стойност.
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/655#5.
Да се напише програма, която въвежда 2 * n цели числа и проверява дали сумата на първите n числа (лява сума) е равна на сумата на вторите n числа (дясна сума). При равенство се печата "Yes" + сумата, иначе се печата "No" + разликата. Разликата се изчислява като положително число (по абсолютна стойност). Форматът на изхода трябва да е като в примерите по-долу.
Вход | Изход | Вход | Изход |
---|---|---|---|
2 10 90 60 40 |
Yes, sum = 100 | 2 90 9 50 50 |
No, diff = 1 |
Първо въвеждаме числото n, след това първите n числа (лявата половина) и ги сумираме. Продължаваме с въвеждането на още n числа (дясната половина) и намираме и тяхната сума. Изчисляваме разликата между намерените суми по абсолютна стойност: Math.abs(leftSum - rightSum)
. Ако разликата е 0, отпечатваме "Yes" + сумата, в противен случай - отпечатваме "No" + разликата.
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/655#6.
Да се напише програма, която въвежда n цели числа и проверява дали сумата на числата на четни позиции е равна на сумата на числата на нечетни позиции. При равенство печата "Yes" + сумата, иначе печата "No" + разликата. Разликата се изчислява по абсолютна стойност. Форматът на изхода трябва да е като в примерите по-долу.
Вход | Изход |
---|---|
4 10 50 60 20 |
Yes Sum = 70 |
4 3 5 1 -2 |
No Diff = 1 |
3 5 8 1 |
No Diff = 2 |
Въвеждаме числата едно по едно и изчисляваме двете суми (на числата на четни позиции и на числата на нечетни позиции). Както в предходната задача, изчисляваме абсолютната стойност на разликата и отпечатваме резултата ("Yes" + сумата при разлика 0 или "No" + разликата в противен случай).
+=
е често използван комбиниран оператор за присвояване, добавя стойността на десния операнд към левия операнд и присвоява крайния резултат на левия операнд.
C += A е еквивалентно на C = C + A.
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/655#7.
Да се напише програма, която въвежда текст (стринг), изчислява и отпечатва сумата от стойностите на гласните букви според таблицата по-долу:
a | e | i | o | u |
---|---|---|---|---|
1 | 2 | 3 | 4 | 5 |
Вход | Изход | Вход | Изход |
---|---|---|---|
hello | 6 (e+o = 2+4 = 6) |
bamboo | 9 (a+o+o = 1+4+4 = 9) |
hi | 3 (i = 3) |
beer | 4 (e+e = 2+2 = 4) |
Прочитаме входния текст s
, зануляваме сумата и завъртаме цикъл от 0 до s.length() - 1
(дължината на текста -1). Проверяваме всяка буква s.charAt(i)
дали е гласна и съответно добавяме към сумата стойността ѝ.
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/655#8.
Можем да повтаряме блок код с for
цикъл:
Можем да четем поредица от n
числа от конзолата:
След като се запознахме с циклите, идва време да затвърдим знанията си на практика, а както знаете, това става с много писане на код. Да решим няколко задачи за упражнение.
Създаваме нов проект в IntelliJ IDEA, за да организираме по-добре решенията на задачите за упражнение, като за всяка задача трябва да създадем по един отделен клас.
Стартираме IntelliJ IDEA, избираме: [Create New Project].
след това в лявото поле избираме Java, ако не сме посочили **PROJECT SDK: ** избираме пътя до инсталираната Java JDK директор след което натискаме [Next].
На следващия прозорец отново избираме [Next].
Наименуваме проекта (Project name:) Loops и избираме директория където да го запазим (Project location:). След което натискаме [Finish].
На следващият прозорец избираме [OK] за да създадем Project location, ако не сме създали предварително.
Така създадохме нов проект. Ако в левият прозорец натиснем триъгълника пред Loops, ще се отвори и самата структура на проекта.
За да създадем в нашият проект пакет, който да съдържа всички класове с решенията на задачите за упражнение, натискаме десен бутон на мишката върху src, избираме New -> Package и наименуваме пакета tasks (с малка първа буква).
За да създадем нов клас за първото упражнение, натискаме десен бутон на мишката върху tasks, избираме New -> Java Class и наименуваме класа Task_01 (с главна първа буква).
След тези промени структурата на проекта ще изглежда по следния начин:
Като за всяко следващо упражнение създадем нов клас, по описания по-горе начин за създаване на клас.
Да се напише програма, която въвежда n цели числа и проверява дали сред тях съществува число, което е равно на сумата на всички останали. Ако има такъв елемент, се отпечатва "Yes" + неговата стойност, в противен случай - "No" + разликата между най-големия елемент и сумата на останалите (по абсолютна стойност).
Вход | Изход | Коментар |
---|---|---|
7 3 4 1 1 2 12 1 |
Yes Sum = 12 |
3 + 4 + 1 + 2 + 1 + 1 = 12 |
4 6 1 2 3 |
Yes Sum = 6 |
1 + 2 + 3 = 6 |
3 1 1 10 |
No Diff = 8 |
|10 - (1 + 1)| = 8 |
3 5 5 1 |
No Diff = 1 |
|5 - (5 + 1)| = 1 |
3 1 1 1 |
No Diff = 1 |
- |
Трябва да изчислим сумата на всички елементи, да намерим най-големия от тях и да проверим търсеното условие.
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/655#9.
Напишете програма, която чете n числа и пресмята сумата, минимума и максимума на числата на четни и нечетни позиции (броим от 1). Когато няма минимален / максимален елемент, отпечатайте "No".
Вход | Изход | Вход | Изход |
---|---|---|---|
6 2 3 5 4 2 1 |
OddSum=9, OddMin=2, OddMax=5, EvenSum=8, EvenMin=1, EvenMax=4 |
2 1.5 -2.5 |
OddSum=1.5, OddMin=1.5, OddMax=1.5, EvenSum=-2.5, EvenMin=-2.5, EvenMax=-2.5 |
1 1 |
OddSum=1, OddMin=1, OddMax=1, EvenSum=0, EvenMin=No, EvenMax=No |
0 | OddSum=0, OddMin=No, OddMax=No, EvenSum=0, EvenMin=No, EvenMax=No |
5 3 -2 8 11 -3 |
OddSum=8, OddMin=-3, OddMax=8, EvenSum=9, EvenMin=-2, EvenMax=11 |
4 1.5 1.75 1.5 1.75 |
OddSum=3, OddMin=1.5, OddMax=1.5, EvenSum=3.5, EvenMin=1.75, EvenMax=1.75 |
1 -5 |
OddSum=-5, OddMin=-5, OddMax=-5, EvenSum=0, EvenMin=No, EvenMax=No |
3 -1 -2 -3 |
OddSum=-4, OddMin=-3, OddMax=-1, EvenSum=-2, EvenMin=-2, EvenMax=-2 |
Задачата обединява няколко предходни задачи: намиране на минимум, максимум и сума, както и обработка на елементите от четни и нечетни позиции. Припомнете си ги.
В тази задача е по-добре да се работи с дробни числа (не цели). Сумата, минимумът и максимумът също са дробни числа. Трябва да използваме неутрална начална стойност при намиране на минимум / максимум, например 1000000000.0 и -1000000000.0. Ако получим накрая неутралната стойност, печатаме “No”.
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/655#10.
Дадени са 2 * n числа. Първото и второто формират двойка, третото и четвъртото също и т.н. Всяка двойка има стойност – сумата от съставящите я числа. Напишете програма, която проверява дали всички двойки имат еднаква стойност.
В случай, че е еднаква отпечатайте "Yes, value=…" + стойността, в противен случай отпечатайте максималната разлика между две последователни двойки в следния формат - "No, maxdiff=…" + максималната разлика.
Входът се състои от число n, следвано от 2*n цели числа, всички по едно на ред.
Вход | Изход | Коментар |
---|---|---|
3 1 2 0 3 4 -1 |
Yes, value=3 | стойности = {3, 3, 3} еднакви стойности |
2 1 2 2 2 |
No, maxdiff=1 | стойности = {3, 4} разлики = {1} макс. разлика = 1 |
4 1 1 3 1 2 2 0 0 |
No, maxdiff=4 | стойности = {2, 4, 4, 0} разлики = {2, 0, 4} макс. разлика = 4 |
1 5 5 |
Yes, value=10 | стойности = {10} една стойност еднакви стойности |
2 -1 0 0 -1 |
Yes, value=-1 | стойности = {-1, -1} еднакви стойности |
2 -1 2 0 -1 |
No, maxdiff=2 | стойности = {1, -1} разлики = {2} макс. разлика = 2 |
Прочитаме входните числа по двойки. За всяка двойка пресмятаме сумата ѝ. Докато четем входните двойки, за всяка двойка, без първата, трябва да пресметнем разликата с предходната. За целта е необходимо да пазим в отделна променлива сумата на предходната двойка. Накрая намираме най-голямата разлика между две двойки. Ако е 0, печатаме “Yes” + стойността, в противен случай - “No” + разликата.
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/655#11.
В настоящата глава се запознахме с циклите като конструкция в програмирането, която ни позволява да повтаряме многократно дадено действие или група от действия. Сега нека си поиграем с тях. За целта ще начертаем няколко фигурки, които се състоят от голям брой повтарящи се графични елементи, но този път не на конзолата, а в графична среда, използвайки "графика с костенурка". Ще е интересно. И никак не е сложно. Опитайте!
Целта на следващото упражнение е да си поиграем с една библиотека за рисуване, известна като “графика с костенурка” (turtle graphics). Ще изградим графично приложение, в което ще рисуваме различни фигури, придвижвайки нашата “костенурка” по екрана чрез операции от типа “отиди напред 100 позиции”, “завърти се надясно на 30 градуса”, “отиди напред още 50 позиции”. Приложението ще изглежда приблизително така:
Нека първо се запознаем с концепцията за рисуване “Turtle Graphics”. Може да разгледаме следните източници:
- Дефиниция на понятието “turtle graphics”: http://c2.com/cgi/wiki?TurtleGraphics
- Статия за “turtle graphics” в Wikipedia – https://en.wikipedia.org/wiki/Turtle_graphics
- Интерактивен онлайн инструмент за чертане с костенурка – https://blockly-games.appspot.com/turtle
Започваме, като създаваме нов Java проект в IntelliJ IDEA. След това, добавяме нов пакет app
(описано е как се прави по-рано в тази глава). Сваляме MyTurtle.java
и jturtle-0.1.1.jar
от https://github.com/SoftUni/Programming-Basics-Book-Java-BG/tree/master/assets/chapter-5-1-assets. MyTurtle.java
е предварително написан клас, който ще ни помогне по-бързо да се запознаем с библиотеката jturtle-0.1.1.jar
, която управлява костенурката. Като използваме файл навигатор, копираме MyTurtle.java
в директорията app
на създадения проект. След това трябва да добавим външната библиотека jturtle-0.1.1.jar
в нашия проект. Това става по следния начин:
- Избираме от File менюто Project Structure (CTRL + SHIFT + ALT + S).
- Натискаме Select Modules в левия панел.
- Натискаме Dependencies таба.
- Натискаме '+' → JARs or directories.
На следващия прозорец задаваме пътя до jturtle-0.1.1.jar, след това натискаме [ОК].
На следващия прозорец маркираме само classes кутийката, след това натискаме [ОК].
На следващия прозорец избираме [ОК] и сме готови да отворим MyTurtle.java
.
Това е основните действия в класа Turtle
, с които чертаем:
Връщана стойност |
Метод и неговото описание |
---|---|
Turtle | back(double distance) – мести костенурката назад |
Turtle | bk(double distance) – работи като back(double distance) |
Turtle | forward(double distance) – мести костенурката напред |
Turtle | fd(double distance) – работи като forward(double distance) |
Turtle | hideTurtle() – скрива костенурката |
Turtle | ht() – действието е същото като hideTurtle() |
Turtle | home() – измества костенурката обратно до началната й позиция, обърната на север |
Turtle | left(double degrees) – завърта костенурката на ляво(в градуси) |
Turtle | lt(double degrees) – действа като left(double degrees) |
Turtle | penDown() – закача писалка за костенурката, която оставя линия, когато костенурката се движи |
Turtle | pd() – работи като penDown() |
Turtle | penUp() – откача писалката от костенурката |
Turtle | penWidth(int newWidth) – задава широчина на писалката |
Turtle | right(double degrees) – завърта костенурката на дясно (в градуси) |
Turtle | rt(double degrees) – работи като right(double degrees) |
Turtle | setColor(Color color) – задава цвят на писалката |
Turtle | setLineWidth(double lineWidth) – задава дебелина на линията |
Turtle | setPenColor(Color color) – задава цвят на писалката за чертане |
Turtle | setPos(double x, double y) – измества костенурката на нова позиция с координати(x, y) |
Turtle | showTurtle() – показва костенурката |
Turtle | st() – работи като showTurtle() |
Turtle | speed(double newSpeed) – задава скорост на костенурката |
За да създадем метод който чертае триъгълник, в MyTurtle.java
намираме празния метода drawTriangle()
и написваме следния код:
Този код мести и върти костенурката, която в началото е в центъра на екрана (в средата на формата), и чертае равностранен триъгълник. Може да го редактирате и да си поиграете с него.
Стартираме приложението с [Shift + F10]. Тестваме го дали работи (натискаме [Draw] бутона няколко пъти):
Сега може да променим и усложним кода на костенурката, като добавим следния код към нашия метод drawTriangle()
:
Отново стартираме приложението с [Shift + F10]. Тестваме дали работи новата програма за костенурката:
Вече нашата костенурката чертае по-сложни фигури.
Нека напишем кода и за останалите два бутона: целта на бутона [Reset] е да изтрие начертаната графика и да позиционира костенурката в нейната начална позиция, допълваме метода resetTurtle()
със следния код:
Целта на бутона [Hide / Show Turtle] е да показва или скрива костенурката, допълваме метода showTurtle()
със следния код::
Отново стартираме приложението с [Shift + F10] и тестваме, дали двата бутона работят коректно.
Добавете бутон [Hexagon], който чертае правилен шестоъгълник:
Подсказка:
В цикъл повторете 6 пъти следното:
- Ротация на 60 градуса.
- Движение напред 100.
За добавяне нов бутон за чертане на нова фигура, може да проследим логиката в MyTurtle.java
за бутона [Draw] и да създадем нов бутон за чертане на шестоъгълник Hexagon.
Първо добавяме новата фигура в enum Shape
:
Създаваме нов бутон и му добавяме ActionListener
, който присвоява на shape
новата enum
стойност:
След това добавяме новия бутон в bList
:
Създаваме нов метод drawHex()
, чрез който костенурката чертае шестоъгълник.
Задължително в края на метода shape = ""
, този ред предотвратява многократното изпълнение на нашия метод!
В Thread t
добавяме case "Hexagon
", който да извиква метода drawHex()
:
Добавете бутон [Star], който чертае звезда с 5 върха (петолъчка), като на фигурата по-долу:
Подсказка:
Сменете цвета: turtle.setPenColor(Color.green);
.
В цикъл повторете 5 пъти следното:
- Движение напред 200.
- Ротация на 144 градуса.
Добавете бутон [Spiral], който чертае спирала с 20 върха като на фигурата по-долу:
Подсказка:
Чертайте в цикъл, като движите напред и завъртате. С всяка стъпка увеличавайте постепенно дължината на движението напред и завъртайте на 60 градуса.
Добавете бутон [Sun], който чертае слънце с 36 върха като на фигурата по-долу:
Добавете бутон [Triangle], който чертае три триъгълника с по 22 върха като на фигурата по-долу:
Подсказка:
Чертайте в цикъл като движите напред и завъртате. С всяка стъпка увеличавайте с 10 дължината на движението напред и завъртайте на 120 градуса. Повторете 3 пъти за трите триъгълника.
Ако имате проблеми с примерния проект по-горе попитайте във форума на СофтУни: https://softuni.bg/forum.