NSView - 绘制 2 色跳棋
NSView - Drawing 2-Color Checkers
我有一个 NSView 的子类,我需要在其中绘制双色跳棋(交替颜色的正方形)。以下是我的。
- (void)drawRect:(NSRect)rect {
NSInteger k = 1;
for (int j = 0; j < self.frame.size.width; j += 20) {
for (int i = 0; i < self.frame.size.height; i +=20) {
if (k%2 == 0) {
[[NSColor whiteColor] set];
}
else {
[[NSColor lightGrayColor] set];
}
[NSBezierPath fillRect:NSMakeRect(j,i,20,20)];
k++;
}
}
}
如果我 运行 它,我会得到交替颜色的方块。如果我改变框架高度,我有时会得到交替颜色的条纹。我怎样才能改进上面的代码?
谢谢。
请记住,您的视图不会因为调整大小而重新绘制!所以你的棋盘会随着视图一起被挤压或拉伸。 setNeedsDisplay
.
由你决定
绘制棋盘图案的另一种方法是在绘图程序中制作一个 2x2 棋盘,将其作为资源添加到您的项目中,将该图像传递给 +[NSColor colorWithPatternImage:]
,然后您就可以填充一个具有该颜色的区域。
好的,所以问题是一行中可能有奇数个方块,在这种情况下,下一行再次显示相同的图案。这是我将如何修复它;我还将您对 NSBezierPath 的使用更改为 NSRectFill(),因为后者在概念上更简单而且可能更快。
- (void)drawRect:(NSRect)rect {
for (int j = 0; j * 20 < self.frame.size.width; j++) {
for (int i = 0; i * 20 < self.frame.size.height; i++) {
if (((i^j) & 1) == 0)
[[NSColor whiteColor] set];
else
[[NSColor lightGrayColor] set];
NSRectFill(NSMakeRect(j*20,i*20,20,20));
}
}
}
(i^j) & 1
使用按位异或(^ 运算符)然后按位与(& 运算符)来组合行和列索引的奇偶状态。有多种方法可以优化乘法,但这段代码似乎是最清晰的方法。
一个更简洁的版本会 运行 更快并且可能会避免一些绘图伪影,这涉及首先清除一种颜色然后只绘制相反颜色的方块:
- (void)drawRect:(NSRect)rect {
[[NSColor whiteColor] set];
NSRectFill(rect);
[[NSColor lightGrayColor] set];
for (int j = 0; j * 20 < self.frame.size.width; j++)
for (int i = 0; i * 20 < self.frame.size.height; i++)
if ((i^j) & 1)
NSRectFill(NSMakeRect(j*20,i*20,20,20));
}
您确定正方形颜色的方法会交替排列一列的颜色,然后继续下一列。如果你有偶数行,每行将以相同的颜色开始,给你条纹。
想想简单,你只需要两种状态 - 黑色或白色 - 所以不是整数,加法和 odd/even 测试将整数减少到两个值之一只是从只有两个值的类型开始, 即布尔值。
要处理奇数或偶数行的问题,请使用两个变量,一个跟踪列中第一个方块的颜色 - 这将翻转外循环的每次迭代,一个跟踪当前方块的颜色 - 对于每一列,这从第一个变量的值开始,并翻转内部循环的每次迭代。
在代码大纲中,在外循环之前:
BOOL colStartsWhite = YES; // or NO, you decide - this is the corner color
外循环内部:
BOOL squareIsWhite = colStartsWhite; // inner tracker
colStartsWhite = !colStartsWhite; // flip ready for next column
在内循环中:
if (squareIsWhite) ... else ... // fill the square
squareIsWhite = !squareIsWhite; // flip for next square
HTH
我有一个 NSView 的子类,我需要在其中绘制双色跳棋(交替颜色的正方形)。以下是我的。
- (void)drawRect:(NSRect)rect {
NSInteger k = 1;
for (int j = 0; j < self.frame.size.width; j += 20) {
for (int i = 0; i < self.frame.size.height; i +=20) {
if (k%2 == 0) {
[[NSColor whiteColor] set];
}
else {
[[NSColor lightGrayColor] set];
}
[NSBezierPath fillRect:NSMakeRect(j,i,20,20)];
k++;
}
}
}
如果我 运行 它,我会得到交替颜色的方块。如果我改变框架高度,我有时会得到交替颜色的条纹。我怎样才能改进上面的代码?
谢谢。
请记住,您的视图不会因为调整大小而重新绘制!所以你的棋盘会随着视图一起被挤压或拉伸。 setNeedsDisplay
.
绘制棋盘图案的另一种方法是在绘图程序中制作一个 2x2 棋盘,将其作为资源添加到您的项目中,将该图像传递给 +[NSColor colorWithPatternImage:]
,然后您就可以填充一个具有该颜色的区域。
好的,所以问题是一行中可能有奇数个方块,在这种情况下,下一行再次显示相同的图案。这是我将如何修复它;我还将您对 NSBezierPath 的使用更改为 NSRectFill(),因为后者在概念上更简单而且可能更快。
- (void)drawRect:(NSRect)rect {
for (int j = 0; j * 20 < self.frame.size.width; j++) {
for (int i = 0; i * 20 < self.frame.size.height; i++) {
if (((i^j) & 1) == 0)
[[NSColor whiteColor] set];
else
[[NSColor lightGrayColor] set];
NSRectFill(NSMakeRect(j*20,i*20,20,20));
}
}
}
(i^j) & 1
使用按位异或(^ 运算符)然后按位与(& 运算符)来组合行和列索引的奇偶状态。有多种方法可以优化乘法,但这段代码似乎是最清晰的方法。
一个更简洁的版本会 运行 更快并且可能会避免一些绘图伪影,这涉及首先清除一种颜色然后只绘制相反颜色的方块:
- (void)drawRect:(NSRect)rect {
[[NSColor whiteColor] set];
NSRectFill(rect);
[[NSColor lightGrayColor] set];
for (int j = 0; j * 20 < self.frame.size.width; j++)
for (int i = 0; i * 20 < self.frame.size.height; i++)
if ((i^j) & 1)
NSRectFill(NSMakeRect(j*20,i*20,20,20));
}
您确定正方形颜色的方法会交替排列一列的颜色,然后继续下一列。如果你有偶数行,每行将以相同的颜色开始,给你条纹。
想想简单,你只需要两种状态 - 黑色或白色 - 所以不是整数,加法和 odd/even 测试将整数减少到两个值之一只是从只有两个值的类型开始, 即布尔值。
要处理奇数或偶数行的问题,请使用两个变量,一个跟踪列中第一个方块的颜色 - 这将翻转外循环的每次迭代,一个跟踪当前方块的颜色 - 对于每一列,这从第一个变量的值开始,并翻转内部循环的每次迭代。
在代码大纲中,在外循环之前:
BOOL colStartsWhite = YES; // or NO, you decide - this is the corner color
外循环内部:
BOOL squareIsWhite = colStartsWhite; // inner tracker
colStartsWhite = !colStartsWhite; // flip ready for next column
在内循环中:
if (squareIsWhite) ... else ... // fill the square
squareIsWhite = !squareIsWhite; // flip for next square
HTH