<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Замещения у 9-1, 10-1, 11-1 зимой 2016/2017</title>
    <description>Замещения у 9-1, 10-1, 11-1 зимой 2016/2017</description>
    <link>http://polarnick.com/239/201612/feed.xml</link>
    <atom:link href="http://polarnick.com/239/201612/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 10 Mar 2026 20:21:39 +0000</pubDate>
    <lastBuildDate>Tue, 10 Mar 2026 20:21:39 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Игры</title>
        <description>&lt;p&gt;Вариации &lt;a href=&quot;/lessons/239/lesson/school/p5js/game/2017/03/08/FlabbyBirds.html&quot;&gt;задания про FlabbyBird&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/static/flabby_bird/results/savon/index.html&quot;&gt;Единорог&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/static/flabby_bird/results/savon/index2.html&quot;&gt;Единорог 2&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/static/flabby_bird/results/aroniya/index.html&quot;&gt;Космонавт&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/static/flabby_bird/results/sahno/index.html&quot;&gt;Flabby bird&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/static/flabby_bird/results/ivanova/index.html&quot;&gt;Vector bird&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Другие игры учеников 239:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/static/239_games/novikova_volleyball/index.html&quot;&gt;Волейбол&lt;/a&gt; (управление: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Z, X, C&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B, N, M&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 15 Mar 2017 09:00:00 +0000</pubDate>
        <link>http://polarnick.com/lessons/239/lesson/school/p5js/game/2017/03/15/Games.html</link>
        <guid isPermaLink="true">http://polarnick.com/lessons/239/lesson/school/p5js/game/2017/03/15/Games.html</guid>
        
        
        <category>lessons</category>
        
        <category>239</category>
        
        <category>lesson</category>
        
        <category>school</category>
        
        <category>p5js</category>
        
        <category>game</category>
        
      </item>
    
      <item>
        <title>Мини-задание 52. Flabby bird (дополнения)</title>
        <description>&lt;h1 id=&quot;примеры&quot;&gt;Примеры&lt;/h1&gt;

&lt;p&gt;Несколько примеров:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/static/flabby_bird/results/savon/index.html&quot;&gt;Единорог&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/static/flabby_bird/results/savon/index2.html&quot;&gt;Единорог 2&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/static/flabby_bird/results/aroniya/index.html&quot;&gt;Космонавт&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/static/flabby_bird/results/sahno/index.html&quot;&gt;Flabby bird&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/static/flabby_bird/results/ivanova/index.html&quot;&gt;Vector bird&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ниже предложены некоторые идеи для развития &lt;a href=&quot;/lessons/239/lesson/school/p5js/game/2017/03/08/FlabbyBirds.html&quot;&gt;Задания 52&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;картинка-вместо-эллипса&quot;&gt;Картинка вместо эллипса&lt;/h1&gt;

&lt;p&gt;Например окружность-птицу можно заменить на картинку. Можно взять любую, например одну из этих двух (осторожно! простой выбор!):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/flabby_bird/unicorn.png&quot; alt=&quot;Unicorn&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/flabby_bird/bird.png&quot; alt=&quot;Flabby bird&quot; /&gt;&lt;/p&gt;

&lt;p&gt;И теперь вместо отрисовки эллипса методом &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ellipse(...)&lt;/code&gt; вам надо делать по аналогии с &lt;a href=&quot;https://p5js.org/examples/image-load-and-display-image.html&quot;&gt;этим примером&lt;/a&gt;.
Обратите внимание, что вместо &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assets/moonwalk.jpg&lt;/code&gt; вам надо указать путь к картинке. В частности вы можете указать адрес одной из этих двух картинок (например &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://polarnick239.github.io/static/flabby_bird/unicorn.png&lt;/code&gt; или то же самое, но с &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bird.png&lt;/code&gt; на конце, но давайте не будем строить иллюзий по поводу идеальности ровно одной картинки из этих двух).&lt;/p&gt;

&lt;h1 id=&quot;наклонять-единорога&quot;&gt;Наклонять Единорога&lt;/h1&gt;

&lt;p&gt;Если в данный момент скорость направлена вниз - то игровой персонаж должен быть наклонен соответствующе (по часовой стрелке), если вверх - то наоборот. Соответственно можно рисовать картинку персонажа повернутой пропорционально текущей вертикальной скорости.&lt;/p&gt;

&lt;h1 id=&quot;рестарт-игры&quot;&gt;Рестарт игры&lt;/h1&gt;

&lt;p&gt;Если игрок врезался в стену - разумно показать очки игрока и потом начать игру заново, но уже хорошо будет, если просто игра начнется с начала.
Обратите внимание что делать перезапуск игры очень просто.
Ведь по сути текущее состояние игры определяется значениями глобальных переменных, которые вы выставляете в некоторые изначальные значения (например в &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup&lt;/code&gt; или просто в место объявления переменной) и обновляете при каждом обновлении кадра.&lt;/p&gt;

&lt;p&gt;Соответственно чтобы начать игру заново достаточно все значения глобальных переменных выставить обратно в значения которые были изначально.&lt;/p&gt;

&lt;h1 id=&quot;поддержка-нескольких-стен&quot;&gt;Поддержка нескольких стен&lt;/h1&gt;

&lt;p&gt;Сделайте так, чтобы набегала не одна стена, а хотя бы две (а еще лучше - чтобы их число могло быть произвольным).&lt;/p&gt;

&lt;h1 id=&quot;смена-времени-суток&quot;&gt;Смена времени суток&lt;/h1&gt;

&lt;p&gt;Достаточно циклически плавно менять цвет фона между темным и светлым, добавить туда ночную луну/звезды/солнце - и будет вполне реалистичная смена суток!&lt;/p&gt;
</description>
        <pubDate>Wed, 15 Mar 2017 09:00:00 +0000</pubDate>
        <link>http://polarnick.com/lessons/239/lesson/school/p5js/game/2017/03/15/FlabbyBirds-update.html</link>
        <guid isPermaLink="true">http://polarnick.com/lessons/239/lesson/school/p5js/game/2017/03/15/FlabbyBirds-update.html</guid>
        
        
        <category>lessons</category>
        
        <category>239</category>
        
        <category>lesson</category>
        
        <category>school</category>
        
        <category>p5js</category>
        
        <category>game</category>
        
      </item>
    
      <item>
        <title>Мини-задание 239: brainfuck</title>
        <description>&lt;p&gt;Brainfuck - эзотерический язык программирования. Он не используется как удобный инструмент решения практических задач (ввиду своей неудобности и непрактичности), но решать простые задачи на нем может быть интересно и полезно - так же как решать любую головоломку.
К тому же brainfuck является наглядным примером &lt;a href=&quot;https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%BF%D0%BE_%D0%A2%D1%8C%D1%8E%D1%80%D0%B8%D0%BD%D0%B3%D1%83&quot;&gt;тьюринг-полного&lt;/a&gt; языка.&lt;/p&gt;

&lt;h2 id=&quot;описание-и-синтаксис&quot;&gt;Описание и синтаксис&lt;/h2&gt;

&lt;p&gt;В этом языке нет переменных и функций, модель языка гораздо проще:&lt;/p&gt;

&lt;p&gt;Есть большой массив 8-битных значений (т.е. каждый элемент от 0 до 255) - так называемая лента памяти. Есть указатель на ячейку памяти. При запуске программы он указывает на первую ячейку. Значения всех ячеек в момент запуска программы равны нулю.&lt;/p&gt;

&lt;p&gt;Команды языка brainfuck:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; - сдвинуть указатель ячейки памяти вправо к следующей ячейке&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; - сдвинуть указатель ячейки памяти влево к предыдущей ячейке&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; - увеличить значение текущей ячейки на 1&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt; - уменьшить значение текущей ячейки на 1&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt; - напечатать символ из текущей ячейки в соответствии с &lt;a href=&quot;http://www.asciitable.com/&quot;&gt;ASCII-таблицей&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;,&lt;/code&gt; - считать в текущую ячейку символ из консоли&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt; - если значение текущей ячейки ноль, то перейти вперёд по тексту программы на команду, следующую за соответствующей &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;]&lt;/code&gt;, иначе продолжить исполнение&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;]&lt;/code&gt; - если значение текущей ячейки не ноль, то вернуться назад на команду, следующую за соответствующей &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt;, иначе продолжить исполнение&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;интерпретаторы&quot;&gt;Интерпретаторы&lt;/h2&gt;

&lt;p&gt;Интерпретатор написать очень просто, их существует очень много. Например есть интерпретатор с визуализацией доступный &lt;a href=&quot;http://fatiherikli.github.io/brainfuck-visualizer/&quot;&gt;из браузера&lt;/a&gt;. Или другой интепретатор тоже &lt;a href=&quot;https://copy.sh/brainfuck/&quot;&gt;из браузера&lt;/a&gt;, но этот вычисляет быстро. Есть также &lt;a href=&quot;https://sites.google.com/site/visualbf/home&quot;&gt;интепретатор&lt;/a&gt; который требует установки, но обладает расширенным функционалом.&lt;/p&gt;

&lt;h2 id=&quot;как-с-этим-жить&quot;&gt;Как с этим жить&lt;/h2&gt;

&lt;p&gt;Давайте подумаем как напечатать тривиальный &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hello world&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Для начала нам надо руководствуясь &lt;a href=&quot;http://www.asciitable.com/&quot;&gt;ASCII-таблицей&lt;/a&gt; понять, какие это символы в представлении ASCII-кодов:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hello world&lt;/code&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;P.S. Это можно делать не обязательно глазами и руками, а например с помощью &lt;a href=&quot;https://www.easycalculation.com/ascii-hex.php&quot;&gt;онлайн-конвертера&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Можно было бы напечатать огромное число операций &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; (и небольшое количество &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt;) и напечатать заветный &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hello world&lt;/code&gt;, но можно воспользоваться умножением и циклами:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                &lt;span class=&quot;c1&quot;&gt;// H = 72 = 9*8&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;// Давайте в первой ячейке положим число 9&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+++++++++&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;// Этот блок кода будет выполняться пока в текущей ячейке не ноль (в данном случае текущая = первая)&lt;/span&gt;

                &lt;span class=&quot;c1&quot;&gt;// И будем 9 раз увеличивать вторую ячейку на 8&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;// Тогда во второй ячейке окажется 72 а это та буква которая нам нужна&lt;/span&gt;

    &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// Переходим ко второй ячейке&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;++++++++&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Увеличиваем ее на 8&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// Возвращаемся к первой ячейке&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// Уменьшаем ее на единицу ведь еще одна итерация прошла успешно&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;// Раз мы пришли сюда значит цикл исполнился 9 раз значит во второй ячейке лежит 72 проверяем:&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;// Переходим ко второй ячейке&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;// Выводим символ&lt;/span&gt;

                &lt;span class=&quot;c1&quot;&gt;// Дальше в том же духе&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Заметим, что можно сэкономить, ведь при переходе от буквы &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e&lt;/code&gt; к &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;l&lt;/code&gt; (т.е. от &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;101&lt;/code&gt; к &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;108&lt;/code&gt;) достаточно увеличить значение всего лишь на 7, а третья и четвертая буквы совпадают.&lt;/p&gt;

&lt;p&gt;Еще несколько примеров:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[-]&lt;/span&gt;             &lt;span class=&quot;c1&quot;&gt;// Зануляет текущую ячейку&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[-&amp;gt;+&amp;lt;]&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Сдвигает переменную в соседнюю ячейку&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[-&amp;gt;+&amp;gt;+&amp;lt;&amp;lt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;[-&amp;lt;&amp;lt;+&amp;gt;&amp;gt;]&amp;lt;&amp;lt;&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Копирует ячейку в сосденюю&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[.&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[-]]&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;// Выводит текущую ячейку, если она не ноль (обратите внимание, что если ее не занулить, или не сдвинуть вместо этого указатель - то этот цикл зависнет)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;упражнение-1&quot;&gt;Упражнение 1&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Условие:&lt;/code&gt; Выведите &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hello world&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;упражнение-2&quot;&gt;Упражнение 2&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Условие:&lt;/code&gt; Выведите английский алфавит (заглавные буквы): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ABCDEFGHIJKLMNOPQRSTUVWXYZ&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Комментарии:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Обратите внимание, что английские буквы в &lt;a href=&quot;http://www.asciitable.com/&quot;&gt;ASCII-таблице&lt;/a&gt; - символы от &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;65&lt;/code&gt; до &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;90&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;26&lt;/code&gt; символов).&lt;/li&gt;
  &lt;li&gt;Попробуйте минимизировать число инструкций (&lt;a href=&quot;http://simvoli.net/&quot;&gt;онлайн счетовод символов&lt;/a&gt;, пробелы в исходном коде за символы не считаются)&lt;/li&gt;
  &lt;li&gt;Посоревнуйтесь с друзьями у кого программа короче (у меня заняло &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;38&lt;/code&gt; инструкций: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;++++++++[-&amp;gt;++++++++&amp;gt;+++&amp;lt;&amp;lt;]&amp;gt;+&amp;gt;++[&amp;lt;.+&amp;gt;-]&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;упражнение-3&quot;&gt;Упражнение 3&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Условие:&lt;/code&gt; Пользователь вводит два символа - выведите наименьший&lt;/p&gt;

&lt;p&gt;Комментарии:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Пример выводящий второй введенный символ: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;,&amp;gt;,.&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Пример выводящий первый введенный символ: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;,&amp;gt;,&amp;lt;.&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Придумайте сначала как сделать операцию &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Если текущая ячейка x == 0, то делаем А&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Спойлер&lt;/code&gt; про предыдущий комментарий: пусть справа от текущей лежат &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0 1 0&lt;/code&gt;, тогда подумайте что сделает инструкция &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&amp;gt;]&amp;gt;&amp;gt;&lt;/code&gt;, заметьте что в случае если изначальная клетка была ноль, то указатель теперь на единице, если же изначально был не ноль - то теперь указатель на нуле&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Спойлер2&lt;/code&gt; итого чтобы сделать предложенную в комментарии выше операцию надо положить справа от текущей ячейки &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0 1 0&lt;/code&gt; и выполнить код &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&amp;gt;]&amp;gt;&amp;gt; [ A ]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;упражнение-4&quot;&gt;Упражнение 4&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Условие:&lt;/code&gt; Пользователь вводит буквы одну за другой, пока не введет символ точки (код &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;46&lt;/code&gt;). Выведите введенные символы в алфавитном порядке (с повторениями)&lt;/p&gt;

&lt;p&gt;Комментарии:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Попробуйте алгоритм &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ищем максимум, поднимаем его вверх&lt;/code&gt; или &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;делаем n^2 сравнений соседей, если они в неправильном порядке - swap между собой&lt;/code&gt; или &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;сортировкой подсчетом&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Поймите сколько вам нужно было бы переменных, и оставьте между хранящамися на ленте символами зазор в столько ячеек, сколько вам нужно переменных&lt;/li&gt;
  &lt;li&gt;Пока вы будете реализовывать - постоянно будет оказываться что зазор надо было брать больше, так что удобнее брать зазор с запасом :)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;отправка-решения&quot;&gt;Отправка решения&lt;/h2&gt;

&lt;p&gt;Если вы сделали второе/третье/четвертое упражнение, то можете отправить мне ваше решение письмом:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Пример темы письма: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Brainfuck 16-1 Полярный Николай Упражнение 4&lt;/code&gt; (в конце темы номер самого сложного упражнения, которое вы осилили)&lt;/li&gt;
  &lt;li&gt;Если ваше решение короче лучшего на данный момент - ваше решение будет выложено ниже&lt;/li&gt;
  &lt;li&gt;Исходный код можно прилагать либо файлом, либо прямо в тексте письма (желательно хоть как-то форматированный)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;лучшие-результаты&quot;&gt;Лучшие результаты:&lt;/h2&gt;

&lt;p&gt;Ниже приведены самые короткие решения. (считаются только символы являющиеся корректными инструкциями, &lt;a href=&quot;http://simvoli.net/&quot;&gt;онлайн счетовод символов&lt;/a&gt;, &lt;a href=&quot;https://copy.sh/brainfuck/&quot;&gt;интерпретатор&lt;/a&gt;, подобные задачки решают на &lt;a href=&quot;https://codegolf.stackexchange.com/&quot;&gt;codegolf&lt;/a&gt;)&lt;/p&gt;

&lt;h1 id=&quot;ps-по-клику-появляется-исходный-код&quot;&gt;&lt;em&gt;P.S. По клику появляется исходный код&lt;/em&gt;&lt;/h1&gt;

&lt;h1 id=&quot;упражнение-1-hello-world&quot;&gt;Упражнение 1 (Hello World)&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Рекорды&lt;/code&gt;:&lt;/p&gt;

&lt;details&gt;
  &lt;summary&gt;131 символов (11-1 Думпис Сергей)&lt;/summary&gt;
  &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+++++ ++++
[
&amp;gt;
+++++ +++
&amp;lt;
-
]
&amp;gt;
.
[-]
&amp;lt;
+++++ +++++
[
&amp;gt;
+++++ +++++
&amp;lt;
-
]
&amp;gt; + .
+++++ ++ . . 
+++ .

&amp;gt; &amp;gt;
+++++ +++
[ &amp;gt; ++++ &amp;lt; -]
&amp;gt; .
&amp;lt;&amp;lt;&amp;lt;

+++++ +++ .
----- ---.
+++.
----- -.
----- --- .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
&lt;/details&gt;

&lt;h1 id=&quot;упражнение-2-алфавит&quot;&gt;Упражнение 2 (Алфавит)&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Рекорды&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;35 символов: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+++++++++++++[&amp;gt;++&amp;gt;+++++&amp;lt;&amp;lt;-]&amp;gt;[&amp;gt;.+&amp;lt;-]&lt;/code&gt; (11-1 Вирачев Арсений)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;36 символов: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+++++++++++++[&amp;gt;+++++&amp;gt;++&amp;lt;&amp;lt;-]&amp;gt;&amp;gt;[&amp;lt;.+&amp;gt;-]&lt;/code&gt; (10-1 Олейник Иван)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;36 символов: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+++[&amp;gt;++++&amp;lt;-]&amp;gt;+[&amp;gt;++&amp;gt;+++++&amp;lt;&amp;lt;-]&amp;gt;[&amp;gt;.+&amp;lt;-]&lt;/code&gt; (11-1 Думпис Сергей)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;упражнение-3-минимум&quot;&gt;Упражнение 3 (Минимум)&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Рекорды&lt;/code&gt;:&lt;/p&gt;

&lt;details&gt;
  &lt;summary&gt;33 символов (11-1 Кохась Дмитрий)&lt;/summary&gt;
  &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+&amp;gt;&amp;gt;&amp;gt;,&amp;gt;,&amp;lt;&amp;lt;&amp;lt;&amp;lt;[&amp;gt;&amp;gt;&amp;gt;-&amp;gt;-&amp;gt;+&amp;gt;+[&amp;lt;]&amp;lt;&amp;lt;]&amp;gt;&amp;gt;&amp;gt;&amp;gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
&lt;/details&gt;

&lt;details&gt;
  &lt;summary&gt;155 символов (11-1 Вирачев Арсений)&lt;/summary&gt;
  &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+&amp;gt;&amp;gt;+&amp;gt;
,
[
   &amp;gt;+&amp;gt;+&amp;lt;&amp;lt;-
]

&amp;gt;&amp;gt;&amp;gt;&amp;gt;+
&amp;gt;

,
[
   &amp;gt;+&amp;gt;+&amp;lt;&amp;lt;-
]
&amp;gt;&amp;gt;&amp;gt;&amp;gt;+

&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;
[
  &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
  [&amp;gt;]&amp;gt;&amp;gt;[
    &amp;lt;&amp;lt;&amp;lt;.&amp;lt;&amp;lt;&amp;lt;&amp;lt;-&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
  &amp;gt;]
  &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;
  -
  [&amp;gt;]&amp;gt;&amp;gt;[
    &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
    [&amp;gt;]&amp;gt;&amp;gt;[
      &amp;lt;&amp;lt;&amp;lt;.&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;-&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
    &amp;gt;]
    &amp;lt;&amp;lt;&amp;lt;
    -
    &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;
    -
    &amp;lt;&amp;lt;&amp;lt;
  &amp;gt;]
  &amp;lt;&amp;lt;&amp;lt;
  +
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
&lt;/details&gt;

&lt;h1 id=&quot;упражнение-4-сортировка&quot;&gt;Упражнение 4 (Сортировка)&lt;/h1&gt;

&lt;details&gt;
  &lt;summary&gt;116 символов (10-1 Олейник Иван)&lt;/summary&gt;
  &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;,[&amp;gt;&amp;gt;,]&amp;lt;&amp;lt;
[
[&amp;lt;&amp;lt;]&amp;gt;&amp;gt;&amp;gt;&amp;gt;
[&amp;lt;&amp;lt;
[&amp;gt;+&amp;lt;&amp;lt;+&amp;gt;-]&amp;gt;&amp;gt;
[&amp;gt;+&amp;lt;&amp;lt;&amp;lt;&amp;lt;[-&amp;gt;]&amp;gt;[&amp;lt;]&amp;gt;&amp;gt;-]&amp;lt;&amp;lt;&amp;lt;
[[-]&amp;gt;&amp;gt;[&amp;gt;+&amp;lt;-]&amp;gt;&amp;gt;[&amp;lt;&amp;lt;&amp;lt;+&amp;gt;&amp;gt;&amp;gt;-]]&amp;gt;&amp;gt;
[[&amp;lt;+&amp;gt;-]&amp;gt;&amp;gt;]&amp;lt;
]&amp;lt;&amp;lt;
[&amp;gt;&amp;gt;+&amp;lt;&amp;lt;-]&amp;lt;&amp;lt;
]&amp;gt;&amp;gt;&amp;gt;&amp;gt;
[.&amp;gt;&amp;gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
&lt;/details&gt;

&lt;details&gt;
  &lt;summary&gt;3092 символа!!! С комментариями!!! (11-1 Вирачев Арсений)&lt;/summary&gt;
  &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;//формат глобально такой: 
//Адрес 0: 1 если надо сделать ещё итерацию(и) вычитания единицы
//1) Дальше много фблоков вида
//2) (флаг начала/конца массива (0=начало/конец))010
//3) число
//4) (число для уменьшения)010
//5) (флаг вывода числа (1=выведено))010
//6) (вспомогательный флаг)010

//В самом конце вводим точку (46) и устанавливаем для неё флаг вывода в 1 и флаг конца в 0

+&amp;gt; //записываем в первую ячейку 1 (это нужно потом)
&amp;gt;&amp;gt;+ //делаем нулевой фиктивный блок 0010 0 0010 1010 0010
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;+
&amp;gt;&amp;gt;+ //флаг вывода = 1
&amp;gt;&amp;gt;+
&amp;gt;&amp;gt;&amp;gt;&amp;gt;+
&amp;gt;&amp;gt;

//вводим остальные числа

+ //1 в начале блока
[
  &amp;gt;&amp;gt;+&amp;gt;
  ,
  [ //делаем 1010aaa
    &amp;gt;+&amp;gt;+&amp;gt;+
    &amp;lt;&amp;lt;&amp;lt;-
  ]
  &amp;gt;&amp;gt;&amp;gt;
  //вычитаем 46=7*7 минус 3 из последней a
  &amp;gt;+++++++
  [
    -
    &amp;lt;-------
    &amp;gt;
  ]
  &amp;lt;+++
  //делаем 1010aa(a минус 46)010
  &amp;gt;&amp;gt;+
  &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;+&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; //пихаем 1 в начало следующего блока
  [&amp;gt;]&amp;gt;&amp;gt;[ //если a=46
    &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;-&amp;gt;&amp;gt;+&amp;lt;&amp;lt; &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; //пихаем 0010 в начало следующего блока
    &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;- //делаем флаг конца=0
    &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
  &amp;gt;]
  &amp;lt;&amp;lt;&amp;lt;
  [-] //обнуляем место где было a минус 46
  &amp;gt;+
  &amp;gt;-
  &amp;gt;&amp;gt;&amp;gt;+
  &amp;gt;&amp;gt;&amp;gt;&amp;gt;+
  &amp;gt;&amp;gt; //перешли в начало следующего блока
]
&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;+ //устанавливаем флаг вывода последнего символа (точки) в 

1
&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; //в начало последнего (фиктивного) блока
&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; //17 назад (начало последнего блока)

//теперь осталось посортить :)

[ //возвращаемся к нулевому блоку
  &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; //17 назад (начало предыдущего блока)
]
&amp;lt; //адрес=0 (там лежит 1)

[
  &amp;gt; //в начало нулевого блока
  &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; //в начало первого блока
  [ //цикла пока не дойдём до последнего блока
    &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
    [&amp;gt;]&amp;gt;&amp;gt;[ //если текущее уменьшенное число = 0
      &amp;gt;&amp;gt;
      [&amp;gt;]&amp;gt;&amp;gt;[ //если флаг вывода = 0
        &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;. //выводим
        &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;+ //флаг вывода = 1
        &amp;gt;&amp;gt;
      &amp;gt;]
      &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;
    &amp;gt;]
    &amp;gt;
    [&amp;gt;]&amp;gt;&amp;gt;[ //если флаг вывода = 0
      &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;- //уменьшаем
      &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;+ //вспомогательные флаг = 1
      &amp;lt;&amp;lt;
    &amp;gt;]
    &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; //в начало следующего блока
  ]
  &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; //17 назад (начало последнего блока)
  [
    &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; //17 вперёд
    -
    [&amp;gt;]&amp;gt;&amp;gt;[ //если есть следующий блок (не фиктивный)
      &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; //вспомогательный флаг следующего блока
      [ //обнуляем этот флаг если он не = 0
        -
        &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; //17 назад (вспомогательный флаг данного 

блока)
        [&amp;gt;]&amp;gt;&amp;gt;[ //если он = 0
          &amp;lt;&amp;lt;+ //устанавливаем его
          &amp;gt;&amp;gt;
        &amp;gt;]
        &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; //17 минус 3 вперёд
      ]
      &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;
    &amp;gt;]
    &amp;lt;&amp;lt;&amp;lt;+
    
    &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; //17 назад (начало данного блока)
    &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; //17 назад (начало предыдущего блока)
  ]
  //мы в начале нулевого блока
  //в вспомогательном флаге первого блока сейчас логическое ИЛИ
  //всех вспомогательных флагов
  //остальные вспомогательные флаги равны 0 
  
  &amp;lt;-&amp;gt; //обнуляем нулевую ячейку

  &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; //17 вперёд
  &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; //вспомогательный флаг первого блока
  [ //если там 1
    &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; //возвращаемся к адресу 0
    &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; //17 назад 
    &amp;lt;+ //ставим туда 1
    &amp;gt; //теперь опять обратно
    &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; //17 вперёд
    &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; //вспомогательный флаг первого блока
    - //обнуляем его
  ]
  &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; //начало первого блока
  &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; //17 назад 
  &amp;lt; //возвращаемся к адресу 0
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
&lt;/details&gt;
</description>
        <pubDate>Tue, 14 Mar 2017 09:00:00 +0000</pubDate>
        <link>http://polarnick.com/lessons/239/lesson/school/brainfuck/2017/03/14/Brainfuck.html</link>
        <guid isPermaLink="true">http://polarnick.com/lessons/239/lesson/school/brainfuck/2017/03/14/Brainfuck.html</guid>
        
        
        <category>lessons</category>
        
        <category>239</category>
        
        <category>lesson</category>
        
        <category>school</category>
        
        <category>brainfuck</category>
        
      </item>
    
      <item>
        <title>Тутор: упаковка программы</title>
        <description>&lt;p&gt;Может быть желательно запаковать программу в один файл так, чтобы программа работала по двойному клику мышки.
Это нужно например в случае когда вы сделали игру/программу и захотели поделиться ею с друзьями.
А т.к. им может быть неудобно/долго/сложно компилировать программу самим, то хочется отправлять уже готовое приложение.&lt;/p&gt;

&lt;p&gt;В общем случае в реальном мире это делается относительно сложно с помощью сборочных инструментов вроде Ant, Maven или Gradle. Но нам подойдет и более простой способ - с помощью встроенной в Intellij IDEA функциональности.&lt;/p&gt;

&lt;h2 id=&quot;0-нужен-готовый-проект&quot;&gt;0) Нужен готовый проект&lt;/h2&gt;

&lt;p&gt;Для того чтобы было что запаковывать в приложение нужен проект открытый в Intellij IDEA, который можно запустить. Т.е. в этом проекте есть &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; функция, которая будет являться точкой входа в приложение, т.е. будет запускаться в момент двойного клика по запакованной программе.&lt;/p&gt;

&lt;p&gt;Дальше будет предполагаться что класс в котором определена желаемая &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; функция называется &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Monoceros&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;1-настройка-упаковки-в-пакет&quot;&gt;1) Настройка упаковки в пакет&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File&lt;/code&gt;-&amp;gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Project Struture&lt;/code&gt;-&amp;gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Artifacts&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Зеленый плюсик сверху-слева -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JAR&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;From modules with dependencies...&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Справа от &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Main Class&lt;/code&gt; нажав на три точки нужно выбрать класс &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Monoceros&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Убедиться, что выбран вариант &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extract to the target JAR&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Нажать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ok&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Еще раз нажать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ok&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;2-компиляция-пакета&quot;&gt;2) Компиляция пакета&lt;/h2&gt;

&lt;p&gt;Теперь можно собирать пакет приложения:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Build&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Build Artifacts...&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Выбираете нужный артефакт, и жмете &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Build&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Теперь в подпапке проекта &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;out/artifacts/&amp;lt;ArtifactName&amp;gt;_jar/&lt;/code&gt; лежит упакованный &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jar&lt;/code&gt; файл. Его можно запустить на любом компьютере, на котором установлена Java-машина (она же &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JVM&lt;/code&gt;, она же &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JRE&lt;/code&gt;).&lt;/p&gt;

&lt;h2 id=&quot;3-запуск-jar-пакета&quot;&gt;3) Запуск jar-пакета&lt;/h2&gt;

&lt;p&gt;Двойного клика должно быть достаточно. Но зависит от операционной системы, так что если не будет работать на вашей - напишите мне.&lt;/p&gt;

&lt;h2 id=&quot;4-если-несколько-main-функций&quot;&gt;4) Если несколько main-функций&lt;/h2&gt;

&lt;p&gt;Есть несколько вариантов что делать, если у вас есть несколько &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;-функций. По сути это означает что у вас есть несколько программ. Например сервер и клиент. Самый простой вариант - выполнить эту инструкцию два раза для каждого класса, в котором есть &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;-функция, тогда будет несколько &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jar&lt;/code&gt;-пакетов.&lt;/p&gt;

&lt;h2 id=&quot;если-вдруг-не-запускается&quot;&gt;Если вдруг не запускается&lt;/h2&gt;

&lt;p&gt;Запустите терминал (как это сделать - гуглится по &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;windows N how to run command prompt&lt;/code&gt;, где &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt; - ваша версия ОС). Вероятно почти везде сработает открыть главное меню (пуск или меню-плитка), там запустить программу &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Выполнить&lt;/code&gt;, в ней ввести &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmd&lt;/code&gt; и нажать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;В появившемся черном текстовом окне перейдите в папку где находится &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;ArtifactName&amp;gt;.jar&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;Например если файл находится по пути &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:\A\B\C\&amp;lt;ArtifactName&amp;gt;.jar&lt;/code&gt; то надо выполнить две команды:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd A\B\C&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Теперь надо запустить явным образом &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jar&lt;/code&gt;-файл (то же самое происходит при двойном клике):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java -jar &amp;lt;ArtifactName&amp;gt;.jar&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Скорее-всего как и при двойном клике программа на самом деле запускается но падает на старте, и поэтому создается впечатление что она не запустилась, хотя на самом деле она просто быстро упала.&lt;/p&gt;

