Tuesday 3 July 2012

Tic Tac Toe Board Storage Idea

I'm using a Tic Tac Toe (Noughts and Crosses) AI to test certain ideas for my chess AI, because Tic Tac Toe is an awful lot easier to build. Whilst designing this, I was thinking about the best way to represent the board and where the noughts and crosses are in the board. My first thought was to have two 2d arrays, one for each player, with each position in the array representing a position on the board. The values would be true or false, true if that player had a piece in that position, and false if they didn't. I thought this would be a better idea than having one array with either "X", "O" or "nothing" in the positions, as booleans are faster to compare than strings.

To check for a win with this system would involve checking the 8 possible lines in which there could be three of the same piece in a row, and doing this for each player. This would mean (8 * 3 * 2) = 48 checks would need to be performed on the board.

I came up with another system (which is almost definitely not original, but I hadn't heard of anything like it before), in which each player has a number that represents their board. Both numbers start at 1. The positions on the board are represented as prime numbers, as shown in the picture below:

When a player puts a piece in a position, their number is multiplied by the prime number representing that place. So if a player was to put a piece in the middle, they would multiply their number by 11. Because numbers can be split in to unique prime factors, every board layout can be represented by two numbers, one for the positions of the noughts, and the other number for the positions of the crosses. It should be noted that this approach is heavily influenced by Gödel numbering (http://en.wikipedia.org/wiki/Gödel_numbering).


In the board opposite, the number representing the crosses would be (3 * 7 * 13 * 23) = 6279. The number representing the noughts would be (2 * 11 * 19) = 418. Obviously, this approach greatly reduces the number of values that need to be stored in the computer's memory in order to represent the board. However, more interesting is the way in which this can be used to check for a win. Say you wanted to check whether a certain player had won down the middle column. If they had, their number would at some point have been multiplied by 3, 11 and 19, so (3 * 11 * 19) would be a factor of their number. Every line can be checked by this method, in only one operation, instead of the three it would take with the conventional approach.

What is surprising is just how much more efficient this prime method is. I wrote a short program in Visual Basic that generates a number of tic tac toe boards with noughts and crosses randomly distributed in them, and then the user can use either the conventional boolean array method, or the prime method, to check all of the boards for which player has won, if any. (The source code for this program can be found at  http://pastebin.com/MpnrPKjs). In all cases, both methods returned the same results for the number of wins for each player, so it's safe to say that they're accurate. Here are the results of the tests:



Now, it's difficult to see how this exact method could be of use in my chess AI: on an 8x8 grid with 7 different types of pieces, any system of numbers like this would seemingly be far too large to work. However, this experiment does demonstrate the importance of using efficient methods, especially ones that aren't quite so obvious to begin with. The chess AI will involve looking ahead across many possible moves, and analysing the positions. The more efficient the methods used, the quicker this can be done, and the further ahead the AI can look.

No comments:

Post a Comment