我有一个问题,我需要将小方块合并为更大的矩形。假设我有一个2D网格,填充随机1和0:
1 0 1 1 0
1 0 1 1 1
0 1 0 1 1
0 1 0 1 1
0 0 1 0 0
1表示已填充的区域,我将它们绘制成屏幕方式为正方形。但是,对于这个问题,我需要先将它们匹配成矩形。在示例节目中,左上角的1是>
1
1
可以加入矩形。
我认为这应该足以解释我的需要。然而,优选的是,不在一个以上的矩形中使用特定的正方形。此外,它不一定是具有最少数量矩形的最佳情况,只是具有较少矩形的更好情况。如果它会使事情变得容易,也允许1x1矩形。
任何有关我可以从哪里开始,甚至解决方案的见解都将受到赞赏。
如果你想知道这个问题背后的原因,我正在为我正在研究的游戏开发一个关卡构建器,我希望减少我的顶点数。我以为我会从方块开始,因为它们会很简单,但即使这样也让我难以置信。
感谢您花时间阅读!
答案 0 :(得分:2)
一种简单的方法是寻找相邻的正方形并将它们变成矩形。要做到这一点,首先水平穿过网格并水平相邻的方块连接在一起,然后垂直穿过网格并垂直连接正方形。
考虑:
H =水平矩形
V =垂直矩形
你原来的例子:
1 0 1 1 0
1 0 1 1 1
0 1 0 1 1
0 1 0 1 1
0 0 1 0 0
会变成:
V 0 H H 0
V 0 H H H
0 V 0 H H
0 V 0 H H
0 0 1 0 0
这种方法不是最优的,但如果可以在给定2D网格的情况下这样做,它会将方块变成矩形。
答案 1 :(得分:1)
我正在使用两个步骤来减少游戏中的碰撞器数量。合并水平连续类型,然后合并具有相同宽度的垂直类型。
代码是一项正在进行的工作,但它似乎正在运作〜
public class Tiles
{
public char Type { get; set; }
public int X { get; set; }
public int Y { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public override string ToString()
{
return $@"({X}, {Y}, {Width}, {Height}) '{Type}'";
}
}
public class TilesFromStrings
{
private List<Tiles> Result = new List<Tiles>();
public IEnumerable<Tiles> Create(params string[] lines)
{
Result.Clear();
CreateMergedHorizontalTiles(lines);
MergeVerticallyTilesWithSameWidth();
return Result.Where(f => f.Height > 0);
}
private void MergeVerticallyTilesWithSameWidth()
{
foreach (var current in Result)
{
foreach (var other in Result)
{
if (other.Y + other.Height == current.Y
&& other.X == current.X
&& other.Height > 0
&& current.Height > 0)
{
if (other.Type == current.Type)
{
if (other.Width == current.Width)
{
current.Height--;
current.Y++;
other.Height++;
break;
}
}
}
}
}
}
private void CreateMergedHorizontalTiles(string[] tiles)
{
Tiles currentRect = null;
var lastColumnIndex = tiles[0].Length - 1;
for (int rowIndex = 0; rowIndex < tiles.Length; rowIndex++)
{
for (int columnIndex = 0; columnIndex < tiles[rowIndex].Length; columnIndex++)
{
var currentType = tiles[rowIndex][columnIndex];
if (columnIndex == 0)
{
currentRect = new Tiles
{
X = columnIndex + 1,
Y = rowIndex + 1,
Width = 1,
Height = 1,
Type = currentType
};
continue;
}
if (columnIndex == lastColumnIndex)
{
if (currentRect.Type == currentType)
{
Result.Add(currentRect);
currentRect.Width++;
}
else
{
Result.Add(currentRect);
currentRect = new Tiles
{
X = columnIndex + 1,
Y = rowIndex + 1,
Width = 1,
Height = 1,
Type = currentType
};
Result.Add(currentRect);
}
continue;
}
if (currentRect.Type == currentType)
{
currentRect.Width++;
}
else
{
Result.Add(currentRect);
currentRect = new Tiles
{
X = columnIndex + 1,
Y = rowIndex + 1,
Width = 1,
Height = 1,
Type = currentType
};
}
}
}
}
}