Skip to content

Instantly share code, notes, and snippets.

@snario
Created June 10, 2019 11:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save snario/7f4fd39689eaeda992a47d97577cafe8 to your computer and use it in GitHub Desktop.
Save snario/7f4fd39689eaeda992a47d97577cafe8 to your computer and use it in GitHub Desktop.
pragma solidity 0.5.9;
pragma experimental ABIEncoderV2;
library TicTacToe {
enum OutcomeType {
PLAYER_X_WON,
PLAYER_O_WON,
DRAW
}
enum PlayerType { None, X, O }
struct AppState {
PlayerType[3][3] board;
PlayerType claimToVictory;
}
function placeX(AppState calldata state, uint8 posX, uint8 posY)
external
pure
returns (AppState memory)
{
require(
state.claimToVictory == PlayerType.None,
"Cannot place an X on a board where there is already a winner."
);
require(
state.board[posX][posY] == PlayerType.None,
"Cannot place an X on an already filled spot on the board."
);
AppState memory newState = state;
newState.board[posX][posY] = PlayerType.X;
newState.claimToVictory = computeVictoryClaimant(
newState.board,
PlayerType.X
);
return newState;
}
function placeO(AppState calldata state, uint8 posX, uint8 posY)
external
pure
returns (AppState memory)
{
require(
state.claimToVictory == PlayerType.None,
"Cannot place an O on a board where there is already a winner."
);
require(
state.board[posX][posY] == PlayerType.None,
"Cannot place an O on an already filled spot on the board."
);
AppState memory newState = state;
newState.board[posX][posY] = PlayerType.O;
newState.claimToVictory = computeVictoryClaimant(
newState.board,
PlayerType.O
);
return newState;
}
function computeVictoryClaimant(
PlayerType[3][3] memory board,
PlayerType expectedWinner
)
internal
pure
returns (PlayerType)
{
PlayerType ret = PlayerType.None;
if (
board[0][0] == expectedWinner &&
board[0][1] == expectedWinner &&
board[0][2] == expectedWinner
)
return expectedWinner;
if (
board[1][0] == expectedWinner &&
board[1][1] == expectedWinner &&
board[1][2] == expectedWinner
)
return expectedWinner;
if (
board[2][0] == expectedWinner &&
board[2][1] == expectedWinner &&
board[2][2] == expectedWinner
)
return expectedWinner;
if (
board[0][0] == expectedWinner &&
board[1][0] == expectedWinner &&
board[2][0] == expectedWinner
)
return expectedWinner;
if (
board[0][1] == expectedWinner &&
board[1][1] == expectedWinner &&
board[2][1] == expectedWinner
)
return expectedWinner;
if (
board[0][2] == expectedWinner &&
board[1][2] == expectedWinner &&
board[2][2] == expectedWinner
)
return expectedWinner;
if (
board[0][0] == expectedWinner &&
board[1][1] == expectedWinner &&
board[2][2] == expectedWinner
)
return expectedWinner;
if (
board[2][0] == expectedWinner &&
board[1][1] == expectedWinner &&
board[0][2] == expectedWinner
)
return expectedWinner;
return ret;
}
function computeOutcome(AppState calldata appState)
external
pure
returns (OutcomeType)
{
uint8 xCount = 0;
uint8 oCount = 0;
for (uint8 x = 0; x < 3; x++) {
for (uint8 y = 0; y < 3; y++) {
if (appState.board[x][y] == PlayerType.X) {
xCount++;
} else if (appState.board[x][y] == PlayerType.O) {
oCount++;
}
}
}
if (xCount >= oCount) {
return OutcomeType.PLAYER_X_WON;
} else if (xCount == oCount && xCount + oCount == 9) {
return OutcomeType.PLAYER_O_WON;
} else {
return OutcomeType.DRAW;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment