eth实战项目游戏开发 TICTACTOE 二

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bondsui/article/details/85755404

eth dapp,前端部分,使用使用truffle 框架,前端部分使用react,eht交互库truffle-contract

合约部分请点击 https://blog.csdn.net/bondsui/article/details/85755186

github代码在文末

3 小白如何写前端

github,全球最大的代码库,你想要的基本都有。

3.1 github搜索

TicTacToe,本例中使用react,直接搜索 TicTacToe react,按照starts排序

image-20190103234247776

3.2 clone buile 项目

➜  temp git clone git@github.com:trihargianto/reactjs-tictactoe.git
➜  temp cd reactjs-tictactoe 
➜  npm install
➜  npm start

3.3 查看效果和代码

效果图,自带动画,重点查看点击事件

image-20190103234703062

render() {
        const indexSquares = [0,1,2,3,4,5,6,7,8];

        var squares = indexSquares.map(function(indexSquare, i) {
            return (<Square
                value={this.state.squares[i]}
                key={i}
                index={i}
                winner={this.state.winner}
                xIsNext={this.state.xIsNext}
                onClick={this.handleOnClick.bind(this)} />)
        },this)

        return (
            <div>
                <h1 style={{textAlign: 'center', fontSize: '46px', color: 'rgba(52, 152, 219,1.0)'}} className="animated flipInY">Tic-Tac-Toe</h1>
                <h3 style={{textAlign: 'center'}} id="titlePemenang">{this.state.winner !== null ? <span>Pemenangnya <b>{this.state.winner}</b></span> : ""}</h3>
                <div className="container animated fadeInUp">
                    <div className="row">
                        <br />
                        <div className="col-xs-12">{squares}</div>
                    </div>
                </div>
                <br />
                {this.state.winner !== null || this.state.full === true ? <ResetButton onClick={this.handleResetGame.bind(this)} /> : ""}
            </div>
        )
    }
}

image-20190103235024205

4 前端页面编写

4.1 页面样式

拷贝下载下来的git项目(别忘了css文件一同拷贝),安装包

"bootstrap": "^3.3.7",
"jquery": "^3.2.1",
"react": "^15.4.2",
"react-dom": "^15.4.2",

运行项目,查看页面

4.2 调整页面

通过代码,得知,原页面的棋盘的值为0-8,我们改为[[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]],每个value即棋盘的坐标。同时更改Square的handleClick,把值传递到页面。

运行项目,点击第一个模块,显示log 0,1

剩下的就是与合约交互。

class Board extends React.Component {

    constructor() {
        super();

        this.state = {
            squares : Array(9).fill(null),
            xIsNext : true,
            winner  : null,
            full    : false
        }
    }

    handleOnClick(index, turn) {
        console.log(index,turn)
    }
   
    handleResetGame() {
        window.location.reload()
    }

    render() {
        const indexSquares = [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]];

        var squares = indexSquares.map(function(indexSquare, i) {
            return (<Square
                value={this.state.squares[i]}
                key={i}
                index={i}
                winner={this.state.winner}
                xIsNext={this.state.xIsNext}
                onClick={this.handleOnClick.bind(this)} />)
        },this)

        return (
            <div>
                <h1 style={{textAlign: 'center', fontSize: '46px', color: 'rgba(52, 152, 219,1.0)'}} className="animated flipInY">Tic-Tac-Toe</h1>
                <h3 style={{textAlign: 'center'}} id="titlePemenang">{this.state.winner !== null ? <span>Pemenangnya <b>{this.state.winner}</b></span> : ""}</h3>
                <div className="container animated fadeInUp">
                    <div className="row">
                        <br />
                        <div className="col-xs-12">{squares}</div>
                    </div>
                </div>
                <br />
                {this.state.winner !== null || this.state.full === true ? <ResetButton onClick={this.handleResetGame.bind(this)} /> : ""}
            </div>
        )
    }
}

4.3 下载项目引用包

"truffle-contract": "^3.0.7",
"web3": "^1.0.0-beta.37",
"xmlhttprequest": "^1.8.0"

4.4 搭建框架

补充页面按钮,更新square

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import 'bootstrap/dist/css/bootstrap.min.css'
import './animate.css'
import Square from './Square'
import MenuButtons from './MenuButtons'
import getWeb3 from "./utils/getWeb3"
import contract from 'truffle-contract'
import _TicTacToe from './contracts/TicTacToe.json'


