using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace Grattacieli
{
public partial class Form1 : Form
{
TextBox[,] schema; // contiene la griglia delle textBox
// matrice master
public int[,] schemeM;
internal struct S // la scacchiera ha le seguenti info
{
public byte nRighe; // numero di righe
public byte nColonne; // numero di colonne
public byte wQuadratino; // larghezza del quadratino
public byte hQuadratino; // altezza del quadratino
}
private S Scacchiera; // contiene le info della scacchiera
// matrice della griglia
sbyte[,
] grid
= new sbyte[5, 5
]; byte sizeL = 5;
byte SGL = 5 + 2;
// lista che conterrà tutte le matrici grid con tutte le combinazioni valide possibili (576)
List
<sbyte[,
]> listGrid
= new List
<sbyte[,
]>(); int mostra = -1;
public Form1()
{
InitializeComponent();
int Rg= Grattacieli.Properties.Settings.Default.SizeGInteg;
int Cg = Grattacieli.Properties.Settings.Default.SizeGInteg;
grid
= new sbyte[Rg, Cg
]; SGL = Convert.ToByte(Grattacieli.Properties.Settings.Default.SizeGbyte +2) ;
sizeL = Grattacieli.Properties.Settings.Default.SizeGbyte;
numupdownDimensioneGr.Value = Rg;
preparaGriglia(Rg);
risolviGrid(grid); // creazione di tutte le griglie possibili ma valide
labInfo.Text = "griglie n. " + listGrid.Count.ToString();
}
public void preparaGriglia(int size)
{
if(size == 4)
{ // matrice con una soluzione da trovare
int[,] schemeM4 = {{ 0, 2, 1, 3, 2, 0 },
{ 2, 0, 0, 0, 0, 2 },
{ 1, 0, 0, 0, 0, 3 },
{ 3, 0, 0, 0, 0, 2 },
{ 2, 0, 0, 0, 0, 1 },
{ 0, 2, 3, 2, 1, 0 }};
int len = size + 2;
schemeM
= new int[len, len
]; schemeM = (int[,])schemeM4.Clone();
}
if (size == 5)
{ // matrice con una soluzione da trovare
int[,] schemeM5 = {{ 0, 1, 2, 2, 3, 4, 0 },
{ 1, 0, 0, 0, 0, 0, 5 },
{ 2, 0, 0, 0, 0, 0, 3 },
{ 2, 0, 0, 0, 0, 0, 2 },
{ 3, 0, 0, 0, 0, 0, 2 },
{ 4, 0, 0, 0, 0, 0, 1 },
{ 0, 5, 2, 3, 2, 1, 0 }};
int len = size + 2;
schemeM
= new int[len, len
]; schemeM = (int[,])schemeM5.Clone();
}
if (size == 6)
{ // matrice con una soluzione da trovare
int[,] schemeM6 = {{ 0, 6, 1, 2, 2, 3, 3, 0 },
{ 2, 0, 0, 0, 0, 0, 0, 3 },
{ 3, 0, 0, 0, 0, 0, 0, 2 },
{ 3, 0, 0, 0, 0, 0, 0, 1 },
{ 2, 0, 0, 0, 0, 0, 0, 4 },
{ 2, 0, 0, 0, 0, 0, 0, 2 },
{ 1, 0, 0, 0, 0, 0, 0, 3 },
{ 0, 1, 4, 2, 4, 2, 2, 0 }};
int len = size + 2;
schemeM
= new int[len,len
]; schemeM = (int[,])schemeM6.Clone();
}
}
// *************** GENERAZIONE 576 GRIGLIE VALIDE ****************
public void risolviGrid(sbyte[,] grid)
{
int size = grid.GetLength(0);
int[] row
= new int[size
]; int[] col
= new int[size
]; for (int i = 0; i < size; i++)
{
row[i] = -1;
col[i] = -1;
}
risolviCell(grid, row, col, 0, 0);
}
int conta = 0;
public void risolviCell(sbyte[,] grid, int[] row, int[] col, int r, int c)
{
int size = grid.GetLength(0);
if (r == size)
{
if (ControlloCoerenza(grid)==false)
{
return;
}
conta += 1;
if (conta % (10000) == 0)
{
sbyte[,] clonedGrid = (sbyte[,])grid.Clone();
listGrid.Add(clonedGrid); // aggiungo la griglia valida alla lista
this.Text = "griglie n." + (conta);
}
return;
}
if (c == size)
{
risolviCell(grid, row, col, r + 1, 0);
return;
}
if (listGrid.Count > 99) return;//esce quando raggiunge il limite selezionato.
for (sbyte i = 1; i <= size; i++)
{
if (valida(grid, row, col, r, c, i))
{
grid[r, c] = i;
row[r] = i;
col[c] = i;
risolviCell(grid, row, col, r, c + 1);
grid[r, c] = 0;
row[r] = -1;
col[c] = -1;
}
}
}
static bool valida(sbyte[,] grid, int[] row, int[] col, int r, int c, int num)
{
int size = grid.GetLength(0);
for (int i = 0; i < size; i++)
{
if (row[r] == num || col[c] == num || grid[r, i] == num || grid[i, c] == num)
{
return false;
}
}
return true;
}
static bool ControlloCoerenza(sbyte[,] grid)
{
int size = grid.GetLength(0);
for (int ir = 0; ir < size; ir++)
{
for (int j = 0; j < size; j++)
{
if (grid[ir, j] == 0)
{
return false;
}
}
}
for (int ir = 0; ir < size; ir++)
{
for (int j = 0; j < size; j++)
{
for (int v = j+1; v < size; v++)
{
if (grid[ir, j] == grid[ir, v])
{
return false;
}
}
}
}
for (int ic = 0; ic < size ; ic++)
{
for (int j = 0; j < size; j++)
{
for (int v = j + 1; v < size; v++)
{
if (grid[j, ic] == grid[v, ic])
{
return false;
}
}
}
}
return true;
}
// *************** FINE GENERAZIONE 576 GRIGLIE VALIDE ****************
private void Form1_Shown(object sender, EventArgs e)
{
Scacchiera.nColonne = SGL;
Scacchiera.nRighe = SGL;
Scacchiera.wQuadratino = 40;
Scacchiera.hQuadratino = 35;
sizeL = Scacchiera.nRighe;
creaSchema();
visualizzaScheme(schemeM); // prima visualizzazione
}
private void creaSchema()
{
schema
= new TextBox
[Scacchiera.
nColonne, Scacchiera.
nRighe]; // nuova matrice di textBox vuota for (byte riga = 0; riga < sizeL; riga++)
{
for (byte colonna = 0; colonna < sizeL; colonna++)
{
schema
[colonna, riga
] = new TextBox
(); if (colonna > 0 && colonna < sizeL-1 && riga > 0 && riga < sizeL-1)
{ // griglia interna
schema[colonna, riga].BackColor = Color.Yellow;
schema[colonna, riga].ReadOnly = true;
schema
[colonna, riga
].
Font = new Font
("Microsoft San Serif",8,FontStyle.
Bold); }
else
{ // corona esterna
schema[colonna, riga].TextChanged += schema_TextChanged;
schema[colonna, riga].Click += schema_Click;
}
if (colonna == 0 && riga == 0 || colonna == sizeL - 1 && riga == 0 || colonna == 0 && riga == sizeL - 1 || colonna == sizeL - 1 && riga == sizeL - 1) schema[colonna, riga].Visible = false;
// tutte
schema[colonna, riga].Name = colonna.ToString() + ";" + riga.ToString(); // il nome contiene gli indici "colonna;riga"
schema[colonna, riga].TextAlign = HorizontalAlignment.Center;
schema
[colonna, riga
].
Size = new Size
(Scacchiera.
wQuadratino, Scacchiera.
hQuadratino); schema
[colonna, riga
].
Location = new Point
(colonna
* Scacchiera.
wQuadratino + 20, riga
* Scacchiera.
hQuadratino + 50
); this.Controls.Add(schema[colonna, riga]);
}
}
}
public void schema_Click(object sender, EventArgs e)
{
TextBox tb = (TextBox)sender;
tb.SelectAll(); // seleziona il testo della textBox cliccata
}
public void schema_TextChanged(object sender, EventArgs e)
{
TextBox tb = (TextBox)sender;
int val = 0;
string []coord = tb.Name.Split(';');
if (int.TryParse(tb.Text, out val)) // se il valore è ammesso viene inserito in scheme
{
if (val > 0 && val < Scacchiera.nColonne - 1) schemeM[Convert.ToInt16(coord[1]), Convert.ToInt16(coord[0])] = val; else visualizzaScheme(schemeM);
}
else visualizzaScheme(schemeM); // visualizzo vecchio
tb.SelectAll(); // riseleziona
}
int np = 0;
public void butTrova_Click(object sender, EventArgs e)
{
for (int i = np; i < listGrid.Count; i++)
{
soluzioneN(i, schemeM);
if (Verifica(schemeM)) // se tutti i grattacieli che devono essere visibili lo sono
{
labInfo.Text = "griglia corrispondente n." + (i+1);
visualizzaScheme(schemeM);
np = i+1;
break;
}
else // se anche solo uno dei grattacieli che devono essere visibili non lo è
{
if(i == listGrid.Count-1)
{
labInfo.Text = "griglia n. " + (i + 1).ToString("000") + " nessuna valida trovata";
labInfo.Refresh();
np = 0;
}
}
}
}
public bool Verifica(int[,] scheme) // conta le corrispondenze grattacieli trovati visibili, con il numero nella corona che stabilisce i visibili
{
int size = scheme.GetLength(0);
int quanti = 0;
int Targhet = (size-2) * 4;
int []gratta
= new int[size
-2
]; // vettore che contiene i grattacieli in esame // controllo colonne 1/4 da posizione riga 0
for (int i = 1; i < size - 1; i++)
{
for (int c = 0; c < size - 2; c++) gratta[c ] = scheme[c + 1, i]; // elenco
int trovati = contaGrattaVisibili(gratta);
int visibili = scheme[0,i];
if (trovati == visibili) quanti++;
}
// controllo colonne 1/4 da posizione riga 5
for (int i = 1; i < size - 1; i++)
{
for (int c = 0; c < size - 2; c++) gratta[size - 3 - c] = scheme[c + 1, i]; // elenco al contrario
int trovati = contaGrattaVisibili(gratta);
int visibili = scheme[size - 1, i];
if (trovati == visibili) quanti++;
}
// controllo righe 1/4 da posizione colonna 0
for (int i = 1; i < size - 1; i++)
{
for (int c = 0; c < size - 2; c++) gratta[c] = scheme[i, c + 1]; // elenco
int trovati = contaGrattaVisibili(gratta);
int visibili = scheme[i, 0];
if (trovati == visibili) quanti++;
}
// controllo righe 1/4 da posizione colonna 5
for (int i = 1; i < size - 1; i++)
{
for (int c = 0; c < size - 2; c++) gratta[size - 3 - c] = scheme[i, c + 1]; // elenco al contrario
int trovati = contaGrattaVisibili(gratta);
int visibili = scheme[i, size - 1];
if (trovati == visibili) quanti++;
}
if (quanti == Targhet) return true; else return false;
}
static int contaGrattaVisibili(int[] buildings)
{
int visibleBuildings = 0;
int maxHeight = 0;
foreach (int height in buildings)
{
if (height > maxHeight)
{
visibleBuildings++;
maxHeight = height;
}
}
return visibleBuildings;
}
public void visualizzaScheme(int[,] scheme)
{
Console.WriteLine("---------------------");
int size = scheme.GetLength(0);
for (int i = 0; i < size ; i++)
{
for (int j = 0; j < size ; j++)
{
Console.Write(scheme[i, j] + " ");
schema[j, i].Text = scheme[i,j].ToString(); // indici invertiti tra schema e scheme
}
Console.WriteLine();
}
}
private void soluzioneN(int solN, int[,] scheme)
{
int size = scheme.GetLength(0);
for (int i = 1; i < size-1; i++)
{
for (int j = 1; j < size-1; j++) // mette la griglia in esame in scheme
{
scheme[j, i] = listGrid[solN][i-1, j-1] * 10; // indici invertiti tra schema e scheme
}
}
}
private void butIstruzioni_Click(object sender, EventArgs e)
{
MessageBox.Show("Il gioco consiste nel posizionare i grattacieli in modo da rispettare la visibilità.\n" +
"I grattacieli con più piani coprono i più bassi.\n" +
"se abbiamo -> 30 20 10 40, due sono i grattacieli visibili il 30 e il 40, all'inverso solo il 40\n\n" +
"I numeri nella corona stabiliscono quanti grattacieli sono visibili, " +
"puoi modificare quelli di default.\n\nClicca [trova] per verificare se c'è soluzione\n\n" +
"Il programma non serve per giocare ma per trovare le soluzioni se esistono, inserendo i numeri nella corona.\n\n" +
"Con [<] e [>] si possono esplorare tutte le soluzioni possibili", "Informazione", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void butMeno_Click(object sender, EventArgs e)
{
if (--mostra < 0) mostra = listGrid.Count - 1;
soluzioneN(mostra, schemeM);
calcolaCorona(schemeM);
visualizzaScheme(schemeM);
labInfo.Text = "griglia n." + mostra;
np = 0;
}
private void butPiu_Click(object sender, EventArgs e)
{
if (++mostra > listGrid.Count - 1) mostra = 0;
soluzioneN(mostra, schemeM);
calcolaCorona(schemeM);
visualizzaScheme(schemeM);
labInfo.Text = "griglia n." + mostra;
np = 0;
}
private void calcolaCorona(int[,] scheme)
{
int size = scheme.GetLength(0);
int[] gratta
= new int[size
- 2
]; // vettore che contiene i grattacieli in esame // controllo colonne 1/4 da posizione riga 0
for (int i = 1; i < size - 1; i++)
{
for (int c = 0; c < size - 2; c++) gratta[c] = scheme[c + 1, i];
int trovati = contaGrattaVisibili(gratta);
scheme[0, i] = trovati;
}
// controllo colonne 1/4 da posizione riga 5
for (int i = 1; i < size - 1; i++)
{
for (int c = 0; c < size - 2; c++) gratta[size - 3 - c] = scheme[c + 1, i]; // al contrario
int trovati = contaGrattaVisibili(gratta);
scheme[size - 1, i] = trovati; ;
}
// controllo righe 1/4 da posizione colonna 0
for (int i = 1; i < size - 1; i++)
{
for (int c = 0; c < size - 2; c++) gratta[c] = scheme[i, c + 1];
int trovati = contaGrattaVisibili(gratta);
scheme[i, 0] = trovati;
}
// controllo righe 1/4 da posizione colonna 5
for (int i = 1; i < size - 1; i++)
{
for (int c = 0; c < size - 2; c++) gratta[size - 3 - c] = scheme[i, c + 1]; // al contrario
int trovati = contaGrattaVisibili(gratta);
scheme[i, size - 1] = trovati;
}
}
private void btn_CambiaGriglia_Click(object sender, EventArgs e)
{
int s = Convert.ToInt16(numupdownDimensioneGr.Value);
byte sb = Convert.ToByte(numupdownDimensioneGr.Value);
if (s > 6) return;
Grattacieli.Properties.Settings.Default.SizeGbyte = sb;
Grattacieli.Properties.Settings.Default.SizeGInteg = s;
Grattacieli.Properties.Settings.Default.Save();
MessageBox.Show("Riavviare il programma");
this.Close();
}
}
}