Visualizzazione dei risultati da 1 a 10 su 10
  1. #1

    [C++] Controllo vincoli gioco non funzionante

    buonasera,
    ho un problema con un programma che non restituisce un output corretto, anche se gira.
    in pratica devo realizzare un "s u d o k u" particolare, nel senso che puo avere anche una matrice 2x2 3x3 ed anche piu' grande della classica 9x9.

    Io sono riuscito a creare la matrice generica con una classe Tabella, che contiene un vector di vector-puntatori di oggetti puntatori "Casella", che rappresentano le caselle del gioco con i seguenti attributi.
    -numero (valore che si puo dare alla casella)
    -indice di riga
    -indice di colonna
    -fisso (booleano, true se è un numero fisso cioè una delle caselle iniziali del gioco, false se è vuoto)

    in questo modo riesco a generare una matrice di numeri 0 se la casella e vuota, o con un numero random da 1 fino ad arrivare alla grandezza del size. poi visualizzo la matrice vector di vector.

    IL PROBLEMA E' QUESTO: Nel mio gioco un numero non si puo ripetere sulla stessa riga, nè sulla stessa colonna. MA A ME COMPAIONO ANCORA VALORI RIPETUTI!!!!
    Non so da che dipende, nel costruttore di Tabella cerco di dare dei valori random per generare gli indici e il valore delle Caselle Fisse (Quelle iniziali presenti nel gioco come aiuto), poi applico un metodo booleano
    controllaVincoli(Casella * casellaDaControllare), che fino ad ora dovrebbe controllare solo i vincoli per i quali i numeri su stessa riga e colonna non si possono ripete. Il metodo dovrebbe restituire true se fra la casella generata e quella, ma non funziona bene, è come se non riconoscesse tutti i numeri ripetuti generati.

    Posto solo parte del codice, quella che non funziona.

    STO IMPAZZENDO su questa imperfezione, VI PREGO AIUTATEMI, GRAZIE!!!!


    codice:
    class Tabella
    {
    private:
        int sizeTabella;
        int sizeRegione;
        int livelloDifficolta;
        std::vector<std::vector<Casella*>*> *tabella = new std::vector<std::vector<Casella*>*>();
    
    
    public:
        
        Tabella(int sizeRegione, int livello); /*Crea Tabella di Default a 0*/
        ~Tabella();
        bool controllaVincoli(Casella* casellaDaControllare); 
             .... 
             .... 
             ....    
    };
    
             .... 
             .... 
             ....
             .... 
             .... 
             ....
    
    /*Crea Tabella di Inizio */
    Tabella::Tabella(int sizeRegione, int livelloDifficolta)
    {    
        this->livelloDifficolta = livelloDifficolta;
        this->sizeRegione = sizeRegione;
        this->sizeTabella = sizeRegione*sizeRegione;
    
    
        int quantitaNumeriFissi = this->sizeTabella*this->sizeTabella; //inizializiamo la quantità di fissi alla quantità di numeri in totale in tabella
                                                                      //per calcolare su di essa in seguito la percentuale di numeri fissi tramite lo 
                                                                     //costrutto Switch - Case
        switch (this->livelloDifficolta)                               
        {
        case 3:
            quantitaNumeriFissi = (int)floor((quantitaNumeriFissi * 5) / 100);
            break;
        case 2:
            quantitaNumeriFissi = (int)floor((quantitaNumeriFissi * 25) / 100);
            break;
        case 1:
            quantitaNumeriFissi = (int)floor((quantitaNumeriFissi * 50) / 100);
            break;
        }
    
    
        
        /**** INIZIO CREAZIONE STRUTTURA MATRICIALE ****/
        //Creo un vector di puntatori vector di puntatori Caselle di Default (valore=0). 
        //Simulo così una matrice di 0
        for (int i = 0; i < this->sizeTabella; i++)
        {
            std::vector<Casella*> *vec = new std::vector<Casella*>;
            this->tabella->push_back(vec);
    
    
            for (int j = 0; j < this->sizeTabella; j++)
            {
                Casella *casella = new Casella(i,j); //Il Costruttore di Default di Casella, genera numero=0 e fisso=false
                tabella->at(i)->push_back(casella); //sull'i-esimo vettore di vettore inseriamo in coda una Casella di valore 0
                //std::cout << "inserita casella " << casella->getRiga() <<" "<<casella->getColonna()<< std::endl;
            }
        }
    
    
        /**** INIZIO INSERIMENTO NUMERI FISSI IN TABELLA ****/
        
        int riga = 0; int colonna = 0; int valore = 0;
        srand((unsigned)time(NULL));
        
        for (int i = 0; i < quantitaNumeriFissi; i++)
        {
            riga = (rand() % (this->sizeTabella));
            colonna = (rand() % (this->sizeTabella));
            valore = (rand() % (this->sizeTabella)) + 1;
            std::cout << "rand 1 =" << valore << std::endl;
        
            Casella *casella = new Casella(valore,riga, colonna);
            
            if (this->tabella->at(riga)->at(colonna)->getNumero() == 0 && this->controllaVincoli(casella) == true) //se quel valore è gia presente in riga, colonna o regione
                {
                    valore = (rand() % (this->sizeTabella)) + 1; //calcola un valore diverso
                    std::cout << "rand 2 =" << valore<<std::endl;
                }    
            
            this->tabella->at(riga)->at(colonna)->setNumero(valore);
            this->tabella->at(riga)->at(colonna)->setFisso(true);
            }
        /************FINE INSERIMENTO NUMERI FISSI ******************/
    };
    
    .
    .
    .
    .
    .
    bool Tabella::controllaVincoli(Casella* casellaDaControllare)
    {
    	bool esistenza=false;
    
    
    	//CONTROLLO PRIMO VINCOLO - ESISTENZA SU STESSA RIGA
    	int ii = casellaDaControllare->getRiga();
    	int jj = 0;
    
    
    	while (jj <this->sizeTabella && this->tabella->at(ii)->at(jj)->getNumero()!=casellaDaControllare->getNumero())
    		jj++;
    	if (jj == this->sizeTabella)
    		esistenza = false;
    	else	
    		esistenza = true;
    
    
    	//CONTROLLO SECONDO VINCOLO - ESISTENZA SU STESSA COLONNA
    	
    	ii = 0;
    	jj = casellaDaControllare->getColonna();
    
    
    	while (ii <this->sizeTabella && this->tabella->at(ii)->at(jj)->getNumero() != casellaDaControllare->getNumero())
    		ii++;
    	if (ii == this->sizeTabella)
    		esistenza = esistenza && false;
    	else
    		esistenza = esistenza && true;
    
    
    	std::cout << "esistenza = " << esistenza << std::endl;
    	return esistenza;
    
    
    };
    /*** FINE CONTROLLO VINCOLI ***/

    codice:
    class Casella {
    
    
    private:
        int numero;
        int riga;
        int colonna;
        bool fisso; //Se è Numero Fisso = TRUE, se Numero Non Fisso = FALSE 
    
    
    public: 
        Casella(int riga, int colonna);
        Casella(int numero, int riga, int colonna);
        Casella(int numero, int riga, int colonna, bool fisso);
    
    
        ~Casella();
        void setNumero(int numero){ this->numero = numero; };
        void setRiga(bool fisso){ this->fisso = fisso; };
        void setColonna(int colonna){ this->colonna = colonna; };
        void setFisso(bool fisso){ this->fisso = fisso; };
        int getNumero(){ return this->numero; };
        int getRiga(){ return this->riga; };
        int getColonna(){ return this->colonna; };
        bool getFisso(){ return this->fisso; };
    };
    Ultima modifica di lello82nap; 13-12-2013 a 21:14

  2. #2
    nessun aiuto?

    mio dio

  3. #3
    Forse la gente era intimidita dalle dieci righe di titolo l'ho cambiato in qualcosa di più sintetico.

    Comunque, ad occhio il problema sta qui:
    codice:
            if (this->tabella->at(riga)->at(colonna)->getNumero() == 0 && this->controllaVincoli(casella) == true) //se quel valore è gia presente in riga, colonna o regione
                {
                    valore = (rand() % (this->sizeTabella)) + 1; //calcola un valore diverso
                    std::cout << "rand 2 =" << valore<<std::endl;
                }
    Quell'if dovrebbe essere un while o roba del genere: così com'è ora, se il primo numero generato non va bene ne genera un altro ma non ricontrolla se va bene.

    Comunque, secondo me stai facendo "overengineering" del problema; non ha senso fare un oggetto a parte per ogni casella in cui di nuovo vai a memorizzarne la posizione - basta una semplice matrice di struct contenente valore e flag "fisso".
    Amaro C++, il gusto pieno dell'undefined behavior.

  4. #4
    ciao, si in effetti nel thread l'avevo scritto che il problema è quel metodo che non funziona nell'if, questa era l'unica cosa che mi era chiara dall'inizio.
    però per cortesia nel titolo potresti sostituire la parola sudoku con la parola gioco?
    avevo pensato anche io a un titolo come il tuo solo che non voglio che i miei colleghi usando google vengano a copiarmi il progetto, il prof boccia per queste cose.
    ad ogni mi è tassativamente negato usare struct, malloc e calloc.
    il prof vuole solo classi e istanziamento con NEW

  5. #5
    Titolo cambiato; comunque, in C++ le struct e le class sono esattamente equivalenti (semplicemente nelle class i membri e l'ereditarietà sono private di default). Concordo su new invece di malloc, ma ribadisco che tutte queste istanze allocate sull'heap non mi paiono una buona idea.

    Per il resto, usando un while al posto di un if lì il problema è andato a posto?
    Amaro C++, il gusto pieno dell'undefined behavior.

  6. #6
    grazie infinite per il titolo.

    con il while non ho risolto, credo perchè alla fine il while equivale ad un (for + if)

    tu mastichi c++?

  7. #7
    ho cambiato un pasticcio che avevo fatto anche se non ha risolto il problema, ora ho capito cosa volevi dire con l'inutilità di generare il nuovo oggetto, ora la tabella punta all'oggetto creato, che pasticcio avevo fatto.
    codice:
    if (this->tabella->at(riga)->at(colonna)->getNumero() == 0 && this->controllaVincoli(casella) == true) //se quel valore è gia presente in riga, colonna o regione
    		{
    			valore = (rand() % (this->sizeTabella)) + 1; //calcola un valore diverso
    			std::cout << "rand 2 =" << valore << std::endl;
    			casella->setNumero(valore);
    			casella->setFisso(true);
    			
    		}
    		this->tabella->at(riga)->at(colonna) = casella; //<--------------------- cambiato qui

  8. #8
    Forse conviene se carichi l'intero sorgente (se non ci sta in un post sul forum prova con pastebin o simili), così provo ad eseguirlo e ci do un'occhiata più approfondita.
    Amaro C++, il gusto pieno dell'undefined behavior.

  9. #9
    Ti cairico tutto

    classe Tabella.h
    codice:
     
    
    
    
    
    
    
    #include "Casella.h"
    #include <vector>
    #include <iostream>
    #include <string>
    #include <ctime>
    #include <cstdlib>
    
    
    
    
    class Tabella
    {
    private:
    	int sizeTabella;
    	int sizeRegione;
    	int livelloDifficolta;
    	std::vector<std::vector<Casella*>*> *tabella = new std::vector<std::vector<Casella*>*>();
    
    
    public:
    
    
    	Tabella(int sizeRegione, int livello); /*Crea Tabella di Default a 0*/
    	~Tabella();
    	void mostraSudoku();
    	bool controllaVincoli(Casella* casellaDaControllare); //OVERLOADING DI METODI
    	bool controllaVincoli(int, int, int );
    	long int BackTracking();
    };
    
    
    /*Crea Tabella di Default a 0*/
    Tabella::Tabella(int sizeRegione, int livelloDifficolta)
    {
    	this->livelloDifficolta = livelloDifficolta;
    	this->sizeRegione = sizeRegione;
    	this->sizeTabella = sizeRegione*sizeRegione;
    
    
    	int quantitaNumeriFissi = this->sizeTabella*this->sizeTabella; //inizializiamo la quantità di fissi alla quantità di numeri in totale in tabella
    	//per calcolare su di essa in seguito la percentuale di numeri fissi tramite lo 
    	//costrutto Switch - Case
    	switch (this->livelloDifficolta)
    	{
    	case 3:
    		quantitaNumeriFissi = (int)floor((quantitaNumeriFissi * 5) / 100);
    		break;
    	case 2:
    		quantitaNumeriFissi = (int)floor((quantitaNumeriFissi * 25) / 100);
    		break;
    	case 1:
    		quantitaNumeriFissi = (int)floor((quantitaNumeriFissi * 50) / 100);
    		break;
    	}
    
    
    
    
    	/**** INIZIO CREAZIONE STRUTTURA MATRICIALE ****/
    	//Creo un vector di puntatori vector di puntatori Caselle di Default (valore=0). 
    	//Simulo così una matrice di 0
    	for (int i = 0; i < this->sizeTabella; i++)
    	{
    		std::vector<Casella*> *vec = new std::vector<Casella*>;
    		this->tabella->push_back(vec);
    
    
    		for (int j = 0; j < this->sizeTabella; j++)
    		{
    			Casella *casella = new Casella(i, j); //Il Costruttore di Default di Casella, genera numero=0 e fisso=false
    			tabella->at(i)->push_back(casella); //sull'i-esimo vettore di vettore inseriamo in coda una Casella di valore 0
    			//std::cout << "inserita casella " << casella->getRiga() <<" "<<casella->getColonna()<< std::endl;
    		}
    	}
    
    
    	/**** INIZIO INSERIMENTO NUMERI FISSI IN TABELLA ****/
    
    
    	int riga = 0; int colonna = 0; int valore = 0;
    	srand((unsigned)time(NULL));
    
    
    	for (int i = 0; i < quantitaNumeriFissi; i++)
    	{
    		riga = (rand() % (this->sizeTabella));
    		colonna = (rand() % (this->sizeTabella));
    		valore = (rand() % (this->sizeTabella)) + 1;
    		std::cout << "rand 1 =" << valore << std::endl;
    
    
    		Casella *casella = new Casella(valore, riga, colonna);
    
    
    		if (this->tabella->at(riga)->at(colonna)->getNumero() == 0 && this->controllaVincoli(casella) == true) //se quel valore è gia presente in riga, colonna o regione
    		{
    			valore = (rand() % (this->sizeTabella)) + 1; //calcola un valore diverso
    			std::cout << "rand 2 =" << valore << std::endl;
    			casella->setNumero(valore);
    			casella->setFisso(true);
    			
    		}
    		
    		this->tabella->at(riga)->at(colonna) = casella;
    		this->mostraSudoku();
    		//system("PAUSE");
    	}
    	/************FINE INSERIMENTO NUMERI FISSI ******************/
    };
    
    
    Tabella::~Tabella()
    {
    	for (int i = 0; i < tabella->size(); i++)
    	{
    		for (int j = 0; j < tabella->size(); j++)
    		{
    			delete tabella->at(i)->at(j); //sull'i-esimo vettore di vettore inseriamo in coda 0
    		}
    		tabella->at(i)->clear(); //libera la memoria di ogni vettore
    		delete tabella->at(i);
    	}
    
    
    	tabella->clear();
    	delete tabella;
    }
    
    
    /*** CONTROLLO DEI VINCOLI DI BACKTRACKING ***/
    //Questo metodo, controlla se il numero della casella presa in argomento sia uguale al numero di una presente
    //sulla stessa riga, colonna o regione
    //l'uguaglianza è verificata attraverso RICERCA SEQUENZIALE ITERATIVA
    
    
    bool Tabella::controllaVincoli(Casella* casellaDaControllare)
    {
    	bool esistenza = false;
    
    
    	//CONTROLLO PRIMO VINCOLO - ESISTENZA SU STESSA RIGA
    	int ii = casellaDaControllare->getRiga();
    	int jj = 0;
    
    
    	while (jj < this->sizeTabella && this->tabella->at(ii)->at(jj)->getNumero() != casellaDaControllare->getNumero())
    		jj++;
    	if (jj == this->sizeTabella)
    		esistenza = false;
    	else
    		esistenza = true;
    
    
    	//CONTROLLO SECONDO VINCOLO - ESISTENZA SU STESSA COLONNA
    	ii = 0;
    	jj = casellaDaControllare->getColonna();
    
    
    	while (ii < this->sizeTabella && this->tabella->at(ii)->at(jj)->getNumero() != casellaDaControllare->getNumero())
    		ii++;
    	if (ii == this->sizeTabella)
    		esistenza = esistenza && false;
    	else
    		esistenza = esistenza && true;
    
    
    	//CONTROLLO TERZO VINCOLO - ESISTENZA IN REGIONE
    
    
    	/*
    	.
    	.
    	.
    	.
    	.
    	.*/
    
    
    	std::cout << "esistenza = " << esistenza << std::endl;
    	return esistenza;
    
    
    };
    /*** FINE CONTROLLO VINCOLI ***/
    
    
    void Tabella::mostraSudoku()
    {
    	std::string *barra = new std::string("--------"); //unità semplice di una barra grafica inferiore 
    	for (int k = 0; k < this->sizeRegione - 1; k++) //la barra viene aumentata in relazione alla grandezza e alla quantità di Regioni
    	{
    		barra->append(*barra);
    	}
    
    
    	for (int i = 0; i < tabella->size(); i++)
    	{
    
    
    		for (int j = 0; j < tabella->size(); j++)
    		{
    			if (tabella->at(i)->at(j)->getNumero() >= 10)
    			{
    				std::cout << (tabella->at(i)->at(j)->getNumero()) << " ";
    			}
    			else if (tabella->at(i)->at(j)->getNumero() <= 9 && tabella->at(i)->at(j)->getNumero() >= 0)
    			{
    				std::cout << (tabella->at(i)->at(j)->getNumero()) << "  ";
    			}
    
    
    			if (j % sizeRegione == sizeRegione - 1) std::cout << "| ";
    		}
    
    
    		if (i % sizeRegione == sizeRegione - 1)
    		{
    			std::cout << std::endl << *barra << std::endl;
    		}
    
    
    		std::cout << std::endl;
    	}
    };
    classe Casella.h
    codice:
     #ifndef _SUDOKU_#define _SUDOKU_
    
    
    #include <vector>
    #include <ctime>
    #include <cstdlib>
    
    
    class Casella {
    
    
    private:
        int numero;
        int riga;
        int colonna;
        bool fisso; //Se è Numero Fisso = TRUE, se Numero Non Fisso = FALSE 
    
    
    public: 
        Casella(int riga, int colonna);
        Casella(int numero, int riga, int colonna);
        Casella(int numero, int riga, int colonna, bool fisso);
    
    
        ~Casella();
        void setNumero(int numero){ this->numero = numero; };
        void setRiga(bool fisso){ this->fisso = fisso; };
        void setColonna(int colonna){ this->colonna = colonna; };
        void setFisso(bool fisso){ this->fisso = fisso; };
        int getNumero(){ return this->numero; };
        int getRiga(){ return this->riga; };
        int getColonna(){ return this->colonna; };
        bool getFisso(){ return this->fisso; };
    };
    
    
    /* OVERLOADING DI COSTRUTTORI */
    
    
    Casella::Casella(int riga, int colonna){
        this->numero = 0;
        this->fisso = false;
        this->riga = riga;
        this->colonna = colonna;
    };
    
    
    Casella::Casella(int numero, int riga, int colonna){
        this->numero = numero;
        this->fisso = false;
        this->riga = riga;
        this->colonna = colonna;
    };
    
    
    Casella::Casella(int numero, int riga, int colonna, bool fisso)
    {
        this->numero = numero;
        this->fisso = fisso;
        this->riga = riga;
        this->colonna = colonna;
    
    
    }
    
    
    /* FINE OVERLOADING */
    
    
    Casella::~Casella(){
        delete this;
    }
    
    
    #endif
    file cpp Sudoku.cpp
    codice:
     
    
    
    
    #include "stdafx.h"
    #include "Tabella.h"
    #include <iostream>
    //#include "Tabella.h"
    
    
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        int size = 0;
        int livello = 0;
        std::cout << "Inserisci il size di riga e colonna della Cella: " << std::endl;
        std::cin >> size;
        std::cout << "Inserisci il livello di difficolta' " << std::endl;
        std::cout << "[1] : Inesperto" << std::endl << "[2] : Medio" << std::endl << "[3] : Esperto" << std::endl;
        std::cin >> livello;
        Tabella *tabella = new Tabella(size,livello);
        tabella->mostraSudoku();
        system("PAUSE");
        return 0;
    }

    cmq ho l'impressione che sia il corpo di quel metodo contollaVincoli(Casella *casellaDaControllare) che non funziona bene dentro. ma non mi spiego perchè dato che implementa una semplice ricerca sequenziale presa da wiki!

    spero tu riesca... io sto letteralmente impazzendo.

    GRAZIE MILLE!!!
    Ultima modifica di lello82nap; 14-12-2013 a 20:03

  10. #10
    nada? :-(

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.