div#pop_ad { opacity: 0; }

$ cleos create account ${creator_name} ${contract_account_name} ${contract_pub_owner_key} ${contract_pub_active_key} --permission ${creator_name}@active
# e.g. $ cleos create account inita tic.tac.toe EOS4toFS3YXEQCkuuw1aqDLrtHim86Gz9u3hBdcBw5KNPZcursVHq EOS7d9A3uLe6As66jzN8j44TXJUqJSK3bFjjEEqR4oTvNAB3iM9SA --permission inita@active
// Import necessary library
#include // Generic eosio library, i.e. print, type, math, etc
using namespace eosio;
namespace tic_tac_toe {
static const account_name games_account = N(games);
static const account_name code_account = N(tic.tac.toe); //账户名称,如果需要用其他账户名,在这里改
// Your code here
}
...
namespace tic_tac_toe {
...
typedef eosio::multi_index games;
}
...
namespace tic_tac_toe {
static const uint32_t board_len = 9; //井字游戏3x3,数据长度
struct game {
game() {};
//构造函数
game(account_name challenger, account_name host):challenger(challenger), host(host), turn(host) {
// Initialize board
initialize_board();
};
account_name challenger;
account_name host;
account_name turn; // = account name of host/ challenger
account_name winner = N(none); // = none/ draw/ account name of host/ challenger
uint8_t board[9]; //棋盘数组
// 将3x3上的格子全部清零,即回到最初状态
void initialize_board() {
for (uint8_t i = 0; i
using namespace eosio;
/**
* The apply() method must have C calling convention so that the blockchain can lookup and
* call these methods.
*/
extern "C" {
using namespace tic_tac_toe;
/// The apply method implements the dispatch of events to this contract
void apply( uint64_t receiver, uint64_t code, uint64_t action ) {
// Put your action handler here
}
} // extern "C"
using namespace eosio;
namespace tic_tac_toe {
struct impl {
...
/// The apply method implements the dispatch of events to this contract
void apply( uint64_t receiver, uint64_t code, uint64_t action ) {
if (code == code_account) {
if (action == N(create)) {
\t//注意:eosio::unpack_action_data()用于将收到的动作转换为T
impl::on(eosio::unpack_action_data());
} else if (action == N(restart)) {
impl::on(eosio::unpack_action_data());
} else if (action == N(close)) {
impl::on(eosio::unpack_action_data());
} else if (action == N(move)) {
impl::on(eosio::unpack_action_data());
}
}
}
};
}
...
extern "C" {
using namespace tic_tac_toe;
// apply 方法用来执行广播到该合约的事件
void apply( uint64_t receiver, uint64_t code, uint64_t action ) {
//直接执行impl方法
impl().apply(receiver, code, action);
}
} // extern "C"
...
struct impl {
...
/**
* @param create - action to be applied
*/
void on(const create& c) {
// Put code for create action here
}
/**
* @brief Apply restart action
* @param restart - action to be applied
*/
void on(const restart& r) {
// Put code for restart action here
}
/**
* @brief Apply close action
* @param close - action to be applied
*/
void on(const close& c) {
// Put code for close action here
}
/**
* @brief Apply move action
* @param move - action to be applied
*/
void on(const move& m) {
// Put code for move action here
}
/// The apply method implements the dispatch of events to this contract
void apply( uint64_t receiver, uint64_t code, uint64_t action ) {
...
struct impl {
...
/**
* @brief Apply create action
* @param create - action to be applied
*/
void on(const create& c) {
require_auth(c.host); //从c.host中获取host用户名,并且验证是否已经签名
eosio_assert(c.challenger != c.host, "challenger shouldn t be the same as host"); //确保host和challenger不是一个玩家
//检查是否存在相同的游戏
games existing_host_games(code_account, c.host);
auto itr = existing_host_games.find( c.challenger );
eosio_assert(itr == existing_host_games.end(), "game already exists");
existing_host_games.emplace(c.host, [&]( auto& g ) {
//判断是否是相同的游戏,即challenger一致,host一致,当前庄家一致
g.challenger = c.challenger;
g.host = c.host;
g.turn = c.host;
});
}
...
}
struct impl {
...
/**
* @brief Apply close action
* @param close - action to be applied
*/
void on(const close& c) {
require_auth(c.host); //验证host签名
//检查游戏是否存在,实现方法在上面create中有了
games existing_host_games(code_account, c.host);
auto itr = existing_host_games.find( c.challenger );
eosio_assert(itr != existing_host_games.end(), "game doesn t exists");
//删除游戏,释放链上资源
existing_host_games.erase(itr);
}
...
}
struct impl {
...
bool is_valid_movement(const movement& mvt, const game& game_for_movement) {
// 占位是否有效
}
account_name get_winner(const game& current_game) {
// 是否有胜者
}
...
/**
* @brief Apply move action
* @param move - action to be applied
*/
void on(const move& m) {
require_auth(m.by); //判断当前轮的用户是否已经签名
// 检查游戏是否存在
games existing_host_games(code_account, m.host);
auto itr = existing_host_games.find( m.challenger );
eosio_assert(itr != existing_host_games.end(), "game doesn t exists");
// 检查游戏是否已经结束
eosio_assert(itr->winner == N(none), "the game has ended!");
// 检查指令是否由host或者challenger发出
eosio_assert(m.by == itr->host || m.by == itr->challenger, "this is not your game!");
// 检查发送指令的是不是轮到该轮
eosio_assert(m.by == itr->turn, "it s not your turn yet!");
// 检查占位是否有效
eosio_assert(is_valid_movement(m.mvt, *itr), "not a valid movement!");
// 修改占位数据,1-host,2-challenger
const auto cell_value = itr->turn == itr->host ? 1 : 2;
const auto turn = itr->turn == itr->host ? itr->challenger : itr->host;
existing_host_games.modify(itr, itr->host, [&]( auto& g ) {
g.board[m.mvt.row * 3 + m.mvt.column] = cell_value;
g.turn = turn;
//检查是否有胜者
g.winner = get_winner(g);
});
}
...
}
struct impl {
...
/**
* @brief Check if cell is empty
* @param cell - value of the cell (should be either 0, 1, or 2)
* @return true if cell is empty
*/
bool is_empty_cell(const uint8_t& cell) {
return cell == 0;
}
/**
* @brief Check for valid movement
* @detail Movement is considered valid if it is inside the board and done on empty cell
* @param movement - the movement made by the player
* @param game - the game on which the movement is being made
* @return true if movement is valid
*/
bool is_valid_movement(const movement& mvt, const game& game_for_movement) {
uint32_t movement_location = mvt.row * 3 + mvt.column;
bool is_valid = movement_location 做成网页,前端通过eosjs调用智能合约执行。在合约中加入代币转移,这个游戏则可以立即变成一个有奖惩的小游戏。
添加新手交流群:币种分析、每日早晚盘分析
添加助理微信,一对一亲自指导:YoYo8abc