Yanıtlar:
Muhtemelen en verimli olmayan bir çözüm buldum, ancak yeterince iyi çalışıyor. Temelde:
Bu, işe yarayan ama çoğu zaman oldukça zayıf bir bulmaca yapar. Daha iyi bir sonuç elde etmek için yukarıdaki temel tarifte yaptığım bir takım değişiklikler oldu.
Kısa süre önce Python'da kendim yazdım. Burada bulabilirsiniz: http://bryanhelmig.com/python-crossword-puzzle-generator/ . NYT tarzı yoğun bulmacaları yaratmaz, ancak bir çocuğun bulmaca kitabında bulabileceğiniz bulmaca stilini yaratır.
Birkaç algoritmanın önerdiği gibi kelimeleri yerleştirmek için rastgele bir kaba kuvvet yöntemini uygulayan birkaç algoritmanın aksine, kelime yerleştirmede biraz daha akıllı bir kaba kuvvet yaklaşımı uygulamaya çalıştım. İşte benim sürecim:
Sonunda, hemen hemen aynı oldukları için düzgün bir bulmaca veya kelime arama bulmacanız var. Oldukça iyi çalışma eğilimindedir, ancak iyileştirme konusunda herhangi bir öneriniz varsa bana bildirin. Daha büyük ızgaralar katlanarak daha yavaş çalışır; doğrusal olarak daha büyük kelime listeleri. Daha büyük kelime listelerinin daha iyi kelime yerleştirme sayıları elde etme şansı çok daha yüksektir.
array.sort(key=f)
kararlıdır, bu da (örneğin) alfabetik bir kelime listesini uzunluğa göre sıralamak, tüm 8 harfli kelimeleri alfabetik olarak sıralı halde tutacağı anlamına gelir.
Aslında on yıl kadar önce bir bulmaca oluşturma programı yazmıştım (şifreli idi ama aynı kurallar normal bulmacalar için de geçerliydi).
Bugüne kadar azalan kullanıma göre sıralanmış bir dosyada depolanan sözcüklerin (ve ilişkili ipuçlarının) bir listesi vardı (böylece daha az kullanılan sözcükler dosyanın en üstünde yer alıyordu). Temelde siyah ve serbest kareleri temsil eden bir bit maskesi olan bir şablon, müşteri tarafından sağlanan bir havuzdan rastgele seçildi.
Daha sonra, bulmacadaki tamamlanmamış her kelime için (temel olarak ilk boş kareyi bulun ve sağdaki (kelimenin karşısında) veya alttaki (aşağı-kelime) de boş olup olmadığına bakın), bir arama yapıldı o kelimede zaten bulunan harfleri dikkate alarak, uyan ilk kelimeyi arayan dosya. Sığacak bir kelime yoksa, tüm kelimeyi eksik olarak işaretlediniz ve devam ettiniz.
Sonunda, derleyicinin doldurması gereken (ve istenirse dosyaya kelimeyi ve ipucunu ekleyeceği) tamamlanmamış kelimeler olacaktır. Herhangi bir fikir bulamazlarsa, kısıtlamaları değiştirmek için bulmacayı manuel olarak düzenleyebilirler veya tamamen yeniden oluşturma isteyebilirler.
Kelime / ipucu dosyası belirli bir boyuta ulaştığında (ve bu müşteri için günde 50-100 ipucu ekliyordu), nadiren her bulmaca için yapılması gereken iki veya üçten fazla manuel düzeltme vakası vardı. .
Bu algoritma 60 saniyede 50 yoğun 6x9 ok bulmacası oluşturur . Bir kelime veritabanı (kelime + ipuçları ile) ve bir pano veritabanı (önceden yapılandırılmış panolarla) kullanır.
1) Search for all starting cells (the ones with an arrow), store their size and directions
2) Loop through all starting cells
2.1) Search a word
2.1.1) Check if it was not already used
2.1.2) Check if it fits
2.2) Add the word to the board
3) Check if all cells were filled
Daha büyük bir kelime veritabanı, oluşturma süresini önemli ölçüde azaltır ve bazı tahtaların doldurulması daha zordur! Daha büyük tahtaların doğru şekilde doldurulması için daha fazla zaman gerekir!
Misal:
Önceden Yapılandırılmış 6x9 Anakart:
(#, bir hücrede bir ipucu anlamına gelir,%, bir hücrede iki ipucu anlamına gelir, oklar gösterilmez)
# - # # - % # - #
- - - - - - - - -
# - - - - - # - -
% - - # - # - - -
% - - - - - % - -
- - - - - - - - -
Oluşturulan 6x9 Anakart:
# C # # P % # O #
S A T E L L I T E
# N I N E S # T A
% A B # A # G A S
% D E N S E % W E
C A T H E D R A L
İpuçları [satır, sütun]:
[1,0] SATELLITE: Used for weather forecast
[5,0] CATHEDRAL: The principal church of a city
[0,1] CANADA: Country on USA's northern border
[0,4] PLEASE: A polite way to ask things
[0,7] OTTAWA: Canada's capital
[1,2] TIBET: Dalai Lama's region
[1,8] EASEL: A tripod used to put a painting
[2,1] NINES: Dressed up to (?)
[4,1] DENSE: Thick; impenetrable
[3,6] GAS: Type of fuel
[1,5] LS: Lori Singer, american actress
[2,7] TA: Teaching assistant (abbr.)
[3,1] AB: A blood type
[4,3] NH: New Hampshire (abbr.)
[4,5] ED: (?) Harris, american actor
[4,7] WE: The first person of plural (Grammar)
Bu daha eski bir soru olmasına rağmen, yaptığım benzer çalışmaya dayanarak bir cevap vermeye çalışacağım.
Kısıtlama problemlerini çözmek için birçok yaklaşım vardır (bunlar genellikle NPC karmaşıklık sınıfındadır).
Bu, kombinatoryal optimizasyon ve kısıt programlama ile ilgilidir. Bu durumda kısıtlamalar, ızgaranın geometrisi ve kelimelerin benzersiz olması gerekliliğidir.
Randomizasyon / Tavlama yaklaşımları da işe yarayabilir (uygun ortamda olmasına rağmen).
Etkili basitlik, sadece nihai bilgelik olabilir!
Gereksinimler, az çok eksiksiz bir çapraz kelime derleyicisi ve (görsel WYSIWYG) oluşturucu içindi.
WYSIWYG oluşturucu kısmını bir kenara bırakırsak, derleyicinin ana hatları şuydu:
Kullanılabilir kelime listelerini yükleyin (kelime uzunluğuna göre sıralanmış, yani 2,3, .., 20)
Kullanıcı tarafından oluşturulmuş ızgarada kelime gruplarını (yani ızgara kelimeleri) bulun (örn. X, y uzunluğunda L, yatay veya dikey) (karmaşıklık O (N))
Izgara kelimelerinin (doldurulması gereken) kesişen noktalarını hesaplayın (karmaşıklık O (N ^ 2))
Kelime listelerindeki kelimelerin kullanılan alfabenin çeşitli harfleri ile kesişimlerini hesaplayın (bu, bir şablon kullanarak eşleşen kelimeleri aramaya izin verir, örneğin cwc tarafından kullanılan Sik Cambon tezi ) (karmaşıklık O (WL * AL))
.3 ve .4 adımları bu görevi gerçekleştirmeye izin verir:
a. Izgara kelimelerinin kendileriyle kesişimleri, bu ızgara kelimesi için mevcut kelimelerin ilişkili kelime listesindeki eşleşmeleri bulmaya çalışmak için bir "şablon" oluşturmayı sağlar (bu kelime ile kesişen diğer kelimelerin harflerini kullanarak, önceden belirli bir algoritmanın adımı)
b. Bir kelime listesindeki kelimelerin alfabe ile kesişimleri, belirli bir "şablon" ile eşleşen eşleşen (aday) kelimelerin bulunmasını sağlar (örn. 1. sırada 'A' ve 3. sırada 'B' vb.)
Bu veri yapıları ile uygulanan algoritma şu şekildeydi:
NOT: ızgara ve sözcük veritabanı sabitse, önceki adımlar yalnızca bir kez yapılabilir.
Algoritmanın ilk adımı, rastgele boş bir kelime dilimi (ızgara kelimesi) seçmek ve onu ilişkili kelime listesinden bir aday kelime ile doldurmaktır (randomizasyon, algoritmanın ardışık uygulamalarında farklı çözümler üretmeyi sağlar) (karmaşıklık O (1) veya O ( N))
Hala boş olan her kelime alanı için (önceden doldurulmuş kelime alanlarıyla kesişimleri olan), bir kısıtlama oranı hesaplayın (bu değişebilir, basit, o adımdaki mevcut çözümlerin sayısıdır) ve boş kelime gruplarını bu orana göre sıralayın (karmaşıklık O (NlogN ) veya O (N))
Önceki adımda hesaplanan boş kelime gruplarında döngü yapın ve her biri için birkaç kancdidate çözümü deneyin ("yay tutarlılığının korunduğundan" emin olun, yani bu kelime kullanılırsa ızgaranın bu adımdan sonra bir çözümü vardır) ve bunları şuna göre sıralayın: sonraki adım için maksimum kullanılabilirlik (yani bir sonraki adım, bu kelime o yerde o anda kullanılırsa, maksimum olası çözümleri içerir, vb.) (karmaşıklık O (N * MaxCandidatesUsed))
Bu kelimeyi doldurun (doldurulmuş olarak işaretleyin ve 2. adıma gidin)
Adım .3 kriterlerini karşılayan bir kelime bulunamazsa, önceki adımın başka bir aday çözümüne geri dönmeyi deneyin (kriterler burada değişebilir) (karmaşıklık O (N))
Geriye dönük izleme bulunursa, alternatifi kullanın ve isteğe bağlı olarak sıfırlanması gerekebilecek önceden doldurulmuş sözcükleri sıfırlayın (bunları yeniden doldurulmamış olarak işaretleyin) (karmaşıklık O (N))
Geri dönüş bulunamazsa, çözüm bulunamaz (en azından bu yapılandırma, ilk tohum vb. İle)
Aksi takdirde tüm kelime grupları doldurulduğunda tek bir çözümünüz olur
Bu algoritma, problemin çözüm ağacında rastgele ve tutarlı bir yürüyüş yapar. Bir noktada bir çıkmaz varsa, önceki bir düğüme geri dönüş yapar ve başka bir yolu izler. Bir çözüm bulunana veya çeşitli düğümler için aday sayısı tükenene kadar.
Tutarlılık kısmı, bulunan bir çözümün gerçekten bir çözüm olmasını sağlar ve rastgele kısım, farklı uygulamalarda farklı çözümler üretmeyi ve ayrıca ortalama olarak daha iyi performansa sahip olmasını sağlar.
PS. tüm bunlar (ve diğerleri) saf JavaScript (paralel işleme ve WYSIWYG ile) özelliğinde uygulandı
PS2. Algoritma, aynı anda birden fazla (farklı) çözüm üretmek için kolayca paralelleştirilebilir
Bu yardımcı olur umarım
Neden başlamak için rastgele olasılıklı bir yaklaşım kullanmıyorsunuz? Bir kelime ile başlayın ve sonra tekrar tekrar rastgele bir kelime seçin ve boyut vb. Üzerindeki kısıtlamaları bozmadan bulmacanın mevcut durumuna sığdırmaya çalışın. Başarısız olursanız, her şeye yeniden başlayın.
Böyle bir Monte Carlo yaklaşımının ne kadar sıklıkla işe yaradığına şaşıracaksınız.
İşte nickf'in cevabına ve Bryan'ın Python koduna dayalı bazı JavaScript kodu. Sadece başka birinin js'ye ihtiyacı olması ihtimaline karşı yazıyorum.
function board(cols, rows) { //instantiator object for making gameboards
this.cols = cols;
this.rows = rows;
var activeWordList = []; //keeps array of words actually placed in board
var acrossCount = 0;
var downCount = 0;
var grid = new Array(cols); //create 2 dimensional array for letter grid
for (var i = 0; i < rows; i++) {
grid[i] = new Array(rows);
}
for (var x = 0; x < cols; x++) {
for (var y = 0; y < rows; y++) {
grid[x][y] = {};
grid[x][y].targetChar = EMPTYCHAR; //target character, hidden
grid[x][y].indexDisplay = ''; //used to display index number of word start
grid[x][y].value = '-'; //actual current letter shown on board
}
}
function suggestCoords(word) { //search for potential cross placement locations
var c = '';
coordCount = [];
coordCount = 0;
for (i = 0; i < word.length; i++) { //cycle through each character of the word
for (x = 0; x < GRID_HEIGHT; x++) {
for (y = 0; y < GRID_WIDTH; y++) {
c = word[i];
if (grid[x][y].targetChar == c) { //check for letter match in cell
if (x - i + 1> 0 && x - i + word.length-1 < GRID_HEIGHT) { //would fit vertically?
coordList[coordCount] = {};
coordList[coordCount].x = x - i;
coordList[coordCount].y = y;
coordList[coordCount].score = 0;
coordList[coordCount].vertical = true;
coordCount++;
}
if (y - i + 1 > 0 && y - i + word.length-1 < GRID_WIDTH) { //would fit horizontally?
coordList[coordCount] = {};
coordList[coordCount].x = x;
coordList[coordCount].y = y - i;
coordList[coordCount].score = 0;
coordList[coordCount].vertical = false;
coordCount++;
}
}
}
}
}
}
function checkFitScore(word, x, y, vertical) {
var fitScore = 1; //default is 1, 2+ has crosses, 0 is invalid due to collision
if (vertical) { //vertical checking
for (i = 0; i < word.length; i++) {
if (i == 0 && x > 0) { //check for empty space preceeding first character of word if not on edge
if (grid[x - 1][y].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
} else if (i == word.length && x < GRID_HEIGHT) { //check for empty space after last character of word if not on edge
if (grid[x+i+1][y].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
}
if (x + i < GRID_HEIGHT) {
if (grid[x + i][y].targetChar == word[i]) { //letter match - aka cross point
fitScore += 1;
} else if (grid[x + i][y].targetChar != EMPTYCHAR) { //letter doesn't match and it isn't empty so there is a collision
fitScore = 0;
break;
} else { //verify that there aren't letters on either side of placement if it isn't a crosspoint
if (y < GRID_WIDTH - 1) { //check right side if it isn't on the edge
if (grid[x + i][y + 1].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
}
if (y > 0) { //check left side if it isn't on the edge
if (grid[x + i][y - 1].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
}
}
}
}
} else { //horizontal checking
for (i = 0; i < word.length; i++) {
if (i == 0 && y > 0) { //check for empty space preceeding first character of word if not on edge
if (grid[x][y-1].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
} else if (i == word.length - 1 && y + i < GRID_WIDTH -1) { //check for empty space after last character of word if not on edge
if (grid[x][y + i + 1].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
}
if (y + i < GRID_WIDTH) {
if (grid[x][y + i].targetChar == word[i]) { //letter match - aka cross point
fitScore += 1;
} else if (grid[x][y + i].targetChar != EMPTYCHAR) { //letter doesn't match and it isn't empty so there is a collision
fitScore = 0;
break;
} else { //verify that there aren't letters on either side of placement if it isn't a crosspoint
if (x < GRID_HEIGHT) { //check top side if it isn't on the edge
if (grid[x + 1][y + i].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
}
if (x > 0) { //check bottom side if it isn't on the edge
if (grid[x - 1][y + i].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
}
}
}
}
}
return fitScore;
}
function placeWord(word, clue, x, y, vertical) { //places a new active word on the board
var wordPlaced = false;
if (vertical) {
if (word.length + x < GRID_HEIGHT) {
for (i = 0; i < word.length; i++) {
grid[x + i][y].targetChar = word[i];
}
wordPlaced = true;
}
} else {
if (word.length + y < GRID_WIDTH) {
for (i = 0; i < word.length; i++) {
grid[x][y + i].targetChar = word[i];
}
wordPlaced = true;
}
}
if (wordPlaced) {
var currentIndex = activeWordList.length;
activeWordList[currentIndex] = {};
activeWordList[currentIndex].word = word;
activeWordList[currentIndex].clue = clue;
activeWordList[currentIndex].x = x;
activeWordList[currentIndex].y = y;
activeWordList[currentIndex].vertical = vertical;
if (activeWordList[currentIndex].vertical) {
downCount++;
activeWordList[currentIndex].number = downCount;
} else {
acrossCount++;
activeWordList[currentIndex].number = acrossCount;
}
}
}
function isActiveWord(word) {
if (activeWordList.length > 0) {
for (var w = 0; w < activeWordList.length; w++) {
if (word == activeWordList[w].word) {
//console.log(word + ' in activeWordList');
return true;
}
}
}
return false;
}
this.displayGrid = function displayGrid() {
var rowStr = "";
for (var x = 0; x < cols; x++) {
for (var y = 0; y < rows; y++) {
rowStr += "<td>" + grid[x][y].targetChar + "</td>";
}
$('#tempTable').append("<tr>" + rowStr + "</tr>");
rowStr = "";
}
console.log('across ' + acrossCount);
console.log('down ' + downCount);
}
//for each word in the source array we test where it can fit on the board and then test those locations for validity against other already placed words
this.generateBoard = function generateBoard(seed = 0) {
var bestScoreIndex = 0;
var top = 0;
var fitScore = 0;
var startTime;
//manually place the longest word horizontally at 0,0, try others if the generated board is too weak
placeWord(wordArray[seed].word, wordArray[seed].displayWord, wordArray[seed].clue, 0, 0, false);
//attempt to fill the rest of the board
for (var iy = 0; iy < FIT_ATTEMPTS; iy++) { //usually 2 times is enough for max fill potential
for (var ix = 1; ix < wordArray.length; ix++) {
if (!isActiveWord(wordArray[ix].word)) { //only add if not already in the active word list
topScore = 0;
bestScoreIndex = 0;
suggestCoords(wordArray[ix].word); //fills coordList and coordCount
coordList = shuffleArray(coordList); //adds some randomization
if (coordList[0]) {
for (c = 0; c < coordList.length; c++) { //get the best fit score from the list of possible valid coordinates
fitScore = checkFitScore(wordArray[ix].word, coordList[c].x, coordList[c].y, coordList[c].vertical);
if (fitScore > topScore) {
topScore = fitScore;
bestScoreIndex = c;
}
}
}
if (topScore > 1) { //only place a word if it has a fitscore of 2 or higher
placeWord(wordArray[ix].word, wordArray[ix].clue, coordList[bestScoreIndex].x, coordList[bestScoreIndex].y, coordList[bestScoreIndex].vertical);
}
}
}
}
if(activeWordList.length < wordArray.length/2) { //regenerate board if if less than half the words were placed
seed++;
generateBoard(seed);
}
}
}
function seedBoard() {
gameboard = new board(GRID_WIDTH, GRID_HEIGHT);
gameboard.generateBoard();
gameboard.displayGrid();
}
İki sayı üretirim: Uzunluk ve Scrabble puanı. Düşük bir Scrabble puanının, katılmanın daha kolay olduğu anlamına geldiğini varsayın (düşük puanlar = çok sayıda ortak harf). Listeyi azalan uzunluğa ve artan Scrabble skoruna göre sıralayın.
Ardından, listeye gidin. Sözcük, mevcut bir sözcükle çakışmazsa (sırasıyla her sözcüğün uzunluğuna ve Scrabble puanına göre kontrol edin), sonra sıraya koyun ve sonraki sözcüğü kontrol edin.
Durulayın ve tekrarlayın, bu bir bulmaca oluşturmalıdır.
Tabii ki, bunun O (n!) Olduğundan oldukça eminim ve bulmacayı sizin için tamamlayacağınızın garantisi yok, ama belki birileri onu geliştirebilir.
Bu problem hakkında düşünüyordum. Benim düşünceme göre, gerçekten yoğun bir bulmaca yaratmak için, sınırlı kelime listenizin yeterli olacağını umamazsınız. Bu nedenle, bir sözlüğü alıp bir "trie" veri yapısına yerleştirmek isteyebilirsiniz. Bu, soldaki boşlukları dolduran kelimeleri kolayca bulmanızı sağlayacaktır. Bir üçlüde, diyelim ki size "c? T" biçimindeki tüm kelimeleri veren bir geçiş uygulamak oldukça etkilidir.
Öyleyse, benim genel düşüncem şudur: Burada bazılarının düşük yoğunluklu bir haç oluşturmak için açıklandığı gibi bir tür nispeten kaba kuvvet yaklaşımı yaratın ve boşlukları sözlük kelimeleriyle doldurun.
Başka biri bu yaklaşımı benimsemişse, lütfen bana bildirin.
Bulmaca üretme motoru etrafında oynuyordum ve bunu en önemli buldum:
0.!/usr/bin/python
a. allwords.sort(key=len, reverse=True)
b. Daha sonra rastgele seçimle yinelemek istemediğiniz sürece, kolay yönlendirme için matriste dolaşacak imleç gibi bir öğe / nesne yapın.
birincisi, ilk çifti alın ve 0,0'dan aşağı ve aşağı yerleştirin; ilkini mevcut bulmaca 'liderimiz' olarak saklayın.
imleci çapraz veya rasgele sırayla hareket ettirin ve çapraz olasılıkla bir sonraki boş hücreye geçin
gibi kelimeleri yineleyin ve maksimum kelime uzunluğunu tanımlamak için boş alan uzunluğu kullanın:
temp=[]
for w_size in range( len( w_space ), 2, -1 ) :
# t
for w in [ word for word in allwords if len(word) == w_size ] :
#
if w not in temp and putTheWord( w, w_space ) :
#
temp.append( w )
kelimeyi kullandığım boş alanla karşılaştırmak için:
w_space=['c','.','a','.','.','.'] # whereas dots are blank cells
# CONVERT MULTIPLE '.' INTO '.*' FOR REGEX
pattern = r''.join( [ x.letter for x in w_space ] )
pattern = pattern.strip('.') +'.*' if pattern[-1] == '.' else pattern
prog = re.compile( pattern, re.U | re.I )
if prog.match( w ) :
#
if prog.match( w ).group() == w :
#
return True
Başarıyla kullanılan her kelimeden sonra yön değiştirin. Tüm hücreler doluyken döngü yapın VEYA kelimeleriniz biterse VEYA yineleme sınırı nedeniyle:
# CHANGE ALL WORDS LIST
inexOf1stWord = allwords.index( leading_w )
allwords = allwords[:inexOf1stWord+1][:] + allwords[inexOf1stWord+1:][:]
... ve yeni bulmacayı tekrar yineleyin.
Puanlama sistemini doldurma kolaylığı ve bazı tahmin hesaplamaları ile yapın. Mevcut bulmaca için puan verin ve puanlama sisteminizden puan tatmin edildiyse, bulmacalar listesine ekleyerek sonraki seçimi daraltın.
İlk yineleme oturumundan sonra, işi bitirmek için yapılan bulmacalar listesinden tekrar yineleyin.
Daha fazla parametre kullanarak hız, çok büyük bir faktörle iyileştirilebilir.
Olası çarpımları bilmek için her kelimenin kullandığı her harfin bir dizinini alırdım. O zaman en büyük kelimeyi seçer ve onu temel olarak kullanırdım. Bir sonraki büyük olanı seçin ve onu geçin. Durulayın ve tekrarlayın. Muhtemelen bir NP problemidir.
Başka bir fikir, güç ölçüsünün ızgaraya kaç kelime koyabileceğiniz olduğu genetik bir algoritma oluşturmaktır.
Bulduğum en zor kısım, belirli bir listenin ne zaman aşılamayacağını bilmek.
Bu , Harvard'dan AI CS50 kursunda bir proje olarak görünüyor . Buradaki fikir, çapraz kelime oluşturma problemini bir kısıtlama tatmin problemi olarak formüle etmek ve arama alanını azaltmak için farklı sezgisel yöntemlerle geriye doğru izleme ile çözmektir.
Başlamak için birkaç girdi dosyasına ihtiyacımız var:
'
###_####_#
____####_#
_##_#_____
_##_#_##_#
______####
#_###_####
#_##______
#_###_##_#
_____###_#
#_######_#
##_______#
'
Aday kelimelerin seçileceği bir giriş sözlüğü (kelime listesi / sözlük) (aşağıda gösterilen gibi).
a
abandon
ability
able
abortion
about
above
abroad
absence
absolute
absolutely
...
Şimdi CSP şu şekilde tanımlandı ve çözülecek:
Aşağıda, CSP çözme algoritmasının bir uygulaması kullanılarak elde edilen çıktı gösterilmektedir:
`
███S████D█
MUCH████E█
E██A█AGENT
S██R█N██Y█
SUPPLY████
█N███O████
█I██INSIDE
█Q███E██A█
SUGAR███N█
█E██████C█
██OFFENSE█
'
Aşağıdaki animasyon, geri izleme adımlarını gösterir:
İşte Bangla (Bengalce) kelime listesi olan bir tane daha:
Bu soruna bir JavaScript / jQuery çözümü kodladım:
Örnek Demo: http://www.earthfluent.com/crossword-puzzle-demo.html
Kaynak Kodu: https://github.com/HoldOffHunger/jquery-crossword-puzzle-generator
Kullandığım algoritmanın amacı:
Kullandığım algoritmayı açıklayacağım:
Kelimeleri ortak bir harfi paylaşanlara göre gruplayın.
Bu gruplardan, yeni bir veri yapısı ("kelime blokları") oluşturun, bu bir birincil kelime (tüm diğer kelimeleri geçen) ve sonra diğer kelimeleri (birincil kelimeden geçen).
Çapraz bulmacayı, bulmacanın en üst sol konumunda bu kelime bloklarının ilkiyle başlatın.
Kelime bloklarının geri kalanı için, bulmacanın en sağ-alt konumundan başlayarak, doldurulacak boş alan kalmayıncaya kadar yukarı ve sola doğru hareket edin. Yukarıya doğru soldan daha fazla boş sütun varsa, yukarı doğru hareket edin ve bunun tersi de geçerlidir.
var crosswords = generateCrosswordBlockSources(puzzlewords);
. Sadece bu değeri günlüğe kaydedin. Unutmayın, oyunda hemen değeri almak için "Yanıtı Göster" e tıklayabileceğiniz bir "hile modu" vardır.