美文网首页区块链研习社
在EOS上做个菠菜游戏

在EOS上做个菠菜游戏

作者: Andytl的世界 | 来源:发表于2019-05-12 23:27 被阅读96次

区块链中的随机数》中介绍了一种无需各方信任产生随机数的方法,本文中我们用这个方法做一个双方对赌的菠菜游戏,玩家1给一个随机数,玩家2也给一个随机数,通过计算两个随机数得到0-99内的一个数,如果小于50则玩家1胜利,大于50则玩家2胜利。
代码原型来自:https://learneos.dev/Learn_EOS_Randomness_preview.pdf,做了些修改,让智能合约randprotocol可以跑起来。randprotocol.cpp的源代码如下:

#include <eosiolib/eosio.hpp>
#include <stdlib.h>
#include <math.h>


using namespace eosio;
using namespace std;


CONTRACT randprotocol : public eosio::contract
{
    public:
        randprotocol(name receiver, name code, datastream<const char *> ds) :
            contract(receiver, code, ds), games(receiver, receiver.value) {}
        //字符串形式的十六进制数转换为整数的方法
        uint64_t hex_to_uint64(const string &hex)
            {
                
                char *hexstr;//用指针hexstr遍历字符串中每个代表十六进制数的字符
                int length = 0;//用length记录字符串长度
                const int base = 16;     // 十六进制数的基底是16
                uint64_t decnum = 0; //记录转换的整数
                int i;//循环遍量

                // 遍历整个hex字符串,统计字符串长度
                for (hexstr = (char*)(&hex[0]); *hexstr != '\0'; hexstr++) {
                    length++;
                }
                // 计算hex字符串代表的整数值,大概思路是,用指针从高位到低位指向hex中每个字符,并将字符代表的ASCII码转换位数字,如"a"转换为10,再累加计算出字符串对应的整数值。
                hexstr = (char*)(&hex[0]);
                for (i = 0; i < length; i++, hexstr++) {
                if (*hexstr >= 48 && *hexstr <= 57) {  // *hexstr 属于 0-9
                  decnum += uint64_t((((int)(*hexstr)) - 48) * pow(base, length - i - 1));
                }
                else if ((*hexstr >= 65 && *hexstr <= 70))  {  // *hexstr 属于 A-F
                  decnum += uint64_t((((int)(*hexstr)) - 55) * pow(base, length - i - 1));
                }
                else if (*hexstr >= 97 && *hexstr <= 102) {  //  *hexstr 属于 a-f
                  decnum += uint64_t((((int)(*hexstr)) - 87) * pow(base, length - i - 1));
                }
                else {
                    break;
                }
                }
                return decnum;
            }
               //定义智能合约中的结构体,用于记录数据
        struct [[eosio::table]] game_s
        {
            name player1;
            name player2;
            checksum256 p1_commitment;
            uint64_t p2_rand;

            auto primary_key() const { return player1.value; }
            EOSLIB_SERIALIZE(game_s, (player1)(player2)(p1_commitment)(p2_rand))
        };

        typedef eosio::multi_index<"games"_n, game_s> games_t;
        games_t games;
               //player1首先发送给智能合约一个随机数的哈希值,也就是创建一个“承诺交易”
        ACTION create(name player1, const eosio::checksum256 &commitment)
        {
            require_auth(player1);
            auto itr = games.find(player1.value);
            eosio::check(itr == games.end(), "finish existing game first");

            games.emplace(player1, [&](auto &g) {
                g.player1 = player1;
                g.p1_commitment = commitment;
            });

        }
              //player2响应player1的交易,并上传自己的随机数
        ACTION respond(name player2, name game_host, const string &randomness_as_hex)

        {
            require_auth(player2);
            auto itr = games.find(game_host.value);
            eosio::check(itr != games.end(), "game does not exist");
            uint64_t randomness = hex_to_uint64(randomness_as_hex);

            games.modify(itr, ""_n, [&](auto &g) {
                g.player2 = player2;
                g.p2_rand = randomness;
        });

        }
               //player1揭露自己的随机数,并验证是否位承诺交易的随机数。得到两个人的随机数后,智能合约计算出一个在[0,100)范围内的随机数,如果小于50则player1胜利,大于50则player2胜利
        ACTION reveal(name player1, const string &p1_rand_as_hex)
        {
            require_auth(player1);
            auto itr = games.find(player1.value);
            eosio::check(itr != games.end(), "game does not exist");
            eosio::check(itr->player2.value > 0, "no other player responded yet");

            // checks if sha256(p1_rand_as_hex, bytes_size) == third argument
            assert_sha256(
                (char *)p1_rand_as_hex.c_str(),
                p1_rand_as_hex.size(),
                itr->p1_commitment);
            uint64_t randomness = hex_to_uint64(p1_rand_as_hex) ^ itr->p2_rand;
            randomness = randomness % 100;
            eosio::print(("Rolled " + to_string(randomness) + ". ").c_str());
            if (randomness < 50)
            {
                eosio::print("Player 1 wins!");
            }
            else
            {
                eosio::print("Player 2 wins!");
            }

            games.erase(itr);

        }

};