&lt;p&gt;Преимущество явного запуска из консоли в том, что ошибки приложения будут видны в консоли (аналогично тому, как они были видны в консоли среды разработки).&lt;/p&gt;
</description>
        <pubDate>Mon, 13 Mar 2017 09:00:00 +0000</pubDate>
        <link>http://polarnick.com/lessons/239/lesson/school/java/jar/2017/03/13/StandaloneJavaApp.html</link>
        <guid isPermaLink="true">http://polarnick.com/lessons/239/lesson/school/java/jar/2017/03/13/StandaloneJavaApp.html</guid>
        
        
        <category>lessons</category>
        
        <category>239</category>
        
        <category>lesson</category>
        
        <category>school</category>
        
        <category>java</category>
        
        <category>jar</category>
        
      </item>
    
      <item>
        <title>Мини-задание 52. Flabby bird</title>
        <description>&lt;p&gt;В этом мини-задании будет реализована игра Flabby bird на базе библиотеки из задания &lt;a href=&quot;/lessons/239/lesson/school/p5js/2017/03/01/SimpleDrawingInP5JS.html&quot;&gt;про фракталы&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Должна получиться игра аналогичная &lt;a href=&quot;http://flappybird.io/&quot;&gt;этой&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Предполагается, что перед этим заданием было выполнено и полностью понято задание &lt;a href=&quot;/lessons/239/lesson/school/p5js/2017/03/01/SimpleDrawingInP5JS.html&quot;&gt;про фракталы&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;1-обновление-состояния&quot;&gt;1) Обновление состояния&lt;/h2&gt;

&lt;p&gt;Тривиальная заготовка с фоном цвета неба и линией нарисованной по центру под углом:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;createCanvas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;640&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;480&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;// Указываем размер холста&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;54&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;187&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;205&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// Указываем цвет фона&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;320&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;240&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// Смещаем центр системы координат в центр экрана&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;PI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;// Поворачиваем систему координат вокруг ее текущей точки отсчета&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// Рисуем линию в текущей системе координат&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Игра предполагает что птица летит, а значит требуется обновлять состояние мира с некоторой периодичностью. В используемой библиотеке есть функция &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frameRate(N);&lt;/code&gt; с единственным аргументом - желаемое число кадров в секунду.
Ее вызов на этапе настройки игры (внутри функции &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup&lt;/code&gt;) приведет к тому, что &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw&lt;/code&gt; будет вызываться в секунду столько раз, сколько сказано в вызове функции &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frameRate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Чтобы проверить это предлагается вращать линию в центре холста. Для увеличения угла наклона от отрисовки к отрисовке потребуется глобальная переменная:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;angle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;angle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;angle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;angle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;P.S. &lt;a href=&quot;https://p5js.org/examples/structure-loop.html&quot;&gt;альтернативный пример&lt;/a&gt; обновления состояния.&lt;/p&gt;

&lt;p&gt;Чтобы очищать экран от отрисовки к отрисовке - надо перенести вызов &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background&lt;/code&gt; из функции &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup&lt;/code&gt; (которая вызывается один раз при запуске программы) в функцию &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Теперь отрезок вращается.&lt;/p&gt;

&lt;h2 id=&quot;2-состояние-и-отрисовка-птички&quot;&gt;2) Состояние и отрисовка птички&lt;/h2&gt;

&lt;p&gt;Птица немного сложнее вращающегося отрезка. Подумаем из чего состоит описание состояния птицы:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Высота положения птицы&lt;/li&gt;
  &lt;li&gt;Вертикальная скорость птицы&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Еще для определения гравитации потребуется константа ускорения свободного падения:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;birdHeight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;240.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;birdVerticalSpeed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gravityAcceleration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Создайте функцию отрисовки положения птицы &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawBird&lt;/code&gt;, которая на основе значения &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;birdHeight&lt;/code&gt; нарисует круг (что-то вроде &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ellipse(0, 0, 20, 20);&lt;/code&gt;), который представляет нашу условную птицу. И вызовите эту функцию из функции &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;3-управление-птицей&quot;&gt;3) Управление птицей&lt;/h2&gt;

&lt;p&gt;Хочется как-то управлять происходящим - нажатием кнопки/мышки придавать птице толчек вверх.&lt;/p&gt;

&lt;p&gt;В документации обработка нажатия кнопок описана &lt;a href=&quot;http://staging.p5js.org/reference/#/p5/keyPressed&quot;&gt;здесь&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Достаточно наряду с &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup()&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw()&lt;/code&gt; реализовать функцию обработки нажатия кнопки &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keyPressed()&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;keyPressed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;spaceKeyCode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Это кодовое число соответствующее кнопке пробел&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyCode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;spaceKeyCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Есть специальная переменная keyCode, в которой хранится код нажатой кнопки. Пусть птица поднимается выше только когда нажимается пробел&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;birdHeight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// Выше птица - меньше координата, т.к. в системе координат графики y-ось направлена вниз&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Но заметим, что на самом деле положение птицы в этой функции мы не должны менять. Обновление положения происходит с каждым кадром, поэтому давайте заведем функцию &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;updateBird()&lt;/code&gt; и будем вызывать ее при каждом выполнении &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;updateBird&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;birdHeight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;birdHeight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;birdVerticalSpeed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;birdVerticalSpeed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gravityAcceleration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Теперь птица падает с некоторым ускорением. Подгоните константы так, чтобы это выглядело естественно.&lt;/p&gt;

&lt;p&gt;Чем же мы управляем, если не высотой птицы? Нажатие пробела должно приводить к “толчку” птицы вверх, птица начинает лететь вверх когда ее скорость направлена вверх. Т.е. нажатие пробела должно влиять на значение &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;birdVerticalSpeed&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;4-препятствия&quot;&gt;4) Препятствия&lt;/h2&gt;

&lt;p&gt;Надо сделать так, чтобы одна за другой справа набегали стены с дырами. Для упрощения реализуем сначала так, чтобы на экране была видна ровно одна стена.&lt;/p&gt;

&lt;p&gt;Она описывается:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Размер дыры в стене, в которую хочет проскочить птица&lt;/li&gt;
  &lt;li&gt;Высота дыры в стене&lt;/li&gt;
  &lt;li&gt;Координата стены по x-оси&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Заводим для этих параметров аналогично описанию птицы глобальные переменные (вида &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var someName = 239;&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Теперь надо реализовать отрисовку стены в функции &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawWall()&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;Воспользуемся функцией &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rect(fromX, fromY, width, height)&lt;/code&gt;. Первые два аргумента - координаты начала прямоугольника. Последние два аргумента - знаковые ширина и высота прямоугольника.
Т.е. указав положительную высоту прямоугольник будет рисоваться “вниз” от начальных координат (т.к. система координат так ориентирована),
 указав же отрицательную высоту - прямоугольник будет рисоваться “вверх” от начальных координат.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;P.S.&lt;/code&gt; Чтобы не смешать изменения системы координат отрисовки птицы и отрисовки стены пригодятся &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;push()&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pop()&lt;/code&gt; использованные в &lt;a href=&quot;/lessons/239/lesson/school/p5js/2017/03/01/SimpleDrawingInP5JS.html&quot;&gt;прошлом задании&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Итак рисование стены было сделано. Теперь необходимо двигать стену. Для этого надо реализовать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;updateWall()&lt;/code&gt;, который будет уменьшать координату стены по x-оси, но кроме этого: когда стена пройдет весь экран необходимо создать новую случайную стену.&lt;/p&gt;

&lt;p&gt;Чтобы создать новую случайную стену полезен вызов &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Math.random()&lt;/code&gt;, который вернет случайное число от 0.0 до 1.0.&lt;/p&gt;

&lt;p&gt;Итого &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;updateWall()&lt;/code&gt; принимает приблизительно такой вид:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;updateWall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Если координата x стены вышла за пределы экрана&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;nextWallX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...;&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// крайнее правое положение&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;nextHoleY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;50.0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;240.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;nextWallX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;wallSpeed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// двигаем стену влево&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;5-коллизии&quot;&gt;5) Коллизии&lt;/h2&gt;

&lt;p&gt;При обновлении положения птицы надо так же проверить, не врезалась ли она в стену, и если врезалась - можно например менять цвет эллипса-птицы на другой.&lt;/p&gt;

&lt;h2 id=&quot;6-развитие&quot;&gt;6) Развитие&lt;/h2&gt;

