Newsgroup: it.comp.lang.c
Titolo: "Grafica" nella console DOS di WinXP

Salve a tutti, ho creato una funzione (linguaggio C) che mi genera una 
griglia con i codici ASCII nella console DOS (l'ho fatta tutta con i 
caratteri e i printf senza usare eventuali librerie apposite  ). Ora 
vorrei poter scrivere un'altra funzione che mi vada a scrivere 
all'interno delle celle della griglia. Pensavo di portarmi stampando una 
sequenza di escape, a inizio pagina e poi muovermi quel tanto da poter 
arrivare nella zone della pagina desiderata.
Ho notato che printf non ha sequenze di escape per avanzare di n 
caratteri senza perň cancellare il testo che viene cosě "sorpassato" dal 
cursore (lo "spazio" sovrascrive): come posso fare? Esiste una qualche 
funzione che mi sposta semplicemente nella posizione che voglio io nello 
schermo della console DOS? Tipo gotoXY del Pascal?
Sarebbe piů intelligente usare funzioni "grafiche" apposite? Se si, quali?
Riuscireste a farmi un esempio di codice che mi va a scrivere in 
un'ipotetica cella della mia griglia considerando il cursore a fondo 
pagina dopo aver immesso i caratteri che formano la griglia su stoutput?
Prima di immettere la "griglia" a schermo uso la funzione clrscr() per 
pulire lo schermo.
es. approssimaticvo della griglia che la mia funzione crea:
   ___________________
   |  |  |  |  |  |  |
   -------------------
   |  |  |  |  |  |  |
   -------------------
   |  |  |  |  |  |  |
   -------------------
         grazie anticipatamente, rz


