Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Программа для создания кроссвордов
Форум на CrossPlatform.RU > Курилка > Софт и утилиты
xwicked


Здравствуйте! Есть одна программа для создания кроссвордов. Она состоит из двух частей: создание и отгадывание.

Прошу её код хорошо покритиковать. Для остальных, чтобы могли посмотреть на её работу, дам ссылки на бинарники 32-бит: создание, отгадывание. Qt-4.5.3.

Проекты OpenSource под GPLv2. Ссылки на SourceForge.net - создание, отгадывание.
Это мой первый код на C++(Qt). Жду комментариев :)

Добавлю небольшое описание: Сетка кроссворда представлена обычной таблицей TableCrosswordEdit(QTableWidget), слова загружаются в список слов ListWord(QStringList), толкования(вопросы) находятся в списке вопросов ListQuestions(QListWidget).

Структура файла - динамическая. Когда писал программы на Delphi - использовал статику - расходовалось лишнее дисковое пространство .
XWC: Пароль, количество строк, количество столбцов, ширина(высота) ячейки таблицы, шрифт, структура таблицы(w + 1(x) - белая ячейка, b + 1( c ) - чёрная), строка с данными CrosswordData(QString).
      ... if(file.open(QIODevice::WriteOnly))
                         {
                             QBrush BrushBlack = QBrush(Qt::black, Qt::SolidPattern);
                             QDataStream sfile(&file);
                             QChar sdata;
                             ushort idata;
      
                                 if(State == false) sfile << strPassword;
      
                             sfile << TableCrosswordEdit->rowCount();
                             sfile << TableCrosswordEdit->columnCount();
                             sfile << TableCrosswordEdit->rowHeight(0);
                             sfile << TableCrosswordEdit->font();
      
                                 for(int i = 0; i < TableCrosswordEdit->rowCount(); i++)
                                     for(int j = 0; j < TableCrosswordEdit->columnCount(); j++)
                                         {
                                                 if(TableCrosswordEdit->item(i,j)->background() == BrushBlack)
                                                     {
                                                         sdata = 'b';
                                                         idata = sdata.unicode() + 1;
                                                         sfile << idata;
                                                     }
                                                 else
                                                     {
                                                         sdata = 'w';
                                                         idata = sdata.unicode() + 1;
                                                         sfile << idata;
                                                     }
      
                                             sdata = 0;
                                         }
      
                                 if(State == false) CrosswordToData(2);
                                 if(State == false) sfile << CrosswordData;
      
                             file.close();
      
                                 if(State == false) SaveStateCross = true;
                                 else SaveStateTemplate = true;
                         } ...

CrosswordData: цикл по количеству слов(q, QChar(номер слова), QChar(координата строки в сетке), QChar(координата столбца в сетке), направление слова в сетке), цикл по количеству слов(W, QChar(номер слова), QChar(длина слова), само слово), цикл по количеству вопросов(Q, QChar(номер вопроса), QChar(длина вопроса), сам вопрос).
      ...
                             for(int i = 0; i < ListWord.count(); i++)
                                 {
                                     CrosswordData.append(QChar('W'));
                                     CrosswordData.append(QChar(ushort(i)));
                                     CurrentString.clear();
                                     CurrentString.append(ListWord.at(i));
                                     CrosswordData.append(QChar(ushort(CurrentString.length())));
                                     CrosswordData.append(ListWord.at(i));
                                 }
      
                             for(int i = 0; i < ListQuestions->count(); i++)
                                 {
                                     CrosswordData.append(QChar('Q'));
                                     CrosswordData.append(QChar(ushort(i)));
                                     CrosswordData.append(QChar(ushort(ListQuestions->item(i)->text().length())));
                                     CrosswordData.append(ListQuestions->item(i)->text());
                                 } ...

Шаблон кроссворда(XWTPL) таже структура, но без пароля и без CrosswordData.

Состояние сохранения(tmpcross): цикл по количеству слов(W, QChar(номер слова), QChar(длина слова), само слово).
ViGOur
у нас на сайте, есть раздел исходники, можешь добавить туда. ;)
нцужно просто зайти залогинившись на форуме на сам crossplatform.ru и все увидишь.
xwicked
Цитата(ViGOur @ 2.8.2011, 16:43) *
у нас на сайте, есть раздел исходники, можешь добавить туда. ;)
нцужно просто зайти залогинившись на форуме на сам crossplatform.ru и все увидишь.

Благодарю! Увидел - добавлю :)
xwicked
Продолжаем знакомиться с исходником. Профессиональный кроссворд, версии 0.1.4 - это объединение двух предыдущих: создателя и отгадывателя, с последующей доработкой.
Изменения:
- Добавлена возможность автоматического создания сетки кроссворда(бета-версия).
- Добавлена возможность автоматического составления кроссворда(выбор слов из словаря). Первая бета-версия.
- Присутствуют обе возможности(создание и отгадывыание).

Отмечу, что выбор слов происходит в один проход и могут быть пропуски слов в сетке, после составления кроссворда.

Исходный код + сборки(0.1.4) Отдельный проект на SourceForge.net - Клёст-кроссворд

В Клёст-кроссворде нет возможности сохранять пароль, в то время как в Crossword editor эта возможность есть. Проекты были разделены для большего удобства разработки.

P.S. Профессиональный кроссворд 0.1.7 = Клёст-кроссворд 0.1.7 :)
xwicked
Следующая версия программы - 0.1.5. Исходный код + сборки.

