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
supportata la soluzione classica
e la soluzione Sam Loyd, da adottare quando all'ultimo rigo si ha il 14 e il 15 invertiti
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.