3.0 A High Stakes GameΒΆ
OK how about a friendly wager!
Add a storage variable to hold the placed wagers, beneath
uint256 public turnsTaken_;mapping(address => uint256) public wagers_;
Add a function to allow the players to place a wager
function placeWager() external payable { require(msg.sender == player1_ || msg.sender == player2_, "Not a valid player."); wagers_[msg.sender] = msg.value; }
Update the logic if a winner is found to transfer all the value to them, within the
takeTurnfunctionmsg.sender.transfer(address(this).balance);
Result:
if (isWinner(msg.sender)) { winner_ = msg.sender; gameOver_ = true; msg.sender.transfer(address(this).balance); } else if (turnsTaken_ == 9) { gameOver_ = true; }
Update the logic to refund the value if a draw has occured, within the
takeTurnfunctionplayer1_.transfer(wagers_[player1_]); player2_.transfer(wagers_[player2_]);
Result:
if (isWinner(msg.sender)) { winner_ = msg.sender; gameOver_ = true; msg.sender.transfer(address(this).balance); } else if (turnsTaken_ == 9) { gameOver_ = true; player1_.transfer(wagers_[player1_]); player2_.transfer(wagers_[player2_]); }
Go play! Earn some ETH.
As aboveFinal solution may be found here
Homework!
- What happens when a new game wants to be started in the same contract?
- How to allow this? When to allow this? Reset storage variables?
Important
All done? We recommend reviewing the complementary video series found here.
Completed code:
pragma solidity 0.4.24; contract TicTacToe { address public player1_; address public player2_; mapping(address => uint256) public playerNumbers_; // Map ugly address to number for simpler inspection of game board address public lastPlayed_; address public winner_; bool public gameOver_; uint256 public turnsTaken_; mapping(address => uint256) public wagers_; /** The game board itself * 0, 1, 2 * 3, 4, 5 * 6, 7, 8 */ uint256[9] private gameBoard_; function startGame(address _player1, address _player2) external { player1_ = _player1; playerNumbers_[_player1] = 1; player2_ = _player2; playerNumbers_[_player2] = 2; } /** * @notice Take your turn, selecting a board location * @param _boardLocation Location of the board to take */ function takeTurn(uint256 _boardLocation) external { require(msg.sender == player1_ || msg.sender == player2_, "Not a valid player."); require(gameBoard_[_boardLocation] == 0, "Spot taken!"); require(msg.sender != lastPlayed_, "Not your turn."); require(!gameOver_, "Sorry game has concluded."); gameBoard_[_boardLocation] = playerNumbers_[msg.sender]; lastPlayed_ = msg.sender; if (isWinner(msg.sender)) { winner_ = msg.sender; gameOver_ = true; msg.sender.transfer(address(this).balance); } else if (turnsTaken_ == 9) { gameOver_ = true; player1_.transfer(wagers_[player1_]); player2_.transfer(wagers_[player2_]); } turnsTaken_++; } function getBoard() external view returns(uint256[9]) { return gameBoard_; } function isWinner(address player) private view returns(bool) { uint8[3][8] memory winningFilters = [ [0,1,2],[3,4,5],[6,7,8], // rows [0,3,6],[1,4,7],[2,5,8], // columns [0,4,8],[6,4,2] // diagonals ]; for (uint8 i = 0; i < winningFilters.length; i++) { uint8[3] memory filter = winningFilters[i]; if ( gameBoard_[filter[0]]==playerNumbers_[player] && gameBoard_[filter[1]]==playerNumbers_[player] && gameBoard_[filter[2]]==playerNumbers_[player] ) { return true; } } } }