Программа "Генератор кроссвордов"
Введение
История кроссворда
Кроссворд появился в начале 20 века и быстро завоевал популярность во всем мире. Слово кроссворд образовалось из двух английских слов cross - пересечение и word - слово. Решение кроссвордов тренирует память и расширяет кругозор, некоторые типы кроссвордов способствуют развитию сообразительности и ассоциативного мышления. Медики стали использовать кроссворд как успокаивающее средство. Преподаватели тоже применяют кроссворд в своей работе, это позволяет учащимся усваивать знания в игровой форме. Сфера применения кроссвордов постоянно расширяется, кроссворды применяются для тестирования профессиональных качеств.
Основные методы составления кроссворда. Машинный и творческий подходы к заполнению сетки
Составление кроссворда – занятие достаточно трудоемкое и кропотливое, требующее внимательности и усидчивости. Для составления кроссвордов необходимо иметь доступ к словарям со списками слов и толкований.
Когда появились персональные компьютеры, стали появляться и программы для составления кроссвордов. Процесс составления кроссворда человеком – это творческий процесс – попытка подобрать слово таким образом, чтобы в процессе составления не зайти в тупик, что приведет к отмене заполнения целых блоков сетки и откату назад с целью поиска лучшего варианта.
Машинное составление имеет множество алгоритмов – например перебор с возвратом. Этот метод гарантирует перебор всех возможных вариантов и позволит составить кроссвордов даже при наличии минимального словаря, если точно известно, что из заданного набора слов можно заполнить сетку. Отрицательная сторона этого метода – время. На перебор необходимо затратить коллосальное количество времени, так как число для перебора вариантов настолько велико, что такую ситуацию называют «комбинаторный взрыв».
Другой из способов составления – подбор слов с «просчетом ходов наперед» – оценка возможностей словаря для выбора слов по маскам, которые образуются на пересечениях слов на ключевых буквах а также оценка подобранного слова с целью поиска лучшего решения и отбрасывания варианта, которое не приведет к завершению составления.
Этот метод отработает значительно быстрее, но для него необходим достаточно объемный словарь. И если будет минимальный набор слов, гарантированно позволяющий составить кроссворд, то такой метод этот набор может и не отыскать.
Составление кроссворда – это задача из области поиска решения. В настоящее время, когда типичная персональная ПЭВМ имеет оперативную память, измеряемую в гигабайтах, и процессоры, которые имеют в своем составе несколькоя ядер, а также операционные системы, поддерживающие парралельные вычисления, позволяют реализовывать генераторы кроссвордов, которые заполняют средней плотности и сложности сетки за время, исчисляемое секундами. Но для этого таким программам необходим словарь, объемом, например в 80-100 тысяч слов.
Целью настоящего курсового проекта является разработка классического генератора кроссвордов, а также закрепление полученных навыков в области программирования на языке C++, усвоение ключевых понятий концепции объектно-ориентированного программирования, проявления творческих подходов к разработке сложного программного обеспечения.
Постановка задачи
Составить генератор классических кроссвордов.
Предметная область
Кроссворд - это задача-головоломка, заключающаяся в заполнении буквами перекрещивающихся рядов клеток так, чтобы по горизонталям и вертикалям получились заданные по значениям слова. В переводе с английского языка - cross-word означает пересечение слов. Для заполнения классического кроссворда в качестве вопросов используют толкования слов, однако, есть и другие варианты, например использование слов-анаграмм – слов, которые образуются из текущего слова перестановкой букв. Например «врач è рвач».
Рис. 1Типичная сетка классического суперкроссворда
Существуют и другие виды кроссвордов, (чайнворды, линейные, сотовые и другие) а также периодически появляются новые, основа которых – не слова, например японские кроссворды, хотя они и предназначены для разгадывания картинки, по традиции их называют «перекрестьем слов».
Существуют скандинавские
кроссворды (сканворды), в которых
толкования вписываются прямо в
сетку, направление слова указывается
стрелками. Качественный скандинавский
кроссворд имеет достаточно высокую
плотность пересечений и очень
(достаточно!) сложен для составления.
Поэтому и наблюдается
Рис. 2Типичный современный сканворд
Обзор существующих решений
Существует огромное количество
программ-генераторов
Приведем вкратце описание двух программ данного класса.
Одна из таких программ
– «Крестословица» (http://kslov.chat.ru/obz.html
следующая разработка – Crossword
Forge 5.25 (http://f1cd.ru/soft/windows/
Требования к программе
Для работы программы необходима операционная система Windows XP (SP1-SP3). Программа не тестировалась на старых версиях Windows 3-Windows 98.
Для работы программы достаточно
будет тех минимальных
Программа к ресурсам не требовательна.
Функции программы.
Основная функция программы – составление кроссворда.
В программе имеются функции редактирования сетки – позволяет в несколько щелчков мыши создать сетку любых размеров, расставить на ней слова и сохранить рисунок сетки в файл.
Сохраненную сетку можно загрузить, подкорректировать и сохранить под другим именем.
Рис. 3Главное окно приложения
Описание кнопок.
База слов – позволяет просмотреть базовый словарь, состоящий из нескольких тысяч слов.
Составление – автонумерация и разбиение сетки на отдельные слова, Составление масок. Для начала составления нажимается эта кнопка.
Очистка – очистка сетки от слов. Чистится без предупреждения.
Рисование и разметка – переключает между режимами рисования сетки и блокировеи изменения сетки – режим только просмотра.
Размер сетки – позволяет задать размер:
Рис. 4Изменение размеров сетки
После задания сетки нужно повторно нажать на кнопку Размер сетки. Это скроет панель ввода размеров и выровняет размеры клеток. Изменение размеров сетки приводит к полному уничтожению данных кроссворда.
Ручное составление кроссворда
Щелчок по списку масок приведет к появлению нгового списка – по заданной маске будут подобраны слова:
Рис. 5Подбор слов по маске
Щелчок по правому списку – впишет слово в кроссворд:
Рис. 6Подбор слов
После вставки слова обновляются все маски:
Рис. 7Процесс составления кроссворда
Входные данные
Для работы программы нужен словарь, которые хранится в базе данных WordBase.mdb.
В базе данных имеется только две таблицы – рабочая и словарь. Словарь Words состоит из полей:
Definition – толкование слова;
Length – длина слова;
Word слово в словаре.
Рабочая таблица mWorks состоит из полей:
Mask – маска слова для поиска в словаре
Ok – признак того, что слов заполнено;
Nom – номер слова;
Direction – направление слова (V/H);
Row в каком ряду в сетке слов начинается;
Col в какой колонке в сетке слово начинается;
Length длина слова.
Выходные данные
Каждая клетка в словаре связана со структурой:
Рис. 8База слов
struct WCell
{
char Cell; //0 - Пустое поле // 1 Закрашенная клетка 2 - клетка с буквой
unsigned int Start; // 0 - не начало слова. не 0 - начало слова
char Direction; // 'V' / 'H'
char Letter; // буква
bool Selected; //Выделение слова в сетке
};
Файл хранит в себе в заголовке, состоящем из двух целых чисел (unsigned int) размер сетки, затем описание сетки в виде вышеприведенной структуры.
Вычислительная система
Для работы приложения необходима операционная система Windows (XP/2k/NT/Vista/Seven и другие линейки Windows).
Выбор именно этой системы обоснован тем, что ее не надо «тонко» настраивать, как например *nix системы.
Выбор языка программирования C++ обосновывается тем, что этот язык современный, хотя появился он давно, но современность его в том, что на базе его синтаксиса появляются новые языки, например C#, Java, что говорит о том, что синтаксис его удобный, лаконичный, но в тоже время мощный и гибкий, позволяющий создавать на языке изящные конструкции кода. Однако С++ опасен тем, что не контролирует работу программиста с памятью, поэтому надо четко отслеживать, чтобы не было утечек памяти, чтобы указатели указывали на существующие объекты. В противном случае ошибки, сделанные в программах на C++ могут привести (и приводят) к краху даже такой устойчивой системы, как Windows XP, что вынудит перезагрузить в итоге компьютер.
Выбор среды разработки обоснован тем, что C++ Builder позволяет быстро создать удобный интерфейс пользователя, затратив на это минимум времени, потратив основное усилие на разработку ключевых моментов проекта.
Объектно-ориентированное программирование
Схема приложения
Описание функций
void __fastcall GridDrawCell(TObject *Sender, int ACol, int ARow,
TRect &Rect, TGridDrawState State); отрисовка клеток кроссвордной сетки
void __fastcall EditXChange(TObject *Sender); обработка события изменения размера сетки по горизонтали
void __fastcall EditYChange(TObject *Sender); обработка события изменения размера сетки по вертикали;
void __fastcall GridCellsSize(); выравнивание ячеек сетки
void __fastcall btnModeClick(TObject *Sender); переключение между режимами отрисовки и просмотра
void __fastcall CreateCrossword(); создание кроссворда (создание динамического массива заданной структуры)
void __fastcall KillCrossword(); уничтожение кроссворда (очистка памяти)
void __fastcall GridSelectCell(TObject *Sender, int ACol, int ARow,
bool &CanSelect); обработчик события выбора клетки
void __fastcall SetCell(int C, int R); настройка ячейки в зависимости от режима
void __fastcall btnClearClick(TObject *Sender); обработка нажатия очистки кроссворда
byte __fastcall GetStartPosition(int PosX,int PosY); поиск в сетке признаков начала слова
bool __fastcall CellBack(int PosX,int PosY); проверка выхода за пределы по горизонтали
bool __fastcall CellUp(int PosX,int PosY); проверка выхода за пределы сетки по вертикали
void __fastcall GetMasks(); пориск и формирование масок на основе сетки
void __fastcall GetHorizontalMask(int yy,int xx); получение маски горизонтального слова
void __fastcall GetVerticalMask(int yy,int xx); получение маски вертикального слова
void __fastcall SetWord(int Nom,String Dir); запись слова в сетку
void __fastcall GetWord(int Nom,String Dir); получение слова из сетки
void __fastcall DbGridWorkCellClick(TColumn *Column); обработчки нажатия на список масок
void __fastcall WriteWord(int Nom,String Dir); запись слова в кроссворд
void __fastcall DbGridWordsCellClick(TColumn *Column); выбор слова из списка найденных
Описание аппартных и программных средств
Для работы программы необходима операционная система Windows XP (SP1-SP3). Программа не тестировалась на старых версиях Windows 3-Windows 98.
Для работы программы достаточно
будет тех минимальных
Для работы программы необходим в системе OLEDB провайдер.
Для работы программы необходим IBM совместимый компьютер с утсановленной любой из операционных систем линейки Windows, начиная с версии Windows 2000.
Для работы программы желательно поддержка режима экрана 1920 на 1480.
Заключение
Выполнение Курсового
проекта показало, что, используя
интегрированную среду
В процессе выполнения работы были закреплены навыки работы со структурами, классами, указателяыми, выделением и освобождением памяти, разработке алгоритма генератора кроссвордов.
Список литературы
М. Эллис, Б. Строуструп. Справочное руководство по языку C++ с комментариями: Пер. с англ. - Москва: Мир, 1992. 445с.
Стенли Б. Липпман. C++ для начинающих: Пер. с англ. 2тт. - Москва: Унитех; Рязань: Гэлион, 1992, 304-345сс.
Бруно Бабэ. Просто и ясно о Borland C++: Пер. с англ. - Москва: БИНОМ, 1994. 400с.
В.В. Подбельский. Язык C++: Учебное пособие. - Москва: Финансы и статистика, 1995. 560с.
Ирэ Пол. Объектно-ориентированное программирование с использованием C++: Пер. с англ. - Киев: НИИПФ ДиаСофт Лтд, 1995. 480с.
Т. Фейсон. Объектно-ориентированное программирование на Borland C++ 4.5: Пер. с англ. - Киев: Диалектика, 1996. 544с.
Т. Сван. Освоение Borland C++ 4.5: Пер. с англ. - Киев: Диалектика, 1996. 544с.
Г. Шилдт. Самоучитель C++: Пер. с англ. - Санкт-Петербург: BHV-Санкт-Петербург, 1998. 620с.
У. Сэвитч. C++ в примерах: Пер. с англ. - Москва: ЭКОМ, 1997. 736с.
К. Джамса. Учимся программировать на языке C++: Пер. с англ. - Москва: Мир, 1997. 320с.
В.А. Скляров. Язык C++ и объектно-ориентированное программирование: Справочное издание. - Минск: Вышэйшая школа, 1997. 480с.
Х. Дейтел, П. Дейтел. Как программировать на C++: Пер. с англ. - Москва: ЗАО "Издательство БИНОМ", 1998. 1024с.
Приложение
Исходный код приложения.
Main
//----------------------------
#ifndef uMainH
#define uMainH
//----------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Menus.hpp>
#include "sSkinProvider.hpp"
#include "sButton.hpp"
#include "sScrollBox.hpp"
//============================
#include <ExtCtrls.hpp>
#include <Grids.hpp>
#include "sPanel.hpp"
#include "sSplitter.hpp"
#include <ComCtrls.hpp>
#include <Buttons.hpp>
#include <ImgList.hpp>
#include <Dialogs.hpp>
#include "sSkinProvider.hpp"
#include "acAlphaImageList.hpp"
#include "sCheckBox.hpp"
#include "sEdit.hpp"
#include "sLabel.hpp"
#include "sMemo.hpp"
#include "sPanel.hpp"
#include "sSpeedButton.hpp"
#include "sSplitter.hpp"
#include "sStatusBar.hpp"
#include <Buttons.hpp>
#include <ComCtrls.hpp>
#include <ExtCtrls.hpp>
#include <Grids.hpp>
#include <ImgList.hpp>
#include <DBGrids.hpp>
//----------------------------
class TfrmMain : public TForm
{
__published: // IDE-managed Components
TMainMenu *mm1;
TMenuItem *mniN1;
TsSkinProvider *sknprvdr1;
TStringGrid *Grid;
TsPanel *Panel1;
TsStatusBar *StatusBar;
TsSplitter *Splitter1;
TsPanel *Panel2;
TsAlphaImageList *ImageList;
TsSpeedButton *btn2;
TsPanel *PanelSize;
TsLabelFX *Label1;
TsLabelFX *sLabelFX1;
TsEdit *EditX;
TsEdit *EditY;
TsSpeedButton *btnMode;
TOpenDialog *OpenDialog1;
TSaveDialog *SaveDialog1;
TMenuItem *mniN2;
TMenuItem *mniN3;
TMenuItem *mniN4;
TsPanel *Panel3;
TsCheckBox *chkH;
TsCheckBox *chkV;
TsSpeedButton *btnClear;
TsSpeedButton *btn1;
TsSpeedButton *btn3;
TDBGrid *DbGridWords;
TsSplitter *Splitter2;
TDBGrid *DbGridWork;
void __fastcall GridDrawCell(TObject *Sender, int ACol, int ARow,
TRect &Rect, TGridDrawState State);
void __fastcall FormShow(TObject *Sender);
void __fastcall btn2Click(TObject *Sender);
void __fastcall EditXChange(TObject *Sender);
void __fastcall EditYChange(TObject *Sender);
void __fastcall GridCellsSize();
void __fastcall btnModeClick(TObject *Sender);
void __fastcall CreateCrossword();
void __fastcall KillCrossword();
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
void __fastcall GridSelectCell(TObject *Sender, int ACol, int ARow,
bool &CanSelect);
void __fastcall SetCell(int C, int R);
void __fastcall mniN4Click(TObject *Sender);
void __fastcall mniN3Click(TObject *Sender);
void __fastcall mniN2Click(TObject *Sender);
void __fastcall btnClearClick(TObject *Sender);
byte __fastcall GetStartPosition(int PosX,int PosY);
bool __fastcall CellBack(int PosX,int PosY);
bool __fastcall CellUp(int PosX,int PosY);
void __fastcall btn1Click(TObject *Sender);
void __fastcall GetMasks();
void __fastcall GetHorizontalMask(int yy,int xx);
void __fastcall GetVerticalMask(int yy,int xx);
void __fastcall btn3Click(TObject *Sender);
void __fastcall SetWord(int Nom,String Dir);
void __fastcall Label1Click(TObject *Sender);
void __fastcall GetWord(int Nom,String Dir);
void __fastcall sLabelFX1Click(TObject *Sender);
void __fastcall DbGridWorkCellClick(TColumn *Column);
void __fastcall WriteWord(int Nom,String Dir);
void __fastcall DbGridWordsCellClick(TColumn *Column);
private: // User declarations
public: // User declarations
__fastcall TfrmMain(TComponent* Owner);
};
//----------------------------
extern PACKAGE TfrmMain *frmMain;
//----------------------------
#endif
//----------------------------
#include <vcl.h>
#pragma hdrstop
#include "uMain.h"
#include "uWords.h"
#include "uDm.h"
//----------------------------
#pragma package(smart_init)
/*
#pragma link "sSkinProvider"
#pragma link "sButton"
#pragma link "sScrollBox"
#pragma link "sPanel"
#pragma link "sSplitter"
#pragma link "sStatusBar"
#pragma link "acAlphaImageList"
#pragma link "sSpeedButton"
//#pragma link "acAlphaHints"
#pragma link "sEdit"
#pragma link "sLabel"
#pragma link "sMemo"
#pragma link "sCheckBox"
*/
#pragma link "sSkinProvider"
#pragma link "acAlphaImageList"
#pragma link "sCheckBox"
#pragma link "sEdit"
#pragma link "sLabel"
#pragma link "sMemo"
#pragma link "sPanel"
#pragma link "sSpeedButton"
#pragma link "sSplitter"
#pragma link "sStatusBar"
#pragma resource "*.dfm"
TfrmMain *frmMain;
const AnsiString sModeShow ="Режим отображения";
const AnsiString sModeDraw ="Режим разметки";
struct WCell
{
char Cell; //0 - Пустое поле // 1 Закрашенная клетка 2 - клетка с буквой
unsigned int Start; // 0 - не начало слова. не 0 - начало слова
char Direction; // 'V' / 'H' /'S'- направление слова (V/H - начало слова, S - не начало слова)
char Letter; // буква
bool Selected;
};
struct WCell1
{
unsigned int Start;
};
WCell **Crossword;
WCell1 *aaa;
enum tMode {tDraw,tShow};
enum tSimmetry {tNone,tVert,tHor,tBoth};
tMode CurrentMode;
tSimmetry Simmetry;
unsigned int CrossX = 5;
unsigned int CrossY = 5;
bool Starting;
void __fastcall TfrmMain::CreateCrossword()
{
Crossword = new WCell*[CrossY];
for(int i=0; i<CrossY; i++)
Crossword[i] = new WCell[CrossX];
for(int i=0; i<CrossY; i++)
{
for(int j=0; j<CrossX; j++)
{
Crossword[i][j].Cell= '2';
Crossword[i][j].Start = 0;
Crossword[i][j].Direction = ' ';
Crossword[i][j].Letter = ' ';
}
}
Grid->Repaint();
}
void __fastcall TfrmMain::KillCrossword()
{
if (Crossword != NULL)
//if (CrossX !=0 && CrossY !=0 && !Starting)
{
for(int i=0; i<CrossY; i++)
delete[] Crossword[i];
delete[] Crossword;
Crossword = NULL;
}
}
//----------------------------
__fastcall TfrmMain::TfrmMain(TComponent* Owner)
: TForm(Owner)
{
/*
String pr="MSDataShape.1";
String dpr="Microsoft.Jet.OLEDB.4.0";
AnsiString tmp = ExtractFilePath(Application->
//Получили имя файла ACCESS
const String ConnStr = "Provider=%s;Data Provider=%s;Data Source=%s";
//Строка параметров соединения
if (!Dm->ADOConnection1->
Dm->ADOConnection1->
ARRAYOFCONST((pr,dpr, tmp)));
Dm->ADOConnection1->Open();
//ADOQuery1->Open();
*/
}
//----------------------------
void __fastcall TfrmMain::GridCellsSize()
{
for (int i=0;i<Grid->ColCount;i++) Grid->ColWidths[i] = 30;
for (int i=0;i<Grid->RowCount;i++) Grid->RowHeights[i] = 30;
}
void __fastcall TfrmMain::GridDrawCell(TObject *Sender, int ACol,
int ARow, TRect &Rect, TGridDrawState State)
{
if (Crossword != NULL && ACol<=CrossX && ARow <=CrossY)
{
// Grid->Canvas->CopyMode;
Grid->Canvas->Font->Color = clGreen;
Grid->Canvas->Font->Size = 8;
StatusBar->Panels->Items[2]->
switch(Crossword[ARow][ACol].
{
case '0' :
Grid->Canvas->Brush->Color = clGray;break;
case '1':
Grid->Canvas->Brush->Color = clBlack;break;
case '2':
Grid->Canvas->Brush->Color = clWhite;break;
}
if (Crossword[ARow][ACol].
Grid->Canvas->FillRect(Rect);
if (Crossword[ARow][ACol].Start !=0)
{
Grid->Canvas->TextRect(Rect,
}
Grid->Canvas->TextRect(Rect,
StatusBar->Panels->Items[1]->
}
}
//----------------------------
void __fastcall TfrmMain::FormShow(TObject *Sender)
{
Starting = 1;
CurrentMode = tShow;
StatusBar->Panels->Items[0]->
EditX->Text = "5";
EditY->Text = "5";
PanelSize->Hide();
Grid->FixedCols = 0;
Grid->FixedRows = 0;
Grid->RowCount = 5;
Grid->ColCount = 5;
GridCellsSize();
CrossX = 5;
CrossY = 5;
CreateCrossword();
Grid->Repaint();
Starting = 0;
DbGridWork->DataSource = Dm->DataSourceWork;
Dm->DataSourceWork->DataSet = Dm->ADOQuery;
DbGridWork->ReadOnly = 1;
DbGridWords->ReadOnly = 1;
DbGridWords->DataSource = Dm->DataSourceWrd;
Dm->DataSourceWrd->DataSet = Dm->ADOQueryWrd;
}
//----------------------------
void __fastcall TfrmMain::btn2Click(TObject *Sender)
{
if (PanelSize->Visible)
{
PanelSize->Hide();
GridCellsSize();
}
else PanelSize->Show();
}
//----------------------------
void __fastcall TfrmMain::EditXChange(TObject *Sender)
{
unsigned int x = 5;
try
{
x = StrToInt(EditX->Text.Trim());
Grid->ColCount = x;
KillCrossword();
CrossX = x;
CreateCrossword();
}
catch(Exception &e)
{
x= 5;
EditX->Text = "5";
Grid->ColCount = x;
KillCrossword();
CrossX = x;
CreateCrossword();
}
}
//----------------------------
void __fastcall TfrmMain::EditYChange(TObject *Sender)
{
unsigned int y = 5;
try
{
y = StrToInt(EditY->Text.Trim());
Grid->RowCount = y;
KillCrossword();
CrossY = y;
CreateCrossword();
}
catch(Exception &e)
{
y= 5;
EditY->Text = "5";
Grid->RowCount = y;
KillCrossword();
CrossY = y;
CreateCrossword();
}
}
//----------------------------
void __fastcall TfrmMain::btnModeClick(TObject *Sender)
{
if (CurrentMode == tDraw)
{
CurrentMode = tShow;
StatusBar->Panels->Items[0]->
}
else
{
CurrentMode = tDraw;
StatusBar->Panels->Items[0]->
}
}
//----------------------------
void __fastcall TfrmMain::FormClose(TObject *Sender, TCloseAction &Action)
{
KillCrossword();
}
//----------------------------
void __fastcall TfrmMain::GridSelectCell(
bool &CanSelect)
{ SetCell(ACol,ARow);
int hh,vv;
if (Grid->ColCount
& 1 == 0) hh=-1; else hh=RoundTo(Grid->ColCount/2,0)
if (Grid->RowCount
& 1 == 0) vv=-1; else vv=RoundTo(Grid->RowCount/2,0)
if(chkH->Checked
&& ACol !=hh) SetCell(Grid->ColCount-ACol-1,
if(chkV->Checked
&& ARow !=vv) SetCell(ACol,Grid->ColCount-
if(chkH->Checked&&
ACol !=hh && ARow !=vv) SetCell(Grid->ColCount-ACol-1,
Grid->Repaint();
StatusBar->Panels->Items[4]->
StatusBar->Panels->Items[3]->
}
//----------------------------
void __fastcall TfrmMain::SetCell(int C, int R)
{
if (CurrentMode == tDraw && C <= CrossX && R <= CrossY)
{
if (Crossword[R][C].Cell == '2')
Crossword[R][C].Cell = '1'; else
Crossword[R][C].Cell = '2';
Crossword[R][C].Selected = 0;
Crossword[R][C].Letter = ' ';
}
}
void __fastcall TfrmMain::mniN4Click(TObject *Sender)
{
Application->Terminate();
}
//----------------------------
void __fastcall TfrmMain::mniN3Click(TObject *Sender)
{
AnsiString FileName;
unsigned int k;
if (SaveDialog1->Execute())
{
Grid->ColCount = 0;
Grid->RowCount = 0;
FileName = SaveDialog1->FileName;
TFileStream* fs = new TFileStream(FileName, fmCreate);
fs->Write(&CrossX, sizeof(CrossX));
fs->Write(&CrossY, sizeof(CrossY));
if (Crossword != NULL)
{
for(int i=0; i<CrossY; i++)
{
for(int j=0; j<CrossX; j++)
fs->Write(&Crossword[i][j],
}
}
delete fs;
Grid->ColCount = CrossX;
Grid->RowCount = CrossY;
GridCellsSize();
Grid->Repaint();
}
}
//----------------------------
void __fastcall TfrmMain::mniN2Click(TObject *Sender)
{
AnsiString FileName;
if (OpenDialog1->Execute())
{
FileName = OpenDialog1->FileName;
TFileStream* fs = new TFileStream(FileName, fmOpenRead);
Grid->ColCount = 0;
Grid->RowCount = 0;
KillCrossword();
fs->Read(&CrossX, sizeof(CrossX));
fs->Read(&CrossY, sizeof(CrossY));
CreateCrossword();
Grid->ColCount = CrossX;
Grid->RowCount = CrossY;
if (Crossword != NULL)
{
for(int i=0; i<CrossY; i++)
{
for(int j=0; j<CrossX; j++)
fs->Read(&Crossword[i][j],
}
GridCellsSize();
Grid->Repaint();
delete fs;
}
}
}
//----------------------------
void __fastcall TfrmMain::btnClearClick(
{
if (Crossword != NULL)
for(int i=0; i<CrossY; i++)
{
for(int j=0; j<CrossX; j++)
{
Crossword[i][j].Cell= '2';
Crossword[i][j].Start = 0;
Crossword[i][j].Direction = ' ';
Crossword[i][j].Letter = ' ';
}
}
Grid->Repaint();
}
//----------------------------
bool __fastcall TfrmMain::CellBack(int PosX,int PosY)
{
if (PosX == 0 || Crossword[PosY][PosX-1].Cell !='2') return 1;
else return 0;
}
bool __fastcall TfrmMain::CellUp(int PosX,int PosY)
{
if (PosY == 0 || Crossword[PosY-1][PosX].Cell !='2') return 1;
else return 0;
}
byte __fastcall TfrmMain::GetStartPosition(int PosX,int PosY)
{
byte Flag = 0;
if (Crossword[PosY][PosX].Cell !='2') return Flag;
if(PosX < CrossX-1 && CellBack(PosX,PosY) && Crossword[PosY][PosX+1].Cell =='2') Flag = 1;
if(PosY < CrossY-1 && CellUp(PosX,PosY) && Crossword[PosY+1][PosX].Cell =='2') Flag |=2;
return Flag;
}
void __fastcall TfrmMain::btn1Click(TObject *Sender)
{
int WordsCounter = 0 ;
byte Direction;
if (Crossword != NULL)
{
for(int i=0; i<CrossY; i++)
{
for(int j=0; j<CrossX; j++)
{
Direction = GetStartPosition(j,i);
if(Direction!=0)
{
WordsCounter ++;
Crossword[i][j].Start = WordsCounter;
switch(Direction)
{
case 1:Crossword[i][j].Direction = 'H';break;
case 2:Crossword[i][j].Direction = 'V';break;
case 3:Crossword[i][j].Direction = 'B';break;
}
}
else Crossword[i][j].Start = 0;
Crossword[i][j].Letter = ' ';
}
}
Grid->Repaint();
GetMasks();
Dm->ADOQuery->SQL->Text = "SELECT * FROM mWork";
Dm->ADOQuery->Open();
}
}
//----------------------------
void __fastcall TfrmMain::GetMasks()
{
if (Crossword != NULL)
{
Dm->ADOQuery->SQL->Text = "DELETE FROM mWork;";
Dm->ADOQuery->ExecSQL();
for(int i=0; i<CrossY; i++)
{
for(int j=0; j<CrossX; j++)
{
if (Crossword[i][j].Start !=0)
switch (Crossword[i][j].Direction)
{
case 'H':GetHorizontalMask(i,j);
case 'V':GetVerticalMask(i,j);
case 'B':GetHorizontalMask(i,j);