You have a major scalability issue here, that your table can only contain the information for one game. You're also not able to change the size of the board without changing the entire schema, or support TicTacToe UltimateTicTacToe Ultimate (even though supporting TTT Ultimate would require some more work, but I believe it would be possible if you structure things correctly).
You have a major scalability issue here, that your table can only contain the information for one game. You're also not able to change the size of the board without changing the entire schema, or support TicTacToe Ultimate (even though supporting TTT Ultimate would require some more work, but I believe it would be possible if you structure things correctly).
You have a major scalability issue here, that your table can only contain the information for one game. You're also not able to change the size of the board without changing the entire schema, or support TicTacToe Ultimate (even though supporting TTT Ultimate would require some more work, but I believe it would be possible if you structure things correctly).
There is one big thing that I don't agree with, and that's your SQL schema. In my opinion, it is not normalized.
Each row should only contain one kind of information. One row in your TicTacToe table however, contains three pieces information: The tile A, the tile B and the tile C.
You have a major scalability issue here, that your table can only contain the information for one game. You're also not able to change the size of the board without changing the entire schema, or support TicTacToe Ultimate (even though supporting TTT Ultimate would require some more work, but I believe it would be possible if you structure things correctly).
I would recommend a more normalized approach to this. So let's see what tables we could use:
- Board (with tiles), obviously, where each row contains a tile in the board
- Game, storing information about the current player and having a
Boardfield to connect the game to a board id. If you want flexible size of the boards, you could addsizeXandsizeYfields here. - WinConditions, to store the data about what rows/columns/diagonals are considered as winners. This will remove the win conditions from your code and add them as data. Below, I have only one board and have linked the WinConditions to a specific board. Ideally, you could create a many-to-many relationship between WinConditions and Game, so that all ordinary Tic-Tac-Toe games can share the same set of WinConditions.
Once you have this setup properly, you'll be able to support much more than just TicTacToe. The game Connect Four actually shares a lot of logic with TicTacToe, the only difference is the size and the existence of "gravity".
Here's some SQL to show an example:
CREATE TABLE Board ( ID INT, X INT NOT NULL, Y INT NOT NULL, VALUE VARCHAR(1) NULL, CONSTRAINT position PRIMARY KEY (ID, X, Y) ); CREATE TABLE Game ( TURN INT, BOARD INT ); CREATE TABLE WinConditions ( Board INT, ConditionID INT, TileX INT, TileY INT ); Setup some win-conditions:
INSERT INTO WinConditions (Board, ConditionID, TileX, TileY) VALUES (1, 1, 0, 0); INSERT INTO WinConditions (Board, ConditionID, TileX, TileY) VALUES (1, 1, 1, 1); INSERT INTO WinConditions (Board, ConditionID, TileX, TileY) VALUES (1, 1, 2, 2); INSERT INTO WinConditions (Board, ConditionID, TileX, TileY) VALUES (1, 2, 0, 0); INSERT INTO WinConditions (Board, ConditionID, TileX, TileY) VALUES (1, 2, 1, 0); INSERT INTO WinConditions (Board, ConditionID, TileX, TileY) VALUES (1, 2, 2, 0); INSERT INTO WinConditions (Board, ConditionID, TileX, TileY) VALUES (1, 3, 2, 0); INSERT INTO WinConditions (Board, ConditionID, TileX, TileY) VALUES (1, 3, 2, 1); INSERT INTO WinConditions (Board, ConditionID, TileX, TileY) VALUES (1, 3, 2, 2); Insert some data into the board, causing it to look like
XOO OX_ X_X INSERT INTO Board (id, x, y, value) VALUES (1, 1, 1, 'X'); INSERT INTO Board (id, x, y, value) VALUES (1, 1, 0, 'O'); INSERT INTO Board (id, x, y, value) VALUES (1, 0, 2, 'X'); INSERT INTO Board (id, x, y, value) VALUES (1, 2, 0, 'O'); INSERT INTO Board (id, x, y, value) VALUES (1, 0, 0, 'X'); INSERT INTO Board (id, x, y, value) VALUES (1, 0, 1, 'O'); INSERT INTO Board (id, x, y, value) VALUES (1, 2, 2, 'X'); Query to check for wins:
SELECT MAX(value), MIN(value), COUNT(value) FROM WinConditions `wc` JOIN Board `b` ON (wc.tilex = b.x) AND (wc.tiley = b.y) AND (wc.board = b.id) WHERE wc.board = 1 GROUP BY conditionID; Output from query:
MAX(VALUE) MIN(VALUE) COUNT(VALUE) X X 3 X O 3 X O 2 By looking at this query, we can see that one condition has led to a win for X, because he's the only player to have played there as MAX(VALUE) == MIN(VALUE) and that COUNT(VALUE) == 3 (where three is the number of tiles in the win condition)
Unfortunately, I don't know SQL syntax good enough to expand this into SQL procedures and stuff, I will leave that up to you to do if you wish :)