以太坊智慧合約-猜數字

weixin_33978044發表於2018-08-30

準備

以太坊智慧合約初探,完成猜數字遊戲記錄。
開發工具:智慧合約線上編輯remix,可能需要翻牆使用。
瀏覽器錢包:matemask,需要翻牆安裝在Chrome或者Firefox瀏覽器上面。使用brave(基於Chrome)瀏覽器也可以。
測試網路:matemask-RopstenTestNet獲取測試ETH

思路

猜數字遊戲規則:限定兩個人玩,每個人從1-10中選中一個數字,然後下注一定金額的ETH。當兩個人都下注完成之後開獎。開獎結果是隨機生成一個隨機數,誰猜的數字與隨機數相同則贏得遊戲,並獲取兩個人下注的所有ETH,如果都沒猜中或者都猜中則平分所有下注的ETH。

參考古千峰老師猜數字遊戲教程

碰到的坑:
1、remix的run標籤裡面設定Environment為injected web3,即使用matemask的測試網路。一直設定不成功,提示matemask未啟動。多重新整理幾次
2、之前執行合約的bet方法,一直提示gas 計算不出來,導致交易無法完成,因為把checkPlayerExists這個方法宣告成了private型別,改成public即就ok了。

pragma solidity ^0.4.20;

contract Casino{
    
    address public owner;
    uint8 private decimals = 18;//小數
    uint256 public mininumBet = 1*10**(uint256(decimals)-3);//
    uint256 public totalBet;
    uint256 public numberOfBets;
    uint256 constant public maxAmountOfBets=2;
    uint256 public numberGenerated;
    uint256 public winnerEtherAmount;
    address[] public players;
    
    struct Player{
        uint256 amontBets;
        uint256 numberSelected;
    }
    
    mapping(address=>Player) public playerInfo;
    
    // gouzao 
    constructor()public{
        owner=msg.sender;
    }
    
    function bet(uint256 numberSelected)public payable{
        require(!checkPlayerExists(msg.sender));
        require(numberSelected >= 1 && numberSelected <=10);
        require(msg.value >= mininumBet);
        require(numberOfBets<=maxAmountOfBets);
        
        playerInfo[msg.sender].amontBets = msg.value;
        playerInfo[msg.sender].numberSelected = numberSelected;
        numberOfBets++;
        players.push(msg.sender);
        totalBet += msg.value;
        
        if(numberOfBets>=maxAmountOfBets) generateNumberWinner();
    }
    
    function kill() public{
        if(msg.sender==owner) selfdestruct(owner);
    }
    
    function checkPlayerExists(address player) public constant returns(bool){
        for(uint8 i = 0 ; i < players.length ; i++ ){
            if( players[i]==player ) return true;
        }
        return false;
    }
    
    function generateNumberWinner() private{
        numberGenerated = (block.number % 10 +1);// bu an quan 
        distributePrizze(numberGenerated);
    }
    
    function distributePrizze(uint256 numberWinner) private{
        address[maxAmountOfBets] memory winners;
        bool hasWiner=false;
        uint256 count = 0;
        for(uint16 i = 0 ; i<players.length;++i){
            address playerAddress = players[i];
            if(playerInfo[i].numberSelected==numberWinner){
                winners[count]=playerAddress;
                count++;
            }
            delete playerInfo[playerAddress];
        }
        
        if(count==0){
            count = maxAmountOfBets;
            hasWiner = false;
        }else{
            hasWiner= true;
        }
        
        winnerEtherAmount = totalBet*95/100/count;
        
        for(uint16 j = 0; j < count ; j ++){
            if(hasWiner){
                if(winners[j]!=address(0)) winners[j].transfer(winnerEtherAmount);
            }else{
                if(players[j]!=address(0)) players[j].transfer(winnerEtherAmount);
            }
        }
        players.length = 0;
        totalBet=0;
        numberOfBets=0;
        
    }
}

相關文章