&lt;p&gt;Можно добавить следующие вспомогательные вещи:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Счет&lt;/li&gt;
  &lt;li&gt;Перезапуск игры при коллизии&lt;/li&gt;
  &lt;li&gt;Сделать эллипс немного вытянутым и рисовать его под углом пропорциональным вертикальной скорости (скорость вниз - эллипс смотрит вниз, скорость вверх - эллипс смотрит вверх)&lt;/li&gt;
  &lt;li&gt;Больше одной стены&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;5-отправка-задания&quot;&gt;5) Отправка задания&lt;/h2&gt;

&lt;p&gt;Отправляйте в приложении к письму &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.js&lt;/code&gt; файл который вы редактировали. Если gmail не возволит вам отправить js файл из соображений безопасности - то переименуйте расширение файла в что-нибудь вроде &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.js_&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;Тему письма называйте правильно, например: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Задание 52 16-1 Полярный Коля&lt;/code&gt;&lt;/p&gt;
</description>
        <pubDate>Wed, 08 Mar 2017 09:00:00 +0000</pubDate>
        <link>http://polarnick.com/lessons/239/lesson/school/p5js/game/2017/03/08/FlabbyBirds.html</link>
        <guid isPermaLink="true">http://polarnick.com/lessons/239/lesson/school/p5js/game/2017/03/08/FlabbyBirds.html</guid>
        
        
        <category>lessons</category>
        
        <category>239</category>
        
        <category>lesson</category>
        
        <category>school</category>
        
        <category>p5js</category>
        
        <category>game</category>
        
      </item>
    
      <item>
        <title>Задание 61. Бот для телеграмма</title>
        <description>&lt;p&gt;Задание: реализовать программу-бота для телеграмма, которая будет отвечать на запросы пользователя (обычного человека, использующего телеграмм) и предоставлять для него полезную информацию.&lt;/p&gt;

&lt;p&gt;Тема-пример этой статьи &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Бот-эхо&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Бот отвечает таким же сообщением, какое пользователь отправил&lt;/li&gt;
  &lt;li&gt;Бот шлет &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Привет! Как дела?&lt;/code&gt; в &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;22:39&lt;/code&gt; каждый день&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Тема на оценку &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Бот-Remembrall&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Боту можно отправить сообщение о чем-то важном, например &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;20:00 загамать в доту&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5 марта сделать дз по информатике&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Бот предупредит о важном событии в указанное время (или за день до даты)&lt;/li&gt;
  &lt;li&gt;Придумать какую-нибудь дополнительную полезную функциональность&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Опционально&lt;/code&gt; Напоминание может содержать геотег (метку на карте)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Опционально&lt;/code&gt; Предупреждать за &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt; минут до звонка (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt; - настраиваемое)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Опционально&lt;/code&gt; Да что угодно!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Альтернативные темы:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Генератор мемов (пользователь выбирает картинку и указывает текст для наложения)&lt;/li&gt;
  &lt;li&gt;Оповещатель о новых сообщениях в vkontakte&lt;/li&gt;
  &lt;li&gt;Выдаватель новых/случайных анекдотов/новостей из указанной пользователем группы vkontakte&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Другие темы возможны по согласованию со мной.&lt;/p&gt;

&lt;p&gt;В инструкции описано как сделать бота на &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Java&lt;/code&gt;, но &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Python&lt;/code&gt; для данной задачи на мой взгляд подходит лучше, так что любой другой язык для этого задания разрешен. &lt;a href=&quot;https://core.telegram.org/bots/samples&quot;&gt;Здесь&lt;/a&gt; есть ссылки для многих языков.&lt;/p&gt;

&lt;h2 id=&quot;дедлайн&quot;&gt;Дедлайн:&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TBA&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;1-про-ботов&quot;&gt;1) Про ботов&lt;/h2&gt;

&lt;p&gt;Общая идея в том, что вы регистрируете своего бота в телеграмме, затем запускаете программу, которая будет определять логику бота. Эта программа подключиться к серверам телеграмма, 
и если кто-то отправит сообщение вашему боту - сервера телеграмма оповестят об этом вашу программу. Программа соответственно может сообщать серверам телеграмма о том, какие действия совершает бот, например отправка овтетного сообщения.&lt;/p&gt;

&lt;h2 id=&quot;2-регистрация-бота&quot;&gt;2) Регистрация бота&lt;/h2&gt;

&lt;p&gt;Чтобы ваша программа-бот могла взаимодействовать с серверами телеграмма - ее нужно зарегистрировать, т.е. получить для нее идентификатор, чтобы сервера телеграмма могли понимать с кем они работают.&lt;/p&gt;

&lt;p&gt;Для этого надо открыть &lt;a href=&quot;https://telegram.me/botfather&quot;&gt;https://telegram.me/botfather&lt;/a&gt; и нажать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SEND MESSAGE&lt;/code&gt;, это откроет &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BotFather&lt;/code&gt; в установленном Телеграмме.&lt;/p&gt;

&lt;p&gt;Теперь надо попросить у него выдать для нас идентификатор (и сделать это с уважением):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/start&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/newbot&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Указать имя бота, например &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PolarNickTestBot&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Указать username оканчивающийся на &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_bot&lt;/code&gt;, например &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;polar_nick_test_bot&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;В ответ вам будет выслан &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP API&lt;/code&gt; (в дальнейшем &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ключ бота&lt;/code&gt;), что-то вроде &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;332239602:AAHGJSrMvTxVm239c3JJzHaz239mXyEE9tI&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;3-библиотека-telegram-api&quot;&gt;3) Библиотека Telegram API&lt;/h2&gt;

&lt;p&gt;Все взаимодействие с серверами телеграмма обернуто в нескольких удобных библиотеках, в рамках данной статьи предлагается использовать данную библиотеку - &lt;a href=&quot;https://github.com/rubenlagus/TelegramBots&quot;&gt;TelegramBots&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Создайте пустой проект, назвав его например &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TelegramEcho&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Скачайте &lt;a href=&quot;https://github.com/rubenlagus/TelegramBots/releases/&quot;&gt;отсюда&lt;/a&gt; файл &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;telegrambots-&amp;lt;версия&amp;gt;-jar-with-dependencies.jar&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Теперь эту библиотеку надо подключить к проекту:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File-&amp;gt;Project Structure-&amp;gt;Libraries&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Зеленый плюсик сверху слева -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Java&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Указать скачанный файл, нажать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ok&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;4-простой-echo-bot&quot;&gt;4) Простой echo-bot&lt;/h2&gt;

&lt;p&gt;Создаем какой-нибудь класс и пишем в нем &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;-функцию - точку входа в приложение:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public static void main(String[] args) {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Наследуем наш класс от &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TelegramLongPollingBot&lt;/code&gt;. Например:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public class MyTelegramBot extends TelegramLongPollingBot {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Не забываем все ошибки &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cannot resolve symbol&lt;/code&gt; решать через &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt+Enter-&amp;gt;Import class&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;В данном случае появится в том числе ошибка &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Class must either be declared abstract or implement abstract method...&lt;/code&gt;.
Надо реализовать эти методы, по аналогии с тем как мы это делали при обработки нажатия кнопок/движения мышек/получения сообщений в задании 41 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt+Enter -&amp;gt; Implement methods&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;В &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;-функции надо инициализировать библиотеку и запустить наш бот:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;        &lt;span class=&quot;nc&quot;&gt;ApiContextInitializer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;TelegramBotsApi&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;telegramBotsApi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TelegramBotsApi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;telegramBotsApi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;registerBot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyTelegramBot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TelegramApiException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;printStackTrace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Теперь надо действительно реализовать те абстрактные методы, которые нам достались в наследство. Два из них заполняются тривиально - теми значениями, которые вы указали или получили на шаге 2 (в процессе регистрации бота):&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getBotUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;polar_nick_test_bot&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Username вашего бота, второе значение которое вы указывали при регистрации&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getBotToken&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;332339602:AAHGJSrMvTxVm0iCc3JJzHazToqmXyEE9tI&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Ключ бота, который был выдан в конце регистрации&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Осталось делать что-нибудь, когда бот получает сообщения. Это делается в &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onUpdateReceived&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;        &lt;span class=&quot;nc&quot;&gt;Message&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;// Получаем текст входящего сообщения&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;New message: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getText&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Пишем в консоль о том, какое сообщение было получено&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Но просто записывать в консоль полученное сообщение не интересно. Давайте ответим пользователю этим же сообщением в ответ:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;        &lt;span class=&quot;nc&quot;&gt;SendMessage&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sendMessage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SendMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;// Создаем объект, в котором опишем сообщение, которое хотим послать в ответ&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sendMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setChatId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getChatId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Укажем, что отправить это сообщение следует в чате, из которого мы получили сообщение&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sendMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setText&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Echo: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getText&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;// Укажем текст сообщения&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;sendMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sendMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;                           &lt;span class=&quot;c1&quot;&gt;// Отправим сообщение&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TelegramApiException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;printStackTrace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;                                &lt;span class=&quot;c1&quot;&gt;// Это обработка исключительных ситуаций - на случай если что-то пойдет не так&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Еще например можно было бы отправлять это сообщение как “ответ” на входящее сообщение:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sendMessage.setReplyToMessageId(message.getMessageId());&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;5-дополнительные-материалы&quot;&gt;5) Дополнительные материалы&lt;/h2&gt;

&lt;p&gt;Взаимодействие с vkontakte: для этого есть &lt;a href=&quot;https://vk.com/dev/Java_SDK&quot;&gt;библиотека&lt;/a&gt;, которая оборачивает взаимодействие с API. С помощью этой библиотеки можно написать бота для vkontakte.&lt;/p&gt;

&lt;p&gt;Забор информации с произвольного сайта: для этого надо выкачивать соответствующую html-страницу, и из нее извлекать информацию. Помочь может например библиотека &lt;a href=&quot;https://jsoup.org/&quot;&gt;jsoup&lt;/a&gt;. Примеры работы с этой библиотеки можно нагуглить, например &lt;a href=&quot;https://annimon.com/article/1534&quot;&gt;это&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;6-отправка-задания&quot;&gt;6) Отправка задания&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ВАЖНО&lt;/code&gt; Обратите внимание, что API-ключ бота дает доступ и контроль над ботом. Поэтому если кто-то получит доступ к этому ключу - он сможет перехватить контроль над ботом. Поэтому при отправки кода мне или кому-либо еще - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;обязательно удалите&lt;/code&gt; API-ключ бота из исходников.&lt;/p&gt;

&lt;p&gt;Отправляйте выполненное задание ввиде zip-архива &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt; папки, и пожалуйста:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Тему письма называйте правильно, например: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Задание 61 16-1 Полярный Коля&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Правильно названный zip-архив (или 7zip), внутри которого папка &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt; с &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.java&lt;/code&gt; файлами, пример названия: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;61_16_1_polyarniy_nikolay.zip&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 05 Mar 2017 09:00:00 +0000</pubDate>
        <link>http://polarnick.com/lessons/239/lesson/school/java/telegram/2017/03/05/TelegramBot.html</link>
        <guid isPermaLink="true">http://polarnick.com/lessons/239/lesson/school/java/telegram/2017/03/05/TelegramBot.html</guid>
        
        
        <category>lessons</category>
        
        <category>239</category>
        
        <category>lesson</category>
        
        <category>school</category>
        
        <category>java</category>
        
        <category>telegram</category>
        
      </item>
    
      <item>
        <title>Мини-задание 51. Фрактальные деревья</title>
        <description>&lt;p&gt;Это мини-задание - лирическое отступление о том, как можно рисовать что-нибудь симпатичное и забавное благодаря удобной библиотеке.&lt;/p&gt;

&lt;p&gt;Задание является адаптацией &lt;a href=&quot;https://www.youtube.com/watch?v=0jjeOYMjmDU&quot;&gt;данного видео&lt;/a&gt; на тему использования библиотеки &lt;a href=&quot;https://p5js.org&quot;&gt;p5.js&lt;/a&gt; для рисования фрактальных деревье. &lt;a href=&quot;https://p5js.org/reference/&quot;&gt;Здесь&lt;/a&gt; есть перечень всех доступных функций.&lt;/p&gt;

&lt;p&gt;Получить оценку за данное задание можно только на уроке.&lt;/p&gt;

&lt;h2 id=&quot;0-поднятие-окружения&quot;&gt;0) Поднятие окружения&lt;/h2&gt;

&lt;p&gt;Скачайте архив библиотечки &lt;a href=&quot;https://github.com/processing/p5.js/releases/download/0.5.7/p5.zip&quot;&gt;отсюда&lt;/a&gt; и разархивируйте его в какую-нибудь папку.&lt;/p&gt;

&lt;p&gt;Там куда вы разархивировали библиотечку зайдите в подпапку &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p5-zip/empty-example&lt;/code&gt;. Откройте &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sketch.js&lt;/code&gt; любым текстовым редактором, например Intellij IDEA (в ней можно нажать File-&amp;gt;Open и указать этот файл):&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Первая функция исполняется в начале работы приложения, вторая функция - исполняется для отрисовки каждого кадра.&lt;/p&gt;

&lt;p&gt;Простой рабочий пример может выглядеть так:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;createCanvas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;640&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;480&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// Указываем размер холста на котором будем рисовать&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Указываем цвет фона&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                           &lt;span class=&quot;c1&quot;&gt;// Пример того, как можно объявить переменную, вместо типа перед названием переменной всегда пишется var - от слова variable (в переводе - переменная)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ellipseColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Создаем переменную хранящую цвет&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ellipseColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                    &lt;span class=&quot;c1&quot;&gt;// Указываем цветом заливки - цвет из переменной ellipseColor&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ellipse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;320&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;240&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// Рисуем эллипс с центром в точке (320, 240) и размером 200x100&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Чтобы увидеть результат - достаточно открыть &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p5-zip/empty-example/index.html&lt;/code&gt; в браузере (например дважды кликнув по этому файлу). По мере редактирования &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sketch.js&lt;/code&gt; чтобы увидеть новый результат - достаточно обновить страничку в браузере (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+R&lt;/code&gt; или &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F5&lt;/code&gt;).&lt;/p&gt;

&lt;h2 id=&quot;1-функции&quot;&gt;1) Функции&lt;/h2&gt;

