C, console, mouse GiocoDel15

di il
18 risposte

C, console, mouse GiocoDel15

Sono poco più di due mesi che saltuariamente mi dedico al C.
Posto il mio primo programma completo, il gioco del 15 (fifteen), si gioca con il mouse sulla console


GiocoDel15.gif
GiocoDel15.gif


supportata la soluzione classica
SoluzioneClassica.jpg
SoluzioneClassica.jpg


e la soluzione Sam Loyd, da adottare quando all'ultimo rigo si ha il 14 e il 15 invertiti
SoluzioneSamLoyd.jpg
SoluzioneSamLoyd.jpg


Il programma funziona con compilatore MinGW e VisualStudio su Win7, con Win10 non funziona.
La compilazione va a buon fine, la console appare ma il click del mouse non viene intercettato.

EDIT: il 10 gen 2021, 21:18 postato codice per win10

Se richiesto posso postare il codice modificato per il compilatore di VisualStudio.

Mi piacerebbe che il programma sia uno spunto per parlare del C e le discrepanze tra i vari sistemi, mi piacerebbe con i vostri consigli farlo funzionare anche in Win10, ma anche sapere se ci sono approci diversi.
Con il titolo che ho scelto sarà difficile andare fuori OT.

Codice completo:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

/*************************************
*            GIOCO DEL 15            *
*  Si gioca in console con il mouse. *
*  Se al termine si ha: 13-15-14     *
*  il puzzle si può risolvere con    *
*  il metodo Sam Loyd                *
*************************************/