// 棋盘值
const STONES = [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]];
const EMPTY_ADDRESS = "0x0000000000000000000000000000000000000000"
const GAME_COST = "1"; //1 eth
let web3 = null

class Board extends React.Component {

    state = {
        accounts: null, // 账户

        // 棋盘相关
        instance: null, // 游戏实例
        board: [['', '', ''], ['', '', ''], ['', '', '']],
        player1: '', // 玩家一,等于创建者
        player2: '', // 玩家二,
        nextPlayer: '',// 该谁下棋

        winner: '',
        gameResult: '', // 游戏结果,
    }

    // 获取合约
    getTicTacToe = () => {
        let TicTacToe = contract(_TicTacToe)
        TicTacToe.setProvider(web3.currentProvider);
        return TicTacToe
    }

    componentDidMount = async () => {
        try {
            web3 = await getWeb3();
            console.log("currentProvider", web3.currentProvider)
            const accounts = await web3.eth.getAccounts();
            console.log("accounts", accounts)
            this.setState({accounts});
        } catch (error) {
            alert(`web3 加载失败`,);
            console.error(error);
        }
    }

    componentWillUnmount() {
        this.unRegistNextPlayerEvent()
    }

    // 点击创建游戏
    onCreateGameClick = () => {
        console.log("创建游戏")
    }

    // 加入游戏
    onJoinGameClick = async () => {
        console.log("加入游戏")
    }

    // 更新游戏面板
    updateBoard = () => {
        console.log("更新面板")
    }

    // 设置棋盘
    onStoneClick = (stone) => {
        console.log("设置棋盘",stone)
    }

    // 重置游戏
    onResetGameClick = () => {
        window.location.reload()
    }

    // 设置赢家
    setWinner = (winner) => {
        let gameResult = ""
        if (winner === this.state.player1) {
            gameResult = "恭喜胜利,再来一局"
        } else if (winner === this.state.player2) {
            gameResult = "失败,再接再厉"
        } else {
            gameResult = "旗鼓相当,平局,再来一局"
        }
        this.setState({gameResult})
    }

    // 00 01 02
    // 10 11 12
    // 20 21 22
    render() {
        let {accounts, board, player1, player2, nextPlayer, instance, winner} = this.state
        let gameAddress = instance == null ? "" : instance.address
        console.log("state", this.state)
        console.log("", instance)
        if (winner != ''){
            winner = winner == EMPTY_ADDRESS ? "平局,退回赌金" : "赢家为:"+winner
        }
        let squares = STONES.map((stone, i) => {
            return (<Square
                key={i}
                stone={stone}
                board={board}
                account={accounts == null ? null : accounts[0]}
                nextPlayer={nextPlayer}
                onClick={this.onStoneClick}/>)
        })

        return (
            <div style={{textAlign: 'center'}}>
                {/*标题*/}
                <h2 style={{fontSize: '42px', color: "red"}}
                    className="animated flipInY">性感荷官 在线发牌
                </h2>
                {/* 游戏信息展示*/}
                <div>
                    <h5>当前用户:{accounts == null ? "未检测到" : accounts[0]}</h5>
                    <h5>游戏地址:{gameAddress == "" ? "等待创建" : gameAddress}</h5>
                    <h5>player1:{player1 == "" ? "等待加入" : player1}</h5>
                    <h5>player2:{player2 == "" ? "等待加入" : player2}</h5>
                    <h5>nextPlayer:{player2 == "" ? "游戏未开始" :
                        <span style={{color: "red"}}>{nextPlayer}</span>}</h5>
                    <h3 id="gameResult">
                        <span style={{fontSize: '32px', color: "red"}}>
                            <b>{winner}</b></span>
                    </h3>
                </div>
                {/*棋盘*/}
                <div className="container animated fadeInUp">
                    <div className="row">
                        <div className="col-xs-12">{squares}</div>
                    </div>
                </div>
                <br/>

                <MenuButtons
                    onCreateGameClick={this.onCreateGameClick}
                    onJoinGameClick={this.onJoinGameClick}
                    onResetGameClick={this.onResetGameClick}/>
            </div>
        )
    }
}

ReactDOM.render(
    <Board/>,
    document.getElementById('root')
);

Square.js

es6语法普及,封包与解包

import React from 'react';