&lt;p&gt;Допустим мы хотим сделать функцию “нарисовать человечка”:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;createCanvas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;640&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;480&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// Указываем размер холста на котором будем рисовать&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Указываем цвет фона&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;drawHuman&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;320&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;240&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;// Рисуем человечка вызовом функции, которая объявлена ниже&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;drawHuman&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Смещаем начало отсчета координат из текущего положения (верхний левый угол) на x пикселей вправо и y пикселей вниз&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ellipse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Голова относительно текущей системы координат в точке (0, -40), т.е. на 40 пикселей выше чем (x, y) и с диаметром 20&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;// Тело идет от нижней точки головы (0, -30) до точки (0, 30)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// Рука слева&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Доделайте эти вызовы:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// line(...); // Рука справа&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// line(...); // Нога слева&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// line(...); // Нога справа&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Доделайте функцию &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawHuman&lt;/code&gt;, чтобы получился человечек.&lt;/p&gt;

&lt;p&gt;Если добавить после вызова &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;translate&lt;/code&gt; вызов &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotate(PI / 4)&lt;/code&gt;, то текущая система координат повернется на 45 градусов по часовой стрелке, а значит и дальнейшая отрисовка человечка в этой системе приведет к тому, что человечек повернулся на эти же 45 градусов по часовой стрелке.&lt;/p&gt;

&lt;p&gt;Убедитесь что вы поняли, как работает &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;translate&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotate&lt;/code&gt;. Что будет если отрисовка частей человечка не симметрична относительно точки (0, 0)? Как он будет крутиться в таком случае?&lt;/p&gt;

&lt;h2 id=&quot;2-фрактал&quot;&gt;2) Фрактал&lt;/h2&gt;

&lt;p&gt;Давайте теперь нарисуем такое дерево-фрактал:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/fractal_tree.png&quot; alt=&quot;Fractal tree&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Функция отрисовки такого дерева - рекурсивная, она должна делать следующее:&lt;/p&gt;

&lt;p&gt;функция рисует корневую ветку длины N. В точке где кончается эта ветка функция вызывает отрисовку двух других деревьев:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Одно повернуто на 45 градусов по часовой стрелке с длиной первой ветки N/2&lt;/li&gt;
  &lt;li&gt;Второе повернуто на 45 градусов против часовой стрелки с длиной первой ветки N/2&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;21-правые-ветки-фрактала&quot;&gt;2.1) Правые ветки фрактала&lt;/h2&gt;

&lt;p&gt;Давайте сначала нарисуем более простую вещь - загогулину-веточку:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/fractal_branch.png&quot; alt=&quot;Fractal tree&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Функция отрисовки такой веточки тоже рекурсивная. Она делает следующее: отрисовывает веточку длины N, двигает систему координат в конец этой ветки, поворачивает систему координат на 45 градусов и вновь вызвает себя для отрисовки на этот раз в два раза более короткой веточки:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;createCanvas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;640&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;480&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;320&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;460&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;// Сдвигаем систему координат так, чтобы точка отсчета совпадала с корнем дерева-веточки&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;drawBranch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Провоцируем отрисовку, длина первой ветки должна быть 200&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;coeff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;              &lt;span class=&quot;c1&quot;&gt;// Эта константа используется ниже - это коэффициент, во сколько раз очередная ветка короче предыдущей&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;drawBranch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;// Рисуем ветку переданной длины из центра текущей системы координат вверх данной длиной&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Двигаем систему координат так, чтобы точка отсчета совпала с концом нарисованной ветки&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;PI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;// Поворачиваем систему координат&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;drawBranch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;coeff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Провоцируем рекурсивную отрисовку более короткой ветки&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;22-интерактивная-ветка-фрактала&quot;&gt;2.2) Интерактивная ветка фрактала&lt;/h2&gt;

&lt;p&gt;Давайте сделаем интерактивным изменение угла наклона каждой очередной ветки и то, во сколько раз она уменьшается:&lt;/p&gt;

&lt;p&gt;Сначала надо открыть текстовым редактором &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.html&lt;/code&gt; и заменить эту строчку:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;c&quot;&gt;&amp;lt;!--&amp;lt;script language=&quot;javascript&quot; src=&quot;libraries/p5.dom.js&quot;&amp;gt;&amp;lt;/script&amp;gt;--&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;На такую:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;language=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;javascript&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;libraries/p5.dom.js&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Теперь мы сможем создать слайдер, который сможет интерактивно указывать значение градуса, на который каждый раз делается поворот.&lt;/p&gt;

&lt;p&gt;Для этого достаточно доделать код до следующего:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;slider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Переменная в которой хранится интерактивный объект-ползунок&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;createCanvas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;640&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;480&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;slider&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createSlider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.01&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Создаем ползунок с аргументами: минимальное и максимальное значения, значение по умолчанию, и шаг изменения значения&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;320&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;460&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;drawBranch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;coeff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;drawBranch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;slider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Вместо того чтобы всегда поворачивать на 45 градусов - поворачиваем на значение, которое в данный момент выбрано ползунком&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;drawBranch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;coeff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Теперь у нас есть ползунок, который указывает градус поворота от ветки к ветке.&lt;/p&gt;

&lt;p&gt;Но есть проблема - старое положение всех веток оставляет след, который хотелось бы очистить - очистка происходит вызововм &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background&lt;/code&gt;, который у нас вызывается только в &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup&lt;/code&gt;, так что достаточно перенести его вызов из &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup&lt;/code&gt; в первую строчку метода &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;23-сам-фрактал&quot;&gt;2.3) Сам фрактал&lt;/h2&gt;

&lt;p&gt;Заметьте, что сам фрактал отличается от этой ветки лишь тем, что каждый очередной раз порождается не одна ветка - а две.&lt;/p&gt;

&lt;p&gt;Это значит что нам надо вызвать рекурсивную функцию не один раз после поворота по часовой стрелке на 45 градусов, но два раза - один после поворота по часовой стрелке, второй - после поворота против часовой стрелки. Например так:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;drawFractal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;PI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;drawFractal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;coeff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;nx&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;PI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;drawFractal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;coeff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Но это внезапно не работает. Почему? Потому что когда мы делаем второй поворот системы координат - она уже модифицированна внутренними поворотами первого рекурсивного вызова, а нам хотелось бы восстановить изначальное (на момент текущего вызова функции) состояние системы координат. Для сохранения и восстановления состояния есть метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;push&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pop&lt;/code&gt; соответственно:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;        &lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;                      &lt;span class=&quot;c1&quot;&gt;// Сохраняем текущую систему координат&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;PI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;drawFractal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;coeff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;// Восстанавливаем последнее сохранение системы координат&lt;/span&gt;

        &lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;                      &lt;span class=&quot;c1&quot;&gt;// Сохраняем&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;PI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;drawFractal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;coeff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;// Восстанавливаем&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;24-развитие-фрактала&quot;&gt;2.4) Развитие фрактала&lt;/h2&gt;

&lt;p&gt;Теперь можно поиграть со следующими вещами:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Добавьте ползунок для определения значения &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;coeff&lt;/code&gt; (коэффициент изменения длины ветки)&lt;/li&gt;
  &lt;li&gt;Как можно сделать дерево не симметричным? Например сделать поворот системы координат не на &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;angle&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-angle&lt;/code&gt;, а на &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;angle+delta&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-angle+delta&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 01 Mar 2017 09:00:00 +0000</pubDate>
        <link>http://polarnick.com/lessons/239/lesson/school/p5js/2017/03/01/SimpleDrawingInP5JS.html</link>
        <guid isPermaLink="true">http://polarnick.com/lessons/239/lesson/school/p5js/2017/03/01/SimpleDrawingInP5JS.html</guid>
        
        
        <category>lessons</category>
        
        <category>239</category>
        
        <category>lesson</category>
        
        <category>school</category>
        
        <category>p5js</category>
        
      </item>
    
      <item>
        <title>Задание 41. Многопользовательские чат и рисовалка</title>
        <description>&lt;p&gt;Это задание является последней частью мультиплеерного Paint.&lt;/p&gt;

&lt;p&gt;Как более простой вариант многопользовательского приложения ниже описано как сделать чат. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Для получения четверки&lt;/code&gt; достаточно отправить многопользовательский чат.&lt;/p&gt;

&lt;p&gt;Сделав чат по предложенной инструкции, вы по аналогии сможете сделать мультиплеерный Paint (взяв готовую рисовалку и добавив в ней функционал отправки отрезков как сообщений). &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Для получения пятерки&lt;/code&gt; необходимо сделать многопользовательский пейнт.&lt;/p&gt;

&lt;p&gt;Обратите внимание, что несмотря на то, что клиент и сервер - являются двумя разными программами, удобно их реализовывать в рамках одного проекта. Например можно это сделать в двух разных классах (это могут быть классы &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ChatClient&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ChatServer&lt;/code&gt;) с двумя &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;-функциями.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;P.S.&lt;/code&gt; Игнорируйте строчки вроде &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;synchronized (lock) { ...someCode... }&lt;/code&gt; внутри &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StreamWorker&lt;/code&gt;. Считайте что это то же самое, что и просто &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{ ...someCode... }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;P.P.S.&lt;/code&gt; Обратите внимание, что несмотря на то, что клиент к чату можно скопировать из кода ниже - это не значит что в нем не надо разбираться. Если вы в нем не разберетесь - будет сложно реализовать сервер чата и еще сложнее - многопользовательскую рисовалку. С кодом класса &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StreamWorker&lt;/code&gt; тоже стоит разобраться.&lt;/p&gt;

&lt;h2 id=&quot;дедлайн&quot;&gt;Дедлайн:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;10-1: 16 марта&lt;/li&gt;
  &lt;li&gt;11-1: 16 марта&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;0-про-чат&quot;&gt;0) Про чат&lt;/h2&gt;

&lt;p&gt;В этом задании рассматриваются две программы: сервер и клиент.&lt;/p&gt;

&lt;p&gt;В помощь вам предложена простая библиотечка, которая возьмет на себя задачу создания потока на каждого подключенного клиента, и задачу получения/отправки сообщений от этого/этому клиенту. Аналогично эту библиотечку удобно использовать для клиента, чтобы получать оповещения о входящих сообщениях со стороны сервера. Ниже подробно изложено, как на основе этого сделать чат. После чата аналогично, но уже самостоятельно, вам надо будет сделать мультиплеерную рисовалку.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Задача клиента:&lt;/code&gt; подключиться к серверу и отправлять ему сообщения которые вводит пользователь в консоли. При получении сообщения от сервера - печатать его в консоль.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Задача сервера:&lt;/code&gt; ожидать подключений новых клиентов. С помощью библиотеки обрабатывать поступающие от клиентов сообщения - т.е. пересылать эти сообщения всем клиентам.&lt;/p&gt;

&lt;h2 id=&quot;1-библиотечка&quot;&gt;1) Библиотечка&lt;/h2&gt;

&lt;p&gt;Обрабатывающий потоки данных класс должен как-то оповещать о событиях (новых сообщениях). Раньше мы уже использовали &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeyListener&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MouseListener&lt;/code&gt; для обработки событий нажатия кнопок и мышки. В данном случае используется аналогичный механизм, но абстрактный класс &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageListener&lt;/code&gt; подходящий под наши нужды выглядит например так:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MessageListener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onDisconnect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;printStackTrace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Создаете новый класс (правый клик по &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt;, там &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;New-&amp;gt;Java Class&lt;/code&gt;) с названием &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageListener&lt;/code&gt; и копируете в этот файл приведенный выше код.&lt;/p&gt;

