优雅的国际象棋瓷砖着色解决方案


19

我正在重新开发用Java编写的国际象棋游戏,并且想知道是否存在一种优雅的算法来为编号的国际象棋棋盘上色国际象棋棋盘。

现在,我的解决方案使用if else语句来确定图块是在偶数行还是奇数行上,并基于此判断它应该是亮还是暗的正方形。


为什么需要更优雅的算法来完成如此基本的操作?只是好奇还是...?
ssb 2012年

5
老实说,我很好奇。
阿米尔·阿富汗尼

Answers:


40

考虑到您拥有rowcolumn索引,我想到的最优雅的方法是:

bool isLight = (row % 2) == (column % 2);

或者相反:

bool isDark = (row % 2) != (column % 2);

基本上,棋盘上的瓷砖在列和行彼此奇数或偶数的地方都是亮的,否则在黑暗的地方。


4
非常好的解决方案。尽管您的评论具有误导性:“无论行和列都平齐,棋盘上的瓷砖都很亮”。这是不正确的..假设row为3,column为5(均不均匀3 % 2 == 15 % 2 == 1..因此两者均不均匀,但将显示为“浅色”。并不是说您的解决方案是错误的(很好,因为它将替代模式),但是您的注释/解释似乎是错误的。
bummzack

糟糕,感谢您发现@bummzack。更新了答案。
kevintodisco

放置它的一种好方法可能是说一个图块很轻,只要其坐标具有相同的奇偶性即可。
版本

34
bool isLight = ((row ^ column) & 1) == 0;

将行和列索引进行XOR运算,然后查看最低有效位。将行或列的索引更改为1将反转结果,因此将生成检查器模式。


5
^很好,但+效果也一样。:)
克里斯·伯特·布朗

2
为此,它-也起作用。:)
特雷弗·鲍威尔

2
位操作ftw :)
Mike Cluck 2012年

3
更喜欢其他的,因为这是“难以理解的”(我知道位操作,并不意味着它可维护)
Matsemann 2012年

22

另一个建议,非常简单:

isLight = (row + column) % 2 == 0;

添加行和列可得出离开左上图块的水平和垂直步数。

偶数步给出浅色。
奇数个步骤会产生深色。


基本上与内森的答案相同,只是写法不同。
API-Beast

@ Mr.Beast:& 1比效率要高得多% 2,除非后者经过特别优化。但总的来说,我同意。
LarsH

1
@LarsH编译器会处理这类事情(至少,应该这样做)
neeKo 2012年

@LarsH我的目标是可读性,而不是速度。但是里面没有太多。当我们知道只有64次调用时,我不确定两者之间的速度差异是否会被视为“很多”,我想现代的编译器无论如何都会生成相同的二进制文件。
克里斯·伯特·布朗

@Chris:我说的是%运算的效率,它不受调用次数的影响。但是我同意,这不太可能在程序速度上产生实际差异,而且我也同意可读性相对于潜在速度改进的重要性。
LarsH 2012年

4

这个假设我们的正方形在[0..63]范围内编号。

bool IsLight(int i)
{
    return 0!=(i>>3^i)&1;
}

弄清楚为什么它是成功的一半。:)


有趣的方法。但是,您不必对返回值做些什么才能使其变成布尔值return (i>>3 ^ i) & 1 != 0吗?Java是否允许将整数隐式转换为布尔值?
LarsH 2012年

啊,你是对的。我直接阅读“ Java”部分,并撰写了有关C ++的答案。编辑我的答案。
特雷弗·鲍威尔

这显然是最好的板。
马克·托马斯

1
这种方法对我的吸引力与Perl对我的吸引力相同。这种简洁的不可理解性总是很有趣。调试不太有趣。
Trevor Powell

2
  1. 编号瓷砖。您可以通过计算row * 8 + column或类似内容来得出此信息。

  2. 取网格数的模数16。(重复之前,有16个位置。)

  3. 根据图块是偶数还是奇数为图块上色。如果结果大于7,则翻转图块颜色。

