EOS(六) - DAPP实践之小游戏

    这DAPP主要是实现一个小游戏的智能合约的实现,是为了提供学习EOS智能合约用。

1、编译智能合约,生成abi文件
    eosiocpp -o mygame.wast mygame.cpp
    eosiocpp -g mygame.abi  mygame.cpp
2、部署智能合约
    //创建3个用户账号
    cleos create account eosio banker  EOS6zzuh...  EOS6zzuh...
    cleos create account eosio player1 EOS6zzuh...  EOS6zzuh...
    cleos create account eosio player2 EOS6zzuh...  EOS6zzuh...
    //创建一个新游戏
    cleos push action mygame.co creategame '["banker"]' -p banker
    //玩家开牌
    cleos push action mygame.co opencard '[6,1]' -p player1
    cleos push action mygame.co opencard '[6,2]' -p player2
    //查询数据表
    cleos get table mygame.co mygame.co game
    超级节点部署智能合约:
    cleos set contract eosio /hom/.../contracts/eosio.bios -p eosio
    创建一个智能合约文件
    eosiocpp -n mytest
3、前端调用智能合约接口
import React from 'react'
import ReactDOM from 'react-dom'
import EOSJS from 'eosjs'

let contract_name = 'mygame.co'
let account_name = 'banker'

const EOSJS_CONFIG = {
    contractName: contract_name, //合约名字
    contractSender: account_name, //执行合约的账号(需要与私钥对应)
    clientConfig:{
        keyProvider:['5Jc...'], //账号对应的私钥
        httpEndpoint: 'http://172.0.0.1:8888' //EOS节点程序的http终端
    }
}

class LuckPoint extends React.Component {
    constructor(props){
        super(props)

        this._initGameData = this._initGameData.bind(this)

        this.gameprops = {
            gameIndex: -1,
            gameDataList: [];
            loading_test: '正在读取数据...'
        }

        this.state = {
            gameStatus: false,
            winner: 0
        }
    }

    componentDidMount(){
        this._initGameData()
    }

    _initGameData(){
        console.log('_initGameData::......')
        this._updataGameData()
    }

    // cleos get tale luckpoint.co luckpoint.co game
    _updataGameData(){
        console.log('_updataGameData::......')

        this._showLoading(true, '正在读取游戏数据... ...')

        this.gameprops.gameIndex = -1
        this.gameprops.gameDataList = []

        //读取游戏数据
        let eosjs = EOSJS.Localnet(EOSJS_CONFIG.clientConfig)
        eosjs.contract(contract_name)
            .then((contract)=>{
                console.log('_updataGameData::'+contract_name+'合约加载成功!')

                eosjs.getTableRows({"scope":contract_name, "code":contract_name, "table":"game","json":true})
                    .then(result => {
                        console.log('_updataGameData::读取游戏列表成功')

                        let rows = result.rows
                        let len = rows.length
                        for(let i=0; i<len; i++){

                        }
                    })
            }).catch((err)=>{
                console.log('_updataGameData::读取游戏列表失败')
            })

    }

    // 调用智能合约
    _createGame(){
        console.log('_createGame::创建游戏...')

        this._showLoading(true, '正在创建游戏... ...')

        let _sender = account_name
        let eosjs = EOSJS.Localnet(EOSJS_CONFIG.clientConfig)
        eosjs.contract(EOSJS_CONFIG.contractName)
            .then((contract)=>{
                console.log('_createGame::加载合约成功')

                contract.creategame(_sender, {authorization: [_sender] })
                    .then((res)=>{
                        console.log('_createGame::游戏创建成功')
                        this._updataGameData()
                    })
                    .catch((err)=>{
                        console.log('_createGame::游戏创建失败')
                    })
            })
    }

    //开牌
    _playerOpenCard(game_id, play_id){
        console.log('_playerOpenCard::游戏ID'+game_id+', 玩家'+play_id+'开牌...')
        this._showLoading(true, '玩家'+play_id+ '正在开牌...')

        let _sender = account_name
        let eosjs = EOSJS.Localnet(EOSJS_CONFIG.clientConfig)
        eosjs.contract(EOSJS_CONFIG.contractName)
            .then((contract)=>{
                console.log('_playerOpenCard::加载合约成功')

                contract.opencard(game_id, play_id, {authorization: [_sender]})
                    .then((res)=>{
                        console.log('_playerOpenCard::开牌成功')
                        this._updataGameData()
                    })
                    .catch((err)=>{
                        console.log('_playerOpenCard::开牌失败')
                    })
            })
    }

}