Изменилась функция составления кроссворда, которая теперь позволяет заполнить всю сетку кроссворда словами.
registr
Попробуй рассказать об игре на http://www.gamedev.ru/projects/forum/ Будет дополнительная реклама и возможно какие-нибудь советы и пожелания. Ну и удачи с проектом :)
xwicked
Цитата(registr @ 7.8.2011, 12:26) *
Попробуй рассказать об игре на http://www.gamedev.ru/projects/forum/ Будет дополнительная реклама и возможно какие-нибудь советы и пожелания. Ну и удачи с проектом :)
Благодарю, посмотрю.
-------------------------------------
В новой версии 0.1.6 - исходник + сборки, добавлен экспорт кроссворда в изображения следующих растровых графических форматов: JPG, JPEG, BMP, TIFF, PNG, XPM, XBM, PPM + несколько других исправлений.
xwicked
А вот и новая версия 0.1.7. Изучаем исходный код + сборки.

Что изменено:
Цитата
- Временное название "Профессиональный кроссворд" изменено на "Клёст-кроссворд".
- При вводе слова в кроссворд, производится проверка на количество введённых букв в поле "Введите слово".
- В свойствах таблицы кроссворда отключена возможность ввода букв, непосредственно в ячейку, минуя поле "Введите слово".
- Изменены цветовые стили некоторых компонентов.
- В строку состояния добавлен компонент, отображающий количество букв.
- Добавлена проверка состояния сохранения изменений, произведённые в кроссворде, при выходе, используя меню "Кроссворд->Выход".
xwicked
Если у кого-нибудь будет желание свою изменённую версию кроссворда далее распространять, то для этой цели я подготовил спекфайл для сборки программы в дистрибутиве ОС Linux, основанного на RPM-пакетах.
Также прошу найти в нём ошибки:
Цитата
Summary: Qt program for professional creating and easy guessing the classic crossword puzzles.

Summary(ru): Qt программа для профессионального создания редактирования и лёгкого отгадывания классических кроссвордов

%define version 0.1.7

Group: Games/Puzzles

Name: klest-crossword

BuildRequires: gcc-c++, libqt4-sql-sqlite >= 4.4.3, libqtgui4 >= 4.4.3, libqt4-core >= 4.4.3

BuildArch: %ix86

Provides: klest-crossword

Release: alt1

Source: klest-crossword-%{version}.tar.gz

Url: http://labfreetech.org/index_e.html

Version: %{version}

License: GPLv2

Packager: LabFreeTech.org admin@labfreetech.org

%description
Qt program for creating and guessing the classic crossword puzzles.
Supported features: - Create a crossword puzzle; - Editing a crossword puzzle; - Guessing crossword puzzle; - Check correctness of guessing a crossword puzzle; - Save state incompletely guessed crossword puzzle; - Automatic creation of crossword puzzle grid (beta) - Automatic selection of words from the dictionary (Beta 2); - Adding / removing words from the dictionary; - Conservation created a crossword puzzle grid, as a template for the new; - Editing the font crossword; - Editing the size of the grid cell crossword puzzle; - Export crossword in the image.

%description -l ru
Qt программа для профессионального создания редактирования и лёгкого отгадывания классических кроссвордов
Поддерживаемые функции: - Создание кроссворда; - Редактирование кроссворда; - Отгадывание кроссворда; - Проверка правильности отгадывания кроссворда; - Сохранение состояния неполностью отгаданного кроссворда; - Автоматическое создание сетки кроссворда(бета); - Автоматический выбор слов из словаря(бета 2); - Добавление/удаление слов из словаря; - Сохранение созданной сетки кроссворда, как шаблон для нового; - Редактирование шрифта кроссворда; - Редактирование размера ячейки сетки кроссворда; - Экспорт кроссворда в изображение.

%prep

%setup -q

%build
%make_build

%install

cp -Rv klest/ %buildroot/
%clean

rm -rf $RPM_BUILD_ROOT

%files

