Skip to content
От: Божидар Маринов Дата: Последна промяна:

Урок 8, Цикъл "докато"

Допълнителни линкове към този урок:

Основни точки от този урок

Както говорихме в някои от първите видеа, едно от основните неща които правим, когато програмираме, е това да автоматизираме нещо. А най-често, това автоматизиране е свързано с повторение на някаква операция няколко пъти. Например, ако обработваме един файл с много данни, може да искаме да изпълним код за всеки ред от тези данни.

В този урок ще разгледаме един от най-простите начини, по които може да правим такива повторения: цикъла "while".

Преведено на български, "while" означава "докато". Един while цикъл изпълнява някакъв код докато даденото условие е вярно. Той се записва много подобно на един if, по следния начин:

while (1 > 2) {  // Условие
  rect(0, 0, 100, 100) // Код който се изпълнява докато условието е вярно
}

Така-написания цикъл няма да изпълни кода нито веднъж. Бихме могли да сменим знака в условието на <, но тогава бихме получили един безкраен цикъл. И във връзка с това:

⚠️ Когато изпълняваме код с безкраен цикъл е възможно да блокираме таба на браузъра, в който той се изпълнява.
Ако използвате p5.js редактора, не изпълнявайте код с цикли преди да сте го запазили, тъй като е възможно да не успеете да го спасите след като таба блокира.

Вместо това, искаме кода, който се изпълнява в къдравите скоби на цикъла да променя променлива, от която зависи условието на цикъла. Нещо например като това:

let x = 0
while (x < 10) {
  // Този код се изпълнява 10 пъти 
  x = x + 1
}

Но, за да не е толкова сложно отведнъж, нека да разгледаме как правим подобен цикъл стъпка по стъпка...

0. Повтаряме кода на ръка

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

Например, може да искам да нарисувам няколко правоъгълника долепени един до друг покрай горния край на екрана. Нещо като това:

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
  
  rect(0, 0, 50, 50)
  rect(50, 0, 50, 50) // 50 тъй като там свършва първия
  rect(100, 0, 50, 50) // 100 тъй като там свършва първия
}

1. Променяме кода, така че винаги да е еднакъв

Следващата стъпка включва това да разгледаме кода и да измислим начин, по който може да го напишем, така че частта, която повтаряме, да е една и съща.

В кода отгоре, съм повторил линията rect( .. , 0, 50, 50) три пъти, но всеки път на мястото на многоточието слагам различно число. За да може да не се променя самата линия която повтаряме, ще трябва да използваме променлива. (Между другото, това е много подобно на това, което правихме в урока с функции, само че там използвахме параметри.) Нещо подобно на ето това:

function draw() {
  background(220);
  
  let x = 0
  
  rect(x, 0, 50, 50)
  
  x = 50 // променяме стойността на x, за да не се променя другата линия
  
  rect(x, 0, 50, 50) // Тази линия не се променя
  
  x = 100

  rect(x, 0, 50, 50)
}

По този начин, rect(x, 0, 50, 50) не се променя. Остава само някак да направим новия ред с x да не се променя също.

За целта, може да използваме факта, че от дясната страна на =, оператора за задаване на нова стойност, все още имаме достъп до старата стойност на x; нещо което ни беше от полза и в урока за анимации. Използвайки това, мога да запиша x = 50 в кода отгоре като x = x + 50 тъй като старата стойност на x е 0, и x = 100 като.. x = x + 50, отново, тъй като миналата стойност на x в случая е 50.

function draw() {
  background(220);
  
  let x = 0
  
  rect(x, 0, 50, 50)
  x = x + 50 // Увеличаваме x с 50
  
  rect(x, 0, 50, 50)
  x = x + 50

  rect(x, 0, 50, 50)
  x = x + 50 // (няма разлика дали променяме x тук, но така имаме две линии, които винаги се повтарят)
}

Или, онагледено с таблица:

Предишния код Нова стойност на x Минала стойност на x Новия код Новия код със заместени променливи
let x = 0 0 (празно) let x = 0 let x = 0
x = 50 50 0 x = x + 50 x = 0 + 50
x = 100 100 50 x = x + 50 x = 50 + 50
(x = 150) 150 100 x = x + 50 x = 100 + 50

По този начин, получихме два реда код, които може да повтаряме, колкото искаме, и всеки път получаваме още един правоъгълник в края на реда. 🎉

2. Използваме на цикъл

Последната стъпка на това да напишем работещ цикъл включва това да измислим подходящо условие за край и да сглобим всичко в един цикъл. Или с други думи, последната стъпка включва това да кажем на JavaScript да започне сам да повтаря този код, без ние да трябва да го копираме и поставяме на ръка.

В случая, искаме кода да се повтори няколко пъти, примерно докато променливата x не се увеличи дотолкова, че да излезе от екрана:

function draw() {
  background(220);
  
  let x = 0
  while (x < 400) { // Екрана е широк 400, следователно при x над 400, рисуваме извън
    // Този код се повтаря 8 пъти:
    rect(x, 0, 50, 50)
    x = x + 50
  }
}

Ако разгледаме какво се случва със стойността на x, ще получим таблица подобна на тази:

Повторение Стойност на x Стойност на x < 400
1 x = 0 true
2 x = 50 true
3 x = 100 true
... ... ...
6 x = 250 true
7 x = 300 true
8 x = 350 true
(край) x = 400 false (400 е равно на 400, не по-малко)

И така, получихме цикъл!

Допълнителни експерименти

Може да направим правоъгълниците да стигат до мястото, на което е мишката, използвайки отново mouseX:

  let x = 0 // променливата измерва разстоянието от левия край до правоъгълника който рисуваме
  while (x < mouseX) {
    rect(x, 0, 50, 50)
    x = x + 50
  }

Може да направим правоъгълниците да са през някакво разстояние ако увеличим "стъпката" (числото, с което ги увеличаваме). Например:

  let x = 0
  while (x < 400) {
    rect(x, 0, 50, 50)
    x = x + 55 // 5 пиксела разстояние между правоъгълниците
  }

Може да променяме няколко променливи в цикъла (но обикновено в условието ще използваме само една от тях). Примерно, по този начин получаваме стълбичка:

  let x = 0
  let h = 10 // височината на правоъгълника
  while (x < 400) {
    rect(x, 0, 50, h)
    x = x + 50
    h = h + 3 // (прави следващия правоъгълник малко по-висок)
  }

Задачa

Използвайки while цикъл, нарисувайте ограда от единия до другия край на екрана.

%Например, вашата ограда може да изгледа ето така! (но може и да е по-проста, тъй като все още не сме учили функциите нужни за тази)
Например, вашата ограда може да изгледа ето така!
(но може и да е по-проста, тъй като все още не сме учили функциите нужни за тази)

За допълнителна задача, направете оградата да се изрисува с функция, която получава мястото на което да нарисува оградата като параметри.