2010-11-05 20 views
10

Tengo un número de controles (gráficos en este caso) que se determinan en tiempo de ejecución. Me gustaría poner estos en una cuadrícula con el número adecuado de filas y columnas. Por ejemplo,Determine las filas/columnas necesarias dado un número

  • 4 artículos = 2 x 2
  • 8 artículos = 4 x 2
  • 9 artículos = 3 x 3
  • 20 artículos = 5 x 4
  • 11 artículos = 4 x 3 (No me importa una celda vacía)

Lo siento, realmente no tengo ningún código para mostrar mis intentos. Empecé a jugar para determinar si la raíz cuadrada es un número entero, si el número es divisible por 2, etc. y me di cuenta de que no estoy seguro de cómo atacar este problema. Pero esto es lo que pienso:

  • Si la raíz cuadrada es un número entero, utilice la raíz cuadrada del número de filas y columnas (no hay problema)
  • Si no es así, asegúrese de que el número es incluso (agregue uno si tiene que - no hay problemas allí)
  • Encuentra los dos enteros más altos que producen el número. p.ej. Si tengo 20 controles, la cuadrícula debe ser 5 x 4 y no 10 x 2 (no estoy seguro de la mejor manera para esto)

Agradecería que alguien me señale la dirección correcta - o Sugerir un algoritmo diferente si estoy fuera de la base.

+1

¿Hay restricciones adicionales para ayudar a decidir un 'mejor' en forma? Por ejemplo, 2x17 = 34, pero podría obtener una cuadrícula más 'cuadrada' con un espacio perdido usando 5x7 = 35. Esto puede empeorar arbitrariamente a medida que comience a considerar el doble de números primos cada vez más grandes. –

+1

Hmm, no había pensado en eso, gracias por señalarlo. Creo que preferiría 35 cuadrados con espacio faltante. –

Respuesta

21

Idea: Si la raíz cuadrada no es entera, péguela, luego divida el número entero con esto, ceiléelo.

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

Ejemplo: 21 => columnas = 4, líneas = 6.

UPDATE: bono, también funciona cuando sqrt (número) es entero.No se produce redondeo en ninguna parte, y los valores son correctos.

+1

+1. Corregí la fórmula (que tenía un error de cortar y pegar) ... –

+0

¡Gracias! Cambié el nombre de vars mientras escribía, mala idea;) – jv42

+0

Creo que esto me funcionará, gracias por la respuesta. –

3

La forma "habitual" de manejar este problema es diciendo que siempre habrá N columnas (con menos frecuencia, siempre N filas). El problema se convierte entonces en una cuestión de tomar el número de elementos, dividiendo por N, y ese es el número de filas que tiene (más uno si hay un resto).

Cambiar el tamaño de la cuadrícula crea una interfaz de usuario confusa. Los usuarios no entenderán por qué el tamaño de la cuadrícula cambia constantemente. Realmente no se preguntarán sobre eso, pero se verán confundidos por los cambios aparentemente aleatorios.

Si aún quiere hacer lo que dice, creo que tendrá que definir su problema un poco mejor. ¿Hay un número máximo de elementos que pueden caber en la cuadrícula? ¿Hay un número máximo de columnas que permitirás? Por ejemplo, si permite 50 elementos, ¿deberían estar en 25 filas de 2 elementos? 5 filas de 10 elementos? 10 filas de 5 elementos?

En algún momento deberá desplazarse horizontalmente o decir "la cantidad máxima de columnas es X". Y si va a imponer ese número máximo de columnas, entonces será mejor que solo diga "Siempre habrá X columnas".

A menos que haya una razón convincente para hacer la cuadrícula de dimensión variable que usted solicita, es mucho mejor que simplemente arreglar el número de columnas. Se trata de un código trivialmente simple en lugar de un truco complicado, y presenta una interfaz mucho más consistente para sus usuarios.

+0

De hecho. Puedo terminar yendo con este enfoque. Gracias. –

3

Una revisión rápida de la solución de @ jv42 funciona muy bien:

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

En WPF los UniformGrid de control calculan automáticamente las filas y columnas de la rejilla sin determinar las filas y columnas. por ejemplo:

<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> 

Resultado => mostrar las imágenes en 3 columnas y 3 filas

0

Gracias por esta pregunta y la respuesta!

Aquí está el código Javascript traduce en:

cols = Math.floor(Math.sqrt(totalTiles)); 
rows = Math.floor( Math.ceil(totalTiles/cols)); 
Cuestiones relacionadas