今天來聊聊我們的第三個案例。我們來做一個比大小的下注遊戲。

情境

需要有兩個角色。

  1. GM
  2. 玩家

功能上則需要。

  1. 下注 (讓玩家選擇大 or 小)
  2. 開獎 (判定玩家輸贏,並且依照比例分配獎金)

接下來,我們來看看下面範例。

/ SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.7;

contract BetGame {
    //GM
    address public owner;
    bool isFinshed;

    //紀錄玩家用的 struct
    struct Player {
        address payable addr;
        uint amount;
    }

    //存下大的玩家
    Player[] big;
    //存下小的玩家
    Player[] small;

    //下大的總金額
    uint totalBig;
    //下小的總金額
    uint totalSmall;
    uint nowtime;
    constructor () {
        owner = msg.sender;
        totalSmall = 0;
        totalBig = 0;
        isFinshed = false;
        nowtime = block.timestamp;
    }
    function Bet(bool flag)public payable returns (bool){
        require(msg.value>0);
        Player memory p = Player(payable(msg.sender),msg.value);
        //透過bool true 表示下大
        if (flag){
            big.push(p);
            totalBig += p.amount;
        }
        else {
            small.push(p);
            totalSmall += p.amount;
        }
        return true;
    }

    function open() payable public returns(bool){
        //開獎至少要遊戲開始後60秒
        require(block.timestamp > nowtime+60);
        require(!isFinshed);

        //創造出 0-9的變數 0-4為小 5-9為大
        uint points = uint(keccak256(abi.encode(msg.sender,block.timestamp,block.number)))%9;
        uint i = 0;
        Player memory p;
        if (points >=5 ){
            for (i=0; i<big.length; i++){
                p = big[i];
                //給贏家 下注本金+照比例分配獎金
                p.addr.transfer(p.amount+totalSmall*p.amount/totalBig);
            }
        }
        else{
            for(i = 0 ;i< small.length;i++){
                p = small[i];
                p.addr.transfer(p.amount+totalBig*p.amount/totalSmall);
            }
        }
        isFinshed = true;
        return true;
    }
}