第一个简单的Dapp-猜拳游戏。本智能合约的功能很简单,就是用户与电脑猜拳,用户选择出手后,电脑随机一个选项,然后调用智能合约方法把两个选项值传过去,在智能合约上进行比较,并通过区块链合约事件广播结果,本地监听事件拿到结果后展示猜拳结果。

先大体声明下几个环境跟工具:

1、没有用truffle,直接MetaMask链接以太坊Ropsten测试链后,用Remix部署合约代码

2、前端用web3.js(1.6.1版本)

下面分成几步详细说明:

一、从Ropsten上获取eth

因为调用合约需要消耗eth,所以要先在Ropsten测试网上获取eth,可以复制自己的钱包地址后在这个网站上获取:https://faucet.ropsten.be/  获取过程可能会有延时,多点几次就好。

二、编写猜拳智能合约

Remix上新建GuessGame.sol文件,并写入以下内容:

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
contract GuessGame {
event GuessResult(uint playerChoice,uint computerChoice,uint result);
function play(uint playerChoice,uint computerChoice) public returns (bool){
if(playerChoice > 0 && playerChoice <=3 && computerChoice > 0 && computerChoice <=3){
if(playerChoice == computerChoice){
//平手
emit GuessResult(playerChoice,computerChoice,1);
}else if(playerChoice == (computerChoice + 1) % 3){
//电脑赢了
emit GuessResult(playerChoice,computerChoice,2);
}else{
//其余都算玩家赢了
emit GuessResult(playerChoice,computerChoice,3);
}
return true;
}else{
return false;
}
}
}

编译后部署到Ropsten上,当然首先到MetaMask连上Ropsten网络,并且账户上有足够的eth

部署成功后,这里其实就显示了智能合约上的play方法了,可以直接在这里传值点击transact进行调用,调用成功后再控制台会输出结果,点击Debug可以查看详细信息

三、前端用web3.js调用智能合约

我后台因为集成了项目,所以是用jsp写的,大家简单点可以直接写Html,先贴下文件目录结构:

1、复制ABI文件:在Remix上点击复制ABI文件内容,并新建GuessGame.json文件,将复制的abi内容贴进去

2、引入web3.js等其它js

3、编写guessGame.jsp文件:

<%--
Created by IntelliJ IDEA.
User: ****
Date: 2021/12/13
Time: 21:35
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Access-Control-Allow-Origin" content="*" >
<c:set var="ctx" value="${pageContext.request.contextPath}" />
<script type="text/javascript" src="${ctx}/resource/js/jquery-1.9.1.min.js" charset="utf-8"></script>
<script type="text/javascript" src="${ctx}/resource/js/web3.min-1.6.1.js"></script>
<title>猜拳游戏</title>
<style>
*{margin:0; padding: 0; font-weight: 200;}
.player,.computer{
width: 50%;
float: left;
padding-top: 30px;
text-align: center
}
.player,.computer dt{
font-size: 28px;
}
.player img,.computer img{
margin-top: 30px;
width: 30%;
}
.player img{
transform:rotateY(180deg);
}
.select{
text-align: center;
font-size: 18px;
max-width: 800px;
margin: 0 auto;
padding-top: 2%;
}
.select dt{
width: 100%;
overflow: hidden;
line-height: 50px;
}
.select button{
width: 20%;
border:none;
color: #fff;
border-radius: 8px;
line-height: 45px;
margin: 0 5%;
outline: none;
font-size: 18px;
cursor: pointer;
}
#info{
width: 100%;
text-align: center;
overflow: hidden;
font-size: 25px;
line-height: 50px;
color: red;
padding-top: 2%;
opacity: 0;
}
</style>
<script type="text/javascript">
var web3,guessGameABI,guessGameContract,refresh_timer;
$(function(){
web3Auth();
jspFun();
//var version = web3.version;
//console.log(version);
//web3.eth.net.getNetworkType().then(console.log);
web3.eth.getAccounts(console.log);
$.getJSON('/resource/abi/GuessGame.json',function(data){
guessGameABI = data;
//创建合约实例
guessGameContract = new web3.eth.Contract(guessGameABI, '0x85daAd7dbB5Ba1B4020444Ab2f1D84c58d409edF', []);
console.log(guessGameContract.defaultAccount);
console.log(guessGameContract.defaultBlock);
listenEvent();
}); }) function listenEvent(){
guessGameContract.events.GuessResult({
//filter: {myIndexedParam: [20,23], myOtherIndexedParam: '0x123456789...'}, // 使用数组表示 或:如 20 或 23。
//fromBlock: 0
}, function(error, event){
console.log(event);
}).on("connected", function(subscriptionId){
console.log(subscriptionId);
}).on('data', function(event){
console.log(event); // 与上述可选的回调结果相同
//uint playerChoice,uint computerChoice,uint result
resultDeal(event.returnValues.playerChoice,event.returnValues.computerChoice,event.returnValues.result);
}).on('changed', function(event){
// 从本地数据库中删除事件
console.log("事件删除");
}).on('error', function(error, receipt) {
// 如果交易被网络拒绝并带有交易收据,第二个参数将是交易收据。
console.log("事件被网络拒绝");
});
} function resultDeal(player_choice,computer_choice,r){
//var r = result.args.result.toNumber();
var info = "未知";
if(r == 1){
info = "平手";
}else if(r == 2){
info = "你输了";
}else if(r == 3){
info = "你赢了";
}
update_page(player_choice, computer_choice, info);
} function update_page(player,computer,result){
console.log(player+"----"+computer+"-----"+result);
var info = document.getElementById('info');
var playerImg = document.getElementById('player');
var comImg = document.getElementById('computer');
info.style.opacity = '0';
clearInterval(refresh_timer);
playerImg.src = '/resource/images/'+player+'.png';
comImg.src = '/resource/images/'+computer+'.png';
info.style.opacity = 1;
info.innerText = result;
} function guess(player_choice){
//web3.eth.getCoinbase().then(console.log);
//1:剪刀 2:石头 3:布
var result;
player_choice = parseInt(player_choice);
computer_choice = parseInt(Math.random()*3)+1;
document.getElementById('info').innerText = '';
guessGameContract.methods.play(player_choice,computer_choice).send({
from: '0x229Ea411D368C97b008c7bc19B01Fdd813163701'
}).on('transactionHash', function(hash){
console.log(hash);
beginGame();
}).on('confirmation', function(confirmationNumber, receipt){
console.log(confirmationNumber);
console.log(receipt);
}).on('receipt', function(receipt) {
// receipt 相关例子
console.log(receipt);
}).on('error', function(error, receipt) { // 如果交易被网络拒绝并带有交易收据,则第二个参数将是交易收据。
console.log(error);
console.log(receipt);
}); } function beginGame(){
var playerImg = document.getElementById('player');
var comImg = document.getElementById('computer');
refresh_timer = setInterval(function(){
this.n?this.n:this.n=1;this.n++
this.n>3?this.n=1:this.n;
playerImg.src = '/resource/images/'+this.n+'.png';
comImg.src = '/resource/images/'+this.n+'.png';
},100);
} function jspFun(){
choices = $('button');
for(var i=0; i<choices.length; i++){
choices[i].onclick = function(){
guess(this.value);
}
}
} function web3Auth(){
//初始化过程
//var Web3 = require('web3');
if (typeof web3 !== 'undefined') {
console.info("init web3");
web3 = new Web3(web3.currentProvider);
} else {
console.info("init new web3");
// set the provider you want from Web3.providers
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
} }
</script>
</head>
<body>
<div class="computer">
<dl>
<dt>对手</dt>
<dd><img src="${ctx}/resource/images/2.png" id="computer" alt=""></dd>
</dl>
</div>
<div class="player">
<dl>
<dt>你</dt>
<dd><img src="${ctx}/resource/images/2.png" id="player" alt=""></dd>
</dl>
</div>
<div id="info">平手</div>
<div class="select">
<dl>
<dt>点击下列图标选择要出的选项:</dt>
<dd>
<button value="1"><img src='${ctx}/resource/images/1.png' style="width:80px"></button>
<button value="2"><img src='${ctx}/resource/images/2.png' style="width:80px"></button>
<button value="3"><img src='${ctx}/resource/images/3.png' style="width:80px"></button>
</dd>
</dl>
</div>
</body>
</html>

详细内容参考web3文档看吧,我也是参考文档一点点写的,文档地址:https://learnblockchain.cn/docs/web3.js/

四、运行结果示例:

如果有学习计划的童鞋,可以加我QQ一起交流:

