Torna indietro   Hardware Upgrade Forum > Software > Programmazione

AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequenze al top per il gaming
AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequenze al top per il gaming
AMD Ryzen 7 9850X3D è la nuova CPU gaming di riferimento grazie alla 3D V-Cache di seconda generazione e frequenze fino a 5,6 GHz. Nei test offre prestazioni superiori a 9800X3D e 7800X3D, confermando la leadership AMD nel gaming su PC.
Le soluzioni FSP per il 2026: potenza e IA al centro
Le soluzioni FSP per il 2026: potenza e IA al centro
In occasione del Tech Tour 2025 della European Hardware Association abbiamo incontrato a Taiwan FSP, azienda impegnata nella produzione di alimentatori, chassis e soluzioni di raffreddamento tanto per clienti OEM come a proprio marchio. Potenze sempre più elevate negli alimentatori per far fronte alle necessità delle elaborazioni di intelligenza artificiale.
AWS annuncia European Sovereign Cloud, il cloud sovrano per convincere l'Europa
AWS annuncia European Sovereign Cloud, il cloud sovrano per convincere l'Europa
AWS è il principale operatore di servizi cloud al mondo e da tempo parla delle misure che mette in atto per garantire una maggiore sovranità alle organizzazioni europee. L'azienda ha ora lanciato AWS European Sovereign Cloud, una soluzione specificamente progettata per essere separata e distinta dal cloud "normale" e offrire maggiori tutele e garanzie di sovranità
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


AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequenze al top per il gaming AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequen...
Le soluzioni FSP per il 2026: potenza e IA al centro Le soluzioni FSP per il 2026: potenza e IA al ce...
AWS annuncia European Sovereign Cloud, il cloud sovrano per convincere l'Europa AWS annuncia European Sovereign Cloud, il cloud ...
Redmi Note 15 Pro+ 5G: autonomia monstre e display luminoso, ma il prezzo è alto Redmi Note 15 Pro+ 5G: autonomia monstre e displ...
HONOR Magic 8 Pro: ecco il primo TOP del 2026! La recensione HONOR Magic 8 Pro: ecco il primo TOP del 2026! L...
Le batterie LFP sono piccole e pesanti? ...
Motorola inarrestabile: nuova serie moto...
Decima generazione Pokémon: grafi...
Una nuova legge consente di rottamare un...
Google mostra per sbaglio Android per PC...
Tesla non convince più: crolla il...
OpenAI lancia Prism: l'AI ora lavora fia...
Nissan mette i pannelli solari su Ariya:...
Day 3 a Barcellona: la prima di Norris c...
Usa: il capo della cyber sicurezza ha ca...
Nuovo look per il DJI Store di Milano: f...
I giudici sentenziano: Trump non pu&ogra...
Il kernel Linux si prepara al 'dopo Torv...
Meta, Snap, TikTok e YouTube: la prossim...
Daredevil Born Again seconda stagione: o...
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: 16:35.


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