从零开始的索引代码:

int cellNum = (row*8+column) % 16;
bool isSecondRow = cellNum > 7;
if(cellNum % 2 == 0 ^ isSecondRow){ //XOR operator
    setColor(Color.White);
}else{
    setColor(Color.Charcoal);
}

为什么选择第二行?这应该适用于所有8行
Amir Afghani 2012年

1
我不明白你的问题。该modulus 16操作将问题减少到两行。第二行与第一行的模式不同。如果该if语句是第二行中没有的偶数瓦片XOR,则该语句的评估结果为true。如果两者都为真,则求值为假。查看XOR运算符:msdn.microsoft.com/en-us/library/zkacc7k1.aspx
Jim

1
IsSecondRow确实应该被命名IsEvenRow。这是获取行的低位的相当复杂的方法:首先将行3的位置向右移动,然后丢弃行的LSB以外的所有位,然后检查是否设置了cellnum的第4位。
MSalters 2012年

我知道了。+1为答案。
阿米尔·阿富汗尼

也许一个很好的例子说明了为什么优雅并不总是最好的解决方案。;)
吉姆(Jim

0

尽管对于象棋盘这样简单的东西实际上并不需要这种方法,但是当我想到一种优雅的方式来渲染与视图相关的东西时,我希望尽可能容易地更改渲染的视图。例如,假设您决定要在每一行而不是每一列上交替显示黑白。到目前为止,答案中使用的单行代码必须重新编写。

如果我要尽可能地做到这一点,并使其尽可能容易地在国际象棋棋盘上重新设计图案,这是我会做的:

1)我将制作一个文件,指示棋盘中每个正方形的颜色。

例如,我可以制作一个chess_board_pattern.config看起来像这样的文件:

bwbwbwbw
wbwbwbwb
bwbwbwbw
wbwbwbwb
bwbwbwbw
wbwbwbwb
bwbwbwbw
wbwbwbwb

2)我将编写一个类/组件/任何可以读取此文件并创建某种表示板模式的对象的对象:

public class BoardPattern {
    private Color[][] pattern;

    public BoardPattern(File patternFile)
    {
        pattern = new Color[8][8];
        //Parse the file and fill in the values of pattern
    }

    public Color[][] getPattern {
        return pattern;
    }
}

3)然后,我将在实际绘制木板的函数中使用该类。

File patternFile = new File("chess_board_pattern.ini");
Color[][] pattern = new BoardPattern(patternFile).getPattern();
ChessBoardDrawable chessBoard = new ChessBoardDrawable();

for(int row = 0; row < 8; row++) {
    for(int column; column < 8; column++) {
        chessBoard.drawSquare(row, column, Color[row][column]);
    }
}

同样,这比国际象棋棋盘要难得多。我认为,总的来说,当处理更复杂的项目时,最好提出这样的通用解决方案,而不是编写以后很难更改的代码。


8
您应该将其发布到thedailywtf.com。:)
avakar

11
不够企业,需要更多XML。
Maximus Minimus 2012年

3
你好,凯文。您编写了代码,但是您The one-liners used in answers so far would have to be re-written.it's best to come up with generalized solutions like this instead of writing code that's difficult to change later.必须编写代码,但是您必须了解,与单行代码相比,拆除和重写该代码要困难得多。因此我拒绝了您的意见,因为这样做不明智或不明智。
克里斯·伯特·布朗

1
+1-优雅不仅简短。如果能够更改电路板配置是要求之一,那么这是一个好方法。我在一些益智游戏中做了类似的事情。我不希望象棋程序有此要求。我不会同意广义的解决方案总是最好的。可以做的总结是没有止境的,因此,如果不实现LALR解析器和OpenGL解释器,就无法编写Hello World。关键是要知道何时使用YAGNI。
LarsH 2012年

2
我喜欢这个答案。如果按小时计费,这是最大化利润的最优雅方式!
熊猫睡衣
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.