区块链开发学习第七章:第一个Dapp-猜拳游戏的更多相关文章

  1. 区块链开发学习第三章:私有链上部署helloBlockchain简单合约

    前面讲了部署私有链以及新增账户,现在进行到了部署合约了,此操作真是踩了无数无数无数的坑,到写文章为止确实是已经部署好了,但是还有些坑是还没有解决的! 一.Solidity编译器 开始的时候用的http ...

  2. 区块链开发(七)truffle使用入门汇总

    截止上篇博客,以太坊区块链开发的环境和框架基本上搭建完毕.这一篇博客重点梳理一下基本的流程和操作演示. 前奏 基于前面的安装配置,现在重新梳理一遍,以前博客讲到的就在这里一笔带过. (1)创建一个工作 ...

  3. 转:区块链开发(一)搭建基于以太坊go-ethereum的私有链环境

    区块链开发(一)搭建基于以太坊go-ethereum的私有链环境 wo541075754 · 2016-11-07 13:00:03 · 3730 次点击 · 预计阅读时间 3 分钟 · 约1小时前  ...

  4. golang区块链开发的视频教程推荐

    目前网上关于golang区块链开发的资源很少,以太坊智能合约相关的课程倒是很多,可能是由于前者的难度比后者难度大,课程开发需要投入更多精力.搜了一圈之后没结果,我就直接去之前没覆盖的视频网站找资源,包 ...

  5. Knockout应用开发指南 第七章:Mapping插件

    原文:Knockout应用开发指南 第七章:Mapping插件 Mapping插件 Knockout设计成允许你使用任何JavaScript对象作为view model.必须view model的一些 ...

  6. HyperLedger Fabric 1.4 区块链开发平台(4.1)

    目前区块链开发平台分“公有链平台”和“联盟链系统”两类,“公有链平台”主要以以太坊为主的平台,可以在该类平台上进行代币的发行和根据各种模块搭建应用:“联盟链系统”主要以超级账本为主的开源系统,该类开源 ...

  7. 微软Azure区块链开发工具包三大功能详解

    2018年11月15日,微软宣布了Azure区块链开发工具包,它基于微软的无服务器技术构建,并且利用微软和第三方SaaS,完美集成了区块链.该工具包扩展了微软的区块链开发模板和Azure Blockc ...

  8. FISCO BCOS WorkShop | 区块链开发特训营,开课啦!

    FISCO BCOS是完全开源的联盟区块链底层技术平台,由金融区块链合作联盟(深圳)(简称金链盟)成立开源工作组通力打造.开源工作组成员包括博彦科技.华为.深证通.神州数码.四方精创.腾讯.微众银行. ...

  9. Android TV开发总结(七)构建一个TV app中的剧集列表控件

    原文:Android TV开发总结(七)构建一个TV app中的剧集列表控件 版权声明:我已委托"维权骑士"(rightknights.com)为我的文章进行维权行动.转载务必转载 ...

随机推荐

  1. [noi795]保镖

    容易证明,最终方案一定是某一个排列无限循环,那么就要满足$\sum ai<=max(bi+ai)$,对所有数按照ai+bi排序后,枚举最大值,用权值线段树维护之前的ai最少要选几个 1 #inc ...

  2. cube+FreeRTOS联合开发采坑笔记

    加了看门狗之后不断重启的可能 原因: 任务容量分配不足,在"FreeRTOSConfig.h"的配置中,有个configTOTAL_HEAP_SIZE中将堆大小调到最大.

  3. JavaScript中的多种进制与进制转换

    进制介绍 JavaScript 中提供的进制表示方法有四种:十进制.二进制.十六进制.八进制. 对于数值字面量,主要使用不同的前缀来区分: 十进制(Decimal): 取值数字 0-9:不用前缀. 二 ...

  4. Codeforces 1373F - Network Coverage(模拟网络流)

    Codeforces 题面传送门 & 洛谷题面传送门 提供一个模拟网络流的题解. 首先我们觉得这题一脸可以流的样子,稍微想想可以想到如下建图模型: 建立源点 \(S,T\) 和上下两排点,不妨 ...

  5. 【2020五校联考NOIP #4】今天的你依旧闪耀

    题面传送门 题意: 对于一个长度为 \(n\)(\(n\) 为偶数)的排列 \(p\),定义一次"变换"后得到的排列 \(p'\) 为: \(p'_i=\begin{cases}p ...

  6. rabbit mq的php使用 php-amqplib操作消息队列

    rabbit mq的php使用 php-amqplib操作消息队列 有大神翻译的教程,非常清楚可以参考: https://xiaoxiami.gitbook.io/rabbitmq_into_chin ...

  7. 前端3 — js — BOM没完( 不了解也行 )

    1.js是什么? -- 英文全称javascript javaScript(简称"JS") 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言.虽然它是作为开发Web页面的脚 ...

  8. 学习java 7.9

    学习内容: Date类 Date类常用方法 SimpleDateFormat 1.格式化(从Date到String) public final String format(Date date) 将日期 ...

  9. 为构建大型复杂系统而生的微服务框架 Erda Infra

    作者|宋瑞国(尘醉) 来源|尔达 Erda 公众号 ​ 导读:Erda Infra 微服务框架是从 Erda 项目演进而来,并且完全开源.Erda 基于 Erda Infra 框架完成了大型复杂项目的 ...

  10. 【leetcode】122.Best Time to Buy and Sell Stock II(股票问题)

    You are given an integer array prices where prices[i] is the price of a given stock on the ith day. ...