C# 确定给定数字所需的行/列

C# 确定给定数字所需的行/列,c#,algorithm,silverlight,math,C#,Algorithm,Silverlight,Math,我有许多在运行时确定的控件(本例中为图表)。我想把它们放在一个有适当行数和列数的网格中。比如说, 4项=2 x 2 8项=4 x 2 9项=3 x 3 20项=5 x 4 11项=4 x 3(我不在乎空单元格) 抱歉,我没有任何代码来显示我的尝试。我开始尝试确定平方根是否是整数,数字是否可以被2整除等等,然后意识到我不确定如何解决这个问题。但这就是我的想法: 如果平方根是整数,则使用平方根表示行数和列数(没有问题) 如果不是,请确保数字为偶数(如果必须,请添加一个-没有问题) 找到生成该数

我有许多在运行时确定的控件(本例中为图表)。我想把它们放在一个有适当行数和列数的网格中。比如说,

  • 4项=2 x 2
  • 8项=4 x 2
  • 9项=3 x 3
  • 20项=5 x 4
  • 11项=4 x 3(我不在乎空单元格)
抱歉,我没有任何代码来显示我的尝试。我开始尝试确定平方根是否是整数,数字是否可以被2整除等等,然后意识到我不确定如何解决这个问题。但这就是我的想法:

  • 如果平方根是整数,则使用平方根表示行数和列数(没有问题)
  • 如果不是,请确保数字为偶数(如果必须,请添加一个-没有问题)
  • 找到生成该数字的最高两个整数。e、 g.如果我有20个控件,网格应该是5x4,而不是10x2(不确定最好的方式)
如果有人能给我指出正确的方向,或者如果我偏离了正确的方向,建议一种不同的算法,我将不胜感激。

处理这个问题的“通常”方法是说总是有N列(较少出现,总是N行)。然后问题就变成了用项数除以N,这就是你拥有的行数(如果有余数,加上一行)

更改网格的大小会导致用户界面混乱。用户不会理解为什么网格的大小不断变化。他们不会真的对此感到惊讶,但他们会被看似随机的变化弄糊涂

如果你仍然想做你所说的,我认为你需要更好地定义你的问题。网格上可以容纳的项目是否有最大数量?是否有允许的最大列数?例如,如果您允许50个项目,那么它们应该在25行中,共2个项目吗?5行10项?10行5项

在某个时刻,您必须水平滚动或说,“最大列数为X”。如果你打算设置最大列数,那么最好只说“总是有X列。”


除非有令人信服的理由去做你要求的可变维度网格,否则你最好只是固定列的数量。它使代码变得非常简单,而不是复杂的黑客行为,并且它为用户提供了一个更加一致的界面。

想法:如果平方根不是整数,将其加上下限,然后将整数除以它,将其除掉

int columns = (int)sqrt(number);
int lines = (int)ceil(number / (float)columns);
示例:21=>columns=4,lines=6


更新:奖金,当sqrt(数字)为整数时也有效。任何地方都不会进行舍入,并且值是正确的。

快速检查@jv42的解决方案效果良好:

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);
    }

在WPF中,控件UniformGrid自动计算网格的行和列,而不确定行和列。 例如:

   <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>
1 2 3
4 5 6

1 2 3
4 5

1 2 3 4
5 6 7


结果=>以3列3行显示图像

感谢您的提问和回答

下面是翻译成Javascript的代码:

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

我有这个问题,但有一些具体的要求

  • 列的数量永远不能超过一定的数量
  • 如果项目的数量不完全符合一定数量的列,我希望尽可能多的寡妇
例如:

   <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>
1 2 3
4 5 6

1 2 3
4 5

1 2 3 4
5 6 7
我提出了这个(PHP)函数,但我相信它可以改进:

<?php
function optimalColCount ($numItems, $maxCols = 4) {
    $numCols = $numItems;

    if ($numCols > $maxCols and $maxCols === 2) {
        $numCols = 2;
    }
    else if ($numCols > $maxCols) {
        $numCols = sqrt($numItems);

        if (!is_int($numCols) or $numCols > $maxCols) {
            $numCols = -1;

            for ($i = $maxCols; $i > 2; $i--) {
                if ($numItems % $i === 0) {
                    $numCols = $i;

                    break;
                }
            }

            if ($numCols === -1) {
                $rests = [];

                for ($i = $maxCols; $i > 2; $i--) {
                    $rests[$i] = $numItems % $i;
                }

                $numCols = array_search(max($rests), $rests);
            }
        }
    }

    return $numCols;
}

是否有进一步的约束条件来帮助决定“更好”的匹配?例如,2x17=34,但使用5x7=35可以得到一个更“方形”的网格,其中缺少一个空间。当你开始考虑越来越大的素数的双倍时,这种情况可能会变得更糟。嗯,我没想过——谢谢你指出这一点。我想我更喜欢35个正方形,上面没有空格。谢谢!我在打字时确实重命名了vars,这是个坏主意;)的确我可能最终会采用这种方法。谢谢