Здравствуйте.

В этой статье будет показано, как на языке программирования FBD написать простую программу, которая, тем не менее, будет делать что-то полезное. В нашем примере это будет игра в Пятнашки.

Для начала напомню правила игры: игра в «15», «Пятнашки», «Такен» — популярная головоломка, придуманная в 1878 году Ноем Чепмэном. Представляет собой набор одинаковых квадратных костяшек с нанесёнными числами, заключённых в квадратную коробку. Длина стороны коробки в четыре раза больше длины стороны костяшек для набора из 15 элементов, соответственно в коробке остаётся незаполненным одно квадратное поле. Цель игры — перемещая костяшки по коробке, добиться упорядочивания их по номерам, желательно сделав как можно меньше перемещений.

Как мы видим, правила предельно простые. И реализация будет простой и займет минут 15 без графической части и полчаса со всеми картинками. При этом хочу обратить ваше внимание на то, что вопросы оптимизации алгоритмов и логики остаются за рамками этой статьи т.к. эти вопросы уже не такие простые и потребуют куда больше времени.

Вот что получилось в итоге:


Описание программы, комментарии и картинки под катом.

Основа программы


Как видно из описания игры, у нас есть поле из 16 элементов. Таким образом основой программы будет элемент «Клетка пятнашек».
Сформулируем требования к этому элементу:

— Наша «клетка пятнашек» должна принимать внешние команды, когда игрок говорит, что хочет передвинуть ее на соседнее пустое место.
— Клетка должна знать о соседях по вертикали и горизонтали, чтобы понять, есть ли рядом пустая клетка, с которой можно поменяться местами.
— Клетка должна на старте игры установить начальное значение.
— На выход Клетка должна передать значение, установленное в ней на данный момент.
— Если игрок подал команду Клетке переместиться на соседнее пустое поле, то Клетка должна передать команду соседней пустой Клетке о том, что они сейчас будут меняться местами.

Исходя из этих требований получаем набор входных и выходных сигналов.

Входы:
  • УпрКоманда — команда управления от игрока, соседних клеток или начальной установки значения
  • Сверху — значение соседней сверху клетки
  • Снизу — значение соседней снизу клетки
  • Слева — значение соседней слева клетки
  • справа — значение соседней справа клетки
  • УстЗначение — значение, которое должно быть установлено в клетку при старте игры

Выходы:
  • Значение — значение клетки
  • Поехали — команда соседу, что мы хотим «поменяться с ним местами»

«Поменяться местами» в кавычках, потому что сами Клетки пятнашек у нас никуда не будут бегать, они просто будут перезаписывать свое значение.

В итоге получается вот такой макрос:


Поставим таких макросов в нашу задачу 16 штук и свяжем их между собой. В итоге получаем:

Все очень просто. Поставили в задачу шестнадцать макросов «Клетка пятнашки» и связали каждую клетку с соседями по вертикали и горизонтали. Если каких-то соседей у клетки нет (например в клетке_1_1 нет соседа сверху и слева), ставим на соответствующем входе "-1".

Набивка основы


На прошлом шаге мы заложили основу программы. Но т.к. сам элемент «Клетка пятнашки» пока у нас пустой, то ничего хорошего наша программа делать не умеет. Пора это исправить, наполнив логикой макрос «Клетка пятнашки».



Это готовая реализация нашего макроса. Кратко принцип работы:

1. Получаем на вход управляющую команду и распаковываем ее. Выделяем отдельно сигнал длительностью один цикл — признак, что поступила команда, и параметр команды. В нашем случае параметр команды это набор целых чисел от 1 до 6, где числа 1 — 4 это команда поменяться значениями с одним из соседей, число 5 означает команду установить начальное значение в ячейку, а число 6 — что игрок кликнул мышкой по данной клетке и хочет «передвинуть» ее на возможно находящееся по соседству пустое поле.

2. Проверяем всех соседей на нулевое значение (числом 0 у нас обозначается пустое поле).

3. Дальше смотрим на текущее значение данной клетки и команду. Если значение клетки равно нулю (клетка пустая) и одновременно пришла команда поменяться значениями с соседом (команды 1-4), то перезаписываем в клетку значение соседней клетки.

4. Если нам пришла команда 5 (установить начальное значение), то просто записываем в память значение со входа «УстЗначение».

5. Если нам пришла команда 6 (игрок кликнул мышкой по данной клетке) и значение одной из соседних клеток равно нулю, то записываем в данную клетку нулевое значение и отправляем команду «Поехали» на соседние клетки с указанием, с каким именно соседом мы хотим поменяться.

Вот собственно и все. Единственный тонкий момент в нашей реализации, это алгоритмы «Задержка». Но догадаться, зачем они нужны, легко просто представив как проходит выполнение программы:

— мы получили команду от игрока «передвинуть» эту клетку на пустое место.
— проверили, действительно рядом есть пустое место.
— записали в клетку «0» и передали соседу, что хотим поменяться с ним значениями.
— сосед (при этом нужно понимать, что отрабатывает все тот же макрос «Клетка пятнашки», просто другой его экземпляр) видит, что ему пришла команда поменяться местами с другой клеткой.
— сосед проверяет что в нем самом записан «0» т.е. он сейчас пустая клетка и записывает себе значение первой клетки, от которой пришла команда поменяться местами.

Но секундочку! Ведь одновременно с тем, как отправить команду соседу мы в нашу первую клетку записали «0», следовательно сосед тоже запишет себе ноль и у нас получатся две пустые клетки, а одно значение (из ряда 1-15) пропадет. И так пока все игровое поле не станет пустым. Чтобы этого не произошло, задерживаем в первой клетке перезапись нулем. Таким образом пустая соседняя клетка успеет себе записать правильное значение.

