Newsgroup: it.comp.lang.c
Titolo: Scacchiera

Mi servirebbe un aiuto per un mio programma: vorrei creare una scacchiera di
dimensioni fornite dall'utente.
La scacchiera può essere anche rettangolare (purchè base e altezza siano
composte da un numero di pixels pari). Supponiamo che sia 1 = bianco e 0 =
nero, quindi vorrei costruire una matrice fatta così :
101010....                                           110011001100
010101....       e anche così  :           110011001100
101010....                                           001100110011
................                                             001100110011
cioè una matrice con scacchi di lato 1 pixel e una matrice con scacchi di
lato 2 pixels.
Mi potreste suggerire una soluzione ? Grazie.
Luca.

Mi potreste suggerire una soluzione ? Grazie.
Il programma che ti ho scritto di seguito esegue il calcolo di una
scacchiera di qualsiasi dimensione in forma quadrata.
Il programma e' *sicuramente* ottimizzabile.
Puoi adattarlo per cio' che ti serve :
#include <stdio.h>
#include <stdlib.h>
typedef unsigned long  DWORD ;
typedef unsigned short BIT  ;
const unsigned MAX_WIDTH = sizeof ( DWORD ) * 8 ;
/* questa e' la massima dimensione in bit di una DWORD */
void put_bit ( DWORD * b, BIT bit )
/* shifta di 1 posto a sinistra e introduce il bit meno significativo
*/
{
     *b <<= 1 ;
     *b |= (DWORD) bit ;
}
BIT get_bit ( DWORD * b, unsigned dim )
/* estrae il bit piu' significativo e shifta di 1 posto a sinistra */
{
     unsigned v = (*b >> (dim - 1) ) & 1L ;
     *b <<= 1 ;
     return v ;
}
void bit_expand ( DWORD * b, unsigned dim, unsigned zoom_factor )
/* espande i bit di una DWORD */
/* es.: 1010 in 11001100      */
{
     DWORD new_buffer = 0L ;
     unsigned i, j ;
     BIT bit ;
     for (i = 0 ; i < dim ; i++)
     {
         bit = get_bit ( b, dim ) ;
         for (j = 0 ; j < zoom_factor ; j++)
             put_bit ( &new_buffer, bit ) ;
     }
     *b = new_buffer ;
}
DWORD create_line ( unsigned dim )
/* crea una linea che cominci con una sequenza di 1 */
{
      DWORD l = 0L ;
      BIT b = 0 ;
      while ( dim-- )
            put_bit ( &l, b = !b ) ;
      return l ;
}
void write_line ( DWORD line, unsigned dim )
/* scrive una linea di bit */
{
     unsigned d = dim ;
     BIT b ;
     while (d--)
     {
           b = get_bit ( &line, dim ) ;
           putchar ( b ? '1' : '0' ) ;
     }
}
int main ( void )
{
    DWORD * chess_table, line ;
    unsigned i, j, dim, new_dim, zoom_fact, max_zoom ;
    do
    {
       printf ( "dimensione scacchiera (max %u) = ", MAX_WIDTH ) ;
       fflush ( stdout ) ;
       scanf ( "%u", &dim ) ;
    } while ((dim % 2) || (dim > MAX_WIDTH)) ;
    max_zoom = MAX_WIDTH / dim ;
    /* fattore massimo di zoom effettuabile */
    do
    {
       printf ( "fattore di zoom [1..%u] = ", max_zoom ) ;
       fflush ( stdout ) ;
       scanf ( "%u", &zoom_fact ) ;
    } while ( (zoom_fact < 1) || (zoom_fact > max_zoom) ) ;
    chess_table = calloc ( dim * zoom_fact , sizeof ( DWORD ) ) ;
    /* alloca la scacchiera */
    line = create_line ( dim ) ;
    /* crea la prima linea del tipo 1010.... */
    bit_expand ( &line, dim, zoom_fact ) ;
    /* espande la linea secondo il fattore di zoom desiderato */
    new_dim = dim * zoom_fact ;
    /* calcola la dimensione *reale* della scacchiera */
    for ( i = 0 ; i < new_dim ; i += zoom_fact )
    /* espande la scacchiera in verticale */
    {
        for ( j = i ; j < i+zoom_fact ; j++)
            chess_table [ j ] = line ;
        line = ~line ;
    }
    for ( i = 0 ; i < new_dim ; i++ )
    /* scrive a video la scacchiera linea per linea */
    {
        write_line ( chess_table [ i ], new_dim ) ;
        printf ( "\n" ) ;
    }
    return 0 ;
}
Andrea Laforgia

