Kreuzworträtsel Gitter erstellen
-
Hallo,
ich bin leidenschaftlicher Rätselrater und möchte daher einen Kreuzworträtselgenerator programmieren in C++.
Dazu habe ich folgendes Problem zum Aufbau eines leeren Rätselgitters, dh es sollen nur die Felder, die die Fragen aufnehmen vorhanden sein und in welcher Richtung das Lösungswort eingetragen werden muss.
Das "leere" Gitter soll folgende Bedingungen erfüllen:
1. Größe des Rätsels fest vorgegeben
2. jedes Feld nimmt entweder einen Buchstaben oder 1 Frage auf (es gibt also keine leeren Felder)
3. zu jedem Wort gibt es genau eine Frage, die in dem entsprechenden benachbarten Feld untergebracht ist(4. eine freie zusammenhängende Reihe (senkrecht/waagerecht) mit mind. 2 Buchstaben enthält ein Wort) muss nicht unbedingt sein
Frage: Wie sollte ich am besten an die Sache herangehen?
Eine Möglichkeit scheint mir ein Backtracking-Algorithmus sein, aber nach welchen Bedingungen soll ich die Felder für die Fragen setzen.
mori
PS: Falls jemand nicht weiß, welche Art Rätsel ich meine. Das Schwedenrätsel aus der Wikipedia:
http://de.wikipedia.org/wiki/Kreuzwortr%C3%A4tsel
-
Um das Kreuzworträtsel zu füllen, würde ich, um es schon mal sauber zu machen, eine "Wort"-Klasse und eine "Kreuzworträtsel"-Klasse anlegen. Das Kreuzworträtsel kann ja theoretisch aus einem zweidimensionalen char-Array "herstellen"; die Fragen muss man dann mit Zahlen repräsentieren oder irgendwie da reinpfriemeln...wie auch immer.
Als nächstes würde ich das Rätsel in vertikale Spalten unterteilen (sehr rechenintensiv
)und einen Algorithmus bauen, der immer prüft, wie viele Felder ein "Wort" benötigt (vertikal (wortlänge) und horizontal (1)) und dann die passenden "Wörter" auswählt. Wie man die leeren Felder dann macht, ist egal. Man kann ja z.B. noch ein zweites Kreuzworträtsel-Objekt machen und da alle Buchstaben rauslöschen, sodass man nur noch die Zahlen übrig hat.
Gut, dann fröhliche Weihnachten :xmas1: und viel Spaß beim Kreuzworträtseln,
LauritzG
-
mori schrieb:
Eine Möglichkeit scheint mir ein Backtracking-Algorithmus sein, aber nach welchen Bedingungen soll ich die Felder für die Fragen setzen.
Ich gehe davon aus, daß Du das 8-Damen-Problem schon gelöst hast.
Ich würde mich gar nicht an ein Schwedenrätsel trauen, sondern nur an ein amerikanisches Kreuzworträtsel (,wobei ich netterweise die Trennstriche schon drucken würde), zumal dabei die Vernetzung größer sein wird und auch mal längere Fragen möglich sind, wie "Wie heißt der Bürgermeister von Wesel? (Weskamp)" (muß man ja wissen).Auch würde ich wenn ich mich an ein Schwedenrätsel wagen würde, trotzdem vorher ein Amirätsel implementieren, um genug zu lernen für den Endsieg. Im Prinzip Backtracking, dabei für waagerecht und senkrecht unabhängig mitschreiben, welche Felder schon benutzt sind, es entsteht eine schräge "Küste" zwischen belegt und nicht-belegt. (Dieselbe Küste, die der Löser hat.) Nee, ist Unfug. Ich nehme alles zurück.
Mit so wenig Ahnung, wie ich davon habe, könnte ich nur genetische Algorithmen gegen das Problem werfen. Qualitätsmaß sind Vernetzung und tausendfach die Anzahl der Leerplätze.
Ich denke, ich würde erstmal eine Woche lang oder mehr Schwedenrätsel per Hand erstellen. Dabei muß0 sich einfach genug Durchblick ergeben, wie ich das programmtechnisch ansetzen sollte. Muß. Wenn nicht, halt zwei Wochen oder drei.
-
volkard schrieb:
Ich denke, ich würde erstmal eine Woche lang oder mehr Schwedenrätsel per Hand erstellen. Dabei muß0 sich einfach genug Durchblick ergeben, wie ich das programmtechnisch ansetzen sollte. Muß. Wenn nicht, halt zwei Wochen oder drei.
So viel ich weiss werden die durchaus noch von Menschen zusammengestellt. Habe mal irgendwo was gesehen, wo ein Mann das als Job hatte. Kann aber nicht mehr sagen, wo und wann das war. Kann mir aber durchaus vorstellen, dass die Zeitungsfirmen da durchaus Leute angeheuert haben, die die Dinger von Hand erstellen und keine Programmierer, die das ausprogrammieren.
Ich würde wahrscheinilch auch was mit Backtracking versuchen, auch wenn das bei so grossen Feldern ja recht mühsam werden kann..
-
Also ich würde vermuten, dass du vor allem erstmal eine wahnsinnig umfangreiche Datenbank mit Frage-Antwort-Kombinationen brauchst. Besonders viele kurzen Wörter mit 1-6 Buchstaben. Dann wird mit ein paar langen Wörtern ein Grundgerüst erstellt (meinetwegen von Hand) und dann irgendwie (das Wie ist dann der Trick) der Rest mit passenden Wörtern aus der Datenbank gefüllt.
Das ist zumindest meine Vermutung nachdem ich mal während eines Krankenhausaufenthaltes ein Kreuzworträtselheftchen durchgebracht habe. Die langen Wörter (>6 Buchstaben) sind immer andere, sie geben dem Rätsel Struktur. Der Rest ist immer das gleiche Füllmaterial, manchmal sogar mehrmals das gleiche in einem einzigen Rätsel.
-
drakon schrieb:
So viel ich weiss werden die durchaus noch von Menschen zusammengestellt.
Ja, die guten sind noch per Hand, so scheint es. Um so interessanter ist es, mal einen guten Bot zu bauen. Da steckt für denjenigen, der es gut schafft, ein mehrfaches Einkommen drin.
-
Danke erstmal für die Antworten.
drakon schrieb:
Als nächstes würde ich das Rätsel in vertikale Spalten unterteilen (sehr rechenintensiv
)und einen Algorithmus bauen, der immer prüft, wie viele Felder ein "Wort" benötigt (vertikal (wortlänge) und horizontal (1)) und dann die passenden "Wörter" auswählt. Wie man die leeren Felder dann macht, ist egal. Man kann ja z.B. noch ein zweites Kreuzworträtsel-Objekt machen und da alle Buchstaben rauslöschen, sodass man nur noch die Zahlen übrig hat.
Wegen der Komplexität des Problems, habe ich die Erstellung des Gitters und die "Lösung" (Füllen mit Wörtern) getrennt.
Bisher folgender Aufbau:
1. Grid-Klasse: liefert mir eine std::list<list_entry> mit den Positionen für Beschreibungsfelder und "Dummy-Wörtern".
struct list_entry { int len; // laenge int dir; // richtung int x; // start x-pos for word int y; // start y-pos for word int dx; // position for description int dy; // position for description std::string descr; std::string word; };
zur Zeit habe ich zu Testzwecken einen einfachen trivialen Ansatz gewählt.
Zuerst fülle ich die erst Zeile mit Beschreibungen und "Wörtern";
00 = leere Felder
| = Buchstabe für senkrechtes Wort
- = Buchstabe für waagerechtes Wort
+ = sowohl als auchZahlen grösser Null sind Beschreibungsfelder
04,32, |, |,08,16,16,16,16,16, -, -, +, +, -, |, |, |, |, |, 00,00, |, |,00, |, |, |, |, |, 00,00, *, *,00, |, |, |, |, |, 00,00,00,00,00, |, *, |, *, |, 00,00,00,00,00, |,00, *,00, |, 00,00,00,00,00, *,00,00,00, *, 00,00,00,00,00,00,00,00,00,00, 00,00,00,00,00,00,00,00,00,00, 00,00,00,00,00,00,00,00,00,00,
Dann die erste Spalte:
04,32, |, |,08,16,16,16,16,16, -, -, +, +, -, |, |, |, |, |, -, -, +, +, *, |, |, |, |, |, 02,00, *, *,00, |, |, |, |, |, 01, -, -, -, *, |, *, |, *, |, 04,00,00,00,00, |,00, *,00, |, -, -, -, *,00, *,00,00,00, *, 04,00,00,00,00,00,00,00,00,00, -, -, -, *,00,00,00,00,00,00, 01, -, -, -, *,00,00,00,00,00,
Dann der übrige Rest:
04,32, |, |,08,16,16,16,16,16, -, -, +, +, -, +, +, +, +, +, -, -, +, +,01, +, +, +, +, +, 02,16,01, +, -, +, +, +, +, +, 01, +, -, +,16, |,16, |,16, |, 04, |,16,01, +, +, +,16, |, |, -, +, +,16, |,01, +, +, +,16, 04,01, +, +, +, -, +, +, +, +, -, -, +, +, +,01, +, +, +, +, 01, -, +, +,01, -, +,01, +, +,
Dabei werden Sterne(Wortendemarkierungen), die im Wege sind einfach gelöscht.
Wie man an diesem Beispiel sieht, kommen durchaus brauchbare Lösungen heraus.
Aber bei weitem nicht immer. Bei dieser Variante ist eben nur garantiert, dass keine leeren Felder enstehen.Leider ist damit nicht garantiert, dass sich die Wörter überschneiden. Auch kommt es zu isolierten Worten (Wörter die durch Beschreibungsfelder komplett vom Rest des Rätsels getrennt sind).
Frage: Irgendwelche Ideen, wie ich auf dieser Grundlage das Gitter besser generieren kann??
2. Crosswordklasse: füllt die std::list<list_entry> mit Worten und der Beschreibung (das funkioniert bereits)
Beispiel: (für ein 10x10 felder grosses Rätsel)
Solved 47: ---------------- ZP FERIENGAST OLEA UTRUM SAMHARA HIT E R K Y TNS RA GDP H UOE ELEGIKER QUALM ZITA DKB RA ZN 1: (0,0) (0,1) dir=1 len=10 word= FERIENGAST = Urlauber 2: (1,0) (2,0) dir=0 len=3 word= ZRE = Auto-Z. Zaire 3: (4,0) (3,0) dir=0 len=5 word= PIAST = Angeh÷riger eines poln. Herrscherhauses 4: (5,0) (5,1) dir=0 len=5 word= NUMEN = Gottheit (lat.) 5: (6,0) (6,1) dir=0 len=3 word= GTH = Auto-Z. Gotha 6: (7,0) (7,1) dir=0 len=4 word= ARAR = Wadi in Saudi-Arabien 7: (8,0) (8,1) dir=0 len=3 word= SUR = Nebenfluss der Aare 8: (9,0) (9,1) dir=0 len=5 word= TMAKA = Nebenfluss der Wolga 9: (4,2) (5,2) dir=1 len=5 word= UTRUM = Begriff aus der Sprachwissenschaft 10: (0,3) (0,2) dir=1 len=4 word= OLEA = rauchende Schwefelsõuren 11: (1,3) (1,4) dir=0 len=3 word= HYD = griech.: Wasser 12: (2,3) (3,3) dir=1 len=7 word= SAMHARA = afrik. Staat 13: (0,4) (1,4) dir=1 len=3 word= HIT = zugkrõftiges Angebot, Objekt 14: (4,4) (4,5) dir=0 len=4 word= THEM = engl.: sich 15: (6,4) (6,5) dir=0 len=5 word= SUIZA = span.: Schweiz 16: (8,4) (8,5) dir=0 len=5 word= REETZ = Stadt in der Neumark 17: (0,5) (0,6) dir=1 len=3 word= GDP = Abk.: gesamtdt. Partei 18: (2,5) (2,6) dir=0 len=4 word= PEAK = engl.: Berggipfel 19: (3,5) (4,5) dir=1 len=3 word= TNS = Trõger der Erbanlagen 20: (7,5) (7,6) dir=0 len=3 word= OKI = jap. Insel 21: (3,6) (3,7) dir=0 len=3 word= LLB = Abk.: legum baccalaureus 22: (5,6) (6,6) dir=1 len=3 word= UOE = Abk.: und ÷fters 23: (9,6) (9,7) dir=0 len=3 word= RAN = nord. Herrin des Meeres 24: (0,7) (0,8) dir=1 len=5 word= QUALM = Schwaden 25: (1,7) (2,7) dir=1 len=8 word= ELEGIKER = Klagelieddichter 26: (5,8) (6,8) dir=1 len=4 word= ZITA = Frauenname 27: (0,9) (1,9) dir=1 len=3 word= DKB = Auto-Z. Dinkelsb³hl 28: (4,9) (5,9) dir=1 len=2 word= RA = Papyrusboot Thor Heyerdahls 29: (7,9) (8,9) dir=1 len=2 word= ZN = chem. Z. f³r Zink
mori
PS: Das Gitter zu Pkt. 1 ist das selbe, was unter Pkt.2 mit Wörtern gefüllt wurde.
-
Das ist nicht mein Quote.
-
@drakon: per hand und per generator gibt es beides und teilweise auch zusammen. Handarbeit kommt heutzutage meistens nur noch dann ins Spiel, wenn Wunsch- bzw. Pflichtbegriffe ins Kreuzworträtsel integriert werden sollen. Oder bei Querdenker-Rätseln zum um die Ecke denken.
@volkard bzgl. "mal einen guten bot bauen":
Es gibt bereits rund ein Dutzend Kreuzworträtselgeneratoren auf dem Markt. Wieso glaubst du, dass die ALLE stümperhaft oder zumindest nicht gut programmiert haben?@SeppJ.: Deine Vermutung ist goldrichtig. Das Wesentliche ist eine riesengroße Datenbank. Mit nur 10.000 oder 20.000 Begriffen braucht man erst gar nicht anzufangen. Man bekommt zwar komplette Rätsel hin, aber die Qualität ist leider unter aller Sau.
@mori: Sorry, aber die Begriffe aus deiner Datenbank sind absolut nicht zumutbar. Mal ehrlich, ... wieviele der 29 Fragen sind für Normalsterbliche beantwortbar? Zwei? Vier? Nur ganze drei Begriffe haben mehr als 5 Buchstaben, zwei Drittel sind Füllwörter. Einige Erdkundefragen und Kfz-Kennzeichen sind seit 20 oder 30 Jahren veraltet und nicht mehr gültig. Ich möchte dich bei deinem Projekt nicht entmutigen, aber überprüf doch bitte mal, wieviele der Begriffe im Duden oder in der Wikipedia zu finden sind. Wenn du dir mit so einer Vorgehensweise Erfolg erhoffst, wirst du dir zwar eine Menge Arbeit, aber keine Freunde in der Rätselgemeinde machen. Egal wie gut programmiert dein zukünftiger Rätselgenerator sein mag.
Rätselhafte Grüße, Andreas.
P.S.: ich weiß, wovon ich schreibe --->
www.raetsel4u.de
www.raetselfieber.de
www.kreuzifix.de
-
@ andydoubleyou : Das bei meinem Beispiel so viele kleine Worte vorkommen, liegt einfach an der von mir so gewollten Einstellung, da diese Gittererstellung für meinen Generator schwieriger ist.
Was die Qualität der Datenbank angeht, ist beim 1. Beispiel nur so viel Schrott dabei, weil ich zum Testen keine Filtereinstellungen verwende.
anderes Beispiel gefällig:
FA WI K CABARET L DW STATER BEACHTLICH NE ABISKO NR NEK SE MUT SWEBEN DS NERR RE CHR ABS LUEBBECKE 1: (0,0) (1,0) dir=0 len=10 word= FADENNUDEL = Teigware 2: (3,0) (2,0) dir=0 len=8 word= ABWAERTS = nach unten 3: (4,0) (5,0) dir=0 len=10 word= WETTBEWERB = Konkurrenz 4: (7,0) (6,0) dir=0 len=8 word= ITALIKER = alte Bewohner Italiens 5: (9,0) (8,0) dir=0 len=7 word= KLECKSE = Spritzer, Fleck (Mz.) 6: (7,1) (7,2) dir=0 len=3 word= TIS = Nebenfluss des Jenissei 7: (9,1) (9,2) dir=0 len=5 word= RHOEN = Gebirge in Mitteldeutschland 8: (0,2) (0,1) dir=1 len=7 word= CABARET = Musicalfilm 9: (3,2) (4,2) dir=1 len=6 word= STATER = altgriech. M³nze 10: (0,4) (0,3) dir=1 len=10 word= BEACHTLICH = stattlich 11: (3,4) (4,4) dir=1 len=6 word= ABISKO = Naturschutzgebiet in Schweden 12: (0,5) (0,6) dir=1 len=3 word= MUT = Draufgõngertum 13: (3,5) (4,5) dir=1 len=3 word= NEK = it. Popsõnger 14: (7,5) (7,6) dir=0 len=4 word= BRAC = jugoslawische Adriainsel 15: (3,6) (4,6) dir=1 len=6 word= SWEBEN = westgerman. V÷lkergruppe 16: (0,7) (0,8) dir=1 len=2 word= RE = zur³ck 17: (3,7) (4,7) dir=1 len=4 word= NERR = hollõnd. Maler 18: (8,7) (8,8) dir=0 len=2 word= BK = Zeichen f. chemisches Element Berkelium 19: (9,7) (9,8) dir=0 len=2 word= SE = Abk.: South East 20: (2,8) (3,8) dir=1 len=3 word= CHR = Abk.: Christus 21: (6,8) (7,8) dir=1 len=3 word= ABS = dt. Bankier 22: (0,9) (1,9) dir=1 len=9 word= LUEBBECKE = Stadt in NRW
mori
-
#include <stdio.h> #include <string.h> #define GROESSFELDX 16 // war 5 s unten war 10 #define GROESSFELDY 16 #define NUM_WORDS 33 // war 152 long int runs=0; unsigned char screen[GROESSFELDX][GROESSFELDY]; unsigned char screeno[GROESSFELDX][GROESSFELDY]; int wordnum; struct { unsigned char word[30]; unsigned int len; unsigned int taken; } words[NUM_WORDS]; long best_score; int fieldnotfull; void backupfield(long score) { int x=0, y=0; while ( y < GROESSFELDY) { x=0; while ( x < GROESSFELDX) { //if ( screen[x][y]==' ') return ; x++; } y++; } fieldnotfull=0; y=0; while ( y < GROESSFELDY) { x=0; while ( x < GROESSFELDX) { screeno[x][y]=screen[x][y]; x++; } y++; } best_score=score; system("cls\n"); y=0; while ( y < GROESSFELDY+2) { x=0; while ( x < GROESSFELDX+2) { if ( y== GROESSFELDY+1 || y==0) printf("-"); else if ( x==0 || x == GROESSFELDX+1) printf("|"); else printf("%c",toupper(screeno[x-1][y-1])); x++; } printf("\n"); y++; } printf("%d\n",best_score); } int crossword(int rec_depth, long score ) { int n; unsigned char wordbuf[50]; //if ( rec_depth < 30)printf("%d ",rec_depth); if ( score >= best_score || fieldnotfull==1 ) backupfield(score); if ( rec_depth > NUM_WORDS ) return 0; long score2=0; int y=0, x=0; int horv=0; int wordnum; wordnum=0; while ( wordnum < NUM_WORDS && words[wordnum].taken==1)wordnum++; if ( wordnum==NUM_WORDS) return 1; //while ( wordnum < NUM_WORDS) if ( rec_depth > 0 && rand()%(score+1)==0) return 1; repeat: if ( kbhit()) return ; if ( rand()%2==0) horv='h'; else horv='v'; x=rand()%GROESSFELDX, y=rand()%GROESSFELDY; wordnum=0; while ( words[wordnum].taken==1 && wordnum < NUM_WORDS )wordnum++; if ( wordnum==NUM_WORDS) return 1; do { wordnum=rand()%NUM_WORDS; }while ( words[wordnum].taken==1 ); //printf("binda %d\n", wordnum); score2=0; if ( horv=='h' ) { if ( x+words[wordnum].len >= GROESSFELDX ) { x++; goto repeat; } n=0; while ( n < words[wordnum].len && x+n < GROESSFELDX ) { if ( screen[x+n][y]!= words[wordnum].word[n] && screen[x+n][y]!=' ' ) { x++; score2=0; goto repeat; } if ( screen[x+n][y]==words[wordnum].word[n] && words[wordnum].taken==0) score2+=100; if ( screen[x][y+n]==' ') score2++; n++; } if ( n!= words[wordnum].len) score2=0; n=0; while ( n < words[wordnum].len && n+x < GROESSFELDX) { wordbuf[n]=screen[x+n][y]; screen[x+n][y]= words[wordnum].word[n]; n++; } int old_wordnum; int wbuflen; wbuflen=words[wordnum].len; old_wordnum=wordnum; //wordnum++; words[wordnum].taken=1; if ( rec_depth==0 || score2 > 100) { if (score+score2>5000) crossword(rec_depth+1,score+score2+words[wordnum].len/40); if (score+score2>2000) crossword(rec_depth+1,score+score2+words[wordnum].len/40); if (score+score2>1000) crossword(rec_depth+1,score+score2+words[wordnum].len/40); if (score+score2>400) crossword(rec_depth+1,score+score2+words[wordnum].len/40); if (score+score2>300) crossword(rec_depth+1,score+score2+words[wordnum].len/40); if (score+score2>200) crossword(rec_depth+1,score+score2+words[wordnum].len/40); if (score+score2>100) crossword(rec_depth+1,score+score2+words[wordnum].len/40); /* if ( */if (score+score2>=0) crossword(rec_depth+1,score+score2+words[wordnum].len/40); /* ==0) return 0; */ // else } { int n2=0; n2=0; while ( n2 < wbuflen && n2+x < GROESSFELDX ) screen[x+n2][y]=wordbuf[n2],n2++; score2=0; words[old_wordnum].taken=0; //wordnum=old_wordnum; x++; goto repeat; } } if ( horv=='v' ) { if ( y+words[wordnum].len >= GROESSFELDY ) { x++; goto repeat; } n=0; while ( n < words[wordnum].len && y+n < GROESSFELDY ) { if ( screen[x][y+n]!= words[wordnum].word[n] && screen[x][y+n]!=' ' ) { x++; score2=0; goto repeat; } if ( screen[x][y+n]==words[wordnum].word[n] && words[wordnum].taken==0) score2+=100; if ( screen[x][y+n]==' ') score2++; n++; } if ( n!= words[wordnum].len) score2=0; n=0; while ( n < words[wordnum].len && n+y < GROESSFELDY) { wordbuf[n]=screen[x][y+n]; screen[x][y+n]= words[wordnum].word[n]; n++; } int old_wordnum; int wbuflen; wbuflen=words[wordnum].len; words[wordnum].taken=1; old_wordnum=wordnum; //wordnum++; if ( rec_depth==0 || score2 > 100) { if (score+score2>5000) crossword(rec_depth+1,score+score2+words[wordnum].len/40); if (score+score2>2000) crossword(rec_depth+1,score+score2+words[wordnum].len/40); if (score+score2>1000) crossword(rec_depth+1,score+score2+words[wordnum].len/40); if (score+score2>400) crossword(rec_depth+1,score+score2+words[wordnum].len/40); if (score+score2>300) crossword(rec_depth+1,score+score2+words[wordnum].len/40); if (score+score2>200) crossword(rec_depth+1,score+score2+words[wordnum].len/40); if (score+score2>100) crossword(rec_depth+1,score+score2+words[wordnum].len/40); /* if ( */if (score+score2>=0) crossword(rec_depth+1,score+score2+words[wordnum].len/40); /* ==0) return 0; */ // else } { int n2=0; n2=0; while ( n2 < wbuflen && n+y < GROESSFELDY ) screen[x][y+n2]=wordbuf[n2],n2++; score2=0; words[old_wordnum].taken=0; //wordnum=old_wordnum; x++; goto repeat; } } /* wordnum++; while ( words[wordnum].taken==1 && wordnum < NUM_WORDS )wordnum++; if ( wordnum==NUM_WORDS) return 1; wordnum%=NUM_WORDS; */ return 1; } int main(void) { FILE *input; int wc; unsigned char cpstring[30]; wc=0; input=fopen(".\\words.txt","rb"); while ( wc < NUM_WORDS ) { fscanf(input,"%s\n",cpstring); strcpy(words[wc].word,cpstring); words[wc].len=strlen(cpstring); words[wc].taken=0; wc++; } wordnum=0; fclose(input); int x=0,y=0; while ( y < GROESSFELDY ) { x=0; while ( x < GROESSFELDX) { screen[x][y]=' '; screeno[x][y]=' '; x++; } y++; } best_score=0; fieldnotfull=1; crossword(0,0); system("cls\n"); y=0; while ( y < GROESSFELDY+2) { x=0; while ( x < GROESSFELDX+2) { if ( y== GROESSFELDY+1 || y==0) printf("-"); else if ( x==0 || x == GROESSFELDX+1) printf("|"); else printf("%c",toupper(screeno[x-1][y-1])); x++; } printf("\n"); y++; } } /* #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> struct { unsigned char wort[255]; }woerter[250000]; int main(int argc, char *argv[]) { FILE *input, *output; unsigned char c; unsigned long int n; unsigned long int wc; unsigned char cmpstring[255]; if ( argc!=2) return 1; input=fopen(argv[1],"rb"); if ( input==NULL) { printf("Datei nicht gefunden!"); return 1; } wc=0; while (1) { n=0; while (!isalpha(c=fgetc(input))&& !feof(input)) { } do { if ( feof(input)) { fclose(input); printf("%d\n", wc); goto writelist; } cmpstring[n]=tolower(c); n++; if ( n==254) break; } while (isalpha(c=fgetc(input))&& !feof(input)&&n < 254); cmpstring[n]='\0'; if ( n > 2 ) // { // n=0; while ( n < wc) { if ( strcmp(cmpstring,woerter[n].wort)==0) { break; } n++; } if ( n==wc) { strcpy(woerter[n].wort,cmpstring); wc++; } if ( wc==250000) { printf("Mindestens eine viertel Million Woerter!"); return 2; } } } // writelist: if ( wc > 0) { output=fopen(".\\wortliste.txt","wb"); while (wc > 0) { wc--; fprintf(output,"%s\n", woerter[wc].wort ); } fclose(output); } return 0; } */
Es dürfte halt für ein Schwedenrätsel nur horizontale mit vertikalen Buchstaben und umgekehrt überkreuzen. So findet es halt auch teilweise Buchstabenübereinstimmungen in Wörtern und versucht, so viele wie möglich ins so und so große Raster zu quetschen.
Der Trick besteht wohl hauptsächlich darin, daß das Backtracking nur dann tiefer gräbt, wenn bereits eine (oder mehrere?) Überkreuzungen gefunden wurden.