Re: Скрипт/код/база данни за кръстословица
Posted: Thu Oct 29, 2020 8:33 pm
Може би ще помогне, ако гледаш малко по-абстрактно на нещата (думи и позиции вместо букви и двумерен масив).
Виж това: https://bg.wikipedia.org/wiki/%D0%91%D0 ... 0%BD%D0%B3
Начинът, по който аз генерирах кръстословица преди 2-3 години, беше:
1. имам клас, който представлява една дума. Той има координати (x, y) - къде започва, ориентация (хоризонтално, вертикално), и самата дума.
2. имам списък от думи, който при желание разбърквам преди да започне алгоритъма.
3. взимам първата дума и я слагам на (0,0), хоризонтално и я слагам в списъка с решения.
4. "влизам едно ниво навътре" (рекурсия), взимам следващата дума.
5. минавам през списъка с решения и се пробвам да я сложа някъде (условия: две думи да имат обща буква и ориентацията да е различна)
6. ако намеря, добавям я в решенията - ако имат обща буква, лесно можеш да изчислиш началната точка и ориентацията.
7. проверявам дали частичното решение е правилно (всички думи, които се пресичат, имат еднакви букви) - може би това е най-сложното. Може би ще помогне да пазиш във всяка дума къде се пресича.
8.1. АКО е наред, продължавам (докато не свърши списъка с думи или друго условие, например размер на кръстословицата)
8.2. АКО не е наред, махам думата от решението, махам едно ниво от рекурсията (бектрекинг) - например return null, и пробвам следващата дума.
Решението ти е списък с думи, техните позиции и ориентация, което е лесно да се визуализира.
Бектрекинг по принцип се имплементира почти буквално, както е описан – възможно е да има готови решения за PHP. Има разни оптимизации (forward checking, определена подредба на списъка с думи, и др.), които отхвърлят лоши решения по-рано. Това, което описах, може да се разшири (например, при лошо частично решение да не се отхвърля думата, а да се пробва друга позиция, ако съществуват няколко пресечни точки).
Виж това: https://bg.wikipedia.org/wiki/%D0%91%D0 ... 0%BD%D0%B3
Начинът, по който аз генерирах кръстословица преди 2-3 години, беше:
1. имам клас, който представлява една дума. Той има координати (x, y) - къде започва, ориентация (хоризонтално, вертикално), и самата дума.
2. имам списък от думи, който при желание разбърквам преди да започне алгоритъма.
3. взимам първата дума и я слагам на (0,0), хоризонтално и я слагам в списъка с решения.
4. "влизам едно ниво навътре" (рекурсия), взимам следващата дума.
5. минавам през списъка с решения и се пробвам да я сложа някъде (условия: две думи да имат обща буква и ориентацията да е различна)
6. ако намеря, добавям я в решенията - ако имат обща буква, лесно можеш да изчислиш началната точка и ориентацията.
7. проверявам дали частичното решение е правилно (всички думи, които се пресичат, имат еднакви букви) - може би това е най-сложното. Може би ще помогне да пазиш във всяка дума къде се пресича.
8.1. АКО е наред, продължавам (докато не свърши списъка с думи или друго условие, например размер на кръстословицата)
8.2. АКО не е наред, махам думата от решението, махам едно ниво от рекурсията (бектрекинг) - например return null, и пробвам следващата дума.
Решението ти е списък с думи, техните позиции и ориентация, което е лесно да се визуализира.
Бектрекинг по принцип се имплементира почти буквално, както е описан – възможно е да има готови решения за PHP. Има разни оптимизации (forward checking, определена подредба на списъка с думи, и др.), които отхвърлят лоши решения по-рано. Това, което описах, може да се разшири (например, при лошо частично решение да не се отхвърля думата, а да се пробва друга позиция, ако съществуват няколко пресечни точки).