Torna indietro   Hardware Upgrade Forum > Software > Programmazione

WoW Forever: la beta è stato uno dei momenti più alti della storia dei videogiochi, e non si ripeterà
WoW Forever: la beta è stato uno dei momenti più alti della storia dei videogiochi, e non si ripeterà
Un mondo affollato e vivo, personaggi destinati a sparire a fine test e nessuno a inseguire l'oggetto giusto. Beta e stress test di World of Warcraft: Forever hanno fatto emergere un roleplay spontaneo, tra danze a Goldshire e code ordinate ai PNG
Oracle AI World 2026: in Europa prima la sovranità, poi la sicurezza e solo dopo l'IA
Oracle AI World 2026: in Europa prima la sovranità, poi la sicurezza e solo dopo l'IA
In tre giorni a Las Vegas Oracle ha presentato agenti che eseguono il lavoro, l'alleanza con OpenAI e un cloud aperto agli acceleratori di tutti. Ma i clienti europei chiedono garanzie prima ancora delle funzionalità
DS N°7 E-Tense: il SUV premium made in Melfi che punta su autonomia e comfort
DS N°7 E-Tense: il SUV premium made in Melfi che punta su autonomia e comfort
Fino a 740 km WLTP con la batteria da 97,2 kWh, sospensioni che leggono la strada con una telecamera e un abitacolo da salotto parigino. La nuova DS N°7 raccoglie l'eredità della DS 7 e la porta, per la prima volta, nel mondo 100% elettrico. Ecco come è fatta, cosa offre e quanto costa.
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 29-11-2011, 00:07   #1
ercand
Member
 