Несколько слов про оптимизацию
Как несложно заметить, сам макрос «Клетка пятнашки» достаточно прост. Однако его можно еще упростить, выкинув оттуда часть блоков. Идея простая. Сейчас мы проверяем команду и соседние клетки перед выполнением перестановок. Однако, как было сказано выше, при любой перестановки отрабатывает два экземпляра одного и того же макроса. И в первом экземпляре мы проводим проверку перед отправкой команды, а во втором экземпляре проводим ту же самую проверку при получении команды. Таким образом одну из проверок можно смело выкидывать. Это первое, что сразу бросается в глаза. Второй момент — лишняя задержка на значении. Ведь значение хранится в блоке «Память», куда перезаписывается только по команде. Следовательно достаточно задержать только команду перезаписи значения, а само значение подавать как есть.

Победа или поражение


Собственно основа нашей программы готова и уже прекрасно работает. Можно играть. Все дальнейшие действия нужны только для внедрения вспомогательных функций.

Начнем с автоматической проверки победы или проигрыша игрока.

В игре «пятнашки» есть забавный момент заключающийся в том, что из всех возможных начальных раскладов плиток половина раскладов нельзя собрать если плитки с номерами «14» и «15» стоят не в том порядке.

Исходя из этого сформируем два условия:
— условие 1: значение, записанное в каждую клетку соответствует ее порядковому номеру. Т.е. игрок победил.
— условие 2: значения, записанные в клетки соответствуют их порядковому номеру за исключением клеток «14» и «15», которые поменяны местами. Т.е. немного не повезло с раскладом.

Ставим 18 алгоритмов сравнения, и собираем по И два набора по шестнадцать равенств. По ИЛИ формируем признак, что мы пришли к одному из концов расклада.

18 алгоритмов потому, что мы проверяем соответствие 16 ячеек для первого случая и дополнительно перестановку ячеек «14» и «15» для второго случая. Кстати т.к. у нас массив данных заранее определенный, то достаточно пятнадцати проверок для всего поля, т.к. последняя ячейка проверяется автоматом.



Начальная расстановка


Итак, программа у нас готова. Можно играть и при победе выдается сообщение. Все хорошо за исключением того, что в начале игры нужно расставить плитки в поле случайным образом. И оказалось, что в данном примере это самая сложная задача. Но если не упираться в быстродействие, оптимальность алгоритмов и т.п. то можно решить эту задачу «в лоб» малой кровью сравнительно быстро.

Сначала делаем генератор случайных целых чисел 0 — 15. Пойдем старым проверенном способом. Это вполне допустимый вариант т.к. получившаяся последовательность случайных чисел зависит от момента времени, когда была нажата кнопка «Новая игра». А т.к. этот момент времени случает и никогда не повторяется, то в итоге мы получаем довольно простой и хороший генератор случайных чисел.



На выходе алгоритма Действительное-в-Целое (ДвЦ) получаем случайное целое значение 0 — 15.

Теперь стоит задача сформировать ряд неповторяющихся значений, и записать каждое значение в свою ячейку.

Как я уже сказал, конкретно для языка FBD более или менее хорошее решение этой задачи сделать сложно. Или может просто я не вижу очевидное для остальных красивое и простое решение. Конечно всегда есть вариант сделать вставку на ST, но цель сделать задачу именно целиком на языке FBD.

Решение задачи «в лоб» заключается в следующем:

— ставим управляющие элемент.
— при подаче команды забиваем начальный массив "-1" (можно было и любыми числами вне диапазона [0..15]).
— обнуляем счетчик.
— далее генерируем случайное число от 0 до 15 и проверяем, есть ли такое в нашем массиве. Если есть — продолжаем генерацию случайных чисел.
— если такого числа нет — увеличиваем счетчик на единицу и записываем в соответствующую ячейку памяти наше значение.
— повторяем эти действия еще 15 раз.
— проверяем, если мы дошли до шестнадцатого шага, то формируем импульс, по которому отправляем команду на запись этих значений во все ячейки.

Главным недостатком данного алгоритма является многократный перебор выкинутых ранее значений. В теории время генерации такой случайной последовательности может быть бесконечным. В реальности при десятках прогонов программы оно не было больше чем полсекунды. В любом случае на время генерации (раз оно не мгновенное) ставим блокировку на действия игрока.

Вот что в итоге получилось:



Приделываем графику


Теперь, когда задача у нас полностью готова, самое время приделать UI.

Для этого выбираем в интернете любые понравившиеся картинки с пятнашками. Одновременно выбираем картинки для удачного сбора расклада и неудачного. Я решил поместить туда Гомера Симпсона.

Ставим 16 картинок и приделываем к ним анимацию чтобы они показывали число, соответствующее числу в ячейке. А в ячейке с нулем плитка должна быть невидимой. Ставим на каждую плитку формирование команды «6». Снизу располагаем кнопку «Новая игра» по которой будем запускать алгоритм генерации случайной начальной расстановки. Одновременно не забываем поставить блокировку на все плитки во время генерации. Поверх всего этого дела помещаем Гомера. Все. Графика готова, можно играть.

Нарисованный вариант. Можно заметить что изначально все плитки у нас с единицей.


Начальная позиция.


Неудачный расклад.


И победа!


Что осталось нереализованным


На самом деле не так уж и много:

— можно приделать счетчик ходов. Делается это элементарно. В макросе «Клетка пятнашки» есть команда «6» — команда игрока. Достаточно взять от нее логический сигнал длительностью в один цикл. Вывести этот сигнал наружу. Собрать все шестнадцать сигналов по ИЛИ и завести на алгоритм сложения, охваченный обратной связью. Т.е. всего три дополнительный алгоритма и пара минут работы.

— статистика. Можно сделать счетчик выигранных и неудачных игр. Добавляется два алгоритма сложения и пару алгоритмов обвязки. Тоже пара минут работы.