/usr/games/*
/usr/share/*

%post

test -e /usr/bin/klest-crossword-0.1.7 || ln -s /usr/games/klest-crossword-0.1.7 /usr/bin/klest-crossword-0.1.7
test -e $HOME/Desktop/klest-crossword.desktop || cp -r /usr/share/applications/klest-crossword.desktop $HOME/Desktop/klest-crossword.desktop

%postun

test -L /usr/bin/klest-crossword-0.1.7 && rm -r /usr/bin/klest-crossword-0.1.7
test -e $HOME/Desktop/klest-crossword.desktop && rm -r $HOME/Desktop/klest-crossword.desktop
Специальный архив версии 0.1.7.
Устанавливаем дополнительный пакет rpm-build и собираем командой в консоли:
Цитата
$rpmbuild -bb /home/username/RPM/SPECS/klest-crossword-0.1.7-alt.spec
xwicked
Продолжение: 0.1.8. Исходник + сборки.

Изменения:
Цитата
- Изменился алгоритм выбора слов из словаря(бета 3), с небольшой оптимизацией;
- Исправлена ошибка при экспорте кроссворда в изображение;
- Изменилось автоматическое переключение между направлением слов, на ручное - щелчком правой кнопки мыши.
xwicked
Здравствуйте!

Хочу порадовать Вас тем, что я сделал дополнительный архив исходного кода, для сборки программы в ОС GNU / Linux Debian( / Ubuntu).
Для сборки deb-пакета необходимо наличие установленных пакетов: autotools-dev, dh-make, fakeroot, cdbs, dpkg, dpkg-dev и другие.
Команда сборки:
Цитата
user@pc:/klest-crossword-0.1.9-deb$ dpkg-buildpackage -rfakeroot

Для проверки правильности соответствия стандартам дистрибутива Debian, используйте пакет Lintian.
0.1.9. Исходный код + сборки

Что нового:
Цитата
- Исправлена фатальная ошибка, возникающая при отсутствии словаря.
- Исправлена фатальная ошибка, возникающая когда заканчиваются слова в словаре.
- Добавлена возможность несимметричного ручного редактирования сетки кроссворда.
- Изменён режим работы программы по умолчанию на режим просмотра.
xwicked
Следующая версия = 0.2.0.

Исходный код + сборки: 0.2.0.

Важное изменение: добавление значков Oxygen. Ещё добавлены 2-а новых словаря: русский на 31 000 слов и английский на 41 000 слов. Теперь программа выглядит вот так -


Произведённые изменения:
Цитата
- Добавлены значки "Oxygen", распространяемые по лицензии GNU GPL;
- Исправлена ошибка экспорта кроссворда в изображение форматов JPG, JPEG, TIFF;
- Добавлена возможность выбора словаря для составления кроссворда. Возможные варианты: русский и английский;
- Изменена стандартная панель - добавлены несколько новых действий, исправлены ошибки;
- Изменён формат файла свойств программы, в сторону более простого добавления в него будущих свойств.
Алексей1153
xwicked,

Цитата
Структура файла - динамическая.


Цитата
Изменён формат файла свойств программы, в сторону более простого добавления в него будущих свойств.


я, даже не уточняя формат файла, сразу советую перейти к XML ;) Если, конечно, уже не. Поверь, в случае использования XML процитированный тект не имеет смысла упоминать вообще.
xwicked
Цитата(Алексей1153 @ 23.8.2011, 7:36) *
...я, даже не уточняя формат файла, сразу советую перейти к XML ;) Если, конечно, уже не. Поверь, в случае использования XML процитированный тект не имеет смысла упоминать вообще.
Все форматы файлов двоичные. От XML я отказался и в будущем не буду его использовать вообще.
Аргументы:
1. Громоздкость самого формата;
2. Переносимость моего двоичного формата созданных файлов;
3. Увеличение размера Win и Mac сборок программы, за счёт добавления лишней библиотеки.
Думаю достаточно ;)
Алексей1153
xwicked, громоздкость ? Да ерунда. Имена неосновных узлов можно задавать покороче. Всё остальное хорошо сожмётся архиватором

Минусы двоичных форматов:
1. громоздкость самого формата. Давай, сохрани туда вектор или мапу :) Опупеешь.
2. Непереносимость и трудность переходов между версиями. Байт влево , байт вправо - расстрел на месте. Также нужно постоянно помнить и трястись над тем, чтобы (см п1) содержимое структур можно было бы побайтово копировать, а также чтобы не менялся порядок сохранения данных
3. за счёт чего увеличение ? Например, я сохраняю XML "вручную" (мне так показалось удобнее), а парсю готовым классом с открытыми исходниками. Ну добавит это всё от силы пару килобайт в модуль.

ЗАТО

- забудешь про пункт 2
- экономия кучи нервов и времени
- вложенность: можно для каждого класса определить функцию, которая дописывает в поток кусочек с XML-узлом класса.
- отладка. Попробуешь - поймёшь. Видно визуально, правится прямо в студии (ну это я про себя - у меня студия), она и UTF8 понимает, и форматирование расставит.
- непринуждённая расширяемость. Добавляй, что хочешь, удаляй, что хочешь.

лично я раньше сохранял в двоичные файлы, но когда узнал про XML - теперь никогда такой хренью не страдаю )))

xwicked, ох, а как весело поддерживать программы, где программист вовсю сохранял структурированные данные в двоичные файлы... Я вот сейчас такой проект веду. Как внезапно начинало рушиться - а поразбираешься, вот она, причина. Поменял местами переменные в структуре, а он, гат такой, в двоичные файлы любит записывать, в результате записывается указатель (и читается тоже). Не поленился, потратил два дня на переделывание в XML - теперь полёт нормальный )

Ещё один интересный момент: как думаешь, что сохранится в файл, если запишешь туда переменную типа B ?

Раскрывающийся текст
struct A
{
    int a;

    A():a(0x00)
    {
    }

    A(int a):a(a)
    {
    }

    virtual ~A()
    {
    }
};

struct B:A
{
    A a2;
    int b;

    B():a2(0x11),b(0x22)
    {
    }
};


B b;
int i=sizeof(b); //сколько ?
void* p=&b;      //что там ?
Litkevich Yuriy
Цитата(Алексей1153 @ 23.8.2011, 12:03) *
1. громоздкость самого формата. Давай, сохрани туда вектор или мапу
это элементарно, по сравнению с XML
Цитата(Алексей1153 @ 23.8.2011, 12:03) *
Непереносимость и трудность переходов между версиями. Байт влево , байт вправо - расстрел на месте.
это смотря как опишешь формат.

Цитата(Алексей1153 @ 23.8.2011, 12:03) *
Ещё один интересный момент: как думаешь, что сохранится в файл, если запишешь туда переменную типа B ?
приведи тотже пример только с XML
Алексей1153
Цитата
это элементарно, по сравнению с XML

сравнимо. Плюс в дальнейшей совместимости и поддержке, а также в человекочитаемости контента

Цитата
это смотря как опишешь формат.


в том и прелесть, что в XML не надо думать, как был описан формат. Главное - не упадёт ничего

Цитата
приведи тотже пример только с XML


не понял вопроса
xwicked
Цитата(Алексей1153 @ 23.8.2011, 10:03) *
xwicked, громоздкость ? Да ерунда. Имена неосновных узлов можно задавать покороче. Всё остальное хорошо сожмётся архиватором

Минусы двоичных форматов:
1. громоздкость самого формата. Давай, сохрани туда вектор или мапу :) Опупеешь.
2. Непереносимость и трудность переходов между версиями. Байт влево , байт вправо - расстрел на месте. Также нужно постоянно помнить и трястись над тем, чтобы (см п1) содержимое структур можно было бы побайтово копировать, а также чтобы не менялся порядок сохранения данных
3. за счёт чего увеличение ? Например, я сохраняю XML "вручную" (мне так показалось удобнее), а парсю готовым классом с открытыми исходниками. Ну добавит это всё от силы пару килобайт в модуль. ...
Вы немножко не осведомлены в вопросе даваемого Вами совета:
1
Цитата
# Размер XML-документа существенно больше бинарного представления тех же данных. В грубых оценках величину этого фактора принимают за 1 порядок (в 10 раз).
# Размер XML-документа существенно больше, чем документа в альтернативных текстовых форматах передачи данных (например JSON[4], YAML, Protocol Buffers) и особенно в форматах данных, оптимизированных для конкретного случая использования.
# Избыточность XML может повлиять на эффективность приложения. Возрастает стоимость хранения, обработки и передачи данных.
# XML содержит метаданные (об именах полей, классов, вложенности структур), и одновременно XML позиционируется как язык взаимодействия открытых систем. При передаче между системами большого количества объектов одного типа (одной структуры), передавать метаданные повторно нет смысла, хотя они содержатся в каждом экземпляре XML описания.
# Для большого количества задач не нужна вся мощь синтаксиса XML и можно использовать значительно более простые и производительные решения.

Ссылка на Википедию. Не привожу статьи из журналов, где многие думают о пересмотре стандарта XML и как от него отказываются.
2. Это если речь идёт о структурах и о стандартном C++. Я же сохраняю типы QStringList, QFont и подобные, их сможет загрузить только Qt, который изначально переносимый.
3. Вручную это делать глупо, когда есть интерфейсы DOM и SAX. Увеличение за счёт добавление библиотеки QtXml + библиотека для сжатия этого XML.

ЗЫ: Всё просто :)
Алексей1153
xwicked, я прекрасно осведомлён о содержимом и устройстве простейшего XML, который использую очень часто :)

Я не навязываю. К этому сам потом придёшь, когда будешь зарабатывать на жизнь программированием. XML против бинарников - это экономия сил, времени и , соответственно, денег. Я советую именно потому, что всё это прошёл и знаю разницу. Есть выбор:
1) бинарник + малый объём + много гемора при отладке и совместимости версий
2) XML + чуть побольше объём + удобная отладка, поддержка и совместимость


А рост объёма сейчас мало кого волнует - ресурсы машин растут несоизмеримо быстрее.

Цитата
# Размер XML-документа существенно больше бинарного представления тех же данных. В грубых оценках величину этого фактора принимают за 1 порядок (в 10 раз).
# Размер XML-документа существенно больше, чем документа в альтернативных текстовых форматах передачи данных (например JSON[4], YAML, Protocol Buffers) и особенно в форматах данных, оптимизированных для конкретного случая использования.
# Избыточность XML может повлиять на эффективность приложения. Возрастает стоимость хранения, обработки и передачи данных.
# XML содержит метаданные (об именах полей, классов, вложенности структур), и одновременно XML позиционируется как язык взаимодействия открытых систем. При передаче между системами большого количества объектов одного типа (одной структуры), передавать метаданные повторно нет смысла, хотя они содержатся в каждом экземпляре XML описания.
# Для большого количества задач не нужна вся мощь синтаксиса XML и можно использовать значительно более простые и производительные решения.

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

Цитата
Вручную это делать глупо

зато эффективно и не делает
Цитата
3. Увеличение размера Win и Mac сборок программы, за счёт добавления лишней библиотеки.


;)


В общем-то , не хотел "зафлуживать" тему , я дал совет - тебе решать. Я думал, плюсы и так очевидны

xwicked, но всёж-таки, интересно, каков у тебя ответ на вопрос

Цитата
B b;
int i=sizeof(B ); //сколько ?
void* p=&b; //что там ?


и какова будет реакция деструктора переменной при попытке считывания из файла :)
xwicked
Цитата(Алексей1153 @ 23.8.2011, 12:08) *
... когда будешь зарабатывать на жизнь программированием. ...
У меня нет СМИ на подхвате, как у Попова, вопреки светофору - всё будет у меня отлично!!! :)

ЗЫ: Осторожно, толстый юмор(продолжение)! :lol:
Алексей1153
xwicked, осторожно! Кроссворды тебя погубят :D
xwicked
Программа доведена до стабильности. Релиз 0.2.1. Исходник + сборки.

Все изменения:
Цитата
- Исправлена фатальная ошибка, возникающая при повторном автоматическом выборе слов, после автоматического создания сетки;
- Исправлена ошибка алгоритма выбора слов из словаря;
- Исправлена ошибка автоматической вставки слов в сетку кроссворда;
- Исправлена ошибка неправильного ввода слова в сетку кроссворда, при повторных нажатиях на кнопку "ОК";
- Исправлена ошибка экспорта в изображения, при ручном создании кроссворда;
- Исправлена ошибка передачи текущего шрифта в диалог выбора шрифта, при его открытии;
- Оптимизирован алгоритм автоматического создания сетки кроссворда;
- Оптимизирован алгоритм автоматического выбора слов из словаря;
- Оптимизированы алгоритмы: создания, изменения, сохранения, открытия, закрытия кроссворда;
- Изменён формат файла кроссворда и формат файла сохранения состояния неполностью отгаданного кроссворда;
- Для повышения интереса к игровому процессу, после проверки правильности отгадывания, кроссворд закрывается.
xwicked
А в новой версии 0.2.2 я реализовал импорт кроссворда из текстового формата AcrossLite первой версии. Вторая версия будет загружаться, но за исключением дополнительной головоломки.

Что нового:
Цитата
- Появилась возможность импортировать кроссворд, из текстового формата AcrossLite;
- Исправлена фатальная ошибка, не позволяющая создавать кроссворды больше чем 18х18;
- В меню "Помощь" добавились пункты: "Пожертвовать" и "Получить исходный код";
- Сохранение состояния неполностью отгаданного кроссворда AcrossLite(TXT) имеет своё расширение, при оставленной той же структуре файла;
- В окне о программе все ссылки изменили свой цвет на синий, для удобства поиска;
- Появилась возможность вводить слово в сетку кроссворда, нажатием на клавишу "Ввод".
Дабы быть уверенным в том, что файлы не побились, при закачке, я добавил текстовик с md5-контрольными суммами.
Git-репозиторий:
Цитата
git://klest-crossword.git.sourceforge.net/gitroot/klest-crossword/klest-crossword (read-only)
xwicked
Здравствуйте!
Цитата
- Добавлена возможность полуавтоматического ввода слов из словаря;
- Добавлена возможность печати кроссворда;
- Добавлены горячие клавишы;
- Увеличен максимальный размер кроссворда до 999х999х999(столбцы/строки/размер ячейки);
- Во избежании ошибки, теперь после отмены выбора слов нельзя сделать экспорт в изображение;
- После отладки, возвращено автоматическое определение направления слов при выделении, убранное в версии 0.1.8;
- Добавлена возможность ввода имени игрока;
- Добавлена статистика;
- Исправлена ошибка неисчезновения пунктов меню автоматизации, в режиме просмотра;
- Исправлена ошибка, при ручном вводе слов в кроссворд;
- Добавлен пункт меню "Получить техподдержку";
- Некоторые окна теперь не разворачиваются на весь экран по-умолчанию. Изменились также размеры нескольких окон.
В новой версии 0.2.7 Появилась возможность печати кроссворда. Хочу обратить особое внимание на тестирование этой функции, так как у меня дома нету принтера. Очень интересно, как ведёт себя печать на разных принтерах под всеми ОС.
Полуавтоматический ввод слов позволит создавать тематические кроссворды и задавать различную сложность, при составлении.

P.S. Ещё один очень важный момент: версии 0.2.7, 0.2.8 - сборки являются минимальными. То есть, чтобы посмотреть на все функции, необходимо программу собрать из исходника . Это делалось для проверки аудитории пользователей на заинтересованность в программе, путем отправки мне запроса на получение исходного кода. Что было не очень удачной идеей и, с версии 0.2.9, сборки программы уже снова полнофункциональны. Прошу извинить меня за данное неудобство :blink: .
xwicked
В версии 0.2.8 я добавил функции горизонтального и вертикального отражения кроссворда как изображения. Так же добавил инверсию цветов ячеек сетки кроссворда. Но... я не смог быстро придумать функцию обрезания сетки кроссворда, если он, например, получился меньше созданных рамок. Интересует самое простое решение данного вопроса. Благодарю!

Ещё изменения:
Цитата
- Добавлена возможность рисования сетки, как карандашом;
- Добавлена функция автоматического создания, сохранения и экспорта неограниченного числа кроссвордов из одного шаблона по нажатии одной клавиши, предварительно установив соотвествующие настройки;
- Добавлены функции очистки слов, сетки и всего кроссворда;
- Добавилось окно "Параметры";
- Выбор словаря перенесён в окно "Параметры";
- Добавлена возможность выбора папки, из которой будут показываться шаблоны, для последующего их использования;
- Добавлена возможность задания пути для экспортируемого изображения в окне "Параметры";
- Добавлена возможность задания папки для экспорта вопросов и ответов в окне "Параметры";
Алексей1153
Цитата
Но... я не смог быстро придумать функцию обрезания сетки кроссворда, если он, например, получился меньше созданных рамок.

две переменные для подсчёта максимальной использованной ширины и высоты

int xmax=0;
int ymax=0;

перебрать все слова и запоминать (вернее - обновлять эти переменные). По итогам станет ясно, какой размер прямоугольника кроссворда нужен
Sokoloff
Цитата(xwicked @ 8.11.2011, 2:39) *
Появилась возможность печати кроссворда. Хочу обратить особое внимание на тестирование этой функции, так как у меня дома нету принтера.

Для отладки печати под виндой можно использовать программу fineprint. Триальная версия добавляет строку внизу страницы, но для тестов это не существенно.
В линухе можно настроить виртуальный принтер печатающий в PostScript файл.
xwicked
Цитата(Sokoloff @ 29.11.2011, 12:05) *
... В линухе можно настроить виртуальный принтер печатающий в PostScript файл.
Благодарю! Я собственно говоря, так и делал. Без этой возможности печать вообще не появилась бы ;) Ну а если разница между печатью в файл и на физическом принтере нулевая, то я и дальше продолжу тестировать её таким же образом :)
xwicked
Следующая версия программы 0.2.9. В ней я походу вышел за предел стека :lol: Ошибку я уже нашёл.

Цитата
- Оптимизирован алгоритм выбора слов в 2,5 раза;
- Добавлена возможность экспорта кроссворда в файл, форматов: HTML, PDF, PostScript, текстовый формат AcrossLite, OpenKlest(*.ok);
- Добавлена возможность поворота кроссворда;
- Добавлена возможность автоматического создания и экспорта кроссворда в форматы HTML, PDF, PostScript, текстовый формат AcrossLite, OpenKlest(*.ok);
- Добавлена возможность импорта кроссворда в формате OpenKlest(*.ok);
Экспорт в PDF и PostScript осуществляется достаточно просто: подготавливается HTML-страница и распечатывается на принтере, но печать идёт не на физическое устройство а в файл :)
    QTextEdit textEdit;
    textEdit.setHtml(strHTML);
#ifndef QT_NO_PRINTER

    QPrinter printer(QPrinter::HighResolution);//Настройка принтера на  высокое качество
    printer.setOutputFormat(QPrinter::PostScriptFormat);//Выбор печати в файл PostScript
    printer.setOutputFileName(sExportName);//Присваивание имени файла
    textEdit.document()->print(&printer);//Сама печать

#endif
Хотелось бы отметить, что с появлением функции экспорта кроссворда в Across Lite TXT, у программы across lite 2.0 появилась возможность отгадывать не только американские кроссворды, но и классические, правда всё в английском языке. Можете поэксперементировать, ради интереса :rolleyes:
xwicked
Здравствуйте! Как я избавился от переполнения стека:
ushort usTable[50][50];//Массив сетки кроссворда
Если делал больше 50-ти, то отваливался импорт файла и запуск руководства пользователя :D
Изменил на:
ushort **usTable;//Массив сетки кроссворда
...
//Создание двумерного динамического массива
        usTable = new ushort*[TableKlestCrossword->rowCount()];

        for(int i = 0; i < TableKlestCrossword->rowCount(); i++)
            usTable[i] = new ushort[TableKlestCrossword->columnCount()];
Далее введены константы:
//Определение путей констант, в соответствии с системой
#if defined(Q_WS_WIN)

    #define PATH_TMP_SET QApplication::applicationDirPath() + "/settings.xwsc"
    #define PATH_SHARE_DOC QApplication::applicationDirPath()
    #define PATH_SHARE_APP QApplication::applicationDirPath()
    #define PATH_TMP_STAT QApplication::applicationDirPath() + "/cstat.html"


#elif defined(Q_WS_X11)

    #define PATH_TMP_SET "/tmp/klest-crossword-0.3.7/settings.xwsc"
    #define PATH_SHARE_DOC "/usr/share/doc/klest-crossword-0.3.7"
    #define PATH_SHARE_APP "/usr/share/klest-crossword-0.3.7"
    #define PATH_TMP_STAT "/tmp/klest-crossword-0.3.7/cstat.html"

#elif defined(Q_WS_MAC)

    #define PATH_TMP_SET QApplication::applicationDirPath() + "/settings.xwsc"
    #define PATH_SHARE_DOC QApplication::applicationDirPath()
    #define PATH_SHARE_APP QApplication::applicationDirPath()
    #define PATH_TMP_STAT QApplication::applicationDirPath() + "/cstat.html"


#endif

//Пути для разработки и отладки программы
/*#define PATH_TMP_SET QApplication::applicationDirPath() + "/settings.xwsc"
#define PATH_SHARE_DOC QApplication::applicationDirPath()
#define PATH_SHARE_APP QApplication::applicationDirPath()
#define PATH_TMP_STAT QApplication::applicationDirPath() + "/cstat.html"*/