Puoi adattarlo per cio' che ti serve :
Il programma va benissimo , però a me servirebbe avere la scacchiera
all'interno di una matrice 640x480 di unsigned short int, e non in un
vettore di unsigned long come chess_table. Questo perchè devo poter accedere
a ogni singolo elemento della scacchiera(=matrice) in quanto devo poi fare
il prodotto elemento a elemento
con un'altra matrice 640x480 di unsigned short int che creo nel mio
programma.
Posso farlo modificando il tuo algoritmo? e come?
Scusa per l'insistenza ma non sono molto esperto.
Ti ringrazio moltissimo per l'interessamento.
ciao, Luca.

programma.
Potresti essere piu' preciso ?
Una matrice di 640x480 unsigned short int che cosa rappresenta ?
Perche', per intenderci, gli unsigned long che contiene chess_table
nel mio programma contengono la configurazione di ogni linea della
scacchiera, mentre nel tuo caso gli unsigned short ?
Poi, tieni presente che l'occupazione di memoria e' davvero ingente
(640x480 = 307200 byte x 2 (se short e' a 16 bit) = 600 Kb)
Andrea Laforgia
*************************************************
Cerca sempre di percorrere una strada contromano.
Sara' piu' difficile prenderti alle spalle.
*************************************************


La matrice 640x480 di unsigned short int è la matrice figura in cui è
contenuto il contorno che devo considerare: ogni suo elemento è un punto del
contorno; essa contiene un "1" in corrispondenza di un punto del contorno e
tutti gli altri elementi sono "0". Questa matrice va moltiplicata elemento a
elemento con la matrice scacchiera di dimensioni 640x480 anch'essa, in cui
però la dimensione degli scacchi deve poter essere variabile come succede
nel tuo programma. In questo modo il risultato del prodotto sarà una matrice
640x480 con degli "1" in corrispondenza dei punti del contorno che cadevano
su degli "1" della scacchiera e "0" tutti gli altri.
A presto, Luca.

Ti puoi spiegare meglio ?
La matrice di 1 e 0 la vuoi disegnare o vuoi una classica matrice del tipo
MATRICE[10][10] riempita di 1 e 0 ?


La seconda che hai detto :-)
ciao, Luca.

La matrice 640x480 di unsigned short int č la matrice figura in cui č
Ho capito che cosa vuoi fare.
In tal caso ti basta modificare il codice che ti ho postato, cambiando
il tipo "unsigned long" della chess_table con un tipo che identifica
una riga di 640 "unsigned short".
Puoi introdurre i bit e shiftarli, simulando le stesse operazioni con
gli unsigned short int.
Il codice seguente ne e' una dimostrazione :
#include <stdio.h>
#include <stdlib.h>
typedef unsigned short USHORT ;
typedef USHORT row_t [640] ;
static int put_bit_index = 0 ;
static int get_bit_index = 0 ;
void line_expand ( row_t * r, unsigned * dim, unsigned zoom_factor )
{
     row_t new_r ;
     unsigned i, j, k = 0 ;
     for (i = 0 ; i < *dim ; i++)
         for (j = 0 ; j < zoom_factor ; j++)
             new_r[k++] = (*r)[i] ;
     *dim *= zoom_factor ;
     memcpy ( r, &new_r, sizeof ( row_t ) ) ;
}
void put_bit ( row_t * r, USHORT bit )
{
     (*r)[put_bit_index++] = bit ;
}
USHORT get_bit ( row_t r )
{
    return r[get_bit_index++] ;
}
void make_line ( row_t * r, unsigned dim )
{
     USHORT start = 1 ;
     unsigned i ;
     for (i = 0 ; i < dim ; i++ )
     {
           (*r)[i] = start ;
           start = !start ;
     }
}
void write_line ( row_t r, unsigned dim )
{
     unsigned i ;
     for (i = 0 ; i < dim ; i++)
         putchar ( r[i] ? '1' : '0' ) ;
}
int main()
{
    row_t r, neg_r ;
    unsigned dim = 10, zoom_factor = 3 ;
    make_line ( &r, dim ) ;
    puts("linea non espansa : ");
    write_line ( r, dim ) ;
    puts("");
    line_expand ( &r, &dim, zoom_factor ) ;
    puts("linea espansa : ");
    write_line ( r, dim ) ;
    puts("");
    return 0 ;
}
Che da' un output del genere :
linea non espansa : 
1010101010
linea espansa : 
111000111000111000111000111000
Il codice esegue l'operazione solo per la prima riga.
Non ti ho riscritto tutto il programma perche' e' facile espandere la
scacchiera anche in verticale e calcolare le righe complementari.
Ma se hai problemi chiedi pure ;)