在区块链上编程:DApp 开发实战——来写个竞猜游戏吧

导读:本文旨在引导对 DApp 开发感兴趣的开发者,构建一个基于以太坊去中心化应用,通过开发一款功能完备的竞猜游戏,迈出 DApp 开发的第一步,通过实例讲解 Solidity 语言的常用语法,以及前端如何与智能合约进行交互。如果正在阅读的你,从未接触过 DApp 开发也不要紧,可以先阅读【区块链上编程:DApp开发简介】进行前置知识补充。随着加密猫、FOMO3D 等游戏的火爆,去中心化应用在游戏领域遍地开花,下面就带着大家一起开发一款简单有趣的 DApp 游戏,帮助大家熟悉 DApp 开发。本 DApp 实现的合约功能:用户从 0-6 的数字中,任意组合三位数进行投注,合约计算出 3 位随机数,根据随机数的组合规则分别给予用户不同倍数的奖励,如随机数为 AAA ,A 等于 6 则奖励至少 20 倍投注金额,即奖池所有余额;A 不等于 6 则奖励 5 倍投注金额;随机数为 AAB,则奖励 2 倍投注金额;随机数为 ABC 则不奖励,同时用户可查看奖池余额和个人投注记录。合约编写可以看出合约需要实现用户投注、生成随机数、发放奖励、奖池余额查询的功能,接下来编写我们的合约代码。新建Lottery.sol合约文件,声明合约版本,^表示合约编译版本为 0.4.0 至 0.5.0(不含 0.5.0)。pragma solidity ^0.4.0;定义合约基本内容,同时声明最低投注金额。contract Lottery { uint public betMoney = 10 finney;}生成随机数,通过区块难度block.difficulty和内置函数keccak256生成随机数,在EVM中常用的数据存储位置:memory、storage,函数的参数、返回值默认存储在memory中,状态变量默认存储在storage中,我们可以通过声明memory、storage改变默认存储位置,两者的存储都需要消耗gas,但storage的开销远大于memory。contract Lottery { … function generateRandomNumber() private view returns(uint[]) { uint[] memory dices = new uint; for (uint i = 0; i < 3; i++) { dices[i] = uint(keccak256(abi.encodePacked(block.difficulty, now, i))) % 6 + 1; } return dices; } …}获取合约余额,address类型比较重要的成员属性主要有balance、transfer,分别为获取地址余额、转移eth至该地址,默认eth单位是wei。contract Lottery { … function getBankBalance() public view returns(uint) { return address(this).balance; } …}用户投注,投注方法需要使用payable关键字描述,用来表示可以接收eth;通过msg.sender和msg.value获得交易发送者地址和当前交易附带的eth。通常使用require来校验外部输入参数,当判定条件为false时,则会将剩余的gas退回,同时回滚交易;assert则用来处理合约内部的逻辑错误,当错误发生时会消耗掉所有gas,同时回滚交易。contract Lottery { … function bet() public payable { uint amount = msg.value; require(amount >= betMoney, ‘bet money not less than 10 finney’); require(address(this).balance >= amount * 20, ‘contract money not enough to pay reward’); uint[] memory dices = generateRandomNumber(); require(dices.length == 3, ‘dices illegal’); address addr = msg.sender; bool isReward = false; uint reward = 0; if ((dices[0] == dices[1]) && (dices[1] == dices[2]) && (dices[0] == 6)) { isReward = true; reward = address(this).balance; } else if ((dices[0] == dices[1]) && (dices[1] == dices[2]) && (dices[0] != 6)) { isReward = true; reward = amount * 5; } else if ((dices[0] == dices[1]) || (dices[0] == dices[2]) || (dices[1] == dices[2])) { isReward = true; reward = amount * 2; } if (isReward) { addr.transfer(reward); } } …定义事件,通过合约内部触发事件,web3 监听到事件回调进行相应逻辑处理,从而进行页面 UI 更新;同时前端也可以通过对应事件名称获取日志信息。contract Lottery { … event BetList( address addr, uint amount, bool isReward, uint reward, uint[] dices ); function bet() public payable { … emit BetList(addr, amount, isReward, reward, dices); } …与合约进行交互至此,我们已经写完了合约代码,前端页面实现就不在此赘述,主要介绍如何使用 web3 与合约交互,这里使用到的 web3 版本是 1.0,web3 1.0 和 0.2x.x 的 API 调用方式差别较大,1.0 的 API 支持异步调用。安装 Metamask 浏览器插件后,会在浏览器页面内注入一个 web3 实例。检测页面中是否存在 web3 实例,如果不存在则连接自己的实例。import Web3 from ‘web3’;if (typeof web3 !== ‘undefined’) { web3 = new Web3(web3.currentProvider);} else { web3 = new Web3(new Web3.providers.HttpProvider(NODE_NRL));}传入合约 ABI,合约地址,实例化合约对象。this.contract = new web3.eth.Contract( CONTRACT_ABI, CONTRACT_ADDR,);调用合约中的投注方法,通过try catch可以捕获到 Metamask 弹窗取消交易操作。userBet = async () => { try { await this.contract.methods .bet( … ) .send({ from: ACCOUNT, value: MONEY, }); } catch (error) { … }}查询记录的日志,可以通过指定事件名称、区块高度及过滤条件来进行日志查询,值得注意的是,在合约内不能查询到日志信息。queryEvent = async () => { const event = await this.contract.getPastEvents( EVENT_NAME, { filter: {}, fromBlock: 0, toBlock: ’latest’, } )}功能拓展比如修改用户投注金额及充值这类敏感操作,就需要管理员的权限来进行操作。同样地,我们也可以拓展赞助商的功能,通过充值奖池的累计金额排名来展示赞助商的广告,这里就不做展开了。定义修饰器,在构造函数里设置管理员地址,将创建合约的账户设置为管理员。contract Lottery { … address public owner; modifier onlyOwner() { require(owner == msg.sender); _; } constructor() public { owner = msg.sender; } …}实现修改投注金额的功能,仅管理员账户可触发。contract Lottery { … function setBetMoney(uint _betMoney) public onlyOwner { betMoney = _betMoney; } function deposit() public payable onlyOwner {} …}总结当前随机数的实现通过链上信息生成,这种生成随机数的方式容易受到不诚实的节点攻击。下一篇文章将通过多个实例介绍相应的第三方工具库的使用(Oricalize、SafeMath、OpenZepplin),生成安全的随机数。参考资料SolidityWeb3jsCryptozombiesCoursetro前置文章:在区块链上编程:DApp 开发简介文 / ielapp一个简单的程序员编 / 荧声本文已由作者授权发布,版权属于创宇前端。欢迎注明出处转载本文。本文链接:https://knownsec-fed.com/2018…想要订阅更多来自知道创宇开发一线的分享,请搜索关注我们的微信公众号:乐趣区。欢迎留言讨论,我们会尽可能回复。欢迎点赞、收藏、留言评论、转发分享和打赏支持我们。打赏将被完全转交给文章作者。感谢您的阅读。 ...

October 9, 2018 · 2 min · jiezi

再也不用担心网吧开黑队友听不清了!降噪解决方案了解一下?

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~本文由腾讯游戏云发表于云+社区专栏经常逛游戏论坛的朋友会深有感触,很多玩家经常会在论坛里吐槽在网吧开黑的体验很差,噪音太多。在游戏语音开黑的过程中,如果其中一个队友身处网吧,则其他人的耳机总是难免会被各种嘈杂的噪音所充斥,这是十分糟糕的体验,甚至会影响整个团队的发挥,那么在这样的场景下,降噪就成为了提升游戏体验的基本操作。网吧场景下的降噪难度往往大于普通噪音环境下的降噪难度,其源于网吧的噪音环境和普通的噪声环境差别很大,网吧的噪音来源比较广泛,包括有众多人的聊天、呼喊声,大幅度的鼠标键盘敲击声,桌椅挪动人员走动等等,有些网吧还像理发店那样广播背景音乐及一些语音广播。并且网吧座位离得较近,几乎每个人左右都有很近的邻居,这些近距离的声音互相干扰更加恼人。消除这些复杂的噪音却不是一件简单的事情,网吧环境下的噪声几乎都是非平稳的,所以传统噪声消除方法难以很好的应用在网吧场景下。腾讯云游戏多媒体引擎GME(Gaming Multimedia Engine,以下简称 GME)针对网吧场景提出了一套降噪技术解决方案,能在复杂的环境下将噪音对语音的影响降到最低。如何在复杂的网吧环境下实现降噪?在网吧嘈杂环境下的降噪诉求是:队友不讲话时,听不到任何其他声音,当队友讲话的时候,希望听到的是队友清晰的声音,当队友话毕其他声音随即静默。以上要解决的问题可以抽象成嘈杂环境里单一主讲人的通话处理。针对可容忍的体验诉求,需要一个排除主讲人以外声音的语音活性检测算法(VAD)。而这个VAD算法和常规意义的语音检测有所不同,因为它不但要排除掉非语音,还要排除掉主讲人以外的语音,否则队友附近的人的话音甚至环境较远处的嘈杂语音仍会被发送给耳机这头的你。针对这样的情况,GME朝着满足诉求的方向,给出了这个“VAD”算法,流程如下:在判断声音性质时,一个要进行的过程是,计算语音的相关性,相关性测度定义如下:E()=N−1∑n=0[s(n)−s(n−)]2 其中 为增益因子,N 为分析帧长。令∂E()∂=0 ,求得:=N−1∑n=0s(n)−s(n−)N−1∑n=0s2(n−) 从而,有E()=N−1∑n=0s2(n)−[N−1∑n=0s(n)s(n−)]2N−1∑n=0s2(n−) 相对误差能量为R[E()]=E()N−1∑n=0s2(n)=1−2()其中()=N−1∑n=0s(n)s(n−)√N−1∑n=0s2(n)N−1∑n=0s2(n−) 为了得到这个结果,还需要做一些预处理:1,去均值:分析窗口内非零均值或非常低的低频噪声出现时,() 会在所有 上都很大,这对依赖() 进行清浊分类时的安静段语音尤其麻烦。解决办法是去掉均值:s′(n)=s(n)−1NN−1∑n=0s(n)2,低通滤波:为减小高频共振峰和高频噪声的影响,要进行一个800赫兹的低通滤波,去掉大部分共振峰影响,并可以再基音频率最高500赫兹时仍能保留其一次,二次谐波,其技术指标要求为:1T=8000Hz ,c2=800Hz,r2=1200Hz,1−1=−0.25dB,2=−50dB据此,由双线性变换法设计一个五阶的滤波器,幅频响应如图:3,数值滤波:上述低通滤波可以较为有效的去掉第三个第四个共振峰的影响,但前两个共振峰的影响仍然存在,浊音语音周期性会模糊,为了去掉这一影响,进行数值滤波。数值滤波能正确显现信号的趋势,如上升沿:y(n)=12K+1K∑i=−Kx(n+i)但这个是个非因果的数字系统,为了因果性改写如下:y(n)=1NN∑i=0x(n−i)注意,这个过程引入了算法延时。在一些参数编码原理的语音编码器中,会用LPC过程的残差来估计基音周期,就是因为残差经过“白化”排出了共振峰影响。因为lpc分析主要产出并非为计算基音,而其又涉及加重叠窗又需要求解尤利沃克方程或burg迭代所以本文并未使用。我们最终关心的是,周期性水平的度量,我们定义如下Zperiod=max1+max2+max33+max当这个周期性水平满足条件后,还要看周期是否满足语音信号基音周期范围:语音信号的基音频率范围是60Hz到500Hz;对于8k采样,用采样周期表示的区间为[80,147],[40,79],[20,39],同时满足周期性和周期范围,我们认为该声音性质具备语音特性。其他环节,诸如底噪包络跟踪,主讲声强跟踪这里不再详述。在此方案下,我们将大部分嘈杂的声音从时间段上全部排除掉了,如图:上侧:原始声音,下方:排除掉嘈杂后的声音通过效果图可以明显看到,噪声被大大的抑制了,但没有影响玩家正常的语音对话,网吧嘈杂环境的诉求得到了满足。通过自研技术,GME已经能在复杂的网吧环境下也准确的检测到特定的人声并有效的去掉环境音或其他玩家带来的噪声,给玩家带来了极致的开黑体验,让好友之间的语音互动不再有噪点,目前游戏多媒体引擎GME 已正式登陆腾讯云,为广大游戏厂商开发者提供服务,详细信息可点击这里浏览。问答策略游戏服务器概念是什么?相关阅读3行代码,为QQ轻游戏加上语音互动能力实时语音趣味变声,大叔变声“妙音娘子”Get一下内行看门道:看似“佛系”的《QQ炫舞手游》,背后的音频技术一点都不简单 云学院 · 课程推荐 | 腾讯专项技术测试组长,结合8年经验为你细说冷热分离法则

August 30, 2018 · 1 min · jiezi