// **** costanti
const char RigSopra[]={(CHAR)201,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)203,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)203,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)203,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)187,'\0'};
const char RigheCentro[]={(CHAR)204,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)206,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)206,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)206,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)185,'\0'};
const char RigSotto[]={(CHAR)200,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)202,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)202,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)202,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)188,'\0'};
// in aControllo, gli indici in base zero del vettore iSequenza che devono essere esplorati, in base alla casella cliccata
const unsigned int aControllo[16][4]={{1, 4, 0, 0}, {0, 2, 5, 1}, {1, 3, 6, 2}, {2, 7, 3, 3}, {0, 5, 8, 4}, {4, 1, 6, 9}, {5, 2, 7, 10}, {11, 3, 6, 7}, {4, 9, 12, 8}, {8, 5, 10, 13}, {14, 9, 6, 11}, {15, 10, 7, 11}, {8, 13, 12, 12}, {12, 9, 14, 13}, {13, 10, 15, 14}, {14, 11, 15, 15}};
const char Titolo[]="Gioco del15 CB2021";
const unsigned char iClassica[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0}; // soluzione classica
const unsigned char iSamLoyd[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; // soluzione Sam Loyd

// **** pubbliche
unsigned char iSequenza[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0}; // sequenza di partenza, contiene sempre lo stato del gioco
struct {
    unsigned int riga;
    unsigned int colonna;
    unsigned int casella;
    unsigned int mosse;
}GiocoDel15;

// **** prototipi
int Schermo(HANDLE *Cons); // disegna lo schema con i numeri
void mescola(HANDLE *Cons);
void TrovaCasella(int x, int y, HANDLE *Cons); // aggiorna la struct GiocoDel15 in base alla casella cliccata

int main()
{
    SetConsoleTitle(Titolo);
    POINT pCoor;
    struct timespec ts;
    ts.tv_sec=0;
    HWND hwnd=0;

    //attende la creazione della finestra per prelevare hwnd
    while (hwnd==0)
        hwnd=FindWindow(NULL, Titolo);
    //------------------------------------------------------

    HANDLE console=GetStdHandle(STD_OUTPUT_HANDLE);
    Schermo(console); // prima visualizzazione schema

    while(1){ // loop infinito mouse
        ts.tv_nsec=5000000L; // ritardo ns. mentre il mouse si muove
        nanosleep(&ts, NULL); // lascia la CPU libera, inutile fare milioni di cicli al secondo
        if((GetKeyState(VK_LBUTTON) & 0x8000) != 0){ // bottone sinistro mouse
            GetCursorPos(&pCoor); // coordinte assolute cursore
            ScreenToClient(hwnd, &pCoor); // coordinate relative cursore
            TrovaCasella(pCoor.x, pCoor.y, console); // TrovaCasella modifica la struct GiocoDel15
            if (GiocoDel15.riga!=0 && GiocoDel15.colonna!=0){ // click dentro lo schema
                int vuota=99; // se resta a 99 il numero cliccato non si può muovere
                for (int i=0; i<4; i++) // controllo in 4 direzioni
                   if (iSequenza[aControllo[GiocoDel15.casella][i]]==0) vuota=i; // se una direzione è disponibile salvo l'indice in vuota

                if (vuota!=99){ // se vuota non è 99 swap dei valori
                    iSequenza[aControllo[GiocoDel15.casella][vuota]]=iSequenza[GiocoDel15.casella]; // l'indice è memorizzato in aControllo, scambio il valore
                    if (GiocoDel15.casella!=aControllo[GiocoDel15.casella][vuota]) iSequenza[GiocoDel15.casella]=0; // nella casella cliccata metto zero, solo se non è sestessa
                }
                unsigned int risolto=Schermo(console); // aggiorno lo schermo, la funzione restituisce se c'è soluzione
                printf("\n\n  ");
                if (risolto==1) printf("Risolto con soluzione classica, ");
                if (risolto==2) printf("Risolto con soluzione Sam Loyd, ");
                if (risolto==0) GiocoDel15.mosse++; // nessuna soluzione incremento le mosse
                printf("mosse = %d",GiocoDel15.mosse); // visualizzo le mosse

                /* per test
                printf("\n\nCasella = %d", casella+1);
                if (vuota!=99) printf(" Vuota = %d", aControllo[casella][vuota]+1);
                */
            }
            ts.tv_nsec=200000000L;
            nanosleep(&ts, NULL); // Ritardo evita doppio click
        }
    }
}

int Schermo(HANDLE *Cons){

    system("cls");
    int i=0;
    SetConsoleTextAttribute(Cons, 11|0); // ciano nero
    printf("\n   ***** GIOCO DEL15 *****\n   ");
    printf("\n   ");

    // disegno schema con sequenza ***************
    SetConsoleTextAttribute(Cons, 15|204); // bianco rosso
    printf("                       ");
    SetConsoleTextAttribute(Cons, 11|0); // ciano nero
    printf("\n   ");
    SetConsoleTextAttribute(Cons, 15|204); // bianco rosso
    printf(" %s ",RigSopra);
    for (i=0; i<16; i+=4){
        SetConsoleTextAttribute(Cons, 11|0); // ciano nero
        printf("\n   ");
        SetConsoleTextAttribute(Cons, 15|204); // bianco rosso
        // il numero zero viene sostituito con gli spazi (casella vuota)
        for (int ind=0; ind<4; ind++){
            printf(" %c ", (CHAR)186);
            if (iSequenza[ind+i]==0) printf("  "); else printf("%02d", iSequenza[ind+i]);
        }
        printf(" %c ", (CHAR)186);
        SetConsoleTextAttribute(Cons, 11|0); // ciano nero
        printf("\n   ");
        SetConsoleTextAttribute(Cons, 15|204); // bianco rosso
        if (i==12) printf(" %s ", RigSotto); else printf(" %s ", RigheCentro);
    }
    SetConsoleTextAttribute(Cons, 11|0); // ciano nero
    printf("\n   ");
    SetConsoleTextAttribute(Cons, 15|204); // bianco rosso
    printf("                       ");
    SetConsoleTextAttribute(Cons, 11|0); // ciano nero
    printf("\n   ");
    printf("\n    [MESCOLA]     [ESCI]");
    SetConsoleTextAttribute(Cons, 10|0); // verde nero
    //****************************************

    unsigned char risolto=1; // 0 = non risolto, 1 = Classica, 2 = Sam Loyd

    /* per test
    unsigned char risolto = 1;
    printf("\n\nSequenza = [");
    for (i=0; i<16; i++){
        printf("%02d", Seq[i]);
        if (iSoluzione[i] != Seq[i])risolto = 0; // non risolto
    }
    printf("]");
    */

    for (i=0; i<16; i++){
        if (iClassica[i] != iSequenza[i]){risolto = 0; break;}  // non risolto classico
    }
    if (risolto == 1) return 1; // risolto classico
    for (i=0; i<16; i++){
        if (iSamLoyd[i] != iSequenza[i]) return 0; // non risolto classico e Sam Loyd
    }
    return 2; // risolto Sam Loyd
}

void mescola(HANDLE *Cons){

    srand((unsigned) time(NULL)); // init random
    int ind=0;
    iSequenza[ind] = rand() % 16 ; //(0/15)
    while (ind<15){ // finquando il vettore è pieno
        ind++;
        iSequenza[ind] = rand() % 16 ; //(0/15)
        for (int check = 0; check<ind; check++){ // controllo duplicati
            if (iSequenza[check]==iSequenza[ind]){ind--;break;}
        }
    }
    GiocoDel15.mosse = 0;
    Schermo(Cons); // visualizzazione
}

void TrovaCasella(int x, int y, HANDLE *Cons){ // controllo coordinate mouse

    GiocoDel15.riga = 0; // base 1
    GiocoDel15.colonna = 0; // base 1
    GiocoDel15.casella = 0; // base zero

    if (x>39 && x<73) GiocoDel15.colonna = 1; // casella 0
    if (x>79 && x<113) {GiocoDel15.colonna = 2; GiocoDel15.casella = 1;}
    if (x>119 && x<153) {GiocoDel15.colonna = 3; GiocoDel15.casella = 2;}
    if (x>158 && x<193) {GiocoDel15.colonna = 4; GiocoDel15.casella = 3;}
    if (y>55 && y<76) GiocoDel15.riga = 1;
    if (y>79 && y<100) {GiocoDel15.riga = 2; GiocoDel15.casella +=4;}
    if (y>103 && y<123) {GiocoDel15.riga = 3; GiocoDel15.casella +=8;}
    if (y>129 && y<148) {GiocoDel15.riga = 4; GiocoDel15.casella +=12;}
    if (x>37 && x<100 && y>180 && y<190) mescola(Cons);
    if (x>149 && x<188 && y>180 && y<190) {printf("\n"); exit(0);}
    // printf( "\nPosizione x = %d y = %d rig = %d col = %d cas = %d",x ,y, GiocoDel15.riga, GiocoDel15.colonna, GiocoDel15.casella);
}
Scritto di getto in 4 ore... ma avevo già in mente come approciare, perché avevo già scritto un programma simile tempo fa con altro linguaggio.

18 Risposte

  • Re: C, console, mouse GiocoDel15

    Due i problemi individuati, in Win10 nella console con il tasto sinistro del mouse si attiva la selezione.
    Usando il tasto destro del mouse il problema scompare.

    Le coordinate del mouse nella diversa console tra win7 e win10, non corrispondono.
    Correggendo le coordinate il gioco funziona.

    Prima di postare il codice corretto vorrei un consiglio su come sapere su che tipo di console si opera, altrimenti prima della partenza del gioco bisogna implementare una sorta di settaggio e verifica coordinate.
  • Re: C, console, mouse GiocoDel15

    Se vuoi identificare il sistema operativo ci sono queste macro
    https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-160
  • Re: C, console, mouse GiocoDel15

    Weierstrass ha scritto:


    Se vuoi identificare il sistema operativo ci sono queste macro
    https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-160
    Grazie, per quanto ne sai quando è stata cambiata la finestra console?, e se si sceglie un "tema" diverso, lo stile della console cambia?
    Per esempio in Win 10 si può scegliere il "tema" Win7...
  • Re: C, console, mouse GiocoDel15

    Bellissimo come esercizio di stile eseguito in modalità console.

    Ho provato a vedere se funzionava su Win10 64bit... purtroppo non và.
    Comunque compila tranquillamente e parte con codeblocks + miniGW in modalità console, poi non rileva il mouse.
  • Re: C, console, mouse GiocoDel15

    Rubik ha scritto:


    e la soluzione Sam Loyd, da adottare quando all'ultimo rigo si ha il 14 e il 15 invertiti
    Volendo non è affatto complicato verificare se una generica configurazione casuale è impossibile e in tal caso "correggerla":
    http://www.lidimatematici.it/blog/2014/08/25/sam-loyd-e-il-gioco-del-15/
  • Re: C, console, mouse GiocoDel15

    ramcrack ha scritto:


    Bellissimo come esercizio di stile eseguito in modalità console.

    Ho provato a vedere se funzionava su Win10 64bit... purtroppo non và.
    Comunque compila tranquillamente e parte con codeblocks + miniGW in modalità console, poi non rileva il mouse.
    Il mouse viene rilevato, ma bisogna usare il tasto destro, perché il sinistro seleziona.
    Poi le coordinate sono sballate perché la finestra non ha i bordi, inoltre la dimensione in pixel delle caselle è diversa, insomma un bel po' di numeri che dovrebbero essere aggiustati con i dovuti rapporti...
    Poi non sapendo se le coordinate cambiano anche al variare dell'ingrandimento del testo impostato su win, per ora ho gettato la spugna, e ho solo scritto una versione per win10, dimmi se ti funziona, ricorda di usare il tasto destro:
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <windows.h>
    
    /*************************************
    *            GIOCO DEL 15            *
    *  Si gioca in console con il mouse. *
    *  Se al termine si ha: 13-15-14     *
    *  il puzzle si può risolvere con    *
    *  il metodo Sam Loyd                *
    *************************************/
    
    // **** costanti
    const char RigSopra[]={(CHAR)201,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)203,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)203,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)203,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)187,'\0'};
    const char RigheCentro[]={(CHAR)204,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)206,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)206,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)206,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)185,'\0'};
    const char RigSotto[]={(CHAR)200,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)202,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)202,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)202,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)205,(CHAR)188,'\0'};
    // in aControllo, gli indici in base zero del vettore iSequenza che devono essere esplorati, in base alla casella cliccata
    const unsigned int aControllo[16][4]={{1, 4, 0, 0}, {0, 2, 5, 1}, {1, 3, 6, 2}, {2, 7, 3, 3}, {0, 5, 8, 4}, {4, 1, 6, 9}, {5, 2, 7, 10}, {11, 3, 6, 7}, {4, 9, 12, 8}, {8, 5, 10, 13}, {14, 9, 6, 11}, {15, 10, 7, 11}, {8, 13, 12, 12}, {12, 9, 14, 13}, {13, 10, 15, 14}, {14, 11, 15, 15}};
    const char Titolo[]="Gioco del15 CB2021";
    const unsigned char iClassica[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0}; // soluzione classica
    const unsigned char iSamLoyd[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; // soluzione Sam Loyd
    
    // **** pubbliche
    unsigned char iSequenza[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0}; // sequenza di partenza, contiene sempre lo stato del gioco
    struct {
        unsigned int riga;
        unsigned int colonna;
        unsigned int casella;
        unsigned int mosse;
    }GiocoDel15;
    
    // **** prototipi
    int Schermo(HANDLE *Cons); // disegna lo schema con i numeri
    void mescola(HANDLE *Cons);
    void TrovaCasella(int x, int y, HANDLE *Cons); // aggiorna la struct GiocoDel15 in base alla casella cliccata
    
    int main()
    {
        SetConsoleTitle(Titolo);
        POINT pCoor;
        struct timespec ts;
        ts.tv_sec=0;
        HWND hwnd=0;
    
        //attende la creazione della finestra per prelevare hwnd
        while (hwnd==0)
            hwnd=FindWindow(NULL, Titolo);
        //------------------------------------------------------
    
        HANDLE console=GetStdHandle(STD_OUTPUT_HANDLE);
        Schermo(console); // prima visualizzazione schema
    
        while(1){ // loop infinito mouse
            ts.tv_nsec=5000000L; // ritardo ns. mentre il mouse si muove
            nanosleep(&ts, NULL); // lascia la CPU libera, inutile fare milioni di cicli al secondo
            if((GetKeyState(VK_RBUTTON) & 0x8000) != 0){ // bottone destro mouse
                GetCursorPos(&pCoor); // coordinate assolute cursore
                ScreenToClient(hwnd, &pCoor); // coordinate relative cursore
                TrovaCasella(pCoor.x, pCoor.y, console); // TrovaCasella modifica la struct GiocoDel15
                if (GiocoDel15.riga!=0 && GiocoDel15.colonna!=0){ // click dentro lo schema
                    int vuota=99; // se resta a 99 il numero cliccato non si può muovere
                    for (int i=0; i<4; i++) // controllo in 4 direzioni
                       if (iSequenza[aControllo[GiocoDel15.casella][i]]==0) vuota=i; // se una direzione è disponibile salvo l'indice in vuota
    
                    if (vuota!=99){ // se vuota non è 99 swap dei valori
                        iSequenza[aControllo[GiocoDel15.casella][vuota]]=iSequenza[GiocoDel15.casella]; // l'indice è memorizzato in aControllo, scambio il valore
                        if (GiocoDel15.casella!=aControllo[GiocoDel15.casella][vuota]) iSequenza[GiocoDel15.casella]=0; // nella casella cliccata metto zero, solo se non è sestessa
                    }
                    unsigned int risolto=Schermo(console); // aggiorno lo schermo, la funzione restituisce se c'è soluzione
                    printf("\n\n  ");
                    if (risolto==1) printf("Risolto con soluzione classica, ");
                    if (risolto==2) printf("Risolto con soluzione Sam Loyd, ");
                    if (risolto==0) GiocoDel15.mosse++; // nessuna soluzione incremento le mosse
                    printf("mosse = %d",GiocoDel15.mosse); // visualizzo le mosse
    
                    /* per test
                    printf("\n\nCasella = %d", casella+1);
                    if (vuota!=99) printf(" Vuota = %d", aControllo[casella][vuota]+1);
                    */
                }
                ts.tv_nsec=200000000L;
                nanosleep(&ts, NULL); // Ritardo evita doppio click
            }
        }
    }
    
    int Schermo(HANDLE *Cons){
    
        system("cls");
        int i=0;
        SetConsoleTextAttribute(Cons, 11|0); // ciano nero
        printf("\n   ***** GIOCO DEL15 *****\n   ");
        printf("\n   ");
    
        // disegno schema con sequenza ***************
        SetConsoleTextAttribute(Cons, 15|204); // bianco rosso
        printf("                       ");
        SetConsoleTextAttribute(Cons, 11|0); // ciano nero
        printf("\n   ");
        SetConsoleTextAttribute(Cons, 15|204); // bianco rosso
        printf(" %s ",RigSopra);
        for (i=0; i<16; i+=4){
            SetConsoleTextAttribute(Cons, 11|0); // ciano nero
            printf("\n   ");
            SetConsoleTextAttribute(Cons, 15|204); // bianco rosso
            // il numero zero viene sostituito con gli spazi (casella vuota)
            for (int ind=0; ind<4; ind++){
                printf(" %c ", (CHAR)186);
                if (iSequenza[ind+i]==0) printf("  "); else printf("%02d", iSequenza[ind+i]);
            }
            printf(" %c ", (CHAR)186);
            SetConsoleTextAttribute(Cons, 11|0); // ciano nero
            printf("\n   ");
            SetConsoleTextAttribute(Cons, 15|204); // bianco rosso
            if (i==12) printf(" %s ", RigSotto); else printf(" %s ", RigheCentro);
        }
        SetConsoleTextAttribute(Cons, 11|0); // ciano nero
        printf("\n   ");
        SetConsoleTextAttribute(Cons, 15|204); // bianco rosso
        printf("                       ");
        SetConsoleTextAttribute(Cons, 11|0); // ciano nero
        printf("\n   ");
        printf("\n    [MESCOLA]     [ESCI]");
        SetConsoleTextAttribute(Cons, 10|0); // verde nero
        //****************************************
    
        unsigned char risolto=1; // 0 = non risolto, 1 = Classica, 2 = Sam Loyd
    
        /* per test
        unsigned char risolto = 1;
        printf("\n\nSequenza = [");
        for (i=0; i<16; i++){
            printf("%02d", Seq[i]);
            if (iSoluzione[i] != Seq[i])risolto = 0; // non risolto
        }
        printf("]");
        */
    
        for (i=0; i<16; i++){
            if (iClassica[i] != iSequenza[i]){risolto = 0; break;}  // non risolto classico
        }
        if (risolto == 1) return 1; // risolto classico
        for (i=0; i<16; i++){
            if (iSamLoyd[i] != iSequenza[i]) return 0; // non risolto classico e Sam Loyd
        }
        return 2; // risolto Sam Loyd
    }
    
    void mescola(HANDLE *Cons){
    
        srand((unsigned) time(NULL)); // init random
        int ind=0;
        iSequenza[ind] = rand() % 16 ; //(0/15)
        while (ind<15){ // finquando il vettore è pieno
            ind++;
            iSequenza[ind] = rand() % 16 ; //(0/15)
            for (int check = 0; check<ind; check++){ // controllo duplicati
                if (iSequenza[check]==iSequenza[ind]){ind--;break;}
            }
        }
        GiocoDel15.mosse = 0;
        Schermo(Cons); // visualizzazione
    }
    
    void TrovaCasella(int x, int y, HANDLE *Cons){ // controllo coordinate mouse
    
        GiocoDel15.riga = 0; // base 1
        GiocoDel15.colonna = 0; // base 1
        GiocoDel15.casella = 0; // base zero
    
      	if (x > 39 && x < 74) GiocoDel15.colonna = 1; // casella 0
    	if (x > 78 && x < 112) { GiocoDel15.colonna = 2; GiocoDel15.casella = 1; }
    	if (x > 119 && x < 154) { GiocoDel15.colonna = 3; GiocoDel15.casella = 2; }
    	if (x > 158 && x < 192) { GiocoDel15.colonna = 4; GiocoDel15.casella = 3; }
    	if (y > 76 && y < 103) GiocoDel15.riga = 1;
    	if (y > 107 && y < 135) { GiocoDel15.riga = 2; GiocoDel15.casella += 4; }
    	if (y > 140 && y < 167) { GiocoDel15.riga = 3; GiocoDel15.casella += 8; }
    	if (y > 173 && y < 197) { GiocoDel15.riga = 4; GiocoDel15.casella += 12; }
    	if (x > 37 && x < 100 && y>240 && y < 251) mescola(Cons);
    	if (x > 149 && x < 188 && y>240 && y < 251) { printf("\n"); exit(0); }
    
        //printf( "\nPosizione x = %d y = %d rig = %d col = %d cas = %d",x ,y, GiocoDel15.riga, GiocoDel15.colonna, GiocoDel15.casella);
    }
    
    EDIT: Ho pubblicato i progetti CODE::BLOCKS e VisualStudio qui: http://www.pierotofy.it/pages/sorgenti/dettagli/19631-GiocoDel15/
  • Re: C, console, mouse GiocoDel15

    Nippolo ha scritto:


    Rubik ha scritto:


    e la soluzione Sam Loyd, da adottare quando all'ultimo rigo si ha il 14 e il 15 invertiti
    Volendo non è affatto complicato verificare se una generica configurazione casuale è impossibile e in tal caso "correggerla":
    http://www.lidimatematici.it/blog/2014/08/25/sam-loyd-e-il-gioco-del-15/
    Grazie, me lo guardo, sappi che in una mia versione del gioco del 15 in VB.Net, per evitare la variante Sam Loyd, mescolavo il puzzle veramente via software, perché da solo, non ho trovato un metodo per verificare la sequenza.
  • Re: C, console, mouse GiocoDel15

    @ Rubik

    Perfettamente funzionante, ora anche su Windows 10.
    Ho provato a spostare anche la posizione della finestra dove c'e' il tuo gioco e le coordinate vengono rilevate senza nessun problema.

    Ovviamente, ripeto, ho compilato con Codeblocks + MiniGW.
    Mi sono già conservato il tuo codice, lo terrò presente per mie eventuali future implementazioni. Mi piace molto la gestione del mouse da Console Application.
  • Re: C, console, mouse GiocoDel15

    ramcrack ha scritto:


    @ Rubik

    Perfettamente funzionante, ora anche su Windows 10.
    Ho provato a spostare anche la posizione della finestra dove c'e' il tuo gioco e le coordinate vengono rilevate senza nessun problema.

    Ovviamente, ripeto, ho compilato con Codeblocks + MiniGW.
    Mi sono già conservato il tuo codice, lo terrò presente per mie eventuali future implementazioni. Mi piace molto la gestione del mouse da Console Application.
    Bene, le istruzioni che permettono di avere le coordinate riferite alla finestra console sono:
    
                GetCursorPos(&pCoor); // coordinate assolute cursore
                ScreenToClient(hwnd, &pCoor); // coordinate relative cursore
    
    se elimini: ScreenToClient(hwnd, &pCoor);
    le coorinate saranno quelle del desktop win

    Per chi usa C++ e VisualStudio

    Il programma funziona anche con il compilatore C++ di VisualStudio, bisogna sostituire: nanosleep(&ts, NULL); con Sleep(50);
    e il frammento di codice per il C MinGW:
    
        SetConsoleTitle(Titolo);
        POINT pCoor;
        struct timespec ts;
        ts.tv_sec=0;
        HWND hwnd=0;
    
        //attende la creazione della finestra per prelevare hwnd
        while (hwnd==0)
            hwnd=FindWindow(NULL, Titolo);
        //------------------------------------------------------
    
    diventa per il C++ di VisualStudio
    
         SetConsoleTitleW(L"Gioco del15 CB2021");
         POINT pCoor;
         HWND hwnd = 0;
    
         //attende la creazione della finestra per prelevare hwnd
         while (hwnd == 0)
              hwnd = FindWindow(NULL, L"Gioco del15 CB2021");
         //------------------------------------------------------
    
  • Re: C, console, mouse GiocoDel15

    Grazie, tutto memorizzato, mi sarà utile in futuro.
  • Re: C, console, mouse GiocoDel15

    Cerco aiuto dai volenterosi.

    Il gioco del 15 è un gioco meccanico, se viene smontato e si invertono gli ultimi due numeri 14 e 15 il puzzle non è più risolvibile nella maniera classica, ma può essere risolto partendo dal basso a destra con il 15 e si risale fino a lasciare la casella vuota in alto a sinistra, soluzione Sam Loyd.

    In un gioco programmato quando si mesola il puzzle in modo casuale non sono in grado di stabilre se la sequenza generata sarà risolvibile in modo classico o in modo Sam Loyd, Nippolo ha postato il link: http://www.lidimatematici.it/blog/2014/08/25/sam-loyd-e-il-gioco-del-15/
    dove si trova una base di partenza per un ragionamento... si contano le coppie in sequenza crescente e se sono pari la sequenza è classica, se sono dispari la sequenza è Sam Loyd.

    Altro spunto è dato dal fatto che per semplificare il conteggio delle coppie, le sequenze prese in esame avranno sempre la casella vuota (00) in basso a destra.

    Di seguito alcune sequenze risolvibili in modo classico:
    
    10,14,02,03,06,07,04,11,01,13,12,09,05,15,08,00
    01,02,03,04,05,06,07,08,09,10,12,15,13,14,11,00
    07,14,04,02,01,06,12,03,15,13,08,11,05,10,09,00
    02,06,07,03,01,09,11,04,05,14,10,08,13,15,12,00
    12,14,02,03,04,06,07,08,01,05,09,11,15,13,10,00
    
    e non risolvibili in modo classico:
    
    01,05,02,03,04,09,06,07,08,13,11,15,12,14,10,00
    01,02,03,04,05,06,07,09,08,10,15,11,12,13,14,00
    05,01,03,04,08,15,13,09,12,07,11,14,02,06,10,00
    15,05,14,03,01,09,13,11,12,07,04,10,02,08,06,00
    05,09,03,11,07,13,14,10,15,02,04,06,01,12,08,00
    
    Tempo fa, non riuscii a trovare un algoritmo per riconoscere le sequenze, ora riprovo, se qualcuno si cimenterà, il confronto è bene accetto.
  • Re: C, console, mouse GiocoDel15

    Per il conteggio delle coppie bastano 3-4 righe di codice, poi se esse sono in numero dispari per rendere la configurazione risolvibile basta scambiare il penultimo elemento col terzultimo!
  • Re: C, console, mouse GiocoDel15

    Nippolo ha scritto:


    Per il conteggio delle coppie bastano 3-4 righe di codice, poi se esse sono in numero dispari per rendere la configurazione risolvibile basta scambiare il penultimo elemento col terzultimo!
    Infatti, ho riletto meglio il tuo link, a prima vista non avevo capito che con le info date si potesse capire come risolvere, pensavo che ci volessero ulteriori ragionamenti.
    ecco la funzione che ho scritto, restituisce 0 se la sequenza non è valida e 1 se è valida
    
    unsigned char iSequenza[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0};
    
    int SeqValida(){
        unsigned int coppie = 0;
        for (int i=0; i<15;i++){
            for (int y=i; y<15;y++){
                if (iSequenza[i] < iSequenza[y]) coppie++;
            }
        }
        return coppie%2;
    }
    
  • Re: C, console, mouse GiocoDel15

    Innanzitutto la y puoi anche farla partire direttamente da i+1, inoltre anche se la tua versione è ugualmente funzionante (non ho approfondito più di tanto la questione dal punto di vista logico-matematico), volendo seguire alla lettera il ragionamento riportato in quel sito avresti dovuto fare qualcosa del genere:
    int SeqValida()
    {
        unsigned int coppie = 0;
        for(unsigned int i = 0; i < 15; ++i)
        {
            for(unsigned int y = i + 1; y < 15; ++y)
            {
                if(iSequenza[i] > iSequenza[y]) ++coppie;
            }
        }
        return !(coppie % 2);
    }
Devi accedere o registrarti per scrivere nel forum
18 risposte