pragma solidity ^0.4.26; contract TicTacToe { enum CellState { Clear, Owner, Player } enum NextMove { Owner, Player } struct Game { address owner; address player; NextMove nextMove; CellState[3][3] state; } uint256 private nextGameId = 0; mapping(uint256 => Game) private games; function createGame() public returns (uint256 gameId) { Game memory game; game.owner = msg.sender; gameId = nextGameId; nextGameId++; games[gameId] = game; } function acceptInvite(uint256 gameId) public returns (NextMove nextMove) { Game storage game = games[gameId]; require(game.owner != address(0), "Game not found"); require(game.player == address(0), "Game invite was already accepted"); game.player = msg.sender; bytes32 draw = keccak256(abi.encodePacked(block.coinbase, game.owner, game.player)); if (draw[0] >> 7 == 0x0) nextMove = NextMove.Player; else nextMove = NextMove.Owner; game.nextMove = nextMove; } function makeMove(uint256 gameId, uint256 row, uint256 column) public returns (CellState winner) { Game storage game = games[gameId]; require(game.owner != address(0), "Game not found"); require(game.player != address(0), "Game was not accepted"); require(game.state[row][column] == CellState.Clear, "This cell is taken"); require(checkGameStatus(game) == CellState.Clear, "This game is over"); if (game.nextMove == NextMove.Owner) { require(game.owner == msg.sender, "Not your move"); game.state[row][column] == CellState.Owner; game.nextMove = NextMove.Player; } else { require(game.player == msg.sender, "Not your move"); game.state[row][column] == CellState.Player; game.nextMove = NextMove.Owner; } return checkGameStatus(game); } function checkGameStatus(Game storage game) private view returns (CellState status) { CellState[3][3] storage state = game.state; if (state[0][0] != CellState.Clear && state[0][0] == state[0][1] && state[0][1] == state[0][2]) return state[0][0]; // TODO all rows, columns, diagonals return CellState.Clear; } }
0.4.26