#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
int LeggiClock ( void );
void Maschera ( void );
void Regine ( int );
void VediSoluzione ( void );
/*---------------------------------------------------------------------------
P R O B L E M A
D E L L E N R E G I N E
Si voglia disporre su una scacchiera quadrata con Lato assegnato, un numero
di Regine (degli Scacchi) pari al numero di caselle del lato, senza che
alcun pezzo ne tenga un altro sotto scacco.
La scacchiera, con righe e colonne da 1 a Lato, viene solo immaginata e
non corrisponde ad una reale variabile in memoria: ne controlliamo le
proprietà tramite gli array:
Casa [] indica la colonna occupata da ciascuna Regina
usato solo per visualizzare le soluzioni
Colonne [] segnala le colonne occupate
Destre [] segnala le diagonali principali occupate
Sinistre[] segnala le diagonali secondarie occupate
Le diagonali sono in numero quasi doppio rispetto alle righe e alle colonne,
andranno quindi dimensionate adeguatamente.
--------------------------- Variabili Globali ----------------------------*/
int Lato;
// misura del lato della scacchiera in esame
long Totale; // totale delle configurazioni trovate
int Casa [ 50]; // indica la colonna occupata da ciascuna Regina
int Colonne [ 50]; // segnala le colonne occupate
int Destre [100]; // segnala le diagonali principali occupate
int Sinistre[100]; // segnala le diagonali secondarie occupate
/*=========================================================================*/
void main (void)
{ int i,
Time1, Time2;
char Buffer[100];
do
{ Maschera();
gotoxy (20, 23); textcolor(11);
cprintf("Lato della scacchiera (1..20): ");
Lato = atoi (gets(Buffer));
}
while (Lato<1 || Lato>20);
Maschera();
Totale = 0;
for (i=0; i< 50; Colonne [i] = 0, i++);
for (i=0; i<100; Sinistre[i] = Destre[i] = 0, i++);
Time1 = LeggiClock ();
Regine (1);
Time2 = LeggiClock () - Time1;
gotoxy (8, 23); textcolor(10);
cprintf ("Scacchiera con lato %2d :%10ld soluzioni in %8.3f secondi\n",
Lato, Totale, Time2/18.2 );
while (getch() != 27);
}
/*=========================================================================
Funzione ricorsiva per il posizionamento delle Regine sulla Scacchiera
Utilizza le variabili globali
Lato lato della scacchiera da esaminare
Totale totale delle configurazioni trovate
Casa [] indica la colonna occupata da ciascuna Regina
Colonne [] segnala le colonne occupate
Destre [] segnala le diagonali principali occupate
Sinistre[] segnala le diagonali secondarie occupate
Le case della diagonale destra hanno costante la differenza tra gli indici.
Le case di una diagonale sinistra hanno costante la somma degli indici.
Nei tre array 0 indica la linea libera, 1 indica la linea occupata.
--------------------------------------------------------------------------*/
void Regine
( int Rig
)
{ int Col, // 1 <= Col <= Lato successive posizioni sul rigo da tentare
Sin, // su diagonale sinistra: Sin = Col + Rig
Dex; // su diagonale destra: Dex = Col - Rig + Lato
// (+Lato per evitare indici negativi).
for (Col=Lato, Sin=Col+Rig, Dex=Col-Rig+Lato; Col; Col--, Sin--, Dex--)
{ // poiché Rig e Lato sono costanti, Sin e Dex sono funzione
// solo di Col e quindi vengono decrementate parallelamente.
if ( ! Colonne [Col] &&
! Sinistre [Sin] &&
! Destre [Dex]
)
{ Colonne [Col] = Sinistre [Sin] = Destre [Dex] = 1; Casa[Rig] = Col;
if ( Rig < Lato ) Regine (Rig+1);
else
Totale ++, VediSoluzione();
Colonne [Col] = Sinistre [Sin] = Destre [Dex] = 0;
}
}
}
/*=========================================================================
Lettura del Timer di sistema all'indirizzo RAM 0046Ch,
aggiornato dal PIT, tramite l'IRQ0, 18.2 volte al secondo
--------------------------------------------------------------------------*/
int LeggiClock (void)
{ asm { push Es
xor Ax, Ax
mov Es, Ax
mov Ax, Es:[0x046c]
pop Es
}
return _AX;
}
/*=======================================================================*/
void Maschera (void)
{ int i;
clrscr(); textbackground(4); textcolor(0);
gotoxy( 2, 1); for(i=2; i<=79; cprintf(" "),i++);
gotoxy(20, 1); cprintf("P R O B L E M A d e l l e
N R E G I N E");
gotoxy( 2,25); for(i=2; i<=79; cprintf(" "),i++);
gotoxy(58,25); cprintf("di Luigi Lamberti");
textbackground(0); textcolor(7); gotoxy (1, 3);
}
/*==========================================================================
Visualizza una soluzione del gioco. Utilizza le variabili globali
Lato lato della scacchiera da esaminare
Totale totale delle configurazioni trovate
Casa [] indica la colonna occupata da ciascuna Regina
--------------------------------------------------------------------------*/
void VediSoluzione (void)
{ int r, c, x;
textcolor(11);
for (r=1; r<=Lato; r++)
{ gotoxy (20,r+2); c = Casa[r];
for (x=1; x<c; cprintf ("ù "), x++);
cprintf ("W ");
for (x=c+1; x<=Lato; cprintf ("ù "), x++);
}
gotoxy (8, 23); textcolor(10);
cprintf ("Lato %2d :%10ld soluzioni", Lato, Totale);
}
|