const EMPTY_ADDRESS = "0x0000000000000000000000000000000000000000"
export default class Square extends React.Component {

    constructor(props) {
        super(props)
        // es6 语法
        // 本页面要设置状态,用户点击,提前显示该位置内容,避免等待,如不需要否则可直接使用props或者无状态组件
        // 保存所有属性到状态变量
        this.state = {...props}

        // 等价
        // let {key,stone,board,account,nextPlayer,onClick}=props
        // this.state = {key,stone,board,account,nextPlayer,onClick}
        console.log(this.state)
    }


    componentWillReceiveProps(nextProps) {
        this.state = {...nextProps}
    }

    // 状态变量未Object,可以不写默认值,
    state = {}
    
    // 点击事件
    onItemClick(event) {
        let errMsg = this.mustCheck()
        if (errMsg != "") {
            event.target.className += " animated shake";
            alert(errMsg)
            return
        }
        // 引用点击
        this.state.onClick(this.state.stone);
        // 设置 修改
        event.target.className += " animated rubberBand square-container-active";
    }

    // 下棋校验,返回错误信息,没有返回空
    mustCheck() {
        let {account, nextPlayer} = this.state
        console.log(this.state)
        if (this.state.account == null) {
            return "用户未登录"
        }

        if (nextPlayer == '') {
            return "游戏未开始"
        }

        if (account.toLowerCase() != nextPlayer.toLowerCase()) {
            return "等待对方下子"
        }
        if (this.getHtmlValue() != '') {
            return "这里不能下子"
        }
        return ""
    }

    // 获取该位置的文本显示
    getHtmlValue() {
        let {stone, board, account,nextPlayer} = this.state
        // 获取该位置的地址值
        let x = stone[0]
        let y = stone[1]
        let stoneValue = board[x][y]

        // 未登录显示空
        if (account == null||nextPlayer==""||stoneValue==EMPTY_ADDRESS||stoneValue==""){
            return ""
        }
        console.log(x,y,stoneValue==EMPTY_ADDRESS,stoneValue)
        // 自己显示X,否则显示O
        return stoneValue.toString().toLowerCase() == account.toString().toLowerCase() ? 'X' : 'O'
    }

    render() {
        let stoneHtmlValue = this.getHtmlValue()
        return (
            <div onClick={this.onItemClick.bind(this)} className="col-xs-4 square-container">
                {stoneHtmlValue}
            </div>
        )
    }
}

4.5 创建游戏,监听事件

  • 第一种方式GameOver.watch(function(error,event){})

  • 第二种方式allEvents(function(error,event){})

  • 第三种方式 调用函数返回值的logs字段

  • 第四中,web3.js 中subscribe

// 点击创建游戏,监听合约事件
// 通过打印instance,可以看到合约中的每个事件,都提供了一个方法
    onCreateGameClick = () => {

        const {accounts} = this.state
        let TicTacToe = this.getTicTacToe()
        TicTacToe.new({from: accounts[0], value: web3.utils.toWei(GAME_COST, "ether")})
            .then(instance => {
                console.log("instance", instance)
                this.setState({instance, player1: accounts[0]})
                this.registEvent()
                alert("游戏创建成功,邀请好友\n" + instance.address)
            })
            .catch(error => {
                console.log("new TicTacToe", error)
            })
    }

image-20190104001206279

  • 第二种方式allEvents(function(error,event){})
// 注册事件,监听所有(也可以单独监听)
registEvent = () => {
    let {instance, accounts} = this.state
    instance.allEvents( (err,data)=> {
        console.log(err,data)
        let {event, args} = data
        if (event == "GameStart") {
            alert("游戏即将开始\n" + "玩家1: " + args.player1 + "\n玩家2: " + args.player2)
            this.setState({...args})
        } else if (event == "NextPlayer") {
            alert("下一个玩家\n" + args.nextPlayer)
            this.updateBoard()
            this.setState({...args})
        } else if (event == "GameOver") {
            this.setState({...args})
            alert("GameOver")
        } else if (event == "Withdraw") {
            alert("游戏结束\n已向" + args.to + "转入赌金" + args.balance)
        }
    })
}

4.6 加入游戏

