Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am re-developing a chess game I wrote in Java, and was wondering if there is an elegant algorithm to color chess tiles on a numbered chess board.

Right now my solution uses if else statements to determine if the tile is on an even or odd row, and based on that, if it should be a light or dark square.

share|improve this question
    
Why do you need a more elegant algorithm to do something so basic? Just curiosity or...? –  ssb Dec 5 '12 at 5:45
4  
Honestly I'm just curious. –  Amir Afghani Dec 5 '12 at 5:54

6 Answers 6

up vote 39 down vote accepted

The most elegant way I can think of, given that you have the row and column indices, is the following:

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

or, conversely:

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

Basically, a tile on a chessboard is light wherever both the column and row are mutually odd or even, and is dark otherwise.

share|improve this answer
4  
Very nice solution. Although your comment is misleading: "a tile on a chessboard is light wherever both the column and row are even". That's not true.. assume row is 3 and column is 5 (both are uneven) 3 % 2 == 1 and 5 % 2 == 1.. so both are uneven but will be colored "light". Not saying your solution is wrong (it's good, as it will alternate the pattern) but your comment/explanation seems wrong. –  bummzack Dec 5 '12 at 7:00
    
Whoops, thanks for spotting that @bummzack. Updated the answer. –  ktodisco Dec 5 '12 at 7:11
    
A nice way of putting it might be saying a tile is light as long as its coordinates have the same parity. –  ver Dec 31 '12 at 11:03

This one assumes that our squares are numbered in the range [0..63].

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

Figuring out why it works is half the fun. :)

share|improve this answer
    
Interesting approach. But don't you have to do something to the return value to get it into a bool, e.g. return (i>>3 ^ i) & 1 != 0? Does java allow implicit conversion of integer to boolean? –  LarsH Dec 5 '12 at 20:20
    
Ah, you're right; I read straight over the "Java" bit, and wrote the answer thinking about C++. Editing my answer. –  Trevor Powell Dec 5 '12 at 20:45
    
This is clearly the best board. –  Marcks Thomas Dec 5 '12 at 21:21
1  
This approach appeals to me the same way that Perl appeals to me. This sort of succinct incomprehensibility is always fun to write. Less fun to debug. –  Trevor Powell Dec 5 '12 at 22:54

Although this approach isn't really necessary for something as simple as a chess board, when I think of an elegant way to render something related to the view, I want to make it as easy as possible to change the rendered view as possible. For example, suppose you decided you wanted to alternate black and white on each row, but not each column. The one-liners used in answers so far would have to be re-written.

If I was to go as far as I could with this and make it as easy to redesign the pattern on the Chess board as possible, here is what I would do:

1) I would make a file that indicates what color each square in the chess board is.

For example, I could make a file chess_board_pattern.config that looks something like this:

bwbwbwbw
wbwbwbwb
bwbwbwbw
wbwbwbwb
bwbwbwbw
wbwbwbwb
bwbwbwbw
wbwbwbwb

2) I would write a class/component/whatever that can read this file and create some kind of object that represents the board pattern:

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) I would then use that class in the function that actually draws the board.

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

Again, this is a lot harder than is necessary for a Chess board. I think in general, though, when working on more complicated projects, it's best to come up with generalized solutions like this instead of writing code that's difficult to change later.

share|improve this answer
8  
You should post this to thedailywtf.com. :) –  avakar Dec 5 '12 at 13:04
11  
Not enterprisey enough, needs more XML. –  Darth Satan Dec 5 '12 at 13:32
3  
Hello, Kevin. You wrote The one-liners used in answers so far would have to be re-written. but also it's best to come up with generalized solutions like this instead of writing code that's difficult to change later. But you must understand that this code is much harder to tear down and rewrite than a single line. So I downvoted you because it isn't elegant or advisable to do this. –  Chris Burt-Brown Dec 5 '12 at 14:22
1  
+1 - Elegance is not just in brevity. If being able to change board configurations is one of the requirements, this is a good way to go. I've done similar things in some puzzle programs. I wouldn't expect a chess program to have this requirement though. And I wouldn't agree that generalized solutions are always best. There is NO END to generalizations that could be made, such that you can't write Hello World without implementing an LALR parser and an OpenGL interpreter. The key is knowing when YAGNI. –  LarsH Dec 5 '12 at 21:11
2  
I like this answer. It's the most elegant way to maximize your profits if you're being billed by the hour! –  Panda Pajama Dec 6 '12 at 3:13

