文章最早由EOS节点eoswing (pomelo wing)在EOSWing.io博客上发表,授权由智比(Zhibi)发表。COM)。内容会不定期更新,仅供学习交流。
0.正式介绍
0.1教程概述
手把手教你eos系列教程,从基础开始一步步教你如何使用eos。比如发行代币,开发DAPP等等。
本文是第五篇,主要讲如何用eos智能合同写一个游戏:三网融合。
0.2学习内容
1.相关准备知识
2.撰写智能合同
3.编译和运行智能合同
0.3机器环境
Cpu: 1个内核
内存:2G
操作系统:CentOS 7.4 64位
服务器位置:香港
建议把服务器放在网络质量比较好的环境,比如香港。否则会出现很多依赖配置的下载问题。
提示:默认情况下,以下命令行是在根权限下执行的。如果出现权限问题,请在命令前添加sudo。
1.相关准备知识
1.1三网融合的游戏规则
三盘棋,又称“井字棋”,是一种棋类。棋盘是一个九方形的格子,呈“井”形。玩家互相代表或者×,在棋盘上,任何一方可以形成三个(横、竖、斜)并获胜。
1.2多指标
Multi-Index是EO io上的数据库管理接口,可以通过EO io::multi _ Index智能契约写入、读取和修改EO io数据库的数据。
完整的多索引表定义如下:
structlimit_order{
uint64 _ tid
uint128 _ tprice
uint64 _ texpiration
account_name所有者;
autoprimary_key()常量{ returnid}
uint 64 _ t get _ expire()const { return expire;}
uint 128 _ t get _ price()const { return price;}
EOLIB _ SERIEL(limit _ order,(id)(价格)(到期)(所有者) )
};
1.3建立项目框架
使用eosiocpp创建项目框架:
CD/合同
eosiocpp -n tictactoe
cd tictactoe
陆线 (landlines的缩写)
命令行输出如下:
2.撰写智能合同
2.1撰写hpp文件
介绍标准库,编译基本结构
#包括
class tictactoe:public eosio::contract {
公共:
tictactoe(account _ name self):contract(self){ }
//...游戏数据定义...
//...游戏命令定义...
};
游戏数据定义见1.2多索引。
structgame{
static const uint 16 _ tboard _ width = 3;
static const uint 16 _ tboard _ height = 3;
游戏(){
initialize _ board();
}
account_name挑战者;//挑战者
account_name主机;//主角
account_name转;//当前角色主持人/挑战者
account_name winner = N(无);//无/抽签/主持人姓名/挑战者姓名
STD::vector board;
//初始化棋盘
voidinitialize_board(){
board = STD::vector(board _ width * board _ height,;
}
//初始化游戏
虚空重置_游戏(){
initialize _ board();
turn = host
winner = N(无);
}
autoprimary _ key()const { return challenger;}
EOSLIB _ SERIALIZE(游戏,(挑战者)(主机)(回合)(赢家)(棋盘))
};
typedefosio::multi _ index games;
游戏命令定义
/// @abi动作
///创建新游戏
void create(const account _ name & amp;challenger,constaccount _ name & amp主机);
/// @abi动作
///重启游戏
void restart(const account _ name & amp;challenger,constaccount _ name & amphost,constaccount _ name & ampby);
/// @abi动作
///结束游戏
无效关闭(constaccount _ name & ampchallenger,constaccount _ name & amp主机);
/// @abi动作
///下棋
void move(const account _ name & amp;challenger,constaccount _ name & amphost,constaccount _ name & ampby,const uint16 _ t & amprow,const uint16 _ t & amp列);
hpp的完整源文件可以在github官方代码库中找到:
https://github . com/EOSIO/EOS/blob/master/contracts/TIC _ tac _ toe/TIC _ tac _ toe . HPP
在本教程中,为了避免代码文件冲突,只有tic_tac_toe被更改为tictactoe
2.2准备cpp文件
写出基本结构
#包含“tictactoe.hpp”
使用namespaceeosio
创建新游戏:
创建(constaccount _ name & ampchallenger,constaccount _ name & amp主机){
//验证主角签名
require_auth(主机);
//验证主角和挑战者不是同一个人
eosio_assert(challenger!=主机,“挑战者不应该和主机一样”);
//验证主角和挑战者目前没有游戏
gamesexisting_host_games(_self,host);
auto itr = existing _ host _ games . find(challenger);
eosio _ assert(itr = = existing _ host _ games . end(),“game exists”);
//初始化游戏
existing_host_games .侵位(host,[& amp;】(汽车& ampg ) {
g.challenger =挑战者;
g.host = host
g.turn = host
});
}
重新开始游戏:
voittictactoe::restart(const account _ name & amp;challenger,constaccount _ name & amphost,constaccount _ name & ampby) {
//验证请求者的签名
require _ auth(by);
//验证这个游戏的存在
gamesexisting_host_games(_self,host);
auto itr = existing _ host _ games . find(challenger);
eosio_assert(itr!= existing_host_games.end(),“game不存在”);
//验证请求者是主角还是挑战者
eosio _ assert(by = = itr-& gt;host || by == itr->挑战者,这不是你的游戏!);
//重启游戏
existing_host_games.modify(itr,itr->;主持人,[】(汽车& ampg ) {
g . reset _ game();
});
}
结束游戏:
voittictactoe::close(const account _ name & amp;challenger,constaccount _ name & amp主机){
//验证主角签名
require_auth(主机);
//验证这个游戏的存在
gamesexisting_host_games(_self,host);
auto itr = existing _ host _ games . find(challenger);
eosio_assert(itr!= existing_host_games.end(),“game不存在”);
//删除游戏
existing _ host _ games . erase(itr);
}
象棋:
void tictactoe::move(const account _ name & amp;challenger,constaccount _ name & amphost,constaccount _ name & ampby,const uint16 _ t & amprow,const uint16 _ t & amp列){
//验证请求者的签名
require _ auth(by);
//验证这个游戏的存在
gamesexisting_host_games(_self,host);
auto itr = existing _ host _ games . find(challenger);
eosio_assert(itr!= existing_host_games.end(),“game不存在”);
//验证游戏没有结束
eosio_assert(itr->;winner == N(无),“游戏结束了!”);
//验证请求者是主角还是挑战者
eosio _ assert(by = = itr-& gt;host || by == itr->挑战者,这不是你的游戏!);
//验证是否轮到请求者下棋
eosio _ assert(by = = itr-& gt;转身,“还没轮到你!”);
//验证此步骤中的棋子是否放置在空的棋盘格子中
//是_ valid _ move方法,后面单独写
eosio _ assert(is _ valid _ movement(row,column,itr->;板),“不是一个有效的运动!”);
//记录这一步棋的数据
const uint8_tcell_value = itr->。turn == itr->。主持人?1:2;
const auto urn = itr->turn == itr->。主持人?itr->。挑战者:itr->主机;
existing_host_games.modify(itr,itr->;主持人,[& amp;】(汽车& ampg ) {
g . board[row * tictactoe::game::board _ width+column]= cell _ value;
g.turn = turn
//验证这一招是否赢了比赛
//Winner验证通过get_winner方法提取,以后单独编写
g . winner = get _ winner(g);
});
}
棋步的有效验证方法是_有效_移动
boolis _ empty _ cell(const uint 8 _ t & amp;单元格){
returncell = =
}
boolis _ valid _ movement(const uint 16 _ t & amp;row,const uint16 _ t & ampconstvector&。board){
uint 32 _ t movement _ location = row * tictactoe::game::board _ width+column;
bool _ valid = movement _ location
returnis _ valid
}
获胜者验证
游戏规则:通过在任意水平、垂直或对角线方向上连接三个点来赢得游戏。
account _ name get _ winner(constictactoe::game & amp;current_game){
汽车&。board = current _ game.board
boolis _ board _ full = true
//使用&运算符计算水平、垂直和对角线方向的连接值。
//3 == 0b11,2 == 0b10,1 = 0b01,0 = 0b00
vector consumeration _ column(tictactoe::game::board _ width,3);
vector consecution _ row(tictactoe::game::board _ height,3);
uint32 _ tconsecutive _对角线_反斜杠= 3;
uint32 _ tconsecutive _对角线_斜线= 3;
for(uint 32 _ ti =;我
is _ board _ full & amp= is _ empty _ cell(board[I]);
uint 16 _ trow = uint 16 _ t(I/tictactoe::game::board _ width);
uint 16 _ t column = uint 16 _ t(I % tictactoe::game::board _ width);
//计算水平和垂直连接值
continuous _ row[column]= continuous _ row[column]& amp;board[I];
continuous _ column[row]= continuous _ column[row]& amp;board[I];
//计算对角线的连接值
if(row == column) {
continuous _对角线_反斜杠= continuous _对角线_反斜杠& ampboard[I];
}
if(row+column = = tictactoe::game::board _ width-1){
continuous _对角线_斜线= continuous _对角线_斜线& ampboard[I];
}
}
//检查所有水平、垂直和对角线连接值,并决定获胜者
vectoraggregate = { continuous _对角线_反斜杠,continuous _对角线_斜杠};
aggregate.insert(aggregate.end()、continuous _ column . begin()、continuous _ column . end());
aggregate.insert(aggregate.end()、continuous _ row . begin()、continuous _ row . end());
for(autovalue: aggregate) {
if(值==1) {
returncurrent _ game.host
}else if(value ==2) {
returncurrent _ game.challenger
}
}
//检查是否有赢家,有就返回。
returnis_board_full?N(平局):N(无);
}
cpp的完整源文件可以在github官方代码库中找到:
https://github . com/EOSIO/EOS/blob/master/contracts/TIC _ tac _ toe/TIC _ tac _ toe . CPP
在本教程中,为了避免代码文件冲突,只有tic_tac_toe更改为tictactoe
3.编译和运行智能合同
3.1编制合同
EOS iocpp-o tictactoe . wast tictactoe . CPP
EOS iocpp-g tictactoe . ABI tictactoe . CPP
陆线 (landlines的缩写)
命令行输出如下:
3.2创建合同账户
解锁xiao钱包,创建一个公钥私钥对,将公钥私钥对导入钱包,最后用公钥创建tttaccount。
具体步骤不再赘述,不熟悉的可以看前面的教程。
创建tttaccount后的命令行输出如下:
3.3将合同上传至账户
cleossetcontract tttaccount/contracts/tictactoe-p tttaccount @ active
命令行输出如下:
3.4运行智能合同
创建游戏
cleos推送操作tttaccount创建“{ challenger”:“xiaoaccount”,“host”:“tttaccount”} '-p tttaccount @ active
命令行输出如下:
下国际象棋
cleos推送操作tttaccount移动“{ challenger”:“xiaoaccount”,“host”:“tttaccount”,“by”:“tttaccount”,“row”:0,“column”:0 }”-权限tttaccount@active
cleos push action tttaccount move“{ challenger”:“xiaoaccount”,“host”:“tttaccount”,“by”:“xiaoaccount”,“row”:1,“column”:1 }”-权限xiaoaccount@active
命令行输出如下:
要查看游戏状态数据:
cleos get table tttaccount tttaccount游戏
命令行输出如下:
重启游戏
cleos推送操作tttaccount重新启动“{ challenger”:“xiaoaccount”,“host”:“tttaccount”,“by”:“tttaccount”} '-权限tttaccount@active
命令行输出如下:
结束游戏
cleos推送操作tttaccount close“{ challenger”:“xiaoaccount”,“host”:“tttaccount”} '-权限tttaccount@active
命令行输出如下:
4.附言
1.《eos智能合约 手把手教你玩eos:编写智能合约游戏——三连棋》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《eos智能合约 手把手教你玩eos:编写智能合约游戏——三连棋》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/keji/1635873.html