— отбор раскладов. Как уже говорилось, половина раскладов не сходится изначально из-за невозможности поменять местами плитки «14» и «15». Можно при старте проверять «неудачный расклад» и сразу менять эти две плитки местами.

Сделать все это не сложно, поэтому оставлю такую возможность всем желающим.

Выводы


В этот раз за полчаса на языке FBD была реализована простенькая игрушка «Пятнашки». При этом все используемые алгоритмы простые и понятные. Вся логика обработки сигналов очевидная. Разобраться в такой программе не составит труда любому человеку, знакомому с азами логики и основами языков программирования МЭК 61131.

Для проверки накидал примерно то же самое на С. Вот что получилось:
Текст программы на С
Т.к. программированием на языке С/С++ я не владею, то скорее всего программа ужасна. Более того я сразу вижу несколько «сомнительных» мест. Однако она работает и работает без ошибок.

Главная идея состоит в том, что одна и та же программа, написанная на языке С и на языке FBD имеет разную сложность понимания человеком «со стороны». И если с языком функциональных блоков разобраться не представляет никакого труда, то с реализацией на С придется повозиться.

И хотя программа на FBD состоит из 153 блоков (и мы помним, что там еще есть 16 макросов, каждый из которых состоит из 32 блоков), но на написание ее ушло гораздо меньше времени, чем на написание 50 строчек кода на С.

#include <iostream>
#include "cstdlib"
#include <locale.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <cmath>

using namespace std;