// 加入游戏
    onJoinGameClick = async () => {
        let gameAddress = prompt("请输入游戏地址")
        if (gameAddress === "") {
            return
        }
        let {accounts} = this.state;
        let TicTacToe = this.getTicTacToe()
        try {
            // 获取合约实例
            let instance = await TicTacToe.at(gameAddress)
            console.log("at", instance == null, instance)

            // 更新状态,监听事件
            this.setState({instance})
            this.registEvent()
            alert("游戏加载成功,加入赌金立即开始游戏")
            let result = await instance.joinGame({
                from: accounts[0],
                value: web3.utils.toWei(GAME_COST, 'ether')
            })
        } catch (e) {
            console.log("join error", e)
            this.setState({instance: null})
        }
    }

4.7 加入游戏

 // 更新游戏面板
    updateBoard = () => {
        let {instance, accounts} = this.state
        instance.getBoard.call({from: accounts[0]})
            .then(board => {
                // 更新面板
                this.setState({board})
                console.log("updateBoard", board)
            })
            .catch(error => {
                console.error("updateBoard", error)
            })
    }

4.8 设置棋盘

事件方式3,通过调用函数的返回result,其中的字段logs 封装了该函数调用产生的logs

// 设置棋盘
onStoneClick = (stone) => {
    console.log("onStoneClick", stone)
    let {instance, accounts} = this.state
    instance.setPosition(stone[0], stone[1], {from: accounts[0]})
        .then(result => {
            console.log("setStone", result)
            // this.handleLog(result.logs)
            // 通过事件,也可以直接处理log
        })
        .catch(error => {
            console.error("setStone", error)
        })
}

4.9 设置赢家

// 设置赢家或者平局
setWinner = (winner) => {
    let gameResult = ""
    if (winner === this.state.player1) {
        gameResult = "恭喜胜利,再来一局"
    } else if (winner === this.state.player2) {
        gameResult = "失败,再接再厉"
    } else {
        gameResult = "旗鼓相当,平局,再来一局"
    }
    this.setState({gameResult})
}

4.9 监听event方式2

// 下一个玩家,更新页面
registNextPlayerEvent = () => {
    let {instance} = this.state
    let nextPlayerEvent = instance.NextPlayer()
    //  下一个是一个状态 需保存到state
    this.setState(nextPlayerEvent)
    event.watch((error, event) => {
        console.log("event---NextPlayer")
        if (error == null) {
            console.log("NextPlayer", event)
        } else {
            console.error("event", error)
        }
    })
}

// 取消下一个玩家监听
unRegistNextPlayerEvent = () => {
    let {nextPlayerEvent} = this.state
    if (nextPlayerEvent != null) {
        nextPlayerEvent.stopWatching()
    }
}

// 游戏结束事件,只需监听一次
registGameOverEvent = () => {
    let {instance} = this.state
    let event = instance.GameOver()
    event.watch((error, event) => {
        console.log("GameOverEvent", event)
        if (error == null) {
            event.stopWatching()
            this.unRegistNextPlayerEvent()
        } else {
            console.error("event", error)
        }
    })
}

// 游戏结束提现事件 ,只需一次监听
registWithdrawEvent = () => {
    let {instance} = this.state
    let event = instance.WithdrawEvent()
    event.watch((error, event) => {
        console.log("WithdrawEvent")
        if (error == null) {
            alert("有钱到账了")
            event.stopWatching()
            console.log("WithDrawEvent", event)
        } else {
            console.error("event", error)
        }
    })
}

4.10 完整代码

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import 'bootstrap/dist/css/bootstrap.min.css'
import './animate.css'
import Square from './Square'
import MenuButtons from './MenuButtons'
import getWeb3 from "./utils/getWeb3"
import contract from 'truffle-contract'
import _TicTacToe from './contracts/TicTacToe.json'


// 棋盘值
const STONES = [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]];
const EMPTY_ADDRESS = "0x0000000000000000000000000000000000000000"
const GAME_COST = "1"; //1 eth
let web3 = null

class Board extends React.Component {

    state = {
        accounts: null, // 账户

        // 棋盘相关
        instance: null, // 游戏实例
        board: [['', '', ''], ['', '', ''], ['', '', '']],
        player1: '', // 玩家一,等于创建者
        player2: '', // 玩家二,
        nextPlayer: '',// 该谁下棋

        winner: '',
        gameResult: '', // 游戏结果,
    }