&lt;p&gt;Класс &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StreamWorker&lt;/code&gt;, который будет заниматься тем, чтобы получать новые сообщения из входного потока данных (поток может быть как от клиента, так и от сервера):&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.io.*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.net.SocketException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StreamWorker&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Runnable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Closeable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BufferedReader&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Входной поток данных&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PrintWriter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;// Выходной поток данных&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// private  - означает, что до этого поля нельзя дотянуться извне, ведь напрямую с ним никто другой кроме данного класса работать не должен&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// final    - означает, что этот объект всегда будет один и тот же (почти то же самое, что и const), т.е. что это финальный объект&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MessageListener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listeners&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Зарегистрированные обработчики входящих собщений&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outputLock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// Не обращайте внимания, эти два объекта&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listenerLock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// используются в synchronized-блоках&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;StreamWorker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;InputStream&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;OutputStream&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BufferedReader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;InputStreamReader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PrintWriter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// true - флаг autoFlush, он приводит к тому, что буфер будет отправляться сразу - на каждое сообщение&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addListener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MessageListener&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;listeners&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Это метод, который StreamWorker обязался реализовать в связи с реализацией интерфейса Runnable (т.к. выше написано StreamWorker implements Runnable)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// В этом методе StreamWorker ждет поступления новых сообщений, и каждое новое сообщение передает обработчику входящих сообщений&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// Пока входящее сообщение не отсутствует - читаем сообщения одно за другим&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;readLine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;// Отдаем полученное сообщение на обработку&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;synchronized&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listenerLock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MessageListener&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listeners&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
                    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SocketException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Connection reset&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;// Если случившаяся исключительная ситуация - разрыв соединения, то вызываем соответствующую обработку события&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;synchronized&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listenerLock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MessageListener&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listeners&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onDisconnect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
                    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;// Иначе - просто обрабатываем ошибку&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;synchronized&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listenerLock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MessageListener&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listeners&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
                    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// Провоцируем обработку случившейся исключительной ситуации (например клиент разорвал соединение)&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;synchronized&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listenerLock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MessageListener&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listeners&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Этот метод запускает цикл в методе run(), который будет считывать входящие сообщения и отдавать их на обработку в listeners&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Thread&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;thread&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;StreamWorker&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Это метод отправки сообщения&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sendMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;synchronized&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;outputLock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Это метод, реализовать который StreamWorker обязуется в связи с реализацией интерфейса Closeable (т.к. выше написано StreamWorker implements Closeable)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Общая идея что Closeable = &quot;закрываемый&quot; как например файл. В нашем случае StreamWorker просто закрывает оба потока данных&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Закрываем входной поток&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Закрываем выходной поток&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Создаете новый класс (правый клик по &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt;, там &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;New-&amp;gt;Java Class&lt;/code&gt;) с названием &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StreamWorker&lt;/code&gt; и копируете в этот файл приведенный выше код.&lt;/p&gt;

&lt;h2 id=&quot;2-пример-использования-библиотеки-для-реализации-чата&quot;&gt;2) Пример использования библиотеки для реализации чата&lt;/h2&gt;

&lt;h2 id=&quot;21-клиент-чата&quot;&gt;2.1) Клиент чата&lt;/h2&gt;

&lt;p&gt;Теперь на базе скопированного обработчика входящих сообщений (почтальона) достаточно просто можно реализовать клиент.&lt;/p&gt;

&lt;p&gt;Создайте класс &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ChatClient&lt;/code&gt;. Т.к. это будет исполняемая программа - надо определить точку входа - создать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;-функцию внутри класса &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ChatClient&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// TODO&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;На этапе запуска программы разумно создать объект типа &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ChatClient&lt;/code&gt; и вызвать у него метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;start&lt;/code&gt; (который мы тут же и реализуем):&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;ChatClient&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chatClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ChatClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;chatClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// TODO&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Теперь устанавливаем соединение с сервером аналогично тому как это было сделано в предыдущем задании:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Socket&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Socket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(...);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// TODO&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Для получения и отправки сообщений серверу можно воспользоваться &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StreamWorker&lt;/code&gt;, дав ему входной и выходной поток данных - полученных от установленного соединения с сервером, и запустив его:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;StreamWorker&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StreamWorker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getInputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOutputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Аналогично тому как обрабатывались нажатия кнопок в змейке и движения мышки в рисовалке нужно подписаться на обработку сообщений у почтальона (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StreamWorker&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Наследовать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ChatClient&lt;/code&gt; от MessageListener&lt;/li&gt;
  &lt;li&gt;Реализовать (через &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt+Enter&lt;/code&gt;) методы: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onMessage&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onDisconnect&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Добавить текущий объект как обработчик входящих сообщений к “почтальону”: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;postman.addListener(this)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Теперь предыдущий кусок кода становится таким:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;StreamWorker&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StreamWorker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getInputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOutputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addListener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// TODO: считываем сообщения из консоли и отправляем их&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Чтобы отправлять сообщения можно воспользоваться методом &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sendMessage(String text)&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;StreamWorker&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StreamWorker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getInputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOutputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addListener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;BufferedReader&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BufferedReader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;InputStreamReader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;userInput&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;readLine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userInput&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sendMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userInput&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;userInput&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;readLine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;22-сервер-чата&quot;&gt;2.2) Сервер чата&lt;/h2&gt;

&lt;p&gt;Сервер на базе предложенной библиотечки получается из примерно следующих набросков кода:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Создаем серверный сокет - швейцара, который будет пускать в наш чат долгожданных гостей&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;ServerSocket&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ServerSocket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Дожидаемся очередного гостя&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Socket&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;accept&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Создаем почтальона, который будет ожидать входящие сообщения от данного пользователя, и оповещать о них нас - сервер&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;StreamWorker&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StreamWorker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getInputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOutputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addListener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Поток, следящий за входными строчками от этого клиента запускается:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Запоминаем почтальона, выделенного данному клиенту в перечне всех почтальонов&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;postmans&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Соответственно примерно так может выглядить обработка входящего сообщения:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Пробегаем по всем почтальонам&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postmans&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;StreamWorker&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postmans&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Шлем полученное сообщение каждому клиенту (включая клиента являющегося оригинальным отправителем):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;postman&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sendMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Чат готов!&lt;/p&gt;

&lt;h2 id=&quot;3-многопользовательская-рисовалка&quot;&gt;3) Многопользовательская рисовалка&lt;/h2&gt;

&lt;p&gt;Теперь вам предлагается аналогичным образом сделать многопользовательскую программу для рисования:&lt;/p&gt;

&lt;p&gt;Каждое сообщение в многопользовательской рисовалке будет описывать отрезок. Соответственно сообщение имеет вид:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Segment x0 y0 x1 y1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Где:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Segment&lt;/code&gt; - фиксированная строка, она указывает тип сообщения (в данном задании достаточно одного вида сообщений, но это задел на развитие рисовалки)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x0 y0&lt;/code&gt; - пара целых чисел через пробел, описывающих координаты начала отрезка&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x1 y1&lt;/code&gt; - пара целых чисел через пробел, описывающих координаты конца отрезка&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;В случае если вы хотите добавить имя/идентификацтор пользователя в сообщение, то его вид может стать например таким:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Segment UserId x0 y0 x1 y1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;В случае если вы хотите добавить цвет к отрезку:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Segment x0 y0 x1 y1 r g b&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Где &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r g b&lt;/code&gt; - три числа в диапазоне от 0 до 255 (включительно).&lt;/p&gt;

&lt;h2 id=&quot;31-с-точки-зрения-клиента&quot;&gt;3.1) С точки зрения клиента:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Клиент может рисовать непрерывные (пока кнопка зажата) линии движениями мышки (как в &lt;a href=&quot;/lessons/239/lesson/school/java/paint/swing/2017/01/24/Simple-drawer.html&quot;&gt;Задании 39 - Пункт 6&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Клиент отправляет на сервер сообщения, описывающие новые нарисованные отрезки&lt;/li&gt;
  &lt;li&gt;Клиент получает сообщения об отрезках и отображает их по мере рисования другими пользователями&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;32-с-точки-зрения-сервера&quot;&gt;3.2) С точки зрения сервера:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Постоянно ожидать подключения новых пользователей&lt;/li&gt;
  &lt;li&gt;Когда клиент присылает новый отрезок - рассылать его всем пользователям&lt;/li&gt;
  &lt;li&gt;Помнить о всех отрезках, накопившихся с момента запуска сервера&lt;/li&gt;
  &lt;li&gt;Когда новый клиент подключается - в первую очередь отправить ему все отрезки, которые были нарисованы с момента запуска сервера&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;4-отправка-задания&quot;&gt;4) Отправка задания&lt;/h2&gt;

&lt;p&gt;Отправляйте выполненное задание ввиде zip-архива &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt; папки, и пожалуйста:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Тему письма называйте правильно, например: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Задание 41 16-1 Полярный Коля&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Правильно названный zip-архив (или 7zip), внутри которого папка &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt; с &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.java&lt;/code&gt; файлами, пример названия: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;41_16_1_polyarniy_nikolay.zip&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;5-частые-проблемы&quot;&gt;5) Частые проблемы&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ситуация:&lt;/code&gt; При запуске сервера выводится исключение &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.net.BindException: Address already in use (Bind failed)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Это означает что слушать по такому порту сервер не смог, т.к. этот порт уже кем-то занят. Скорее-всего вы забыли остановить запущенный ранее сервер (нажать красную квадратную стоп-кнопку).&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ситуация:&lt;/code&gt; При запуске клиента не устанавливается соединение с исключением &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.net.ConnectException: Connection refused: connect&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Это означает, что клиент попытался установить соединение по какому-то порту, но на этом порту никто не ждал гостей, т.е. сервер не был запущен и не создал на этом порту свой &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerSocket&lt;/code&gt;.&lt;/p&gt;
</description>
        <pubDate>Tue, 14 Feb 2017 09:00:00 +0000</pubDate>
        <link>http://polarnick.com/lessons/239/lesson/school/java/socket/2017/02/14/MultiPaint.html</link>
        <guid isPermaLink="true">http://polarnick.com/lessons/239/lesson/school/java/socket/2017/02/14/MultiPaint.html</guid>
        
        
        <category>lessons</category>
        
        <category>239</category>
        
        <category>lesson</category>
        
        <category>school</category>
        
        <category>java</category>
        
        <category>socket</category>
        
      </item>
    
      <item>
        <title>Задание 40. Простой echo-сервер</title>
        <description>&lt;p&gt;Это задание является вторым из трех частей мультиплеерного Paint. В результате получится программа в которой пользователи сервера и клиента рисуют и видят общую картину.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Важно&lt;/code&gt; Обратите внимание, что в данном задании есть три части:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Разминка (пункт 0) - работа с консолью, это подзадание делать и отправлять не обязательно, но оно должно существенно упростить выполнение остальной части задания&lt;/li&gt;
  &lt;li&gt;Сервер&lt;/li&gt;
  &lt;li&gt;Клиент&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Несмотря на то, что сервер и клиент две программы - их можно создавать в одном проекте. Например можно создать классы &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MainServer&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MainClient&lt;/code&gt;, где в каждом классе будет своя &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;-функция. Чтобы запустить какую-то одну из них - можно нажать правой кнопкой на класс, в котором она объявлена и там Run.&lt;/p&gt;

&lt;h2 id=&quot;дедлайн&quot;&gt;Дедлайн:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;9-1: когда-нибудь не скоро&lt;/li&gt;
  &lt;li&gt;10-1: 26 февраля&lt;/li&gt;
  &lt;li&gt;11-1: 26 февраля&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Это задание является вводным в сетевое взаимодействие. Когда вы открываете этот сайт, играете в мультиплеерную игру, используете мессенджер и т.п. - происходит взаимодействие вашего устройства с другими устройствами посредством интернета.
Т.е. программа которую вы используете отправляет очень много сообщений серверу (различного содержания: это может быть текст вашего сообщения или координаты вашего персонажа в игровом мире).
Так же используемая программа получает много сообщений от других устройств: в случае чата - это входящие сообщения, в случае игры - координаты остальных игроков.&lt;/p&gt;

&lt;p&gt;В этом задании рассматриваются две простые программы: сервер и клиент.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Задача клиента:&lt;/code&gt; подключиться к серверу и отправлять ему сообщения которые вводит пользователь, получать на них ответ и отображать текст ответа пользователю. (т.е. после запуска программы пользователь может вводить сообщения в консоль строчка за строчкой)&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Задача сервера:&lt;/code&gt; ожидать подключения клиента и отвечать на все входящие сообщения тем же текстом, который прислал клиент.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ачивка TypicalBackendDeveloper:&lt;/code&gt; ожидать подключения многих клиентов и при получении входящего сообщения - высылать полученный текст всем подключенным клиентам (т.е. например клиент 1 отправил текст “A”, клиент 2 отправил текст “Б”, тогда сервер каждое из этих сообщений отправит этим двум клиентам, и каждый клиент увидит как свое сообщение, так и сообщения остальных клиентов).&lt;/p&gt;

&lt;h2 id=&quot;0-про-работу-с-потоками-данных&quot;&gt;0) Про работу с потоками данных&lt;/h2&gt;

&lt;p&gt;Обмен данными по сети происходит почти так же, как и работа с файлами или консолью. Поэтому сначала для практики надо решить простую “псевдо-олимпиадную” задачку.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/lessons/239/school/java/olymp/2017/01/10/olymp-stub.html&quot;&gt;Здесь&lt;/a&gt; написано о том, как это делается.&lt;/p&gt;