Another suggestion, very straightforward:

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

Adding the row and column gives the number of horizontal and vertical steps away from the top-left tile.

Even number of steps gives light colour.
Odd numbers of steps gives dark colour.

share|improve this answer
    
Basically the same as Nathan's answer just written differently. –  API-Beast Dec 5 '12 at 15:07
    
@Mr.Beast: & 1 is going to be a lot more efficient than % 2, unless the latter is specially optimized. But in general I agree. –  LarsH Dec 5 '12 at 20:19
1  
@LarsH The compiler takes care of those kind of things (or at least, it should) –  Niko Drašković Dec 5 '12 at 22:29
    
@LarsH I was aiming for readability, not speed. But there is not much in it. I'm not sure that the speed difference between the two can be considered "a lot" when we know it will only be called 64 times, and I would like to think that a modern compiler would generate identical binaries anyway. –  Chris Burt-Brown Dec 5 '12 at 22:48
    
@Chris: I was talking about the efficiency of the % operation, which is not affected by the number of times it is called. But I agree, it's not likely to make a practical difference in speed of the program, and I also agree about the importance of readability relative to potential speed improvements. –  LarsH Dec 6 '12 at 0:20
bool isLight = ((row ^ column) & 1) == 0;

XOR together the row and column indices and look at the least-significant bit. Changing the row or column index by one will invert the result, hence it generates a checker pattern.

share|improve this answer
5  
^ is fine, but + works equally well. :) –  Chris Burt-Brown Dec 5 '12 at 10:46
2  
For that matter, - works, too. :) –  Trevor Powell Dec 5 '12 at 11:00
2  
Bit operations ftw :) –  Mike C Dec 5 '12 at 15:44
3  
prefer the others, as this is "unreadable" (I know bit operations, doesn't mean it's maintainable) –  Matsemann Dec 5 '12 at 22:26
  1. Number the tiles. You could derive this information by calculating row*8+column or something similar.

  2. Take modulus 16 of the grid number. (There are 16 positions before the tiles repeat.)

  3. Color the tile based on if it has an even or an odd number. Flip the tile color if the result is greater than 7.

Code for zero-based indices:

int cellNum = (row*8+column) % 16;
bool isSecondRow = cellNum > 7;
if(cellNum % 2 == 0 ^ isSecondRow){ //XOR operator
    setColor(Color.White);
}else{
    setColor(Color.Charcoal);
}
share|improve this answer
    
Why do you single out the second row? This should work for all 8 rows –  Amir Afghani Dec 5 '12 at 5:55
1  
I don't understand your question. The modulus 16 operation reduces the problem to two rows. The second row follows a different pattern than the first. The if statement only evaluates to true if either it is an even-numbered tile XOR not in the second row. If both are true, it evaluates to false. Review the XOR operator: msdn.microsoft.com/en-us/library/zkacc7k1.aspx –  Jim Dec 5 '12 at 6:20
1  
IsSecondRow really should have been named IsEvenRow. It's a rather convoluted way to get the low bit of row: first shift the bits of row 3 positions to the right, then discard all but the LSB of row, then check if the 4th bit of cellnum is set. –  MSalters Dec 5 '12 at 15:10
    
I see. +1 for the answer. –  Amir Afghani Dec 5 '12 at 17:56
    
Perhaps a good example of why elegance isn't always the best solution. ;) –  Jim Dec 5 '12 at 22:46

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.