]> git.cworth.org Git - lmno.games/blobdiff - tictactoe/tictactoe.jsx
Add an enum (or an enum-like object) for Team values
[lmno.games] / tictactoe / tictactoe.jsx
index 25c8a9f887742312c4537fca678823628be1190d..42c32ef29041345a03d2ca2ddb7ae5cbea5fd2c2 100644 (file)
@@ -1,3 +1,12 @@
+const Team = {
+  X: 0,
+  O: 1,
+  properties: {
+    0: {name: "X"},
+    1: {name: "O"}
+  }
+};
+
 function undisplay(element) {
   element.style.display="none";
 }
@@ -20,9 +29,9 @@ events.onerror = function(event) {
 };
 
 events.addEventListener("move", event => {
-  const square = JSON.parse(event.data);
+  const move = JSON.parse(event.data);
 
-  window.game.receiveMove(square);
+  window.game.receiveMove(move);
 });
 
 events.addEventListener("game-state", event => {
@@ -36,18 +45,31 @@ events.addEventListener("game-state", event => {
 });
 
 function Square(props) {
+  let className = "square";
+
+  if (props.value) {
+    className += " occupied";
+  } else if (props.active) {
+    className += " open";
+  }
+
+  const onClick = props.active ? props.onClick : null;
+
   return (
-    <button className="square" onClick={props.onClick}>
+    <div className={className}
+         onClick={onClick}>
       {props.value}
-    </button>
+    </div>
   );
 }
 
 class Board extends React.Component {
   renderSquare(i) {
+    const value = this.props.squares[i];
     return (
       <Square
-        value={this.props.squares[i]}
+        value={value}
+        active={! this.props.gameOver && ! value}
         onClick={() => this.props.onClick(i)}
       />
     );
@@ -97,7 +119,7 @@ class Game extends React.Component {
         }
       ],
       stepNumber: 0,
-      xIsNext: true
+      next_to_play: Team.X
     };
   }
 
@@ -113,7 +135,7 @@ class Game extends React.Component {
         }
       ],
       stepNumber: 0,
-      xIsNext: true
+      next_to_play: Team.X
     });
   }
 
@@ -124,7 +146,12 @@ class Game extends React.Component {
     if (calculateWinner(squares) || squares[i]) {
       return;
     }
-    squares[i] = this.state.xIsNext ? "X" : "O";
+    squares[i] = Team.properties[this.state.next_to_play].name;
+    let next_to_play;
+    if (this.state.next_to_play === Team.X)
+      next_to_play = Team.O;
+    else
+      next_to_play = Team.X;
     this.setState({
       history: history.concat([
         {
@@ -132,16 +159,16 @@ class Game extends React.Component {
         }
       ]),
       stepNumber: history.length,
-      xIsNext: !this.state.xIsNext
+      next_to_play: next_to_play
     });
   }
 
   async handleClick(i) {
     const response = await this.sendMove(i);
     if (response.status == 200) {
-      const legal = await response.json();
-      if (! legal)
-        add_message("danger", `Illegal move.`);
+      const result = await response.json();
+      if (! result.legal)
+        add_message("danger", result.message);
     } else {
       add_message("danger", `Error occurred sending move`);
     }
@@ -150,7 +177,7 @@ class Game extends React.Component {
   jumpTo(step) {
     this.setState({
       stepNumber: step,
-      xIsNext: (step % 2) === 0
+      next_to_play: (step % 2) === 0
     });
   }
 
@@ -163,7 +190,7 @@ class Game extends React.Component {
     if (winner) {
       status = "Winner: " + winner;
     } else {
-      status = "Next player: " + (this.state.xIsNext ? "X" : "O");
+      status = "Next player: " + (Team.properties[this.state.next_to_play].name);
     }
 
     return (
@@ -173,6 +200,7 @@ class Game extends React.Component {
         </div>
         <div className="game-board">
           <Board
+            gameOver={winner}
             squares={current.squares}
             onClick={i => this.handleClick(i)}
           />