#define MODE_VIEW true
#define MODE_EDIT false

#define ACROSS_ENABLE true
#define ACROSS_DISABLE false

#define LANGUAGE_RUSSIAN true
#define LANGUAGE_ENGLISH false

#define TOOLBAR_SHOW true
#define TOOLBAR_HIDE false

#define EXPORT_YES true
#define EXPORT_NO false

#define TYPE_PDF 0
#define TYPE_POST_SCRIPT 1
Что позволило пути в программе менять всего один раз :) Так же появилась возможность убрать лишние условия и оформить в switch:
        switch(iTypeExport)
        {
        case TYPE_PDF:
            sFilter = ".pdf";
            break;

        case TYPE_POST_SCRIPT:
            sFilter = ".ps";
            break;

        case TYPE_HTML:
            sFilter = ".html";
            break;

        case TYPE_TXT:
            sFilter = ".txt";
            break;

        case TYPE_JPG:
            sFilter = ".jpg";
            break;

        case TYPE_JPEG:
            sFilter = ".jpeg";
            break;

        case TYPE_BMP:
            sFilter = ".bmp";
            break;

        case TYPE_TIFF:
            sFilter = ".tiff";
            break;

        case TYPE_PNG:
            sFilter = ".png";
            break;

        case TYPE_XPM:
            sFilter = ".xpm";
            break;

        case TYPE_XBM:
            sFilter = ".xbm";
            break;

        case TYPE_PPM:
            sFilter = ".ppm";
            break;

        case TYPE_OPEN_KLEST:
            sFilter = ".ok";
            break;
        }
