区块链游戏项目(战舰游戏)基于layer2区块链技术,使用以太坊的solidity语言, 含全栈完整源码

这里介绍一个基于区块链以太坊开发的战舰游戏项目。做这个项目的初衷是对layer2区块链技术的proof-of-concept。因此,本项目是一个可以在每一个人的电脑上面执行的demo。为了让大家也能执行该程序,本人在文末放置了完整源码,同时也说明了项目配置细节和技术。

先看该游戏执行时的一个动图:
在这里插入图片描述
使用的编程技术有:

  • HTML; Javascript; CCS; (网页前端)
  • Web3 (提供了调用智能合约的js接口)
  • ganache-cli (在本地模拟以太坊节点)
  • remix (以太坊智能合约的IDE)
  • Solidity (智能合约编程语言)

具体的环境配置请阅读本人的上一篇文章: 区块链/以太坊/智能合约solidity,全栈开发区块链借贷记账小应用,含完整源码

游戏规则

该游戏名称是“Battleship game”,游戏的规则有很多变种,这里只使用最简单的。具体为:
在这里插入图片描述
每一个玩家都可以看到上图所示的页面。该页面分为两部分,下面部分表示当前玩家的棋盘信息,开始的时候,该玩家随机选择两个格子,用于放置两个战舰;上面部分显示对方玩家的棋盘信息,除了对方玩家的战舰位置。开始的时候,上面部分的棋盘是空的。游戏开始之后,两个玩家轮流猜测对方的战舰的位置,每一次只能猜一个方格。如果对方的战舰不在所猜测的方格中,那么就会在对应位置显示一个水花的图像;反之,则出现一团火的图像。因为双方看不到对方的棋盘,因此,每一次都需要对方玩家回复“所猜测的方格是否有战舰”(我们可以采用密码学的技术检测出对方是否撒谎)。当某一个玩家率先猜中了对方两个战舰的位置,该玩家就赢了,并可以收取自己和对方的赌注。

这里为了便于演示,将所有的棋盘放到一个页面上。

技术细节

这里使用了layer-two区块链协议,使得不需要每走一步棋都要访问区块链和更新区块链的状态。因此,这样可以节省交易手续费和时间。比如,现在以太坊一个交易被打包进区块的时间是13秒左右,如果还要确定该区块确实被包含到区块链中,还需要更长时间来确认;并且,当前时间点的以太坊的一个平均交易费用是11美元,可贵了。因此,如果每走一步棋都要将状态保存到区块链中,是缓慢和不经济的。估计不会有人愿意使用几个小时玩这样的游戏吧。为了解决这个问题,我们使用state channel技术。在正常情况下,一个玩家只需要更新区块链状态两次(游戏开始和结束的时候)。在游戏中途,如果有某一个玩家耍赖,比如中途离开或者撒谎,他们再使用智能合约来解决这些争端(dispute),以确保公平。

下图显示,如果使用layer1的区块链技术,每走一步棋都需要向区块链发布一个交易。
在这里插入图片描述
下图所示的正是我们使用的方式。
在这里插入图片描述

一个问题:如何检测对方玩家撒谎? 具体为,每一个玩家在游戏开始前都需要随机指定两个格子,表示两个战舰的位置,如果某玩家中途变卦,不承认自己所指定的那两个格子呢?再者,当前玩家猜测对方玩家战舰所在的方格位置,对方玩家需要回复该方格下是否有战舰,如果对方玩家不诚信呢?我们使用了Merkle tree进行commit(承诺)。介绍merkle tree(形如下图)不属于本文的范围。
在这里插入图片描述
根据密码学中的hash函数的特点,任意一个节点的变化都会导致根节点变化。并且,我们能够很容易证明某一个节点是否属于该merkle tree。

这里,我们对两位玩家的所有的游戏方格分别生成两棵merkle tree,叶子节点表示方格的编号。这里为了保密性,在编号后面合并一个随机数(合并后的数据作为hash函数的输入)。

因此,解决方法是,在玩家指定两个战舰的位置之后,需要生成一棵merkle tree,并向对方发送根节点。该根节点便是对方的承诺,且它不会泄露战舰的位置信息。在游戏过程中,如果要揭露某一个方格下是否存在战舰,需要将对应编号的叶子节点和从该节点到根节点的路径信息发送给对方。若对方能够构造出相同的根节点,证明该玩家是诚信的。(这里涉及到了密码学hash函数的知识)。

另一个问题:如果一个玩家a中途离开,怎么办?
当前实现的功能:需要玩家b向智能合约中提交一个控告。为了回应该控告,玩家a要在一分钟之内调用智能合约,取消掉该控告。如果一分钟之后玩家a不回复,那么玩家b就可以取走所有的赌注。

区块链和智能合约的作用

在这个游戏中,智能合约充当了裁判的角色:若某个玩家撒谎或者中途离开,那么智能合约就会把赌注给另一个玩家。因此,本质上区块链中的智能合约解决了信用问题,并且,重要的是,不需要依赖任何可信的第三方。游戏玩家不需要相信任何人:不用担心对方不诚信,不用担心游戏平台和对方玩家勾结;不用担心自己的赌注莫名奇妙就被取走;不用担心游戏平台宕机。

下图表示的是智能合约的fields,也即是智能合约需要保存的数据。我们保存了两个玩家的地址,赌注的数量,游戏状态,最终赢家的地址,两个merkle tree的跟节点,超时不回复的数据等等。
在这里插入图片描述

该项目还实现了下图红圈所示的功能。

  • Forfeit Game,表示当前玩家放弃该游戏,包括赌注。(已实现)
  • Claim Win,在当前玩家猜中对方两个战舰之后,点击该按钮就可以取走所有的赌注。(已实现)
  • Accuse Cheating,原本的功能是当发现对方玩家撒谎时,将撒谎的数据发布到智能合约中,让智能合约裁决。如果读者想要实现该功能,需要注意,某一个玩家在向对方发送数据前,需要对该数据签名,以避免耍赖。因此,当某一个玩家要求智能合约裁决时,智能合约需要验证相关签名。(未实现)
  • Accuse Timeout,控告对方玩家中途离开;(已实现)
  • Respond to Accusation, 当当前玩家被控告时,该玩家需要在一分钟内点击该按钮,表示自己在线,来回复控告。(已实现)
  • claim timeout winnings,如果被告人没有在一分钟之内回复,就可以点击该按钮来取走所有的赌注。(已实现)

在这里插入图片描述

需要完善的地方

很明显,这个项目只是一个demo。它距离真实的游戏还有很长的路:

  • 首先,需要将两个玩家的棋盘放到两个页面中,让两个玩家相互看不到对方。
  • 页面还不够友好,比如点击某一个按钮之后,没有弹框显示执行结果。
  • 开始游戏之后,缺少页面UI来重置游戏。目前,需要进入remix来点击函数“clear_state_test”来重置游戏 (如下图所示)。
    在这里插入图片描述
  • 因为只是为了proof-of-concept,本人没有严格检查智能合约的安全性问题。

项目环境搭配和本地代码执行

请参考本人上一篇文章来搭建项目环境:https://liangyihuai.blog.csdn.net/article/details/115913338

在这里插入图片描述
因为该项目是在斯坦福大学课程的一个项目作业的源码之上编写的,如果我把源码放到GitHub上面,那位教授肯定很不开心,因此,本人把完整的源码放到了CSDN资源下载页面中。

下载页面(包含智能合约):https://download.csdn.net/download/liangyihuai/18418646

谢谢

猜你喜欢

转载自blog.csdn.net/liangyihuai/article/details/116459829
今日推荐