4、智能合约的实现

//mygame.hpp
#include <utility>
#include <vector>
#include <string>
#include <eosiolib/eosio.hpp>
#include <eosiolib/asset.hpp>

using eosio:asset;

class mygame: public eosio::contract {
public:
    mygame(account_name self)
    :eosio::contract(self), globals(_self, _self), games(_self, _self) {}

public:
    void creategame(const account_name _owner);
    void opencard(uint64_t _gameid, const uint32_t _player);

    //测试函数
    void sayhi(account_name receiver);
    void printrand(uint64_t _gameid);

private:
    void _checkgame(uint64_t _gameid);
    void _finishgame(uint64_t _gameid);
    uint32_t _getrandnum(uint64_t _gameid);

private:
    //@abi table global i64 全局引用计数表
    struct global{
        uint64_t id = 0;
        uint64_t nextgameid = 0;

        uint64_t primary_key()const { return id; }
        EOSLIB_SERIALIZE(global, (id)(nextgameid) )
    };

    //创建一个多索引容器的游戏引用计数,用于为新游戏生成ID
    typedef eosio::multi_index<N(global), global> global_index;
    global_index globals;

    //@abi table game i64 游戏表
    struct game {
        uint64_t id;        //游戏ID
        uint32_t winner;    //胜出者,0还未决胜负,1玩家1胜出,2玩家2胜出
        uint32_t player1;   //玩家1点数
        uint32_t player2;   //玩家2点数
        time     creattime; //创建时间
        accunt_name owner;  //创建游戏的账号

        uint64_t primary_key()const { return id; } //设定数据主键
        EOSLIB_SERIALIZE(game, (id)(winner)(player1)(player2)(creattime)(owner) )
    };

    //创建一个多索引容器的游戏列表
    typedef eosio::multi_index<N(game), game> game_index;
    game_index games;
};
///////////////////////////////////////////////////////////
//mygame.cpp

#include <mygame.hpp>

void mygame::creategame(const account_name _owner){
    //创建一个全局引用计数器
    auto global_itl = globals.begin();
    if( global_itl == globals.end() ){
        global_itl = globals.emplace(_self, [&](auto& gitr){
            gitr.nextgameid = 0;
        });
    }

    //增加引用计数器
    globals.modify(global_itl, 0, [&](auto& gitr){
        gitr.nextgameid++;
    });

    //创建一个新游戏对象
    auto game_itr = games.emplace(_self, [&](auto& new_game){
        new_game.id = global_itl->nextgameid;
        new_game.winner     = 0;
        new_game.player1    = 0;
        new_game.player2    = 0;
        new_game.createtime = now();
        new_game.owner      = _owner;
    });
}

void mygame::opencard(uint64_t _gameid, const uint32_t _player){
    eosio_assert(_player == 1 || _player == 2, "the player must is 1 or 2.");

    auto game_itr = games.find(_gameid);
    eosio_assert(game_itr != games.end(), "game not found");

    //修改游戏状态
    games.modify(game_itr, 0, [&](auto& gitr){
        if(_player == 1){
            gitr.player1 = 1;
        } else if(_player == 2){
            gitr.player2 = 1;
        }

        //检查游戏是否已经决出胜者
        _checkgame(_gameid);
    });
}

void mygame::sayhi(account_name receiver){
    eosio::print("hi~ luck point world!");
}

void mygame::printrand(uint64_t _gameid){
    eosio::print("printrand::%d",_getrandnum(_gameid));
}

void mygame::_checkgame(uint64_t _gameid){
    auto game_itr = games.find(_gameid);
    eosio_assert(game_itr != ggames.end(), "game not found");

    if(game_itr->player1 != 0 && game_itr->player2 !=0){
        games.modify(game_itr, 0, [&](auto& gitr){
            gitr.winner = _getrandnum(_gameid);
        });
    }
}

uint32_t mygame::_getrandnum(uint64_t _gameid){
    auto game_itr = games.find(_gameid);
    eosio_assert(game_itr != games.end(), "game id not found in games");

    //随机数=游戏创建时间,取余2,再+1,保证是1、2中的任意一个
    return (((uint32_t)(game_itr->createtime))%2) + 1;
}

EOSIO_ABI( mygame, (creategame)(opencard)(sayhi)(printrand))

猜你喜欢

转载自blog.csdn.net/qun_y/article/details/82993703
今日推荐