&lt;p&gt;Условие задачи:&lt;/p&gt;

&lt;p&gt;В консоль вводят команды. Одна строка - одна команда. Перечень поддерживаемых команд:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sum a1 a2 a3 ...&lt;/code&gt; (произвольное количество целых чисел через пробел - поэтому поможет &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tokenizer.hasMoreTokens()&lt;/code&gt;) - выводит сумму чисел&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print sdmasda sfa  412451 251&lt;/code&gt; (сначала название команды &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print&lt;/code&gt;, затем после пробела произвольный текст) - выводит всю строку без изменений, следующую за &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print&lt;/code&gt; через пробел&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exit&lt;/code&gt; - завершает исполнение программы&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;пример&quot;&gt;Пример:&lt;/h1&gt;

&lt;p&gt;Вход:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sum 1 2 3 4 5
sum 239
print Hello world!
sum -1 3 214 1
print 1 2
exit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Выход:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;15
239
Hello world!
217
1 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;1-сетевое-взаимодействие&quot;&gt;1) Сетевое взаимодействие&lt;/h2&gt;

&lt;p&gt;Представьте что у каждого компьютера есть несколько тысяч виртуальных разъемов. Это так называемые &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;порты&lt;/code&gt; - они обладают значениями &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;от 0 до 65536&lt;/code&gt; (рекомендую для использования любой из пространства &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1024—49151&lt;/code&gt;, например &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2391&lt;/code&gt;). 
Они позволяют установить соединение между двумя компьютерами (т.е. сообщения будут идти между одним из портов первого компьютера через интернет к порту второго компьютера).&lt;/p&gt;

&lt;p&gt;Чтобы в интернете или локальной сети можно было обращаться к другим компьютерам - у каждого есть свой адрес, так называемый &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ip&lt;/code&gt;-адрес. Это уникальный идентификатор имеющий вид &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a.b.c.d&lt;/code&gt;, где каждая буква - число от 0 до 255 (например: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5.18.192.135&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Если есть компьютер А с ip-адресом ipA и есть компьютер Б с ip-адресом ipB, то чтобы А смог общаться с Б - им нужно установить связь. Для этого компьютер А стучится (пытается установить соединение) по адресу ipB в конкретный порт, например в нашем случае пусть это будет порт &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2391&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Чтобы соединение успешно установилось - необходимо чтобы на компьютере Б была запущена программа-сервер, которая ожидает подключающихся клиентов по порту 2391.&lt;/p&gt;

&lt;p&gt;Итого если на компьютере Б с адресом ipB запущена программа, которая ожидает подключение клиентов по порту 2391, и есть компьютер А, на котором запустилась программа, которая пытается установить соединение с компьютером по адресу ipB и порту 2391 - то будет установлено двустороннее соединение, по которому можно обмениваться информацией.&lt;/p&gt;

&lt;h2 id=&quot;2-простой-сервер&quot;&gt;2) Простой сервер&lt;/h2&gt;

&lt;p&gt;Итак нам нужно написать программу которая ожидает подключения клиентов по порту 2391 и когда клиент подключается - начинает ему отвечать зеркальными сообщениями (т.е. вести себя как эхо).&lt;/p&gt;

&lt;p&gt;В Java есть специальный класс &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Socket&lt;/code&gt;, который представляет “разъем”/”сокет” соединения, т.е. один из концов канала обмена сообщениями.&lt;/p&gt;

&lt;p&gt;Нам нужно начать ожидать подключающихся клиентов. Т.е. нам нужно поставить на выбранный порт (например 2391) швейцара, который будет ждать гостей, и когда кто-нибудь придет - установит надежное соединение между нашим сервером и гостем-клиентом для дальнейшего общения.&lt;/p&gt;

&lt;p&gt;В Java таким швейцаром является специальный класс &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerSocket&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Создаем его в main-функции:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;ServerSocket&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;serverDoorMan&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ServerSocket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Обратите внимание на параметр конструктора - нужно указать порт (т.е. номер двери выходящей наружу - на улицу), на котором наш сервер (швейцар/привратник) ожидает подключающихся клиентов. Так как порт уже может быть занят другим сервером (швейцаром), то этот конструктор может упасть с исключением &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IOException&lt;/code&gt;,
 об этом IDEA вам подскажет ошибкой &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unhandled exception: java.io.IOException&lt;/code&gt;, мы просто явно пробросим эту ошибку наружу - пусть наша программа упадет (это делается через клик по этому конструктору -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt+Enter&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Add exception to method signature&lt;/code&gt;). Об этой же ошибке упомянуто в конце в секции “частые проблемы”.&lt;/p&gt;

&lt;p&gt;Теперь надо сказать швейцару ждать гостей (accept = принимать/ожидать):&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Socket&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;socketToClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;serverDoorMan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;accept&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Функция &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accept()&lt;/code&gt; приостанавливает исполнение программы до первого подключения клиента по этому порту (первого человека который придет в гости).&lt;/p&gt;

&lt;p&gt;Когда клиент подключится и соответственно соединение будет установлено - эта функция вернет сокет который описывает установленное соединение (т.е. объект класса &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Socket&lt;/code&gt;),
 поэтому результат исполнения функции &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accept&lt;/code&gt; надо сохранить в переменную типа &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Socket&lt;/code&gt; - например логично назвать такую переменную &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socketToClient&lt;/code&gt;, т.к. это сокет соединения с клиентом.&lt;/p&gt;

&lt;p&gt;У &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Socket&lt;/code&gt; (объект в переменной &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socketToClient&lt;/code&gt;) уже можно получить входной и выходной поток (через методы &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getInputStream&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOutputStream&lt;/code&gt;) - они обладают тем же типом, что и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.in&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.out&lt;/code&gt;. Поэтому о том, как считывать из входного потока (который возвращает &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getInputStream&lt;/code&gt; - т.е. это поток данных которые идут от клиента к серверу)
 и как писать в выходной поток (т.е. в результат &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOutputStream&lt;/code&gt; - т.е. в поток данных от сервера к клиенту) в пункте 0 предложена условная задача на понимание &lt;a href=&quot;/lessons/239/school/java/olymp/2017/01/10/olymp-stub.html&quot;&gt;этого&lt;/a&gt; (единственная разница - вторым аргументом в конструктор &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PrintWriter&lt;/code&gt; нужно передать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; - это включит автоматическую отправку буфера на каждое сообщение).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/chat/figure_server.png&quot; alt=&quot;Server figure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Когда клиент закроет канал - метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readLine()&lt;/code&gt; класса &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BufferedReader&lt;/code&gt; вернет &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; - и тогда сервер должен будет вернуться обратно на стадию ожидания нового клиента - т.е. опять вызвать метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accept()&lt;/code&gt;. (т.е. швейцар опять вернулся на свою позицию ожидания гостей)&lt;/p&gt;

&lt;p&gt;Но как и при работе с файлами - сокет соединения с клиентом надо закрывать, т.е. после того как &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readLine()&lt;/code&gt; вернул &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; - требуется вызвать метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;close()&lt;/code&gt; у объекта класса &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Socket&lt;/code&gt;, который представляет соединение с клиентом (т.е. то, что вернул метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accept()&lt;/code&gt;).&lt;/p&gt;

&lt;h2 id=&quot;3-простой-клиент&quot;&gt;3) Простой клиент&lt;/h2&gt;

&lt;p&gt;Итак нам нужно написать программу которая подключается по порту 2391 к компьютеру с каким-то ip-адресом и шлет ему сообщения + получает на них ответы.&lt;/p&gt;

&lt;p&gt;Мы сервер и клиент будем запускать на одном и том же компьютере, и для подобного случая есть зарезервированный специальный ip адрес - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;127.0.0.1&lt;/code&gt; (так же известный как &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localhost&lt;/code&gt;), поэтому можно считать что сервер всегда существует по такому адресу.&lt;/p&gt;

&lt;p&gt;В Java есть специальный класс &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Socket&lt;/code&gt;, который представляет “разъем”/”сокет” соединения, т.е. один из концов канала обмена сообщениями.
 Для того чтобы инициировать соединение с сервером - надо создать сокет с адресом сервера к которому мы стучимся (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;127.0.0.1&lt;/code&gt;) и портом на котором нас ожидает сервер (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2391&lt;/code&gt;). Здесь рпяит возникнет &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unhandled exception: java.io.IOException&lt;/code&gt;, которая обсуждалась выше (конструктор &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerSocket&lt;/code&gt;) и ниже (в &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Частых проблемах&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Создаем такой сокет в main-функции:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;host&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;127.0.0.1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2391&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Socket&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;socketToServer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Socket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Как и у сервера код работающий с потоками такой же как и при работе с консольным вводом-выводом. Методы получения потоков у &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socketToServer&lt;/code&gt; такие же как и у &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socketToClient&lt;/code&gt;, который обсуждался выше. Только теперь &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getInputStream&lt;/code&gt; - канал от сервера к нам (т.е. к клиенту), а &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOutputStream&lt;/code&gt; - от нас к серверу:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/chat/figure_client.png&quot; alt=&quot;Client figure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Т.е. теперь достаточно в цикле слать сообщения серверу через выходной поток получаемый через метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOutputStream&lt;/code&gt; и печатать в консоль получаемые через &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getInputStream&lt;/code&gt;- поток ответные сообщения.&lt;/p&gt;

&lt;p&gt;P.S. не забудьте вызвать метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;close()&lt;/code&gt; у сокета соединения.&lt;/p&gt;

&lt;h2 id=&quot;4-сервер-чата-добровольное&quot;&gt;4) Сервер чата (добровольное)&lt;/h2&gt;

&lt;p&gt;Теперь мы хотим чтобы сервер пересылал все входящие сообщения всем подключенным клиентам.&lt;/p&gt;

&lt;p&gt;Для этого нужно создавать по потоку на клиент. Т.е. есть один поток, который как швейцар ожидает новых клиентов, и как только приходит новый - добавляет его к уже подключенным клиентам.&lt;/p&gt;

&lt;p&gt;На каждый клиент в момент его подключения создается новый поток, который будет ожидать в вченом цикле новые входящие сообщения от этого клиента, и как только сообщение приходит - рассылать его всем остальным клиентам.&lt;/p&gt;

&lt;p&gt;Этот пункт добровольный - на ачивку, поэтому инструкция не подробная.&lt;/p&gt;

&lt;h2 id=&quot;5-тестирование-и-отправка-задания&quot;&gt;5) Тестирование и отправка задания&lt;/h2&gt;

&lt;p&gt;Чтобы протестировать - вам надо сначала запустить сервер, а затем клиент. Переключаться между их консолями можно нажимая мышкой на вкладки в нижней части IDE.&lt;/p&gt;

&lt;p&gt;Отправляйте выполненное задание ввиде zip-архива &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt; папки, и пожалуйста:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Тему письма называйте правильно, например: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Задание 40 16-1 Полярный Коля&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Правильно называнный zip-архив (или 7zip), внутри которого папка &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt; с &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.java&lt;/code&gt; файлами, пример названия: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;40_16_1_polyarniy_nikolay.zip&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;6-частые-проблемы&quot;&gt;6) Частые проблемы&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ситуация:&lt;/code&gt; При запуске сервера выводится исключение &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.net.BindException: Address already in use (Bind failed)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Это означает что слушать по такому порту сервер не смог, т.к. этот порт уже кем-то занят. Скорее-всего вы забыли остановить запущенный ранее сервер (нажать красную квадратную стоп-кнопку).&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ситуация:&lt;/code&gt; Не компилируется с исключением &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unhandled exception: java.io.IOException&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Это означает что вызов может упасть с исключением по работе с IO, т.е. с Input-Output (т.е. ввод-вывод). Чтобы начало компилироваться - достаточно пробросить эту ошибку наружу, т.к. такая прблема в нашем случае должна приводить к падению программы. Подробнее об этом написано выше рядом с описанием вызова конструтора &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerSocket&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ситуация:&lt;/code&gt; При запуске клиента не устанавливается соединение с исключением &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.net.ConnectException: Connection refused: connect&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Это означает, что клиент попытался установить соединение по какому-то порту, но на этом порту никто не ждал гостей, т.е. сервер не был запущен и не создал на этом порту свой &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerSocket&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ситуация:&lt;/code&gt; Подсвечивает красным код с ошибкой “Unhandled exception: java.io.IOException”&lt;/p&gt;

&lt;p&gt;Это означает, что данная строка кода может кинуть исключительную ситуацию. Исключение называется &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IOException&lt;/code&gt;, т.к. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IO&lt;/code&gt; - InputOutput, т.е. исключение связанное с потоком данных. Например в случае работы с файлом это может быть - “файл не найден”, а в случае работы по сети - “соединение было разорвано”. Ее можно либо обработать (например напечатав в консоль “проблемы с соединением”) с помощью &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;блока try-catch&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt+Enter&lt;/code&gt;, затем &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Surround with try/catch&lt;/code&gt;), либо пробросить дальше из этого метода, чтобы смог обработать тот, кто вызвал метод, в котором мы сейчас находимся (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt+Enter&lt;/code&gt;, затем &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Add exception to method signature&lt;/code&gt;).&lt;/p&gt;
</description>
        <pubDate>Wed, 25 Jan 2017 09:00:00 +0000</pubDate>
        <link>http://polarnick.com/lessons/239/lesson/school/java/socket/2017/01/25/Simple-echo-server.html</link>
        <guid isPermaLink="true">http://polarnick.com/lessons/239/lesson/school/java/socket/2017/01/25/Simple-echo-server.html</guid>
        
        
        <category>lessons</category>
        
        <category>239</category>
        
        <category>lesson</category>
        
        <category>school</category>
        
        <category>java</category>
        
        <category>socket</category>
        
      </item>
    
      <item>
        <title>Задание 39. Простой программа рисования</title>
        <description>&lt;p&gt;Это задание является первым из трех частей мультиплеерного Paint. В результате получится программа в которой пользователи сервера и клиента рисуют и видят общую картину.&lt;/p&gt;