Введение структуры файла свойств:
//Структура файла свойств программы
struct TFileOptions
{
     bool bModeWork,//Режим работы программы
          bLanguageProgram,//Язык программы
          bStateStandardToolbar,//Состояние показа стандартной панели
          bStateExport,//Состояние экспортирования
          bCurrentDictionary;//Текущий словарь
     QString sModePassword,//Пароль режима
             sPathCrossword,//Путь для кроссвордов
             sPathExport,//Путь для экспорта
             sPathTemplate;//Путь для шаблонов
     int iNumberTimes,//Количество раз
         iTypeExport;//Тип экспорта
};
Скачать 0.3.7. На данный момент это последняя версия, прошу...
Алексей1153
можно немного встряну ))

предлагаю более ООП варианты:

с массивом лучше так
Раскрывающийся текст
//A - класс кроссвоода
#include <vector>
class A
{
   enum
   {
     e_W=50,
     e_H=50,
     e_init=0,
   };

   typedef ushort               td_elem;//тип элемента
   typedef std::vector<td_elem> td_row;//тип строки
   typedef std::vector<td_row>  td_table;//тип таблицы

   td_table m_usTable;

   A();
};


A::A()
:m_usTable(e_H,td_row(e_W,td_elem(e_init)))
{
}

//где-то в программе:
ushort current_row=4;
ushort current_col=7;
m_usTable[current_row][current_col]=td_elem('A');