In C non c'e' nessun modo per fare quello che chiedi (se non scrivere i 
dati _mentre_ scrivi la griglia, che sarebbe una soluzione semplice e 
portabile... anche se mi rendo conto che a seconda del tuo programma 
puo' essere una cosa fattibile o meno).
Se ti interessano soluzioni _non_ portabili, devi invece chiedere sul 
newsgroup del sistema operativo che usi, per sapere quali librerie sono 
disponibili: ad es., it.comp.programmare.win32 per windows o 
it.comp.os.linux.development per linux.
Cmq, gia' che ci sono, ti do un hint: guarda conio.h (per windows) o le 
ncurses (per linux, ma non mi pare sia il tuo caso ^_^).
-- 
/**
  * Mattia Belletti - Undergraduate student @ 
cs.unibo.it
  * ICQ: 33292311   - email: 
mbel...@cs.unibo.it
  * IRC: BluShine   - site(s): 
http://cs.unibo.it/~mbellett
  * Linux registered user 299762 @ Linux registered machine 213003
  */

 all'interno delle celle della griglia.
La cosa migliore e' scrivere i dati dentro la griglia mentre crei la
griglia..... questo non significa doverli calcolare mentre disegna la
griglia! Infatti calcolarli mentre disegni la griglia potrebbe non essere
possibile oppure, anche se possibile, renderebbe la funzione per disegnare
la griglia completamente mono-uso. In altre parole se vuoi varie griglie con
vari numeri avrai bisogno di varie funzioni..... Uno strazio.
Devi quindi creare una funzione che stampi la griglia e dentro la griglia
dei valori che sono stati calcolati fuori da tale funzione! E.. oltre a
questo devi rendere la funzione per disegnare la griglia *completamente
flessibile*.
Ecco un esempio (che sei libero di copiare-incollare ed usare):
<CODE>
#include<stdio.h>
#include<stdlib.h>
void DrawData(int *data,const int x_size,const int y_size,const int num_len)
{
    int x,y,l,s;
    for(y=0;y<y_size;++y){
        printf("+--");
        for(s=0;s<num_len;++s){
            printf("-");
        }
        for(l=1;l<x_size-1;++l){
            printf("+--");
            for(s=0;s<num_len;++s){
                printf("-");
            }
        }
        printf("+--");
        for(s=0;s<num_len;++s){
            printf("-");
        }
        printf("+\n");
        for(x=0;x<x_size;++x){
            printf("| %*d ",num_len,data[y*x_size+x]);
        }
        printf("|\n");
    }
    printf("+--");
    for(s=0;s<num_len;++s){
        printf("-");
    }
    for(l=1;l<x_size-1;++l){
        printf("+--");
        for(s=0;s<num_len;++s){
            printf("-");
        }
    }
    printf("+--");
    for(s=0;s<num_len;++s){
        printf("-");
    }
    printf("+\n");
}
int main()
{
    int x,y;
    int x_size,y_size;
    int *statistics=NULL;
    ////////////////////////
    // PRIMA TABELLA:
    x_size=8; y_size=3;
    statistics = malloc(sizeof(int)*x_size*y_size);
    // Calcoliamo le cose prima di disegnare la griglia:
    for(x=0;x<x_size;++x){
        for(y=0;y<y_size;++y){
            statistics[y*x_size+x] = (x+1)*(y+1);
        }
    }
    // Disegnamo la griglia con le cose dentro:
    DrawData(statistics,x_size,y_size,3);
    free(statistics);
    ////////////////////////
    // SECONDA TABELLA:
    x_size=4; y_size=6;
    statistics = malloc(sizeof(int)*x_size*y_size);
    // Calcoliamo le cose prima di disegnare la griglia:
    for(x=0;x<x_size;++x){
        for(y=0;y<y_size;++y){
            statistics[y*x_size+x] = rand()%1000000;
        }
    }
    // Disegnamo la griglia con le cose dentro:
    DrawData(statistics,x_size,y_size,6);
    free(statistics);
    return 0;
}
</CODE>
NOTA: se stai usando un compilatore C++ e non C allora dovrai cambiare le
righe:
statistics = malloc(sizeof(int)*x_size*y_size);
in
statistics = (int*)malloc(sizeof(int)*x_size*y_size);
in altre parole mettendo un cast a int* .....
La funzione:
void DrawData(int *data,const int x_size,const int y_size,const int
num_len);
e' la funzione che disegna una griglia di dimensione x_size * y_size con
numeri di lunghezza massima num_len che si trovano nell'array data.
Nel main troviamo due parti, ognuna disegna una tabella. La prima parte
disegna una griglia di tipo:
x_size=8; y_size=3; e num_len = 3 i cui dati sono stati pre-calcolati per
creare una tipica tabellina scolastica...
La seconda parte invece:
x_size=4; y_size=6; e num_len = 6 i cui dati sono stati pre-inseriti a caso.
Ecco quindi il risultato della esecuzione del programma:
+-----+-----+-----+-----+-----+-----+-----+-----+
|   1 |   2 |   3 |   4 |   5 |   6 |   7 |   8 |
+-----+-----+-----+-----+-----+-----+-----+-----+
|   2 |   4 |   6 |   8 |  10 |  12 |  14 |  16 |
+-----+-----+-----+-----+-----+-----+-----+-----+
|   3 |   6 |   9 |  12 |  15 |  18 |  21 |  24 |
+-----+-----+-----+-----+-----+-----+-----+-----+
+--------+--------+--------+--------+
|     41 |  11478 |  23281 |   4827 |
+--------+--------+--------+--------+
|  18467 |  29358 |  16827 |   5436 |
+--------+--------+--------+--------+
|   6334 |  26962 |   9961 |  32391 |
+--------+--------+--------+--------+
|  26500 |  24464 |    491 |  14604 |
+--------+--------+--------+--------+
|  19169 |   5705 |   2995 |   3902 |
+--------+--------+--------+--------+
|  15724 |  28145 |  11942 |    153 |
+--------+--------+--------+--------+
Come vedi la funzione e' completamente flessibile nei parametri! Ah, x_size
e y_size devono essere >=2 oppure non funziona.... Questo non credo tuttavia
sia un problema....
In questo modo invece di disegnare una griglia vuota e poi ritornare nella
griglia a posizionare i valori (che con il C standard non si riesce a fare e
poi e' un metodo "brutto") puoi calcolare tutti di dati da mettere nella
griglia e poi disegnare la griglia con gia' dentro i dati.
Spiego brevemente:
    ////////////////////////
    // PRIMA TABELLA:
    x_size=8; y_size=3;
    statistics = malloc(sizeof(int)*x_size*y_size);
    // Calcoliamo le cose prima di disegnare la griglia:
    for(x=0;x<x_size;++x){
        for(y=0;y<y_size;++y){
            statistics[y*x_size+x] = (x+1)*(y+1);
        }
    }
    // Disegnamo la griglia con le cose dentro:
    DrawData(statistics,x_size,y_size,3);
    free(statistics);
definisci una dimensione per x-size e per y-size.
poi allochi un array monodimensionale (che usiamo come bi-dimensionale)
abbastanza grande da contenere x-size*y-size elementi.
poi inseriamo i valori nell'array.
poi disegnamo la griglia passando l'array con i valori e le dimensioni.
Oltre a queste passiamo la lunghezza massima dei numeri. In questo caso e' 3
visto ma basterebbe anche 2 visto che 8*3 = 24 e questo e' di solo due
cifre.
Ad esempio nella seconda tabella che e' una 4*6, i dati vengono riempiti
con: rand()%1000000
questo crea numeri da 0 a 999999 e per questo abbiamo passato come num_len
6; questa e' la lunghezza massima che un numero generato da tale chiamata a
rand() puo' avere!
Ok, fai un copia-incolla, compila il programma, provalo, prova di vedere
come funziona e quindi se riesci ad adattarlo al tuo uso.
Altrimenti, se questo non ti puo' aiutare, come ti e' stato suggerito
potresti guardare su conio.h. Ma... se riesci evita, il metodo descritto (se
puo' essere utilizzato) e' portabile e.... molto piu' pulito e migliore.
Spero di esserti stato di aiuto,
Tommy

 
Ci ho appena guardato: c'è un bel gotoXY e un whereXY. Mi sa che 
indagando un po' sul loro utilizzo possa riuscire ad usarle per il mio 
scopo.
Ciao e grazie, rz.

 
Ho spulciato conio.c e .h, me le sono stampate e guardate per benino e 
ho risolto: fico! Ringrazio il Belletti.
		ciao, rz.

 più specifiche per farlo....
Vedi, il punto e' che bisogna fare una distinzione
- il linguaggio C, quello che puoi vedere se prendi, ad es., il 
Kernigan-Ritchie. Il linguaggio contiene un minimo di funzioni, 
contenute nella libreria standard (ed e' il linguaggio C il tema di 
questo newsgroup)
- le librerie del sistema operativo. Queste _non_ fanno parte del 
linguaggio C, e quindi non hai nessun assicurazione di trovarle in tutti 
gli ambienti in cui vai a compilare. Tuttavia, per certe operazioni sono 
essenziali.
Conclusione: finche' puoi, usa le funzioni della libreria standard. In 
questo caso, a meno di non utilizzare qualcosa simile al metodo che ti 
abbiamo suggerito, sei obbligato ad usare conio.h, che pero', ad es., se 
vai su uno unix molto prob non c'e'! :)
Questo giusto per chiarire un concetto importante ;)


 ho risolto: fico!
Ok, ma valuta se sia questo o meno il modo migliore..... per alcuni scopi
potrebbe esserlo (ad esempio per accettare input dall'utente in varie
caselle della griglia) e per altri potrebbe non esserlo....
Tommy

In ANSI C non esistono funzioni per il posizionamento arbitrario del
cursore nella console. Per il tuo problema specifico il mio consiglio
è semplicemente allocare una matrice bidimensionale di caratteri,
modificare quest'ultima e stamparla per intero ad ogni modifica... Dal
punto di vista estetico non è sicuramente il massimo soprattutto
perché le griglie ti verranno stampate una sotto l'altra: se conosci
le dimensioni della tua videata (in termini di righe) però a questo
problema si ovvia stampando un opportuno numero di righe vuote.
Le funzioni per il posizionamento arbitrario del cursore nella console
esistono delle librerie specifiche di ogni sistema operativo: per il
Dos, ad esempio, la conio e per Linux/Unix la ncurses. Un programma
che faccia riferimento a queste ultime, tuttavia, perde la
caratteristica di portabilità del codice standard.
S. B.

 
		ciao, rz.

 
Grazie a tutti per le risposte. Ho finito il programma che altro non era 
che un esercizio per casa da consegnare ad un professore. Ecco perchè la 
portabilità di questo programma non mi interessa.
Ho appena consegnato la versione priva di interfaccia grafica del campo 
di gioco. La prox settimana se avrò voglia implementerò la 
visualizzazione del campo di gioco con le funzioni (non trasportabili) 
che ho già creato.
	grazie ancora, rz.