Reputation: 239
I'm building a program that plays Connect 4, and one of the things to check for is cases where your opponent has the following board positions:
[0,1,1,0,0] or [0,1,0,1,0] or [0,0,1,1,0]
where your opponent is one move away from having three pieces in a row with a blank on either side. If you don't fill one of the middle elements on your next move, your opponent can go there and force a checkmate.
What I have is a board of 42 squares, numbered 1:42. And I created a matrix called FiveCheck, where each row maps to five consecutive board positions. For example:
FiveCheck(34,:) = [board(7),board(14),board(21),board(28),board(35)];
FiveCheck(35,:) = [board(14),board(21),board(28),board(35),board(42)];
are two of the diagonals of the board.
I can test for the possible checkmate with
(sum(FiveCheck(:,2:4),2) == 2 + sum(FiveCheck,2) == 2) == 2
And that gives me a vector with 1's indicating that the corresponding FiveCheck row has a possible checkmate. Let's say the 34th element of that vector has a 1, and the pattern for that diagonal (from the example given above) is [0,0,1,1,0]. How do I return 14, the board position I should move to?
Another separate example, if the 35th element of that vector has a 1, and the pattern for that diagonal is [0,1,0,1,0], how do I return 28?
EDIT: I just realized this is impossible without some sort of a map. So I created FiveMap, a matrix the same size of FiveCheck, with the same formulas except the word "board" is removed. For example:
FiveMap(34,:) = [(7),(14),(21),(28),(35)];
FiveMap(35,:) = [(14),(21),(28),(35),(42)];
Upvotes: 2
Views: 215
Reputation: 114786
Since you are dealing with binary vectors of size 5, a very efficient solution might be the use of a look up table.
Consider board
to be a binary matrix. you can filter it with 4 filters (of length 5), representing horizontal, vertical and two diagonals to identify possible positions you are looking for. Then, for specious locations, you can extract the 5 binary bits and use a look up table of size 32 to get the offset to the position where you should place your piece.
a small example:
% construct LUT
LUT = zeros(32,2); % dx and dy offsets for each entry
LUT(12,:) = [ 1 0 ]; % covering the case [0 1 1 0 0] - put piece 1 to the right of center
% continue constructing LUT here...
horFilt = ones(1, 5);
resp = imfilter( board, horFilt ); % need to think about board''s boundaries here...
[yy xx] = find( resp == 2 ); all locations where filter caught 2 out of 5
pat = board( yy, xx + [ -2 1 0 1 2] ); % I assume here only one location was found
pat = bin2dec( '0'+char( pat ) ); % convert binary pattern to decimal entry
board( yy + LUT(pat,2) , xx + LUT(pat, 1) ) = ... ; % your move here...
Upvotes: 1