C# 如何验证2d位图是连续的?
假设您在C#中有以下结构: 但以下情况并非如此:C# 如何验证2d位图是连续的?,c#,bitmap,boolean,area,C#,Bitmap,Boolean,Area,假设您在C#中有以下结构: 但以下情况并非如此: ...# ...# #... #... 如何确定所有位是否连续 编辑:这是完整的代码,包含了Eric Lippert的答案。从性能上看,这当然可以更严格,但它非常可读 struct Point : IEquatable<Point> { public int X, Y; public Point(int x, int y) { X = x; Y = y; } public bool
...#
...#
#...
#...
如何确定所有位是否连续
编辑:这是完整的代码,包含了Eric Lippert的答案。从性能上看,这当然可以更严格,但它非常可读
struct Point : IEquatable<Point> {
public int X, Y;
public Point(int x, int y) {
X = x; Y = y;
}
public bool Equals(Point obj) {
return X == obj.X && Y == obj.Y;
}
public override bool Equals(object obj) {
if (obj == null) return false;
if(obj is Point)
return Equals((Point)obj);
return false;
}
public override int GetHashCode() {
return X ^ ~Y;
}
public static bool operator == (Point p1, Point p2) {
return p1.X == p2.X && p1.Y == p2.Y;
}
public static bool operator !=(Point p1, Point p2) {
return p1.X != p2.X || p1.Y != p2.Y;
}
public static readonly Point Empty = new Point(int.MinValue, int.MinValue);
}
struct Piece : IEquatable<Piece> {
public readonly int size;
public readonly bool[,] data;
private bool valid;
public Piece(Piece p) {
size = p.size;
valid = p.valid;
data = (bool[,])p.data.Clone();
}
public Piece(int s, bool[,] d) {
size = s;
if (d.GetLength(0) != s || d.GetLength(1) != s) throw new ArgumentException();
data = (bool[,])d.Clone();
valid = false;
CalcValidity();
}
public bool IsValid {
get {
return valid;
}
}
private enum Square {
White,
Black,
Red,
Blue,
}
private int NumSquares(Square[,] map, Square q) {
int ret = 0;
for (int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
if (map[x, y] == q) ret++;
}
}
return ret;
}
private Point PickSquare(Square[,] map, Square q) {
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
if (map[x, y] == q) return new Point(x, y);
}
}
return Point.Empty;
}
private void MakeNeighboursRed(Square[,] map, Point p) {
if (p.X > 0 && map[p.X - 1, p.Y] == Square.Black) map[p.X - 1, p.Y] = Square.Red;
if (p.X < size - 1 && map[p.X + 1, p.Y] == Square.Black) map[p.X + 1, p.Y] = Square.Red;
if (p.Y > 0 && map[p.X, p.Y - 1] == Square.Black) map[p.X, p.Y - 1] = Square.Red;
if (p.Y < size - 1 && map[p.X, p.Y + 1] == Square.Black) map[p.X, p.Y + 1] = Square.Red;
}
private void CalcValidity() {
Square[,] map = new Square[size, size];
int count = 0;
Point square = Point.Empty;
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
if (data[x, y]) {
map[x, y] = Square.Black;
square = new Point(x, y);
} else {
map[x, y] = Square.White;
}
}
}
if (square != Point.Empty) {
map[square.X, square.Y] = Square.Red;
}
while (true) {
if (NumSquares(map, Square.Red) == 0) {
if (NumSquares(map, Square.Black) == 0) {
valid = count == size;
return;
} else {
valid = false;
return;
}
} else {
square = PickSquare(map, Square.Red);
MakeNeighboursRed(map, square);
map[square.X, square.Y] = Square.Blue;
count++;
}
}
}
#region IEquatable<Piece> Members
public bool Equals(Piece other) {
if (size != other.size) return false;
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
if (data[x, y] != other.data[x, y]) return false;
}
}
return true;
}
#endregion
}
struct Point:IEquatable{
公共整数X,Y;
公共点(整数x,整数y){
X=X;Y=Y;
}
公共布尔等于(obj点){
返回X==obj.X&&Y==obj.Y;
}
公共覆盖布尔等于(对象对象对象){
if(obj==null)返回false;
如果(obj是点)
返回等于((点)obj);
返回false;
}
公共覆盖int GetHashCode(){
返回X^~Y;
}
公共静态布尔运算符==(点p1,点p2){
返回p1.X==p2.X&&p1.Y==p2.Y;
}
公共静态布尔运算符!=(点p1,点p2){
返回p1.X!=p2.X | | p1.Y!=p2.Y;
}
公共静态只读点空=新点(int.MinValue,int.MinValue);
}
结构件:IEquatable{
公共只读int大小;
公共只读bool[,]数据;
私有布尔有效;
公共件(件p){
尺寸=p.size;
有效=p.valid;
data=(bool[,])p.data.Clone();
}
公共物品(整数s,布尔[,]d){
尺寸=s;
如果(d.GetLength(0)!=s | | d.GetLength(1)!=s)抛出新的ArgumentException();
数据=(bool[,])d.Clone();
有效=错误;
计算有效性();
}
公共布尔是有效的{
得到{
返回有效;
}
}
私有枚举广场{
白色
黑色
红色
蓝色
}
私人整数平方(正方形[,]地图,正方形q){
int-ret=0;
对于(int y=0;y0&&map[p.X-1,p.Y]==Square.Black)map[p.X-1,p.Y]=Square.Red;
如果(p.X0&&map[p.X,p.Y-1]==Square.Black)map[p.X,p.Y-1]=Square.Red;
如果(p.Y
从一个随机的“真”位开始。然后你一次“走”一个北,一个南,一个东,一个西。如果您发现一个“真”位不是“已访问的”,则在一个单独的结构中将该节点标记为“已访问的”,并从那里递归地向各个方向“行走”。如果位为“false”或“visited”,则不执行任何操作并返回到上一个“级别”。如果找不到更多的非“已访问”节点,请计算已访问节点的数量,并与“真实”节点的总数进行比较
编辑:请注意,如果位图很大,递归将耗尽堆栈空间。以下是一种考虑不使用递归的泛洪填充算法的方法 首先,将每个正方形设置为白色(空白)或黑色(填充)。问题是“黑色区域是否相邻?” 您可以使用以下算法:
非常感谢你!这太完美了。我喜欢你的博客,尤其是a
...#
...#
#...
#...
struct Point : IEquatable<Point> {
public int X, Y;
public Point(int x, int y) {
X = x; Y = y;
}
public bool Equals(Point obj) {
return X == obj.X && Y == obj.Y;
}
public override bool Equals(object obj) {
if (obj == null) return false;
if(obj is Point)
return Equals((Point)obj);
return false;
}
public override int GetHashCode() {
return X ^ ~Y;
}
public static bool operator == (Point p1, Point p2) {
return p1.X == p2.X && p1.Y == p2.Y;
}
public static bool operator !=(Point p1, Point p2) {
return p1.X != p2.X || p1.Y != p2.Y;
}
public static readonly Point Empty = new Point(int.MinValue, int.MinValue);
}
struct Piece : IEquatable<Piece> {
public readonly int size;
public readonly bool[,] data;
private bool valid;
public Piece(Piece p) {
size = p.size;
valid = p.valid;
data = (bool[,])p.data.Clone();
}
public Piece(int s, bool[,] d) {
size = s;
if (d.GetLength(0) != s || d.GetLength(1) != s) throw new ArgumentException();
data = (bool[,])d.Clone();
valid = false;
CalcValidity();
}
public bool IsValid {
get {
return valid;
}
}
private enum Square {
White,
Black,
Red,
Blue,
}
private int NumSquares(Square[,] map, Square q) {
int ret = 0;
for (int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
if (map[x, y] == q) ret++;
}
}
return ret;
}
private Point PickSquare(Square[,] map, Square q) {
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
if (map[x, y] == q) return new Point(x, y);
}
}
return Point.Empty;
}
private void MakeNeighboursRed(Square[,] map, Point p) {
if (p.X > 0 && map[p.X - 1, p.Y] == Square.Black) map[p.X - 1, p.Y] = Square.Red;
if (p.X < size - 1 && map[p.X + 1, p.Y] == Square.Black) map[p.X + 1, p.Y] = Square.Red;
if (p.Y > 0 && map[p.X, p.Y - 1] == Square.Black) map[p.X, p.Y - 1] = Square.Red;
if (p.Y < size - 1 && map[p.X, p.Y + 1] == Square.Black) map[p.X, p.Y + 1] = Square.Red;
}
private void CalcValidity() {
Square[,] map = new Square[size, size];
int count = 0;
Point square = Point.Empty;
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
if (data[x, y]) {
map[x, y] = Square.Black;
square = new Point(x, y);
} else {
map[x, y] = Square.White;
}
}
}
if (square != Point.Empty) {
map[square.X, square.Y] = Square.Red;
}
while (true) {
if (NumSquares(map, Square.Red) == 0) {
if (NumSquares(map, Square.Black) == 0) {
valid = count == size;
return;
} else {
valid = false;
return;
}
} else {
square = PickSquare(map, Square.Red);
MakeNeighboursRed(map, square);
map[square.X, square.Y] = Square.Blue;
count++;
}
}
}
#region IEquatable<Piece> Members
public bool Equals(Piece other) {
if (size != other.size) return false;
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
if (data[x, y] != other.data[x, y]) return false;
}
}
return true;
}
#endregion
}
public static IEnumerable<Tile> GetNeighbours(Tile tile)
{
... yield return the north, south, east and west neighbours
... if they exist and they are on
}
bool HasExactlyOneRegion()
{
return (tilesTurnedOn.Count == 0) ?
false :
TransitiveAndReflexiveClosure(GetNeighbours, tilesTurnedOn.First()).Count == tilesTurnedOn.Count;
}