int main(void)
{
	int MyPyatn[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
	int i = 0, x = 0, y = 0, MyRand = 0, MyBuffer = 0, MyButton = 0;
	bool MyGameover = false, MyChange = false;

	setlocale(LC_ALL, "ru-RU");
	srand(time(NULL));

	cout << "Нажми 'n' для новой игры или любую другую кнопку для выхода:  ";

	kbhit();
	if(getch() != 110)
		return 0;
	
	std::system("cls");

	cout << "Играем в пятнашки:  ";

	for(i=0;i<16;i++)
	{
		MyRand = rand() %(16-i);
		MyBuffer = MyPyatn[15-i];
		MyPyatn[15-i] = MyPyatn[MyRand];
		MyPyatn[MyRand] = MyBuffer;
	}
	
	for (i=0;i<16;i++)
	{
		
		if ((i %4) == 0)
		{
			cout << "\n";
			cout << "\n";
		}

		if ((MyPyatn[i]<10) || (MyPyatn[i] == 16))   cout << "   ";
		else cout << "  ";

		if (MyPyatn[i] == 16) 
		{
				cout << "_";
				x = i %4 + 1;
				y = int (i/4) + 1;
		}

		else cout << MyPyatn[i];
	
		cout << "   ";

			
	}
	
	cout << "\n";
	cout << "\n";
	cout << "Управление стрелками вверх-вниз-влево-вправо. Выход - '0' \n";
	cout << "Знак _ это пустая клетка";

	do
	{
		MyChange = false;
		MyGameover = true;
		for(i=0;i<16;i++)
		{
			if (MyPyatn[i] != (i+1))  MyGameover = false; 
		}
		
		while(!kbhit ());

		MyButton = getch();
		
		if ((MyButton == 48) || (MyButton == 72) || (MyButton == 75) || (MyButton == 77) || (MyButton == 80))
		{
		
			if (MyButton == 48) return 0;

			if ((MyButton == 72) && (y > 1))
			{
				MyBuffer = MyPyatn[(y-1)*4 + x - 1];
				MyPyatn[(y-1)*4 + x - 1] = MyPyatn[(y-2)*4 + x - 1];
				MyPyatn[(y-2)*4 + x - 1] = MyBuffer;
				y = y - 1;
				MyChange = true;
			}

			if ((MyButton == 80) && (y < 4))
			{
				MyBuffer = MyPyatn[(y-1)*4 + x - 1];
				MyPyatn[(y-1)*4 + x - 1] = MyPyatn[y*4 + x - 1];
				MyPyatn[y*4 + x - 1] = MyBuffer;
				y = y + 1;
				MyChange = true;
			}

			if ((MyButton == 75) && (x > 1))
			{
				MyBuffer = MyPyatn[(y-1)*4 + x - 1];
				MyPyatn[(y-1)*4 + x - 1] = MyPyatn[(y-1)*4 + x - 2];
				MyPyatn[(y-1)*4 + x - 2] = MyBuffer;
				x = x - 1;
				MyChange = true;
			}

			if ((MyButton == 77) && (x < 4))
			{
				MyBuffer = MyPyatn[(y-1)*4 + x - 1];
				MyPyatn[(y-1)*4 + x - 1] = MyPyatn[(y-1)*4 + x];
				MyPyatn[(y-1)*4 + x] = MyBuffer;
				x = x + 1;
				MyChange = true;
			}
		}

		if (MyChange)
		{
			std::system("cls");

			cout << "Играем в пятнашки:  ";

			for (i=0;i<16;i++)
			{
		
				if ((i %4) == 0)
				{
					cout << "\n";
					cout << "\n";
				}

				if ((MyPyatn[i]<10) || (MyPyatn[i] == 16))   cout << "   ";
				else cout << "  ";

				if (MyPyatn[i] == 16)  cout << "_";
				else cout << MyPyatn[i];
	
				cout << "   ";
		
			}
		
			cout << "\n";
			cout << "\n";
			cout << "Управление стрелками вверх-вниз-влево-вправо. Выход - '0' \n";
			cout << "Знак _ это пустая клетка";
		}
				
	} while(!MyGameover);
	
	std::system("cls");

	cout << "ПОБЕДА!!!";
	
	getch();
	
	return 0; 

}


Другими словами язык FBD это простой и понятный язык, предназначенный для далеких от программирования людей. Программировать простые задачки на нем легко. И разобраться в принципах работы программы, написанной другим человеком тоже обычно не составляет большой проблемы.

На этом все. Надеюсь было интересно.
Поделиться с друзьями
-->

Комментарии (36)


  1. Pinsky
    01.07.2016 16:51
    +3

    По вашему, страница текста хуже воспринимается, чем пара ватманов со связями? ЛИЧНО ДЛЯ МЕНЯ — весьма сомнительно


    1. khim
      01.07.2016 17:22
      +1

      Большая проблема в том, что более простая программа на C++, на самом деле, требует знать больше. Чтобы вместо трёх строк

      MyBuffer = MyPyatn[15-i];
      MyPyatn[15-i] = MyPyatn[MyRand];
      MyPyatn[MyRand] = MyBuffer;
      написать одну
      swap(MyPyatn[MyRand], MyPyatn[15-i]);
      нужно как минимум знать о существовании алгоритма swap. А чтобы не дублировать кусок кода, выводящий поле — нужно знать о существовании функций… с другой стороны мне тяжело представить себе человека способного разобраться с тем, как работают макросы в FBD и не способного понять как устроены функции в C++ — но, возможно, в этой разнице и есть какая-то тайна…


      1. OPCSenator
        01.07.2016 17:44

        Да, про swap(a,b); не знал. Теперь буду знать. И на самом деле таких вот тонкостей полно.
        Что касается функций — опять таки вопрос синтаксиса. Чтобы ее прописать, нужно знать как ее объявить, что ей передать, что она возвращает и как ее вызвать. А на FBD это точно такой же блок как и операция ИЛИ. Поставил на поле, привязал «веревки» и все работает.


    1. OPCSenator
      01.07.2016 17:30

      Возможно. Каждому свое.
      Но уточним пару моментов:
      1. В данном примере явно не «пара ватманов со связями». Вся программа умещается на А3.
      2. Программа на «пару ватманов со связями» в текстовом виде будет явно не один лист. И даже не два. И не три.
      3. Еще хотелось бы обратить внимание, но в данном примере на FBD вся программа это фактически повторение один в один 16 раз связки из одного макроса и семи простейших (сравнение, память, ИЛИ) блоков плюс еще полтора десятка простейших блоков обвязки.

      Поэтому ваш вопрос касается явно утрированной ситуации.

      Главное преимущество FBD — возможность по связям быстро проследить логику работы программы. Вот в подобной вещи я например разберусь без комментариев за пятнадцать минут. С комментариями минут за пять.

      Ну и кроме того (в этом посте я в отличие от предыдущих не акцентировал на этом внимание), написать программу на FBD может любой человек, знакомый с основами логики (операции И, ИЛИ, НЕ) и примерно представляющий как работает счетчик и триггер. А чтобы написать подобную же программу на том же С нужно потратить кучу времени на гугленье основ синтаксиса, возможностей языка, реализаций тех или иных конструкций и т.д. и т.п. Т.е. решить эту задачу с ходу не получится.


      1. khim
        01.07.2016 18:12
        +2

        Ну и кроме того (в этом посте я в отличие от предыдущих не акцентировал на этом внимание), написать программу на FBD может любой человек, знакомый с основами логики (операции И, ИЛИ, НЕ) и примерно представляющий как работает счетчик и триггер.
        Да, но ведь это — весьма небольшой процент от всего населения. Вот и возникает вопрос: а много ли вообще в природе людей способных понять «как работает счетчик и триггер», но неспособных изучить «нормальный» язык программирования?
        Главное преимущество FBD — возможность по связям быстро проследить логику работы программы.
        Всё зависит от размеров оной программы. FBD, насколько я вижу, неплохо соотносится с «железом», он близок к тому же Verilogу. Ну отлично — возьмите небольшую программу, реализацию какого-нибудь 68k где-то на 50-100 тысяч элементов. Вы точно уверены, что в ней будет проще разобраться если это будет диаграмма на уж-не-знаю-сколько-ватманов, чем если это будет записано в текстовом виде?


        1. OPCSenator
          01.07.2016 20:33

          По-моему мы с вами говорим о разных вещах совершенно. FBD это один из пяти языков программирования МЭК 61131.
          Эти языки используются для так называемого «технологического» программирования микроконтроллеров.

          Для каждой задачи один язык подходит больше, другой меньше. И конкретно в программировании в АСУ ТП я считаю, что FBD проще и нагляднее и удобнее всего остального. Это просто я делаю всякую ерунду типа игрушек т.к. узкоспециализированные алгоритмы управления техпроцессами вообще никому кроме пары десятков человек не интересны и непонятны.

          Что касается понимания как работает счетчик или триггер или что значит сложение двух сигналов по И. Могу поспорить, что это за 15 минут можно объяснить это любому школьнику, после чего он из таких блоков сможет писать полноценные технологические программы. А вот основам того же языка С (или ST как что то похожее из МЭК 61131) за 15 минут вы никого не научите.


          1. khim
            01.07.2016 20:46

            Могу поспорить, что это за 15 минут можно объяснить это любому школьнику,
            В это — верю.
            после чего он из таких блоков сможет писать полноценные технологические программы
            А вот в это, извините — но не верю. Особенно в свете вот этого:
            узкоспециализированные алгоритмы управления техпроцессами вообще никому кроме пары десятков человек не интересны и непонятны
            Кобол со своими «x IS GREATER THAN y» тоже преследовал цель «быть понтяным всем и каждому», но оказалось, что это просто никому не нужно.
            И конкретно в программировании в АСУ ТП я считаю, что FBD проще и нагляднее и удобнее всего остального.
            Ну как раз тут всё просто: «в связке» есть ведь разные языки. Нужно просто посмотреть — как часто разные подходы используются. Если использование FBD растёт, а ST падает — значит вы правы, если наоборот — то неправы. Если вы этим занимаетесь, то, может быть, у вас есть статистика?


            1. OPCSenator
              01.07.2016 22:16

              А вот в это, извините — но не верю. Особенно в свете вот этого:

              Почему же? «Реализовать на FBD алгоритм» и «изучить технологию для дальнейшего написания алгоритмов» это совсем разные вещи. Второе нереально, а вот первое — без проблем.

              Если вы этим занимаетесь, то, может быть, у вас есть статистика?

              По моему личному опыту (возможно если сюда заглянут люди, непосредственно занимающиеся внедрением АСУ ТП в различных областях и на разных системах то они поправят/дополнят) процентов 80 всех программ АСУ ТП в области энергетики пишется на FBD. Еще 15% на ST. Остальные 5% на оставшиеся 3 языка.

              И FBD популярен именно потому, что даже если кто-то другой наворотил в контроллере черт знает что, то разобраться что и как там работает при использовании FBD гораздо проще и быстрее, чем на каком-либо другом языке.


              1. khim
                01.07.2016 23:06

                По моему личному опыту (возможно если сюда заглянут люди, непосредственно занимающиеся внедрением АСУ ТП в различных областях и на разных системах то они поправят/дополнят) процентов 80 всех программ АСУ ТП в области энергетики пишется на FBD. Еще 15% на ST. Остальные 5% на оставшиеся 3 языка.
                Вот это — уже серьёзно. И показывает что у программистов — таки мозги реально в чём-то другие.
                И FBD популярен именно потому, что даже если кто-то другой наворотил в контроллере черт знает что, то разобраться что и как там работает при использовании FBD гораздо проще и быстрее, чем на каком-либо другом языке.
                Вот это-то и странно. Потому что у меня — впечатление ровно противоположное: когда я вижу все эти «безумные схемы», то у меня по первости никаких словей, кроме матерных в голове не возникает, а когда первое впечатление проходит и кроме «за что?», «им что — реально так удобнее?» в голове возникают другие мысли и я быстренько превращаю весь этот ужас в нормальный, «удобочитаемый» текстовый вид, после чего обычно проходит «понимание»: «ага… тут они гланды… автогеном… через жопу… но зачем?»…
                «Реализовать на FBD алгоритм» и «изучить технологию для дальнейшего написания алгоритмов» это совсем разные вещи. Второе нереально, а вот первое — без проблем.
                Ну не знаю. Я могу себе придумать примерно как реализовать какой-нибудь алгоритм на ST, но даже представить себе не могу нетривиальный алгоритм, который бы реализовывался на FBD. Ну то есть я представляю себе как на FBD реализовать, скажем, Жизнь, а поскольку та полна по Тьюрингу, то, понятно, там и любой другой алгоритм реализуется, но реализовывать алгоритм напрямую на FBD? Как он выглядеть-то должен, чтобы его «любой школьник» мог реализовать?

                Ну вот, к примеру, если мы уж о пятнашках говорим: вот как на FBD можно реальзовать алгоритм, который бы не требовал нажимать на кнопки, а, скажем, просто нажал бы сколько-то кнопок и раcпутал бы исходную конфигурацию. Написать это на С или там на ST — я смогу, не проблема. Но на FBD?

                И FBD популярен именно потому, что даже если кто-то другой наворотил в контроллере черт знает что, то разобраться что и как там работает при использовании FBD гораздо проще и быстрее, чем на каком-либо другом языке.
                Вы это серьёзно? Если я сейчас через А* решу описанную выше задачку и переведу это решение на FBD — вы в нём разберётесь??? Это же жуть будет!


                1. Serge78rus
                  02.07.2016 12:23

                  В том то и проблема. Когда рассматриваются примеры типа Hello World (а на FBD — элементарная логическая схема) то и там, и там все предельно просто. Когда же дело доходит до действительно сложных задач, в классических подходах к программированию возникает понимание, что одного знания языка недостаточно, человек узнает такие слова как «библиотека», «парадигма», «паттерн программирования» и т. д. Да все это требует времени на понимание, но в итоге затраты окупаются. В FBD же и подобных «языках» вместо всего этого возникают упомянутые «N листов ватмана», потому как на экране обозревать это — как наблюдать жизнь через замочную скважину.

                  К сожалению, имея некоторый опыт программирования, был вынужден 4 года заниматься программированием ПЛК «Siemens». Мне безумно жаль те годы, вычеркнутые из моей жизни.


                  1. alexhott
                    10.11.2016 19:59

                    Кроме теорий ничем не подкрепленных для понятия Время пока ничего нет.
                    Моя теория: время — это выдуманное человеком понятие для измерения промежутков между прошлым и будущим.
                    Если проводить аналогию с чемто более понятным, то время это как Температура.
                    Может быть 0 — то есть я допускаю возможность остановить время
                    Но по аналогии с температурой не может быть ниже 0.
                    По этой теории в будущее можно путешествовать, а в пролое не получится.

                    Если заморозить человека — мы локально для него остановим время, через 20 лет разморозим — и он путешественник во времени.


                    1. khim
                      02.07.2016 18:25

                      У нас сотрудники делали алгоритмы автоматического розжига котла целиком на FBD. Там контроль сотен параметров и управление сотней арматуры. Задача реально большая и сложная.
                      Стоп. Откуда там взялась «сотня разнотипных параметров»? Или это были, условно говоря, сто датчиков температуры, сто датчиков давления и ещё десяток других датчиков? Сколько видов данных в обработке участовало? Потому что ведь только это влияет на сложность задачи: в задаче может быть вообще пяток датчиков, но при этом над ними будет строиться такая математическая модель, что для её обсчёта потребуются гигабайты памяти, а может быть и миллион датчиков, которые просто усредняются — тогда задача, в общем и целом — тривиальна.
                      Как вы считаете, что будет проще: ковыряться в текстовых исходниках, правя константы, ветки if и т.п. или найти несколько блоков проверки условий и задать на них новые значения?
                      Зависит от размеров задачи. Я когда говорил про небольшую программу, реализацию какого-нибудь 68k где-то на 50-100 тысяч элементов — это не было сарказмом. Программа подобного размера действительно программистами обычно воспринимается как «небольшая». Большая программа — это миллионы строк кода. Но судя по описанному выше, где задача с «сотнями параметров и с сотней арматуры» считается «большой и сложной» возникает ощущение, что мы вообще о задачах разных масштабов говорим…


                      1. OPCSenator
                        02.07.2016 22:14

                        возникает ощущение, что мы вообще о задачах разных масштабов говорим…

                        Конечно. Я с самого начала сказал что в технологическом программировании в АСУ ТП есть своя специфика. Просто в посте я не написал подробнее т.к. писал в предыдущих статьях и не хотел повторяться.
                        Откуда там взялась «сотня разнотипных параметров»?

                        Нет никакой сотни разнотипных параметров. Обычно это температура, давление, расход, уровень, положение и остальные по мелочи. Исполнительных механизмов тоже несколько видов: двигатель, задвижка да несколько разных типов клапанов. Однако количество датчиков и исполнительных механизмов напрямую влияет на сложность программы. И программа с несколькими сотнями датчиков и сотней арматурин уже довольно сложная штука.


                    1. Serge78rus
                      03.07.2016 11:53

                      Помимо порога вхождения важен еще и верхний порог, характеризующий возможности инструмента: управление тачкой освоить проще, чем управление автомобилем, но как бы Вы не совершенствовались в дальнейшем в виртуозности владения тачкой, производительность Вашего труда расти не будет.

                      И да, я знаю (не считаю, а знаю по собственному опыту), что править текстовые исходники в нормальном текстовом редакторе намного проще и безопаснее, чем делать это в визуальном редакторе. Разумеется при грамотной организации исходных текстов.


                      1. OPCSenator
                        03.07.2016 20:31

                        Помимо порога вхождения важен еще и верхний порог, характеризующий возможности инструмента

                        Согласен. Поэтому когда мы разрабатывали эту систему, то все время присутствовала обратная связь в лице специалистов по проектированию и эксплуатации. И вот этот верхний порог подгонялся под их нужды и в итоге всех устраивал.
                        Разумеется при грамотной организации исходных текстов.

                        Вот оно, то самое «если». Если текст будет нормально написан. Если везде будут комменты. Если будут использованы стандартные приемы. Если (при большом проекте) будет более или менее логичная и понятная архитектура. И т.д.

                        А если нет?


                        1. khim
                          03.07.2016 21:41

                          А если нет?
                          А если нет — то людей, которые «это» сотворили нужно уволить и нанять других.

                          Собственно сама постановка задачи очень странная: зачем заставлять людей делать то, чего они делать не умеют и учиться не хотят? Вроде как у нас уже не СССР, принимать на работу тех, кого вам «распределили» не нужно.

                          Поэтому когда мы разрабатывали эту систему, то все время присутствовала обратная связь в лице специалистов по проектированию и эксплуатации. И вот этот верхний порог подгонялся под их нужды и в итоге всех устраивал.
                          Что очень и очень грустно. Это значит что вся система разрабатывалась не для того, чтобы успешно создать что-то, что будет конкурировать с пресловутыми «лучшими мировыми образцами», а для того, чтобы с ней могли работать существующие кадры.

                          Спасибо за то, что пояснили лично мне за что именно заплатил миллиарды пару лет назад Гугл — после ваших объяснений мне, наконец, стало ясно, что разработчики в огромном количестве отраслей искренне верят, что им дадут «досидеть до пенсии» на том багаже, который они получили много лет назад и который им и не очень хочется обновлять…

                          Интересно будет посмотреть как ситуация будет в будущем развиваться. Если IoT будет развиваться похожим на развитие мобильников курсом, то ещё несколько лет производители «позолоченных тачек» смогут устанавливать вам «планку» (как руководители разработки в Ericcson'е, Nokia, Siemens'е, и прочих всяких Sony и Panasonic'ов), а потом… потом их просто переподчинят. Людям со стороны, скорее всего. Впрочем большую часть — просто уволят.


                          1. OPCSenator
                            04.07.2016 10:48

                            А если нет — то людей, которые «это» сотворили нужно уволить и нанять других.

                            Экий вы шустрый. Всех уволить, набрать хороших. Очень напоминает высказывание наших чиновников, которые супер компетентные, супер эффективные и вообще профи. Просто с народом им не повезло. И надо всех уволить и набрать других.
                            Что очень и очень грустно.

                            Сколько патетики. Конечно хорошо, что люди переживают за будущее нашей страны. Но так трагично заламывать руки все же не стоит. Везде есть свои плюсы и минусы. Везде есть своя специфика работы. И не разбираясь серьезно в этом делать поспешные выводы неразумно т.к. высока вероятность ошибиться.


                1. OPCSenator
                  02.07.2016 13:00

                  И показывает что у программистов — таки мозги реально в чём-то другие.

                  FBD пишется в основном для технологов. Но кстати и отладка проекта на объекте при непрерывных процессах на FBD гораздо проще чем на том же ST.
                  когда я вижу все эти «безумные схемы», то у меня по первости никаких словей, кроме матерных в голове не возникает

                  Это именно первое впечатление. Достаточно поковыряться минут 15-20 и все становится легко и понятно. Просто вы возможно привыкли к тому же С. Чувствуете там себя как рыба в воде. Разумеется первая реакция на совершенно другую непривычную вещь будет именно такой.
                  вы в нём разберётесь??? Это же жуть будет!

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


                  1. khim
                    02.07.2016 18:11

                    Это будет жуть, но в ней при правильном подходе будет несложно разобраться.
                    Вы это серьёзно? Вы сможете понять, где у меня в «мешанине проводов» находится очередь с приоритетами и как именно в ней кодируются позиции? Надо будет попробовать — но я не верю даже в то, что я сам смогу разобраться в том, что сотворю (вы что — думаете что я реально планирую писать что-то на FBD? конечно нет: если будет время то, разумеется, напишу генератор программ на FBD — а уж что он там нагенерит меня мало волновать будет), а вы хотите «разобраться в алгоритме» глядя на эту кашу.


                    1. OPCSenator
                      02.07.2016 22:06

                      Как пример — посмотрите мой самый первый пост. Там (внезапно) 9000 блоков. И что? Разве такое количество вызывает какие-то непреодолимые проблемы? В той программе можно минут за 20 разобраться от и до.

                      С другой стороны бывает «мешанина» из какой нибудь полусотни блоков. И сделаны они так, что там сам черт ногу сломит, пытаясь разобраться что к чему.

                      Т.е. все зависит от качества написания программ. Хотел программист сделать их удобными и понятными для всех или лепил как получится. И от языка это не сильно зависит. Вот вам пример из С:

                      Мешанина кода
                      if ((MyButton==48)||(MyButton==72)||(MyButton==75)||(MyButton==77)||(MyButton==80)){if (MyButton ==48)return 0;if((MyButton==72)&&(y>1)){MyBuffer=MyPyatn[(y-1)*4+x-1];MyPyatn[(y-1)*4+x-1] = MyPyatn[(y-2)*4+x-1];MyPyatn[(y-2)*4+x-1]=MyBuffer;y=y-1;MyChange=true;}if ((MyButton==80)&&(y< 4)){MyBuffer=MyPyatn[(y-1)*4+x-1];MyPyatn[(y-1)*4+x-1]=MyPyatn[y*4+x-1];MyPyatn[y*4+x-1] = MyBuffer;y =y+1;MyChange=true;}if ((MyButton==75)&&(x>1)){MyBuffer=MyPyatn[(y-1)*4+x-1]; MyPyatn[(y-1)*4+x-1] = MyPyatn[(y-1)*4+x-2];MyPyatn[(y-1)*4+x-2]=MyBuffer;x=x-1; MyChange = true;}if ((MyButton==77)&&(x<4)){MyBuffer=MyPyatn[(y-1)*4+x-1]; MyPyatn[(y-1)*4+x-1] = MyPyatn[(y-1)*4+x];MyPyatn[(y-1)*4+x]=MyBuffer;x=x+1;MyChange = true;}}


                      1. Grief
                        11.11.2016 00:23

                        А память — послания из прошлого. Она более «стабильна», потому что прошлое одно, а будущих много. Я об этом в самом первом сообщении написал. Хотя, скорее всего, на самом деле дежавю — просто небольшой глюк, ложное воспоминание.


                        1. OPCSenator
                          03.07.2016 20:47

                          Зависит, ой как зависит.

                          Я чуть выше неточно выразился. Имеется ввиду популярные и распространенные языки. А то тут есть статья когда человек «Hello, World» писал примерно вот так:
                           ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++
                           .>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.
                           ------.--------.>+.>. 

                          Можно программу написать так, чтоб она была понятной, а можно и запутать так, что нихрена не разберешься даже с поллитрой.
                          А кто мне запретит-то? Откуда такие странные ограничения?

                          Специфика АСУ ТП. Работает объект, управляемый контроллером с такой вот программой. Там все приемосдаточные испытания проведены, протоколы подписаны и т.д. И никто не даст вам лезть и что то сильно менять. Только маленький кусочек или вообще несколько констант. Т.е. любое форматирование того что есть исключено.
                          А сделать это на FBD — это как «автогеном через жопу», я извиняюсь, гланды вырезать…

                          Конечно. Просто в вашем примере и в моем решаются принципиально разные задачи. И если в вашем примере это выглядит как вырезание гланд, то в моем — очень органично.


                          1. khim
                            03.07.2016 22:19

                            Можно программу написать так, чтоб она была понятной, а можно и запутать так, что нихрена не разберешься даже с поллитрой.
                            Да, конечно. Но как тут уже говорилось: для того, чтобы реализовывать реально сложные алгоритмы требуются реально сложные же и языки программирования. А FBD… торетически на нём можно реализовать всё, что угодно, а практически — максимальная сложность алгоритов, которые прямо на нём можно реально реализовать катастрофически низка.
                            Специфика АСУ ТП. Работает объект, управляемый контроллером с такой вот программой. Там все приемосдаточные испытания проведены, протоколы подписаны и т.д. И никто не даст вам лезть и что то сильно менять. Только маленький кусочек или вообще несколько констант. Т.е. любое форматирование того что есть исключено.
                            Да уж. Напомнило историю с Google Maps. Её лет 10 назад представители BMW хотели получить к себе в авто. Пришли с примерно такими же требованиями: вы нам типа — передайте исходники, мы их три года будем тестировать, а потом только в машину поставим. Каждое изменение — через новую сертификацию. Их с этими идеями послали, после чего они ушли, полностью уверенные в своей правоте — ждать пока Гугл «прогнётся». Дождались того, что их поделием люди перестали пользоваться, их отдел сократили, а люди таки пользуются Google Maps.

                            Вы уж меня извините, но FBD — это тупик. Задачи, жёстко завязанные на безопасность (какое-нибудь аварийное отключение атомного реатора) лучше всего делать вообще без всякого ПО (простейшая аппаратная схема), но их, в общем, не так много — а задачи где использовать программного управления позволяет что-то выгадать рано или поздно перерастут сложность того, что комфортно реализуется на FBD.

                            P.S. В Tesla S обновление прошивки — уже штатная операция, случающаяся регулярно. И меняются там далеко не «несколько констант».


                            1. OPCSenator
                              04.07.2016 10:30

                              Но как тут уже говорилось: для того, чтобы реализовывать реально сложные алгоритмы требуются реально сложные же и языки программирования.

                              Ну так МЭК 61131 описывает пять языков. Выбирайте тот, что вам по вкусу.
                              И еще раз повторюсь — сложные алгоритмы и красивая их реализация на чем-нибудь хитровывернутом это хорошо. Вот только обратной стороной медали является полное закрытие технологической программы от эксплуатации из-за высокого порога вхождения. Что полностью убьет конкурентноспособность вашего изделия. Хотя никто не запрещает писать на том же ST.
                              Да уж.

                              Да не вопрос. Хотите менять алгоритмы и переделывать программы на объекте — пожалуйста. Только перед этим бумагу подпишите, что принимаете на себя все риски, связанные с ошибками в программе (причем не только в той части, которую будете править, т.к. сложно разделить единый технологически связанный объект на куски). И вперед. Вот только готова ли будет ваша компания пойти на это?
                              Задачи, жёстко завязанные на безопасность (какое-нибудь аварийное отключение атомного реатора) лучше всего делать вообще без всякого ПО (простейшая аппаратная схема)

                              Звучит как призыв: «Вперед в прошлое!». От релейных схем все уходят. Аппаратные защиты в ответственных узлах уже не используются. Все перенесено на микроконтроллеры. Причем эта тенденция наблюдается во всем мире.


                    1. Serge78rus
                      03.07.2016 12:16

                      Насчет генератора программ — тоже не все так хорошо, а точнее совсем плохо, во всяком случае у Siemens STEP7. В свое время тоже пошел по этому пути: у Сименса имеется возможность импорта/экспорта в текст и само собой напрашивалось сгенерировать исходники своими средствами и подсунуть, но в базе данных проекта у них помимо программных блоков, хранятся еще и их зависимости. В итоге получилось следующее: проект, после N попыток, собирается без ошибок (10<N<100), при этом между попытками никаких правок не вносится, просто в ответ на ворох сообщений об ошибках повторно запускаем сборку и получаем уже ворох поменьше. Причем этот цирк в дальнейшем повторялся при любом малейшем изменении, даже внесенном штатными средствами. Повторюсь, что речь идет именно о Siemens, других подобных поделок не пробовал, но не думаю что там все шоколадно.


  1. khim
    01.07.2016 16:59
    +3

    Забавно. А фраза «язык FBD это простой и понятный язык» — это сарказм или нет?

    Так-то всё напоминает историю Начал в которых Ньютон тщательно избавлялся от «флюксий», чтобы книга стала «понятнее», а в результате добился того, что современному читателю через неё продраться почти нереально.

    Вот лично для меня программа на C — вполне понятна, более-менее логична (не без косяков, конечно, ну да ладно — автор сам сказал, что он не спец в C) и, в общем, вопросов при её чтении особо не возникает. А программа на FBD вызывает острое ощущение забивания гвоздей микроскопами.


    1. Rastishka
      01.07.2016 17:21

      А фраза «язык FBD это простой и понятный язык» — это сарказм или нет?

      Учитывая что статья в хабе "Ненормальное программирование" — все же сарказм.


    1. OPCSenator
      01.07.2016 17:36

      «Забавно. А фраза «язык FBD это простой и понятный язык» — это сарказм или нет?»

      В каждой фразе есть доля сарказма. Но тут его немного.

      Я в следующем посте, когда сойдутся звезды, желание и свободное время, попробую сделать одну и ту же программу на FBD и ST. И можно будет сравнить, что проще. Хотя подозреваю, что любое мнение тут будет субъективным.


  1. rerf2010rerf
    10.11.2016 16:34
    +5

    Да да, и всё это, конечно, сидя «несколько дней» дней на диване, и почитав по теме несколько научно-популярных статеек, судя по уровню владения материалом у автора. Конечно, именно так и делаются великие научные открытия.


    1. OPCSenator
      01.07.2016 20:20

      Приложение для программирования контроллеров в ПТК «Квинт 7». Там внизу тег стоит «Квинт».


  1. gasizdat
    02.07.2016 00:35

    Все-таки программа написана на С++, в Си нет bool, namespace, using и т.п.


    1. OPCSenator
      02.07.2016 12:25

      Ну т.к. я вообще в этом не разбираюсь, то гуглил нужные мне функции. В итоге получилась мешанина из функций С и С++.


    1. OPCSenator
      02.07.2016 13:03

      Почему то не могу отредактировать свой коммент.
      В общем т.к. ничего от объектно ориентированного программирования в тексте нет, то как то совестно было говорить о плюсах :D


      1. storoj
        03.07.2016 16:34

        есть как минимум cout <<


  1. A1one
    02.07.2016 12:23
    +1

    Позволю маленький нюанс, связанный с правилами игры :)
    В оригинальных, «теплых, ламповых» пятнашках можно за один ход перемещать более одной кости, если в конце ряда есть пустышка.
    Здесь, как я посмотрю, этот момент не учтен?


    1. OPCSenator
      02.07.2016 12:34

      Да. Вы правы. Упустил этот момент из вида. (а я думал что эти квадратики и описание к ним вообще никто не смотрит :) )

      В принципе эта функция реализуется легко. Если с минимальными переделками, то нужно на каждую клетку заводить не только ближайших соседей, но и весь ряд вообще. И при клике на клетку просматривать весь ряд и каскадом сдвигать по очереди все (в пределе 3) плитки.

      Т.к. функция уже займет не 2 цикла как сейчас, а шесть, придется еще наружу блокировку вывести, чтобы подстраховаться от наложения команд.

      В целом же алгоритм не изменится.