2010-11-05 22 views
10

Ho un numero di controlli (grafici in questo caso) determinato in fase di esecuzione. Mi piacerebbe metterli in una griglia con il numero corretto di righe e colonne. Per esempio,Determina righe/colonne necessarie dato un numero

  • 4 prodotti = 2 x 2
  • 8 Articoli = 4 x 2
  • 9 Articoli = 3 x 3
  • 20 Articoli = 5 x 4
  • 11 Articoli = 4 x 3 (Non mi interessa una cella vuota)

Siamo spiacenti, non ho alcun codice per mostrare i miei tentativi. Ho iniziato a giocare determinando se la radice quadrata è un intero, se il numero è equamente divisibile per 2 ecc. E ho realizzato che non sono sicuro di come attaccare questo problema. Ma questo è quello che sto pensando:

  • Se la radice quadrata è un numero intero, utilizzare la radice quadrata del numero di righe e colonne (nessun problema)
  • In caso contrario, assicurarsi che il numero è anche (aggiungerne uno se necessario, senza problemi)
  • Trova i due numeri interi più alti che producono il numero. per esempio. Se ho 20 controlli, la griglia dovrebbe essere 5 x 4 e non 10 x 2 (non proprio sicuro il modo migliore per farlo)

Apprezzerei se qualcuno potesse indicarmi la giusta direzione - o suggerire un algoritmo diverso se sono fuori dalla base.

+1

Ci sono ulteriori vincoli per decidere un 'migliore' in forma? Ad esempio, 2x17 = 34, ma potresti ottenere una griglia più "quadrata" con uno spazio mancante usando 5x7 = 35. Ciò può diventare arbitrariamente peggiore quando inizi a considerare il doppio di numeri primi sempre più grandi. –

+1

Hmm, non ci avevo pensato - grazie per avermelo fatto notare. Penso che preferirei 35 quadrati con lo spazio mancante. –

risposta

21

Idea: Se la radice quadrata non è un numero intero, esegui il floor, quindi dividi il numero intero con questo, ceiling.

int columns = (int)sqrt(number); 
int lines = (int)ceil(number/(float)columns); 

Esempio: 21 => colonne = 4, linee = 6.

UPDATE: bonus, funziona anche quando sqrt (numero) è intero.Nessun arrotondamento si verifica ovunque e i valori sono corretti.

+1

+1. Ho corretto la formula (che aveva un errore cut-and-paste) ... –

+0

Grazie! Ho rinominato vars mentre stavo scrivendo, cattiva idea;) – jv42

+0

Penso che questo funzionerà per me, grazie per la risposta. –

3

Il "solito" modo di gestire questo problema è dicendo che ci saranno sempre N colonne (meno spesso, sempre N righe). Il problema diventa quindi prendere il numero di elementi, dividendo per N, e questo è il numero di righe che hai (più uno se c'è un resto).

La modifica della dimensione della griglia crea un'interfaccia utente confusa. Gli utenti non capiranno perché la dimensione della griglia continua a cambiare. Loro non se ne staranno veramente meravigliati, ma saranno confusi dai cambiamenti apparentemente casuali.

Se vuoi ancora fare ciò che stai dicendo, penso che dovrai definire il tuo problema un po 'meglio. Esiste un numero massimo di elementi che possono essere contenuti nella griglia? C'è un numero massimo di colonne che permetterete? Ad esempio, se autorizzi 50 articoli, dovrebbero essere in 25 righe di 2 articoli? 5 righe di 10 articoli? 10 righe di 5 articoli?

A un certo punto è necessario scorrere orizzontalmente o dire "il numero massimo di colonne è X". E se hai intenzione di imporre quel numero massimo di colonne, allora stai meglio dicendo semplicemente "Ci saranno sempre X colonne".

A meno che non ci sia un motivo valido per fare la griglia a dimensione variabile che si richiede, si sta meglio senza correggere il numero di colonne. Rende il codice banalmente semplice piuttosto che un trucco complicato e presenta un'interfaccia molto più coerente per i tuoi utenti.

+0

Infatti. Potrei finire con questo approccio. Grazie. –

3

Un rapido controllo di soluzione @ di jv42 funziona bene:

public struct Grid 
{ 
    public int x; 
    public int y; 

    public Grid(int xx, int yy) 
    { 
     x = xx; 
     y = yy; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Grid g0 = GetGrid(1); Debug.Assert(g0.x == 1 && g0.y == 1); 
     Grid g1 = GetGrid(4); Debug.Assert(g1.x == 2 && g1.y == 2); 
     Grid g2 = GetGrid(8); Debug.Assert(g2.x == 2 && g2.y == 4); 
     Grid g3 = GetGrid(9); Debug.Assert(g3.x == 3 && g3.y == 3); 
     Grid g4 = GetGrid(20); Debug.Assert(g4.x == 4 && g4.y == 5); 
     Grid g5 = GetGrid(30); Debug.Assert(g5.x == 5 && g5.y == 6); 
     Grid g6 = GetGrid(99); Debug.Assert(g6.x == 9 && g6.y == 11); 
    } 

    public static Grid GetGrid(int n) 
    { 
     int columns = (int)Math.Sqrt(n); 
     int lines = (int)Math.Ceiling(n/(double)columns); 

     return new Grid(columns, lines); 
    } 
0

In WPF le UniformGrid controllo calcola automaticamente le righe e le colonne della griglia senza determinano le righe e le colonne. per esempio:

<UniformGrid > 
     <Image Source="Images\Aquarium.jpg" Margin="5"/> 
     <Image Source="Images\Ascent.jpg" Margin="5" /> 
     <Image Source="Images\Autumn.jpg" Margin="5"/> 
     <Image Source="Images\Crystal.jpg" Margin="5"/> 
     <Image Source="Images\DaVinci.jpg" Margin="5"/> 
     <Image Source="Images\Follow.jpg" Margin="5"/> 
     <Image Source="Images\Friend.jpg" Margin="5"/> 
     <Image Source="Images\Aquarium.jpg" Margin="5"/> 
    </UniformGrid> 

Risultato => Mostra le immagini in 3 colonne e 3 righe

0

Grazie per questa domanda e risposta!

Ecco il codice tradotta in Javascript:

cols = Math.floor(Math.sqrt(totalTiles)); 
rows = Math.floor( Math.ceil(totalTiles/cols)); 
Problemi correlati