    // 获取合约
    getTicTacToe = () => {
        let TicTacToe = contract(_TicTacToe)
        TicTacToe.setProvider(web3.currentProvider);
        return TicTacToe
    }

    componentDidMount = async () => {
        try {
            web3 = await getWeb3();
            console.log("currentProvider", web3.currentProvider)
            const accounts = await web3.eth.getAccounts();
            console.log("accounts", accounts)
            this.setState({accounts});
        } catch (error) {
            alert(`web3 加载失败`,);
            console.error(error);
        }
    }

    componentWillUnmount() {
        this.unRegistNextPlayerEvent()
    }

    // 点击创建游戏
    onCreateGameClick = () => {

        const {accounts} = this.state
        let TicTacToe = this.getTicTacToe()
        TicTacToe.new({from: accounts[0], value: web3.utils.toWei(GAME_COST, "ether")})
            .then(instance => {
                console.log("instance", instance)
                this.setState({instance, player1: accounts[0]})
                this.registEvent()
                alert("游戏创建成功,邀请好友\n" + instance.address)
            })
            .catch(error => {
                console.log("new TicTacToe", error)
            })
    }

    // 加入游戏
    onJoinGameClick = async () => {
        let gameAddress = prompt("请输入游戏地址")
        if (gameAddress === "") {
            return
        }
        let {accounts} = this.state;
        let TicTacToe = this.getTicTacToe()
        try {
            // 获取合约实例
            let instance = await TicTacToe.at(gameAddress)
            console.log("at", instance == null, instance)

            // 更新状态,监听事件
            this.setState({instance})
            this.registEvent()
            alert("游戏加载成功,加入赌金立即开始游戏")
            let result = await instance.joinGame({
                from: accounts[0],
                value: web3.utils.toWei(GAME_COST, 'ether')
            })
        } catch (e) {
            console.log("join error", e)
            this.setState({instance: null})
        }
    }

    // 更新游戏面板
    updateBoard = () => {
        let {instance, accounts} = this.state
        instance.getBoard.call({from: accounts[0]})
            .then(board => {
                // 更新面板
                this.setState({board})
                console.log("updateBoard", board)
            })
            .catch(error => {
                console.error("updateBoard", error)
            })
    }

    // 设置棋盘
    onStoneClick = (stone) => {
        console.log("onStoneClick", stone)
        let {instance, accounts} = this.state
        instance.setPosition(stone[0], stone[1], {from: accounts[0]})
            .then(result => {
                console.log("setStone", result)
                // this.handleLog(result.logs)
                // 通过事件,也可以直接处理log
            })
            .catch(error => {
                console.error("setStone", error)
            })
    }

    // 重置游戏
    onResetGameClick = () => {
        window.location.reload()
    }

    // 设置赢家
    setWinner = (winner) => {
        let gameResult = ""
        if (winner === this.state.player1) {
            gameResult = "恭喜胜利,再来一局"
        } else if (winner === this.state.player2) {
            gameResult = "失败,再接再厉"
        } else {
            gameResult = "旗鼓相当,平局,再来一局"
        }
        this.setState({gameResult})
    }

    // 注册事件,监听所有(也可以单独监听)
    registEvent = () => {
        let {instance, accounts} = this.state
        instance.allEvents( (err,data)=> {
            console.log(err,data)
            let {event, args} = data
            if (event == "GameStart") {
                alert("游戏即将开始\n" + "玩家1: " + args.player1 + "\n玩家2: " + args.player2)
                this.setState({...args})
            } else if (event == "NextPlayer") {
                alert("下一个玩家\n" + args.nextPlayer)
                this.updateBoard()
                this.setState({...args})
            } else if (event == "GameOver") {
                this.setState({...args})
                alert("GameOver")
            } else if (event == "Withdraw") {
                alert("游戏结束\n已向" + args.to + "转入赌金" + args.balance)
            }
        })
    }

    // 下一个玩家,更新页面
    registNextPlayerEvent = () => {
        let {instance} = this.state
        let nextPlayerEvent = instance.NextPlayer()
        //  下一个是一个状态 需保存到state
        this.setState(nextPlayerEvent)
        event.watch((error, event) => {
            console.log("event---NextPlayer")
            if (error == null) {
                console.log("NextPlayer", event)
            } else {
                console.error("event", error)
            }
        })
    }

