Если я напишу 2, потом 4, потом 6, тогда мы почувствуем себя хорошо, потому что мы знаем, что дальше идет 8. Мы можем это предвидеть, мы не в руках судьбы. Однако, к сожалению, это не имеет ничего общего с истиной…
х/ф «Оксфордские убийства»
Задача: обнаружить центральную фигуру среди сереньких фигур вокруг.
Данный проект — PsyMatchArea — задумывался в качестве альтернативы знаменитым таблицам Шульте. С теми же целями (тренировка зрительного периферического внимания), но с другими, более «отмороженными» исходными предпосылками. Во-первых, нужно было уйти от цифр и букв — символов, знакомых каждому практически с яслей и потому распознаваемых на автомате без активного вовлечения сознания в процесс. Во-вторых, чтобы внимание как можно меньше подменялось памятью (и вообще не расслаблялось), надо было обеспечить соответствующие «помехи» — смена позиций, мерцания, наложения и т.п.
Самым, наверное, интересным с точки зрения программирования было создать алгоритм, который бы выдавал достаточно разнообразное множество абстрактных символов того или иного типа. Например, символы типа «руна» выращиваются следующим образом: алгоритму на входе предлагается сгенерировать в узловой матрице 3 x 3 пять последовательных соединений с некоторыми топологическими «принуждениями» (ограничение на количество пересечений и повышенная вероятность зацепа всех сторон периметра матрицы). Если в течение определённого количества попыток алгоритм заходит в тупик, он проявляет «толерантность» и пропускает к выходу последний тупиковый вариант (как говорится, что выросло, то выросло).
void CRunePattern::genSolidLink(int linkCount, int crossesCount) { if (this->isEmpty()) return; int broadCharge = 5; while (broadCharge) { m_links.clear(); QVector <int> dots; int currDot = qrand()%(m_cols*m_rows); for (int i = 0; i < linkCount; ++i) { dots.append(currDot); int crossCharge = 5; while (crossCharge) { int nextDotCharge = 5; int nextDot = qrand()%(m_cols*m_rows); while (nextDotCharge && dots.contains(nextDot)) { nextDot = qrand()%(m_cols*m_rows); nextDotCharge --; } if (nextDotCharge) { CDotLink newLink = CDotLink(currDot, nextDot); if (this->hasCrossLink(newLink)) { if (crossesCount) { crossesCount --; } else { // find another link that is'nt crosses with others crossCharge --; continue; } } m_links.append(newLink); currDot = nextDot; } break; } } int maxRow = -1; int minRow = m_rows; int maxCol = -1; int minCol = m_rows; for (int d = 0; d < dots.count(); ++d) { if (rowByDot(dots.at(d)) < minRow) minRow = rowByDot(dots.at(d)); if (rowByDot(dots.at(d)) > maxRow) maxRow = rowByDot(dots.at(d)); if (colByDot(dots.at(d)) < minCol) minCol = colByDot(dots.at(d)); if (colByDot(dots.at(d)) > maxCol) maxCol = colByDot(dots.at(d)); } if (minCol == 0 && minRow == 0 && maxRow == m_rows - 1 && maxCol == m_cols - 1) break; broadCharge --; continue; } }
На данный момент программа способна генерировать знаки нескольких типов:
Так же были реализованы следующие помехи:
- Swap interference — перетасовка фигур
- Hide center pattern — исчезновение центральной фигуры
- Thrill interference — дребезжание фигур
- Color interference — цветовое мерцание (гирлянда)
- Cover interference — концентрические окружности
Кроме того, предусмотрена возможность включения подсказки — Tip Settings (искомая фигура «подсвечивается» через указанное время).
После прохождения таблицы показывается статистика. По горизонтали угадывания, по вертикали время. Зелёный цвет — правильный ответ, красный — неверный, жёлтый — была подсказка.
Пара методических замечаний. Не стоит искать фигуру, разбрасывая взгляд во всех направлениях — это, во-первых, быстро вымотает и, во-вторых, ничего не даст в плане развития фонового внимания. Желательно расслабиться и рассредоточить локус зрительного внимания по всему окну, держа «в уме» искомую фигуру.
Исходный код на GitHub (Qt 4.8)
Сборка под Win32
ссылка на оригинал статьи https://habrahabr.ru/post/277049/
Добавить комментарий