по остальному - глобальные дефайны лучше объединять в класс

файл "mydefines.h"
Раскрывающийся текст
//Определение путей констант, в соответствии с системой
class mydefines
{
public:
    enum
    {
        MODE_VIEW        =true,
        MODE_EDIT        =false,

        ACROSS_ENABLE    =true,
        ACROSS_DISABLE   =false,

        LANGUAGE_RUSSIAN =true,
        LANGUAGE_ENGLISH =false,

        TOOLBAR_SHOW     =true,
        TOOLBAR_HIDE     =false,

        EXPORT_YES       =true,
        EXPORT_NO        =false,
    };

    enum ee_path_id
    {
        PATH_TMP_SET   ,
        PATH_SHARE_DOC ,
        PATH_SHARE_APP ,
        PATH_TMP_STAT  ,
    };

    enum ee_ext_id
    {
        TYPE_PDF         ,
        TYPE_POST_SCRIPT ,
        TYPE_HTML        ,
        TYPE_TXT         ,
        TYPE_JPG         ,
        TYPE_JPEG        ,
        TYPE_BMP         ,
        TYPE_TIFF        ,
        TYPE_PNG         ,
        TYPE_XPM         ,
        TYPE_XBM         ,
        TYPE_PPM         ,
        TYPE_OPEN_KLEST  ,
    };