    // 取消下一个玩家监听
    unRegistNextPlayerEvent = () => {
        let {nextPlayerEvent} = this.state
        if (nextPlayerEvent != null) {
            nextPlayerEvent.stopWatching()
        }
    }

    // 游戏结束事件,只需监听一次
    registGameOverEvent = () => {
        let {instance} = this.state
        let event = instance.GameOver()
        event.watch((error, event) => {
            console.log("GameOverEvent", event)
            if (error == null) {
                event.stopWatching()
                this.unRegistNextPlayerEvent()
            } else {
                console.error("event", error)
            }
        })
    }

    // 游戏结束提现事件 ,只需一次监听
    registWithdrawEvent = () => {
        let {instance} = this.state
        let event = instance.WithdrawEvent()
        event.watch((error, event) => {
            console.log("WithdrawEvent")
            if (error == null) {
                alert("有钱到账了")
                event.stopWatching()
                console.log("WithDrawEvent", event)
            } else {
                console.error("event", error)
            }
        })
    }

    // 00 01 02
    // 10 11 12
    // 20 21 22
    render() {
        let {accounts, board, player1, player2, nextPlayer, instance, winner} = this.state
        let gameAddress = instance == null ? "" : instance.address
        console.log("state", this.state)
        console.log("", instance)
        if (winner != ''){
            winner = winner == EMPTY_ADDRESS ? "平局,退回赌金" : "赢家为:"+winner
        }
        let squares = STONES.map((stone, i) => {
            return (<Square
                key={i}
                stone={stone}
                board={board}
                account={accounts == null ? null : accounts[0]}
                nextPlayer={nextPlayer}
                onClick={this.onStoneClick}/>)
        })

        return (
            <div style={{textAlign: 'center'}}>
                {/*标题*/}
                <h2 style={{fontSize: '42px', color: "red"}}
                    className="animated flipInY">性感荷官 在线发牌
                </h2>
                {/* 游戏信息展示*/}
                <div>
                    <h5>当前用户:{accounts == null ? "未检测到" : accounts[0]}</h5>
                    <h5>游戏地址:{gameAddress == "" ? "等待创建" : gameAddress}</h5>
                    <h5>player1:{player1 == "" ? "等待加入" : player1}</h5>
                    <h5>player2:{player2 == "" ? "等待加入" : player2}</h5>
                    <h5>nextPlayer:{player2 == "" ? "游戏未开始" :
                        <span style={{color: "red"}}>{nextPlayer}</span>}</h5>
                    <h3 id="gameResult">
                        <span style={{fontSize: '32px', color: "red"}}>
                            <b>{winner}</b></span>
                    </h3>
                </div>
                {/*棋盘*/}
                <div className="container animated fadeInUp">
                    <div className="row">
                        <div className="col-xs-12">{squares}</div>
                    </div>
                </div>
                <br/>

                <MenuButtons
                    onCreateGameClick={this.onCreateGameClick}
                    onJoinGameClick={this.onJoinGameClick}
                    onResetGameClick={this.onResetGameClick}/>
            </div>
        )
    }
}

ReactDOM.render(
    <Board/>,
    document.getElementById('root')
);

5 作业

剩余时间显示

玩家超时(或者故意退出)处理

页面刷新,加载游戏状态。

6 游戏扩展

游戏设计

2名玩家,在一个10*10的棋盘,猜对方部署的飞机,优先全部猜中的获胜

  • 增加钱包功能(前面可能有分享到)
  • 创建游戏合约(可先创建平台,平台中创建游戏),邀请好友
  • 大小 10*10
  • 不许重复下棋
  • 棋子按照飞机规则部署。
  • 部署完毕后,准备游戏
  • 双方都准备完毕,游戏开始
  • 超时3分钟,超时失去猜子机会

7 项目扩展

eth游戏平台,玩家玩游戏,开发社申请发布游戏。

由于真实以太坊的延迟,并不适合实时性要求较强类的游戏

  • 网页
    • 用户模式
      • 钱包
      • 玩游戏
    • 开发者模式
      • 钱包
      • 申请开发者
      • 申请上架
      • 佣金提现
    • 管理员模式
      • 代币管理
      • 佣金管理
      • 游戏审批
      • 开发者审批
      • 仲裁管理
  • android
  • ios
  • 微信

转载请说明出处
代码地址:https://github.com/bigsui/eth-game-tictactoe
联系邮箱:suibingyue@gmail.com

没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试