Откопал на диске в своих архивах программу генерации кроссвордов, которую я несколько лет назад делал на заказ, для ученика 11 класса. По этой причине, намеренно многие места в программе упрощены и написаны дилетантски, чтобы ученик мог выдать код за свой собственный. По этой же причине жестко задано количество размещаемых слов и ячеек для ввода ответов — 12 штук. Но я думаю, если кто то захочет это доработать это будет не трудно.
Текст программы снабжен большим количеством подробных комментариев, так что разобраться в деталях будет не трудно. Сама база всех вопросов и ответов содержится в файле 1.txt, если кто либо решит пополнить эту базу нужно не забыть отредактировать строчку Cnt=56 в начале.
скачать программу генерации кроссвордов (Delphi 7)
Обращаю внимание что это не готовый продукт, для любителей кроссвордов, в программе очень маленькая база вопросов — всего 56, а также нет удобной регулировки размеров кроссворда и количества размещаемых вопросов.
Алгоритм генерации кроссворда
Мною был разработан алгоритм выбора и размещения слов на доске, задачей которого является получение максимального количества пересечений с другими словами. Алгоритм, выбирая очередное случайное слово для размещения, последовательно пытается разместить его горизонтально и вертикально, постепенно двигаясь от левого верхнего угла доски к нижнему правому. При этом если не получено ни одного пересечения, либо слово накладывается на уже размещенное слово не правильно то такие варианты отбрасываются, а если размещение признается удачным то запоминается количество полученных пересечений, чтобы потом выбрать вариант с максимальным количеством.
При размещении слова, алгоритм учитывает некоторые ограничения. Например нельзя размещать два слова одно за другим впритык, иначе не будет понятно где заканчивается одно и начинается другое.
Процедуры MapWord и MapWordCheck — содержат основную часть алгоритма размещения слов на доске.
procedure TMainForm.MapWord(WUindex: integer); var Len : integer; x,y,n : integer; i : integer; cnt : integer; // Количество найденых вариантов размещения POst : integer; // Оставшееся число попыток подобрать слово из словаря // Массив для запоминания возможных вариантов размещения слова на доске MX : array[1..Tmax*Tmax] of integer; // Координата X на доске MY : array[1..Tmax*Tmax] of integer; // Координата Y на доске MN : array[1..Tmax*Tmax] of integer; // направление слова - 1 горизонтально, 2 - вертикально begin // Выбрать из словаря и расположить слово на доске // WUindex - порядковый номер размещаемого слова POst := Pmax; // Берем заданное в переменной число попыток выбрать слово cnt := 0; // Изначально количество вариантов, которыми можно разместить слово на доске = 0 while cnt=0 do begin // крутим цикл пока не найдем слово, которое сможем разместить хотябы одним способом POst := POst-1; // Уменьшаем оставшееся число попыток if POst1)and(T[x-1,y]<>' ')and(T[x-1,y]<>'#') then begin // слово не должно лепится вплотную к другому слову Result := false; // размещение невозможно Exit; end; if (x<Tmax)and(T[x+Len,y]<>' ')and(T[x+Len,y]<>'#') then begin // слово не должно лепится вплотную к другому слову Result := false; // размещение невозможно Exit; end; for i := 1 to Len do begin // проверяем символ за символом if T[x+i-1,y]<>' ' then begin // клетка чемто занята if T[x+i-1,y]<>S[i] then begin // символ в клетке не совпадает с символом в слове - размещение невозможно Result := false; Exit; end else begin if (TS[x+i-1,y]=3)or(TS[x+i-1,y]=1) then begin // символ совпал, но тут уже есть пересечение слов, либо тут есть слово, расположенное в том же направлении Result := false; // размещение невозможно Exit; end else begin p := p + 1; // регистрируем удачное пересечение проверяемого слова с уже размещенными end; end; end; end; end else begin // ВЕРТИКАЛЬНО if (y>1)and(T[x,y-1]<>' ')and(T[x,y-1]<>'#') then begin // слово не должно лепится вплотную к другому слову Result := false; // размещение невозможно Exit; end; if (y<Tmax)and(T[x,y+Len]<>' ')and(T[x,y+Len]<>'#') then begin // слово не должно лепится вплотную к другому слову Result := false; // размещение невозможно Exit; end; for i := 1 to Len do begin // проверяем символ за символом if T[x,y+i-1]<>' ' then begin // клетка чемто занята if T[x,y+i-1]<>S[i] then begin // символ в клетке не совпадает с символом в слове - размещение невозможно Result := false; Exit; end else begin if (TS[x,y+i-1]=3)or(TS[x,y+i-1]=2) then begin // символ совпал, но тут уже есть пересечение слов, либо тут есть слово, расположенное в том же направлении Result := false; // размещение невозможно Exit; end else begin p := p + 1; // регистрируем удачное пересечение проверяемого слова с уже размещенными end; end; end; end; end; if p>0 then begin Result := true; // размещение с такими параметрами возможно end else begin Result := false; // размещение невозможно - нчего не мешает, но и пересечений нет end; end;
function TMainForm.RandWord: integer; var r : integer; i : integer; begin // Выбираем слово из словаря, которое еще не использовано r := 0; while r=0 do begin r := 1 + Random(wCnt-1); for i := 1 to WUmax do begin if WU[i]=r then r := 0; // Если выбранное слово уже использовано, сбрасываем выбор, чтобы взять другое end; end; Result := r; end;
procedure TMainForm.SetWord(WUindex: integer); var Len : integer; S : string; i : integer; x,y : integer; begin // Вписываем слово в сетку, при этом (в таблицы T и TS) // WUindex - его порядковый номер в таблицах WU, WX, WY, WN (эти ьаблицы должны быть заполнены предварительно) S := W[WU[WUindex]]; // достаем слово Len := Length(S); // достаем его длину x := WX[WUindex]; y := WY[WUindex]; // помечаем клетки перед и после слова как занятые (чтоб слова своим началом или концом не лепились вплотную к уже размещенным словам) if WN[WUindex]=1 then begin // ГОРИЗОНТАЛЬНО if (x-1)>0 then begin // Ставим ограничительный знак перед словом TS[x-1,y] := 3; T[x-1,y] := '#'; end; if x+Len<=Tmax then begin // Ставим ограничительный знак после слова TS[x+Len, y] :=3; T[x+Len, y] := '#'; end; end else begin // ВЕРТИКАЛЬНО if (y-1)>0 then begin // Ставим ограничительный знак перед словом TS[x,y-1] := 3; T[x,y-1] := '#'; end; if y+Len<=Tmax then begin // Ставим ограничительный знак после слова TS[x, y + Len] :=3; T[x,y+Len] := '#'; end; end; for i := 1 to Len do begin if WN[WUindex]=1 then begin // ГОРИЗОНТАЛЬНО T[x+i-1,y] := S[i]; // Вписываем символ TS[x+i-1,y] := TS[x+i-1,y] + 1; // Вписываем кодовое обозначение того, как оно расположено // if (i=1) then TS[x-1,y] := 3; // помечаем клетку перед словом, как занятую end else begin // ВЕРТИКАЛЬНО T[x,y+i-1] := S[i]; // Вписываем символ TS[x,y+i-1] := TS[x,y+i-1] + 2; // Вписываем кодовое обозначение того, как оно расположено end; end; end;
А можно купить у Вас полный код этой программы ?
Вы невнимательно читали, там есть ссылка для скачивания абсолютно бесплатно 😉
А с английскими словами кроссворд работает?
На Делфи 2007 будет работать?
Спасибо! Взял твою прогу как основу, и уже работал с ней. Отличная идея.