    //Пути для разработки и отладки программы
    static QString GetPath(ee_path_id id);

    //расширение (без точки)
    static QString GetExt(ee_ext_id id);
};


файл "mydefines.cpp"
Раскрывающийся текст
#include <map>
QString mydefines::GetPath(ee_path_id id)
{
    typedef std::map<ee_path_id,QString> td_map;
    static td_map _map;

    if(_map.empty())
    {
        #if defined(Q_WS_WIN)
            _map[PATH_TMP_SET   ]=QApplication::applicationDirPath() + "/settings.xwsc";
            _map[PATH_SHARE_DOC ]=QApplication::applicationDirPath();
            _map[PATH_SHARE_APP ]=QApplication::applicationDirPath();
            _map[PATH_TMP_STAT  ]=QApplication::applicationDirPath() + "/cstat.html";
        #elif defined(Q_WS_X11)
            _map[PATH_TMP_SET   ]="/tmp/klest-crossword-0.3.7/settings.xwsc";
            _map[PATH_SHARE_DOC ]="/usr/share/doc/klest-crossword-0.3.7";
            _map[PATH_SHARE_APP ]="/usr/share/klest-crossword-0.3.7";
            _map[PATH_TMP_STAT  ]="/tmp/klest-crossword-0.3.7/cstat.html";
        #elif defined(Q_WS_MAC)
            _map[PATH_TMP_SET   ]=QApplication::applicationDirPath() + "/settings.xwsc";
            _map[PATH_SHARE_DOC ]=QApplication::applicationDirPath();
            _map[PATH_SHARE_APP ]=QApplication::applicationDirPath();
            _map[PATH_TMP_STAT  ]=QApplication::applicationDirPath() + "/cstat.html";
        #endif
    }

    td_map::const_iterator it=_map.find(id);
    if(it==_map.end())return "";
    return it->second;
}


QString mydefines::GetExt(ee_ext_id id)
{
    switch(id)
    {
        case TYPE_PDF         :return  "pdf";break;
        case TYPE_POST_SCRIPT :return  "ps" ;break;
        case TYPE_HTML        :return  "html";break;
        case TYPE_TXT         :return  "txt";break;
        case TYPE_JPG         :return  "jpg";break;
        case TYPE_JPEG        :return  "jpeg";break;
        case TYPE_BMP         :return  "bmp";break;
        case TYPE_TIFF        :return  "tiff";break;
        case TYPE_PNG         :return  "png";break;
        case TYPE_XPM         :return  "xpm";break;
        case TYPE_XBM         :return  "xbm";break;
        case TYPE_PPM         :return  "ppm";break;
        case TYPE_OPEN_KLEST  :return  "ok" ;break;
    }

    return "";
}


и где-то в прогремме:

QString filename=
    mydefines::GetPath(mydefines::PATH_SHARE_DOC)
    +"1234"
    +"."
    +mydefines::GetExt(mydefines::TYPE_BMP)
;



ну а по структуре TFileOptions - я уже говорил, что там не так
xwicked
Цитата(Алексей1153 @ 9.2.2012, 8:37) *
можно немного встряну ))

предлагаю более ООП варианты: ...
Благодарю, вариант enum ee_path_id, enum ee_ext_id я уже сам собирался так оформить. Насчёт остального мне пока квалификации не хватает, чтобы понять, где что :blink: Вчера прочитал главу про классы(C++) - потихоньку буду разбираться.
А такой вариант покатит, чтобы switch заменить?
char Test[13][6] = {".pdf",".ps",".html",".txt",".jpg",".jpeg",".bmp",".tiff",".png",".xpm",".xbm",".ppm",".ok"};  // подготовка
.....
sFilter = Test[iTypeExport];  // замена свитча
Алексей1153
>>Насчёт остального мне пока квалификации не хватает, чтобы понять, где что

задавай вопросы, расскажу, что там я сделал



Цитата(xwicked @ 9.2.2012, 18:34) *
А такой вариант покатит, чтобы switch заменить?

фиговый вариант :)