&lt;h2 id=&quot;дедлайн&quot;&gt;Дедлайн:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;9-1: когда-нибудь не скоро&lt;/li&gt;
  &lt;li&gt;10-1: 21 февраля&lt;/li&gt;
  &lt;li&gt;11-1: 21 февраля&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;В данной программе можно будет рисовать: сначала кружки в месте где кликнула мышка, затем линии там, где мышка прошла с нажатой кнопкой.&lt;/p&gt;

&lt;h2 id=&quot;1-создаем-окно&quot;&gt;1) Создаем окно&lt;/h2&gt;

&lt;p&gt;Создаем класс &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MainFrame&lt;/code&gt;, который как и в самом начале задания отрисовки змейки (&lt;a href=&quot;/lessons/239/lesson/school/java/swing/game/snake/2017/01/17/Snake-2-Rendering.html&quot;&gt;в задании 32&lt;/a&gt;) является окном, а значит должен быть отнаследован от &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JFrame&lt;/code&gt; (т.е. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class MainFrame extends JFrame {&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;В конструкторе &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MainFrame&lt;/code&gt; нам достаточно указать какой-нибудь разумный размер окна, попросить окно принять этот размер (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pack()&lt;/code&gt;), сказать что мы хотим завершать исполнение программы по нажатию на крестик и сделать окно видимым (все это аналогично тому, что мы делали &lt;a href=&quot;/lessons/239/lesson/school/java/swing/game/snake/2017/01/17/Snake-2-Rendering.html&quot;&gt;в задании 32&lt;/a&gt;):&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;setPreferredSize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dimension&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;800&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;600&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;setDefaultCloseOperation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;WindowConstants&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;EXIT_ON_CLOSE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;setVisible&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Итак, добавим точку входа (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;-функцию), и наше окошко уже появляется при запуске:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;MainFrame&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MainFrame&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;2-рисуем-примитивы&quot;&gt;2) Рисуем примитивы&lt;/h2&gt;

&lt;p&gt;Чтобы что-нибудь нарисовать - надо переопределить метод определяющий то, как &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JFrame&lt;/code&gt; отрисовывается - это метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;void paint(Graphics g)&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;paint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Graphics&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Теперь внутри этого метода обращаясь к &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Graphics g&lt;/code&gt; можно рисовать различные примитивы.&lt;/p&gt;

&lt;p&gt;Например можно нарисовать линию:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;drawLine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;250&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Или овал (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawOval&lt;/code&gt;), или прямоугольник (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawRect&lt;/code&gt;). Поэкспериментируйте с разными фигурами: чтобы увидеть перечень всех функций которые поддерживает &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Graphics&lt;/code&gt; нужно написать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g.&lt;/code&gt; и нажать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+Space&lt;/code&gt; - IDE покажет вам перечень функций.&lt;/p&gt;

&lt;p&gt;Заметьте, что теперь фон окна иногда не чисто серого цвета, а как бы прозрачный - т.е. показывает то, что было на его месте до того как он отрисовался. Это вызвано тем, что раньше &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JFrame&lt;/code&gt; при отрисовке исполнял свой старый метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;paint(...)&lt;/code&gt;, который в частности заливал серым цветом все окно, теперь же мы переопределили этот метод, а следовательно код очистки окошка перестал исполняться. Но есть возможность не целиком заменить старый метод, а расширить его - для этого достаточно в начале реализации &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;paint(...)&lt;/code&gt; добавить вызов &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;super.paint(g)&lt;/code&gt;. Здесь &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;super&lt;/code&gt; это почти как &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt; - только родительская часть текущего объекта, поэтому таким образом можно вызвать родительскую (т.е. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JFrame&lt;/code&gt;) реализацию &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;paint&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Чтобы изменить цвет - перед вызовом очередного &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw...&lt;/code&gt; достаточно вызвать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g.setColor(new Color(255, 0, 0));&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Сложнота:&lt;/code&gt; Чтобы изменить толщину штрихов - нужно преобразовать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Graphics&lt;/code&gt; к &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Graphics2D&lt;/code&gt; и затем вызвать метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setStroke()&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Graphics2D&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g2d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Graphics2D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;g2d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setStroke&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BasicStroke&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;3-обрабатываем-клики-мышки&quot;&gt;3) Обрабатываем клики мышки&lt;/h2&gt;

&lt;p&gt;Чтобы обрабатывать нажатия мышки надо заявить себя “слушателем мышки”, реализовать методы которые обрабатывают события и зарегистрировать себя как “официального слушателя мышки в этом окне”:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Добавить &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implements MouseListener&lt;/code&gt; в объявлении &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MainFrame&lt;/code&gt;, чтобы получилось &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public class MainFrame extends JFrame implements MouseListener {&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Кликнуть в подсвеченном красным implements, затем нажать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt+Enter&lt;/code&gt; и выбрать &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Implement methods&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Добавить в конструктор &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MainFrame&lt;/code&gt; вызов &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addMouseListener(this);&lt;/code&gt; (что зарегистрирует нас как обработчика событий мышки)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Теперь можно например в &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mouseClicked&lt;/code&gt; обрабатывать клики мышки в окне. Чтобы получить координаты мышки надо у аргумента функции обработки события (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;void mouseClicked(MouseEvent e)&lt;/code&gt;) вызвать метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getX()&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getY()&lt;/code&gt;, т.е. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e.getX()&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e.getY()&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;4-рисуем-овалы-в-местах-кликов-мышкой&quot;&gt;4) Рисуем овалы в местах кликов мышкой&lt;/h2&gt;

&lt;p&gt;Давайте заведем списки координат где кликнула мышь. Объявим мы их как поля &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MainFrame&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Теперь в методе &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mouseClicked&lt;/code&gt; достаточно добавлять (методом &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add&lt;/code&gt;) координаты очередного клика к этим массивам.&lt;/p&gt;

&lt;p&gt;Чтобы отрисовать эти клики - надо в методе &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;paint&lt;/code&gt; перебрать все сохраненные на данный момент координаты кликов и отрисовать их, например вот так:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;drawOval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Если теперь запустить и протестировать - мышкой рисовать овалы не получается. Почему? Под отладчиком оказывается что метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mouseClicked&lt;/code&gt; отрабатывает нажатия, но после этого &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;paint&lt;/code&gt; банально не вызывается.&lt;/p&gt;

&lt;p&gt;Дело в том, что отрисовка окна происходит не постоянно, а лишь тогда когда что-то изменилось, например окно изменило размер, или было развернуто на весь экран, или само приложение поняло, что отображаемое в окошке изменилось - а это как раз наш случай, ведь мы приняли решение добавить к отрисовке новый эллипс.
 Чтобы оповестить окно о том, что ему пора перерисоваться - надо вызвать метод &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;repaint()&lt;/code&gt;, что спровоцирует вызов метода &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;paint&lt;/code&gt; (т.е. надо сообщить о том, что окно требуется перерисовать. А делать это надо в тот момент, когда мы это поняли - т.е. в методе обработки клика мышью).&lt;/p&gt;

&lt;h2 id=&quot;5-обрабатываем-движения-мышью&quot;&gt;5) Обрабатываем движения мышью&lt;/h2&gt;

&lt;p&gt;Это опять про “великих обработчиков”. Все то же самое что и про обработку кликов мышью в пункте 3, разве что реализовывать надо интерфейс &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MouseMotionListener&lt;/code&gt;. В результате получается что-то подобное:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MainFrame&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JFrame&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MouseListener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MouseMotionListener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;А так же:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;После &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt+Enter&lt;/code&gt; добавятся переопределения методов &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mouseDragged&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mouseMoved&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Регистрация нашего объекта как слушателя движений мышью вызовом &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addMouseMotionListener(this);&lt;/code&gt; в конструкторе &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MainFrame&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;6-задание-на-пятерку---контуры-движений-мыши&quot;&gt;6) Задание на пятерку - контуры движений мыши&lt;/h2&gt;

&lt;p&gt;Понять, как теперь можно сохранять перечень отрезков отображающих траекторию движения мышки с нажатой кнопкой. Т.е. каждый отрезок - это отрезок между двумя точками, где первая точка - предыдущее положение мыши, а вторая точка - следующее. При этом линия должна выводиться только при зажатой кнопке мыши, если кнопка отпущена - линия завершена, если левая кнопка мыши нажата вновь - новая линия начинается.&lt;/p&gt;

&lt;h2 id=&quot;7-двойная-буферизация-добровольное-необязательное&quot;&gt;7) Двойная буферизация (добровольное, необязательное)&lt;/h2&gt;

&lt;p&gt;Когда элементов отрисовки окажется достаточно много - станет заметно мерцание внутри окна. Это вызвано тем, что отрисовка происходит по-элементно, и каждое промежуточное состояние пользователь видит. В результате элементы которые отрисовываются в конце - пользователь наблюдает крайне малое время.&lt;/p&gt;

&lt;p&gt;Чтобы это поправить, надо включить двойную буферизацию:&lt;/p&gt;

&lt;p&gt;1) Указать число буферов для стратегии буферизации - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;createBufferStrategy(2);&lt;/code&gt; (например вызвав в конце конструирования окна)&lt;/p&gt;

&lt;p&gt;2) В методе &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;paint&lt;/code&gt; удалить вызов &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;super.paint(g)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;3) В самом начале метода &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;paint&lt;/code&gt; написать следующий код:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;BufferStrategy&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bufferStrategy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getBufferStrategy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// Обращаемся к стратегии буферизации&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bufferStrategy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;                               &lt;span class=&quot;c1&quot;&gt;// Если она еще не создана&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;createBufferStrategy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;                                &lt;span class=&quot;c1&quot;&gt;// то создаем ее&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bufferStrategy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getBufferStrategy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;// и опять обращаемся к уже наверняка созданной стратегии&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bufferStrategy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getDrawGraphics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;// Достаем текущую графику (текущий буфер)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getBackground&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;                                &lt;span class=&quot;c1&quot;&gt;// Выставялем цвет в цвет фона&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fillRect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getWidth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getHeight&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;// Зачищаем все окно фоновым цветом&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;4) В самом конце метода &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;paint&lt;/code&gt; написать следующий код:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dispose&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;                &lt;span class=&quot;c1&quot;&gt;// Освободить все временные ресурсы графики (после этого в нее уже нельзя рисовать) &lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;bufferStrategy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;// Сказать буферизирующей стратегии отрисовать новый буфер (т.е. поменять показываемый и обновляемый буферы местами)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;8-отправка-задания&quot;&gt;8) Отправка задания&lt;/h2&gt;

&lt;p&gt;Отправляйте выполненное задание ввиде zip-архива &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt; папки, и пожалуйста:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Тему письма называйте правильно, например: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Задание 39 16-1 Полярный Коля&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Правильно называнный zip-архив (или 7zip), внутри которого папка &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt; с &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.java&lt;/code&gt; файлами, пример названия: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;39_16_1_polyarniy_nikolay.zip&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;9-частые-проблемы&quot;&gt;9) Частые проблемы&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ситуация:&lt;/code&gt; Окошко маленькое&lt;/p&gt;

&lt;p&gt;Либо вы указали маленький размер окна в пикселях (нормальный размер - это например 640x480), либо что-то упустили в условии (например место где указывается размер окна или вызов &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pack()&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ситуация:&lt;/code&gt; Окно прозрачное/за ним мусор/остается мусор с предыдущих отрисовок&lt;/p&gt;

&lt;p&gt;Вы упустили в условии вызов родительской реализации &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;paint()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ситуация:&lt;/code&gt; Окно мерцает&lt;/p&gt;

&lt;p&gt;Это из-за отсутствия двойной буферизации. Меня устраивает если окно мигает в процессе рисования мышью или в процессе изменения размера окна, но не в состоянии “окно не двигается и изображение статично”.
Опционально это можно пофиксить, как это фиксить - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;7 пункт&lt;/code&gt; условия (не обязательный).&lt;/p&gt;

</description>
        <pubDate>Tue, 24 Jan 2017 09:00:00 +0000</pubDate>
        <link>http://polarnick.com/lessons/239/lesson/school/java/paint/swing/2017/01/24/Simple-drawer.html</link>
        <guid isPermaLink="true">http://polarnick.com/lessons/239/lesson/school/java/paint/swing/2017/01/24/Simple-drawer.html</guid>
        
        
        <category>lessons</category>
        
        <category>239</category>
        
        <category>lesson</category>
        
        <category>school</category>
        
        <category>java</category>
        
        <category>paint</category>
        
        <category>swing</category>
        
      </item>
    
  </channel>
</rss>