发布智能合约randprotocol的过程与《手把手教你发行EOS代币》很类似。也可以把上面代码拷贝到在线eos智能合约开发平台Beosin中,几分钟就能编译、部署、执行智能合约,非常方便。只不过Beosin中的debug功能还没完善,在线调试代码很麻烦。

在本地环境中可以验证合约执行情况,如下:

# 计算一个随机数
openssl rand -hex 8
# outputs 021cb69650e3dd84

# 计算随机数的哈希值
echo -n "021cb69650e3dd84" | openssl dgst -sha256
# outputs eb162b76b7830c61e22c3379f83bafc212d408698c9bbeb3923ffb594a3918bd

# player1发起承诺交易
cleos push action rand create '{"player1": "test1", "commitment": "eb162b76b7830c..."}' -p test1

# player2 产生随机数并发起响应
openssl rand -hex 8
# outputs 981b3e64607e49c4
cleos push action rand respond '{"player2": "test2", "game_host": "test1",
"randomness_as_hex": "981b3e64607e49c4"}' -p test2

# player1 揭露随机数并计算出结果
cleos push action rand reveal '{"player1": "test1", "p1_rand_as_hex": "021cb69650e3dd84"}' -p test1

# >> Rolled 76. Player 2 wins!

也可以参考上述代码参数,在Beosin环境中执行智能合约,以验证智能合约。一个简单的菠菜游戏就诞生了,作为一个dapp,它还缺乏前端交互界面,后端分配代币机制,以后补充。

相关文章

  • 在EOS上做个菠菜游戏

    《区块链中的随机数》中介绍了一种无需各方信任产生随机数的方法,本文中我们用这个方法做一个双方对赌的菠菜游戏,玩家1...

  • 关于Poker质押分红

    EOS Poker是建在EOS公链上的扑克类游戏平台,今日24小时平台流水约17.6万EOS,在EOS菠菜...

  • 概率

    最近eos上的菠菜游戏让人忘记了现在的漫长熊市。虽然最近菠菜游戏里处于一个横盘的状态,但事实上却是暗流涌动...

  • 浅谈EOS Max

    EOS Max是建在EOS公链上的菠菜游戏平台,目前平台上的游戏有两种。平台发行的通证是Max,今年11月...

  • # 从菠菜游戏lelego聊起,谈谈EOS游戏

    昨天体验了一款EOS菠菜游戏EOSCAST,今天从另一款游戏lelego聊起,谈谈EOS游戏。 lelego是一款...

  • HelloEOS 10月29日晚报

    DappRadar 显示,排名前10的 EOS DAPP 中有6个属于“菠菜”游戏,在所有的 EOS DAPP 中...

  • 即使头戴王冠,本质还是个骗子

    一、项目分析(6/20) BetDice旨在利用区块链技术,构建全球首款EOS公链上的菠菜游戏平台。运用区块链公开...

  • EOS POKER

    EOS POKER是建在EOS公链上的扑克类游戏平台,今日平台24小时流水约46.9万EOS,在EOS游戏...

  • 再续EOS Cast

    就在上个月月底,员外第一次玩的EOS菠菜类游戏——EOS Cast,游戏刚刚上线约10小时后,就遭遇了黑客的洗礼,...

  • 首个基于迅雷链的DApp——开心问答

    首个基于迅雷链智能合约的DApp——开心问答上线了,与eos上的菠菜类DApp不同,这个DApp是一个问答游戏,发...

网友评论

    本文标题:在EOS上做个菠菜游戏

    本文链接:https://www.haomeiwen.com/subject/rjahaqtx.html