а функция GetPath тоже, наверное, лучше всё же через свич сделать, а не через мап. В данном случае.
xwicked
Цитата(Алексей1153 @ 9.2.2012, 20:52) *
...
фиговый вариант :) ...
Ну, в таком случае, я лучше сам буду разбираться и проверять качество советов. Просто этот совет со switch мне дали с другого форума. Извини, пока вопросов больше нет :)
Алексей1153
свич - это великолепная штука, когда нужно выбрать одину из циферных констант, сравнивая со значением тестируемой переменной (как в mydefines::GetExt )

работает быстро, так как компилятор строит табличную адресацию, а не перебор множества условий, как можно было бы подумать. То есть, практически вычисляется тот же индекс, по которому берётся адрес перехода для jmp , делается переход.
xwicked
Оптимизация констант:
enum eTypeCrossword {TYPE_PDF, TYPE_POST_SCRIPT, TYPE_RTF, TYPE_HTML, TYPE_TXT, TYPE_JPG, TYPE_JPEG, TYPE_BMP,
                    TYPE_TIFF, TYPE_PNG, TYPE_XPM, TYPE_XBM, TYPE_PPM, TYPE_OPEN_KLEST};
Экспорт в RTF вместе с изображением:
QString TCrosswordGrid::wordToUnicode(QString sWord)
{
    QString sTemp;

    for (int i = 0; i < sWord.length(); i++)
//Добавляет один символ Unicode, если этого не получается сделать, то отображается знак вопроса
        sTemp.append("\\u" + QString::number(sWord.at(i).unicode()) + "?");

    return sTemp;
}

//Формирование RTF-документа и сохранение
void TCrosswordGrid::saveToRTF(QString sExportName, QString strRTF, QImage imgExport)
{
    QByteArray baImage;
    QBuffer buffer(&baImage);
    buffer.open(QIODevice::WriteOnly);
    imgExport.save(&buffer, "BMP");//BMP как обязательный формат изображения
    baImage = baImage.toHex();//Побайтовое преобразование изображения в шестнадцатеричную форму
    QFile ifile(sExportName);
    QTextStream istream(&ifile);
    istream.setCodec("UTF-8");//UTF-8 кодировка документа
    ifile.open(QIODevice::WriteOnly);
//Добавление информации об изображении с сохранением изначального размера
    istream << "{\\rtf1\n{\\pict\\wmetafile8\\picw" + QString::number(columnCount() * rowHeight(0) * 27) + "\\pich"
            + QString::number(rowCount() * rowHeight(0) * 27) + "\n";
    
    int j = 0;

    for (int i = 0; i < baImage.size(); i++)
    {
        if (j == 128)//Если количество символов в строке == 128
        {
            istream << "\n";//То перевод строки; Избавляет от ошибок, при чтении документа.
            j = 0;
        }

        istream << baImage.at(i);
        j++;
    }
    istream << "}\\par\\par\n";
    istream << strRTF;
    istream << "}";
    ifile.close();
}

//Формирование RTF-текста вопросов и ответов
QString TCrosswordGrid::makeRTFText(QString ListWordH, QString ListWordV, QStringList ListOutV, QStringList ListOutH)
{
    QString strRTF;
    QString strText1;
    QString strText2;
    QString strText3;

    for(int i = 0; i < ListOutH.count(); i++)
    {
        strText1.append(wordToUnicode(ListOutH.at(i)) + "\\par\n");
    }

    strText2.clear();

    for(int i = 0; i < ListOutV.count(); i++)
    {
        strText2.append(wordToUnicode(ListOutV.at(i)) + "\\par\n");
    }

    strText3.clear();
    strText3 = "{\\b " + wordToUnicode(tr("Horizontal")) + "}:\\par\n" + wordToUnicode(ListWordH) + "\\par\n" + "{\\b " + wordToUnicode(tr("Vertical"))
               +"}:\\par\n" + wordToUnicode(ListWordV) + "\\par\n";

    strRTF.append("{\\b " + wordToUnicode(tr("Horizontal")) + "}:\\par\n"
                   + strText1 + "\\par\n"
                   "{\\b " + wordToUnicode(tr("Vertical")) + "}:\\par\n"
                   + strText2 + "\\par\n"
                   "{\\b\\i " + wordToUnicode(tr("Answers")) + "}:\\par\n"
                   + strText3 + "\\par\n");
    return strRTF;
}
Использовался материал Википедии. Скачать 1.0.0.
Цитата
Список изменений:
- Повышена безопасность работы игры;
- Добавлен экспорт кроссворда в RTF;
- Исправлена нумерация вопросов кроссворда при печати и экспорте;
- Оптимизирована скорость отображения статистики;
- Изменён цветовой стиль сетки кроссворда, уменьшен контраст цветов;
xwicked
Все изменения:
Цитата
- Добавлена возможность создать словарь из текстового файла со
словами;
- Добавлена возможность выбора путей к файлу свойств, файлу статистики, файлу словаря;
- Исправлена фатальная ошибка при вводе слов в сетку, без координат слов;
- Добавлена поддержка файла кроссворда формата OpenKlest 1.1;
- Добавлено сохранение положений панелей инструментов при выходе из программы;
- Добавлены новые классы: TCell, TGrid и tfileoptions;
- Добавлена возможность удалённого расположения файла свойств;
- В свойства игры добавлены кнопки "Сбросить" и "Восстановить умолчания";
- Изменены ссылки баг-трекера и git;
- Добавлена возможность разворачивания на весь экран окон статистики и руководства пользователя;
- Название программы и номер версии вынесены в отдельный заголовочный файл;

Новая версия 1.2.3
Мной было принято решение о прекращении сборок в linux-пакеты в пользу простоты установки, оформив всё в виде мастера-установщика как в ОС Оффтопик. В связи с замедлением процесса разработки прошу давать советы на крайне необходимые функции и указания на исправление критических ошибок.

Благодарю!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.