Iscritto dal: Sep 2004
Messaggi: 216
[C#]Algoritmo per generare un cruciverba

Ciao a tutti, sto cercando di scrivere un semplice generatore di cruciverba.
Credevo fosse più "facile" ed invece mi sono impantanato quasi subito e sono qui a chiedere un po di aiuto per sbloccarmi.

Pensavo di creare una funzione da richiamare ricorsivamente e, ad ogni ricorsione, aggiungere una nuova parola alla griglia.
Purtroppo applicare questa idea è più difficile di quanto pensassi, fino ad ora ho scritto il seguente codice

Codice:
class Coordinate
    {
        public int X { get; set; }
        public int Y { get; set; }

        public Coordinate(int x, int y)
        {
            X = x;
            Y = y;
        }
    }


    public enum Orientation
    {
        Horizontal,
        Vertical
    }

    class Crosswords
    {
        public delegate void DelegateUpgradeScheme(Scheme sender);
        public event DelegateUpgradeScheme HandleUpdateScheme;

        private List<String> dizionario;
        private int nRow = 20;
        private int nCoulumns = 20;
        public char[][] _scheme;

        public Crosswords()
        {
            ReadDictionary();
            ResetGrid();
        }
        public void Fill()
        {
            Scheme tempScheme = new Scheme(20, 20);
            Generate("", new Coordinate(0, 0), tempScheme, Orientation.Horizontal);
        }

        public void Generate(String lastWord, Coordinate coord, Scheme scheme, Orientation orient)
        {
            List<String> candidateWords = FindCandidates(lastWord, coord, scheme, orient);

            for (int i = 0; i < candidateWords.Count; i++)
            {
                Scheme tempScheme = new Scheme(scheme);
                WriteWord(candidateWords[i], tempScheme, coord, orient);
                
                // Aggiorna il form
         //       HandleUpdateScheme.Invoke(tempScheme);

                Generate(candidateWords[i][0].ToString(), coord, tempScheme, Orientation.Vertical);
            }

            return;
        }

        private void WriteWord(String word, Scheme scheme, Coordinate coord, Orientation orient)
        {
            if (orient == Orientation.Horizontal)
            {
                for (int i = 0; i < word.Length; i++)
                {
                    scheme.crossword[coord.X][coord.Y + i] = word[i];
                }

                // Se c'è ancora una casella libera dopo l'ultima lettera la contrassegno come "cella nera"
                if (coord.X + word.Length < scheme.Columns)
                {
                    scheme.crossword[coord.X][coord.Y + word.Length] = '#';
                }
            }
            else
            {
                for (int i = 0; i < word.Length; i++)
                {
                    scheme.crossword[coord.X + i][coord.Y] = word[i];
                }
                // Se c'è ancora una casella libera dopo l'ultima lettera la contrassegno come "cella nera"
                if (coord.X + word.Length < scheme.Rows)
                {
                    scheme.crossword[coord.X + word.Length][coord.Y] = '#';
                }
            }
        }

        private List<String> FindCandidates(String word, Coordinate coord, Scheme scheme, Orientation orient)
        {
            List<String> candidateWords = new List<String>();
            int lenght = 0;

            // Controlla il numero massimo di caratteri ce la parola può contenere
            if (orient == Orientation.Horizontal)
            {
                for (int i = 0 + coord.X; i < scheme.Columns; i++)
                {
                    if (scheme.crossword[coord.X][i] == '.')
                    {
                        lenght++;
                    }
                }
            }
            else
            {
                for (int i = 0 + coord.Y; i < scheme.Rows; i++)
                {
                    if (scheme.crossword[i][coord.Y] == '.')
                    {
                        lenght++;
                    }
                }
            }

            // Se la lunghezza è minore di 2 allora non ci sono possibili parole da inserire
            if (lenght < 2)
                return candidateWords;

            
            // Cicla sulle parole del dizionario e controlla quali possono essere messe
            foreach (String c in dizionario)
            {
                if (c.IndexOf(word) >= 0 && c.Length < lenght)
                {
                    candidateWords.Add(c);
                }
            }

            return candidateWords;
        }


        private void ResetGrid()
        {
            // Resetta la griglia riempendola di caratteri '.'
        }

        private void ReadDictionary()
        {
              //Legge da un file tutte le parole presenti nel mio dizionario
        }
Questa è la classe Scheme, crea semplicemente una griglia
Codice:
class Scheme
    {
        public int Rows { get; set; }
        public int Columns { get; set; }
        
        public char[][] crossword;


        public Scheme(int rows, int columns)
        {
            Rows = rows;
            Columns = columns;
            ResetGrid();
        }

        public Scheme(Scheme scheme):this(scheme.Rows, scheme.Columns)
        {
            for (int i = 0; i < scheme.Rows;i++ )
            {
                for (int j = 0; j < scheme.Columns;j++ )
                {
                    crossword[i][j] = scheme.crossword[i][j];
                }
            }
        }

        private void ResetGrid()
        {
            char[][] tempCrossword = new char[Rows][];
            for (int i = 0; i < tempCrossword.Length; i++)
            {
                tempCrossword[i] = new char[Columns];
                for (int j = 0; j < tempCrossword[i].Length; j++)
                    tempCrossword[i][j] = '.';
            }
            crossword = tempCrossword;
        }
    }
Qualunque consiglio per riuscire a farmi sbloccare sarebbe ben accetto, grazie a tutti per l'aiuto

Ultima modifica di ercand : 29-11-2011 alle 00:11.
ercand è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2011, 05:38   #2
Floris
Senior Member
 
L'Avatar di Floris
 
Iscritto dal: Jan 2007
Messaggi: 2267
Ma le parole devono essere prese da un insieme predefinito o possono essere qualunque?
__________________
Concluso con:...
Floris è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2011, 14:41   #3
ercand
Member
 
Iscritto dal: Sep 2004
Messaggi: 216
Le parole le prendo da un file txt dove sono elencato poco più di 100k parole.
ercand è offline   Rispondi citando il messaggio o parte di esso
Old 03-12-2011, 22:34   #4
ercand
Member
 
Iscritto dal: Sep 2004
Messaggi: 216
Ho sperimentato un poco questi giorni e sono arrivato a scriveere questo

Codice:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using System.Text.RegularExpressions;

namespace CruciverbaNet
{
    class Coordinate
    {
        public int Row { get; set; }
        public int Column { get; set; }

        public Coordinate(int row, int column)
        {
            Row = row;
            Column = column;
        }

        public Coordinate(Coordinate coord) : this(coord.Row, coord.Column)
        {}

        public int CompareTo(Coordinate coord)
        {
            if (Column < coord.Column){
                return -1;
            }
            if (Column > coord.Column){
                return 1;
            }
            
            // Le coordinate sono sulla stessa colonne, controlla le riga
            if (Row < coord.Row){
                return -1;
            }
            if (Row > coord.Row){
                return 1;
            }
            return 0;
        }
    }

    public enum EnumOrientation
    {
        Horizontal,
        Vertical
    }

    class Orientation
    {
        public EnumOrientation Orient;

        public Orientation(EnumOrientation orient)
        {
            Orient = orient;
        }

        public Orientation(Orientation orient)
            : this(orient.Orient)
        {

        }
    }

    class Crosswords
    {
        public delegate void DelegateUpgradeScheme(Scheme sender);
        public event DelegateUpgradeScheme HandleUpdateScheme;

        private List<String> dizionario;
        private Dictionary<int, List<String>> dizionarioAlfabetico;
        private List<String> busyWords;
        private int nRow = 20;
        private int nCoulumns = 20;
        public char[][] _scheme;

        public Crosswords()
        {
            ReadDictionary();
            ResetGrid();
            busyWords = new List<String>();
        }

        public void Fill()
        {
            Scheme tempScheme = new Scheme(20, 20);
            Generate("", new Coordinate(0, 0), tempScheme, new Orientation(EnumOrientation.Vertical));
        }

        public bool Generate(String lastWord, Coordinate coord, Scheme scheme, Orientation orient)
        {
            Orientation tempOrient = new Orientation(orient);

            // Troviamo la prima cella libera
            Coordinate tempCoord = FindNextFreeSPace(tempOrient, scheme);

            // Se è null non ci sono piu celle libere, cruciverba riempito
            if (tempCoord == null){
                return true;
            }

            // Recuperiamo la parola che passa per la coordinata specificata
            String tempWord = intersectingWord(tempCoord, tempOrient.Orient, scheme);
            int tempWordLength = tempWord.Length;

            // Cerco le possibili parole candidate
            List<String> candidatesWord = new List<String>();

            while (tempWord.Length > 1 && tempWord[tempWord.Length - 1] == '.'){
                tempWord = tempWord.Substring(0, tempWord.Length - 1);
            }

            // Trovo le possibili parole che possono essere usate
            for (int i = 0; i < dizionario.Count; i++)
            {
                if (Regex.IsMatch(dizionario[i], "^" + tempWord) && dizionario[i].Length < tempWordLength)
                    if (busyWords.Contains(dizionario[i]) == false) // Controlliamo che non sia tra le parole gia usate
                        candidatesWord.Add(dizionario[i]);
            }

            Scheme tempScheme = new Scheme(scheme);
            for (int i = 0; i < candidatesWord.Count; i++)
            {
                if (WriteWord(candidatesWord[i], tempScheme, tempCoord, tempOrient.Orient))
                {
                    // Aggiorna il form
                    HandleUpdateScheme.Invoke(tempScheme);

                    // Aggiungo la parola lla lista di quelle gia usate
                    busyWords.Add(candidatesWord[i]);

                    // Se le parole non si interseca torna un passo indietro
                    if (Generate(candidatesWord[i][0].ToString(), new Coordinate(0, 0), tempScheme, new Orientation(EnumOrientation.Vertical)) == false)
                    {
                        tempScheme = new Scheme(scheme);
                        HandleUpdateScheme.Invoke(tempScheme);
                        busyWords.Remove(candidatesWord[i]);
                    }
                }

            }

            // Non è stata trovata nessuna combinazione, ritorno false
            return false;
        }

        public Coordinate FindNextFreeSPace(Orientation orient, Scheme scheme)
        {
            Coordinate coordVert = FindNextOrientedFreeSpace(EnumOrientation.Vertical, scheme);
            Coordinate coordHori = FindNextOrientedFreeSpace(EnumOrientation.Horizontal, scheme);

            // Se non sono state trovare ne spazi verticali ne orizzontali
            if (coordHori == null && coordVert == null) {
                return null;
            }
            else if ((coordHori == null || coordVert != null) && coordVert.CompareTo(coordHori) < 0) {
                orient.Orient = EnumOrientation.Vertical;
                return coordVert;
            }
            orient.Orient = EnumOrientation.Horizontal;
            return coordHori;
        }

        public Coordinate FindNextOrientedFreeSpace(EnumOrientation orient, Scheme scheme)
        {
            for (int i = 0; i < scheme.Rows; i++)
            {
                for (int j = 0; j < scheme.Columns; j++)
                {
                    String temp = intersectingWord(new Coordinate(i, j), orient, scheme);
                    if (temp != null && temp.IndexOf(".") >= 0)
                        return new Coordinate(i, j);
                }
            }
            return null;
        }

        /// <summary>
        /// Cerca la stringa passante per la coordinata e con l'orientamento specificato
        /// </summary>
        /// <param name="coord"></param>
        /// <param name="orient"></param>
        /// <param name="scheme"></param>
        /// <returns></returns>
        private String intersectingWord(Coordinate coord, EnumOrientation orient, Scheme scheme)
        {
            // E' una cella nera
            if (getSchemaChar(coord, scheme) == '#')
                return null;

            String result = "" + getSchemaChar(coord, scheme);
            Coordinate tempCoord = new Coordinate(coord.Row, coord.Column);
            if (orient == EnumOrientation.Vertical)
            {	//Se è in verticale concateno i caratteri in colonna spostandomi di riga
                tempCoord.Row--;
                while (tempCoord.Row >= 0 && getSchemaChar(tempCoord, scheme) != '#')
                {
                    result = getSchemaChar(tempCoord, scheme) + result;
                    tempCoord.Row--;
                }
                tempCoord.Row = coord.Row + 1;
                while (tempCoord.Row < scheme.crossword.Length && getSchemaChar(tempCoord, scheme) != '#')
                {
                    result = result + getSchemaChar(tempCoord, scheme);
                    tempCoord.Row++;
                }
            }
            else
            {	//Se è in orizzontale concateno i caratteri in riga spostandomi di colonna
                tempCoord.Column--;
                while (tempCoord.Column >= 0 && getSchemaChar(tempCoord, scheme) != '#')
                {
                    result = getSchemaChar(tempCoord, scheme) + result;
                    tempCoord.Column--;
                }
                tempCoord.Column = coord.Column + 1;
                while (tempCoord.Column < scheme.crossword[coord.Row].Length && getSchemaChar(tempCoord, scheme) != '#')
                {
                    result = result + getSchemaChar(tempCoord, scheme);
                    tempCoord.Column++;
                }
            }
            // Una sola lettera
            if (result.Length == 1)
                return null;

            return result;
        }

        private char getSchemaChar(Coordinate coord, Scheme scheme)
        {
            return scheme.crossword[coord.Row][coord.Column];
        }


        private bool WriteWord(String word, Scheme scheme, Coordinate coord, EnumOrientation orient)
        {
            if (orient == EnumOrientation.Horizontal)
            {
                bool ok = true;

                for (int i = 0; i < word.Length; i++)
                {
                    String intersectedWord = intersectingWord(new Coordinate(coord.Row, coord.Column + i), EnumOrientation.Vertical, scheme);

                    while (intersectedWord.Length > 0 && intersectedWord[intersectedWord.Length - 1] == '.')
                    {
                        intersectedWord = intersectedWord.Substring(0, intersectedWord.Length - 1);
                    }
                    int howManyMatch = 0;

                    // Controlla se esistono parole compatibili con quella che incrociamo
                    for (int j = 0; j < dizionario.Count && howManyMatch == 0; j++)
                    {
                        if (Regex.IsMatch(dizionario[j], intersectedWord))
                        {
                            howManyMatch++;
                        }
                    }
                    if (howManyMatch == 0)
                    {
                        ok = false;
                    }
                }
				
                // La parola è compatibile, la scrivo nello schema
                if (ok == true)
                {
                    for (int i = 0; i < word.Length; i++)
                        scheme.crossword[coord.Row][coord.Column + i] = word[i];

                    // Se c'è ancora una casella libera dopo l'ultima lettera la contrassegno come "cella nera"
                    if (coord.Row + word.Length < scheme.Columns)
                    {
                        scheme.crossword[coord.Row][coord.Column + word.Length] = '#';
                    }
                }
                else
                    return false;

            }
            else
            {
                bool ok = true;

                for (int i = 0; i < word.Length; i++)
                {
                    String intersectedWord = intersectingWord(new Coordinate(coord.Row + i, coord.Column), EnumOrientation.Horizontal, scheme); // Parola che interseca la coordinata attuale

                    if (intersectedWord.IndexOf(".") < 0) // Se le celle sono tutte occupate
                        continue;

                    int toSubtract = 0;
                    while (intersectedWord.Length -toSubtract> 0 && intersectedWord[intersectedWord.Length - 1 - toSubtract] == '.') {
                        ++toSubtract;
                    }
                    intersectedWord = intersectedWord.Substring(0, intersectedWord.Length - toSubtract);

                    int howManyMatch = 0;

                    if (intersectedWord.Length > 0 && intersectedWord[0]!= '.')
                    {
                        int codeChar = Convert.ToInt32(intersectedWord[0]);
                        int wordCount = dizionarioAlfabetico[codeChar].Count;
                        String regExpWord = "^" + intersectedWord + word[i];

                        // Controlla se esistono parole compatibili con quella che incrociamo
                        for (int j = 0; j < wordCount && howManyMatch == 0; j++)
                        {
                            if (Regex.IsMatch(dizionarioAlfabetico[codeChar][j], regExpWord))
                            {
                                howManyMatch++;
                            }
                        }
                    }
                    else
                    {
                        int codeChar = Convert.ToInt32(word[i]);
                        int wordCount = dizionarioAlfabetico[codeChar].Count;
                        String regExpWord = "^" + intersectedWord + word[i];

                        // Controlla se esistono parole compatibili con quella che incrociamo
                        for (int j = 0; j < wordCount && howManyMatch == 0; j++)
                        {
                            if (Regex.IsMatch(dizionarioAlfabetico[codeChar][j], regExpWord))
                            {
                                howManyMatch++;
                            }
                        }
                    }

                    if (howManyMatch == 0) {
                        ok = false;
						return false;
                    }
                }

                

                // La parola è compatibile, la scrivo nello schema
                if (ok == true) {
                    for (int i = 0; i < word.Length; i++)
                        scheme.crossword[coord.Row + i][coord.Column] = word[i];

                    // Se c'è ancora una casella libera dopo l'ultima lettera la contrassegno come "cella nera"
                    if (coord.Row + word.Length < scheme.Columns) {
                        scheme.crossword[coord.Row + word.Length][coord.Column] = '#';
                    }
                }
                else
                    return false;
            }

            // é la parola è stata inserita correttamente
            return true;
        }
    }
}
Purtroppo questo codice è LENTO, infatti non sono riusco a portare a termine neanche un cruciverba, purtroppo questo non mi permette neanche di capire se quello che ho scritto funzioni o meno.
Se qualcuno avesse qualche suggerimento da darmi o indirizzarmi su una via "migliore" sarebbe molto gradito .

Grazie per l'aiuto
ercand è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


WoW Forever: la beta è stato uno dei momenti più alti della storia dei videogiochi, e non si ripeterà WoW Forever: la beta è stato uno dei mome...
Oracle AI World 2026: in Europa prima la sovranità, poi la sicurezza e solo dopo l'IA Oracle AI World 2026: in Europa prima la sovrani...
DS N°7 E-Tense: il SUV premium made in Melfi che punta su autonomia e comfort DS N°7 E-Tense: il SUV premium made in Melfi...
Recensione Samsung Galaxy Tab S12 Ultra: non chiamatelo tablet... è molto di più Recensione Samsung Galaxy Tab S12 Ultra: non chi...
Hyundai IONIQ 5 N, l'elettrica che finge di essere termica (e ci riesce da paura) Hyundai IONIQ 5 N, l'elettrica che finge di esse...
Una tassa di 5,5 centesimi su ogni gigab...
Vuoi clonare un videogioco con l'IA? Cla...
Furto da 6,3 miliardi di dollari, Binanc...
Gli USA dipendono dai robot stranieri: T...
Volkswagen non ha più soldi per l...
Telescopio spaziale Hubble: la NASA cerc...
Più sottile e potente: le nuove i...
Il JPL estende la vita operativa della s...
DAZN Full è in offerta: tutta la ...
GTA 6 su PC potrebbe arrivare prima del ...
Da zero al tracciato in secondi: LibreCo...
Il regista Rian Johnson lancia a 12,99 d...
Microsoft stravolge l'app Sicurezza di W...
Mercato smartphone in caduta libera: -20...
Android 17 QPR3 Beta 3 riporta il blocco...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 06:41.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v