Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
38e7a078
Y
YTBP
项目概览
YottaChain
/
YTBP
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Y
YTBP
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
38e7a078
编写于
7月 06, 2018
作者:
K
Kevin Heifner
提交者:
GitHub
7月 06, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #4130 from EOSIO/tic-tac-toe
Update tic tac toe contract to follow latest eosio framework
上级
2f6963ff
83c97073
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
294 addition
and
369 deletion
+294
-369
contracts/tic_tac_toe/tic_tac_toe.abi
contracts/tic_tac_toe/tic_tac_toe.abi
+70
-39
contracts/tic_tac_toe/tic_tac_toe.cpp
contracts/tic_tac_toe/tic_tac_toe.cpp
+146
-185
contracts/tic_tac_toe/tic_tac_toe.hpp
contracts/tic_tac_toe/tic_tac_toe.hpp
+56
-95
unittests/tic_tac_toe_tests.cpp
unittests/tic_tac_toe_tests.cpp
+22
-50
未找到文件。
contracts/tic_tac_toe/tic_tac_toe.abi
浏览文件 @
38e7a078
{
"____comment": "This file was generated by eosio-abigen. DO NOT EDIT - 2018-07-06T13:38:01",
"version": "eosio::abi/1.0",
"types": [{
"new_type_name": "account_name",
"type": "name"
}],
"types": [],
"structs": [{
"name": "game",
"base": "",
"fields": [
{"name":"challenger", "type":"account_name"},
{"name":"host", "type":"account_name"},
{"name":"turn", "type":"account_name"},
{"name":"winner", "type":"account_name"},
{"name":"board", "type":"uint8[]"}
"fields": [{
"name": "challenger",
"type": "name"
},{
"name": "host",
"type": "name"
},{
"name": "turn",
"type": "name"
},{
"name": "winner",
"type": "name"
},{
"name": "board",
"type": "uint8[]"
}
]
},{
"name": "create",
"base": "",
"fields": [
{"name":"challenger", "type":"account_name"},
{"name":"host", "type":"account_name"}
"fields": [{
"name": "challenger",
"type": "name"
},{
"name": "host",
"type": "name"
}
]
},{
"name": "restart",
"base": "",
"fields": [
{"name":"challenger", "type":"account_name"},
{"name":"host", "type":"account_name"},
{"name":"by", "type":"account_name"}
"fields": [{
"name": "challenger",
"type": "name"
},{
"name": "host",
"type": "name"
},{
"name": "by",
"type": "name"
}
]
},{
"name": "close",
"base": "",
"fields": [
{"name":"challenger", "type":"account_name"},
{"name":"host", "type":"account_name"}
]
},{
"name": "movement",
"base": "",
"fields": [
{"name":"row", "type":"uint32"},
{"name":"column", "type":"uint32"}
"fields": [{
"name": "challenger",
"type": "name"
},{
"name": "host",
"type": "name"
}
]
},{
"name": "move",
"base": "",
"fields": [
{"name":"challenger", "type":"account_name"},
{"name":"host", "type":"account_name"},
{"name":"by", "type":"account_name"},
{"name":"mvt", "type":"movement"}
"fields": [{
"name": "challenger",
"type": "name"
},{
"name": "host",
"type": "name"
},{
"name": "by",
"type": "name"
},{
"name": "row",
"type": "uint16"
},{
"name": "column",
"type": "uint16"
}
]
}
],
...
...
@@ -73,13 +99,18 @@
}
],
"tables": [{
"name": "games",
"type": "game",
"index_type": "i64",
"key_names" : ["challenger"],
"key_types" : ["account_name"]
}
"name": "games",
"index_type": "i64",
"key_names": [
"challenger"
],
"key_types": [
"name"
],
"type": "game"
}
],
"ricardian_clauses": [],
"error_messages": [],
"abi_extensions": []
}
}
\ No newline at end of file
contracts/tic_tac_toe/tic_tac_toe.cpp
浏览文件 @
38e7a078
...
...
@@ -5,206 +5,167 @@
#include "tic_tac_toe.hpp"
using
namespace
eosio
;
namespace
tic_tac_toe
{
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 mvt - the movement made by the player
* @param game_for_movement - 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
<
board_len
&&
is_empty_cell
(
game_for_movement
.
board
[
movement_location
]);
return
is_valid
;
}
/**
* @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 row - the row of movement made by the player
* @param column - the column of movement made by the player
* @param board - the board on which the movement is being made
* @return true if movement is valid
*/
bool
is_valid_movement
(
const
uint16_t
&
row
,
const
uint16_t
&
column
,
const
vector
<
uint8_t
>&
board
)
{
uint32_t
movement_location
=
row
*
tic_tac_toe
::
game
::
board_width
+
column
;
bool
is_valid
=
movement_location
<
board
.
size
()
&&
is_empty_cell
(
board
[
movement_location
]);
return
is_valid
;
}
/**
* @brief Get winner of the game
* @detail Winner of the game is the first player who made three consecutive aligned movement
* @param current_game - the game which we want to determine the winner of
* @return winner of the game (can be either none/ draw/ account name of host/ account name of challenger)
*/
account_name
get_winner
(
const
game
&
current_game
)
{
if
((
current_game
.
board
[
0
]
==
current_game
.
board
[
4
]
&&
current_game
.
board
[
4
]
==
current_game
.
board
[
8
])
||
(
current_game
.
board
[
1
]
==
current_game
.
board
[
4
]
&&
current_game
.
board
[
4
]
==
current_game
.
board
[
7
])
||
(
current_game
.
board
[
2
]
==
current_game
.
board
[
4
]
&&
current_game
.
board
[
4
]
==
current_game
.
board
[
6
])
||
(
current_game
.
board
[
3
]
==
current_game
.
board
[
4
]
&&
current_game
.
board
[
4
]
==
current_game
.
board
[
5
]))
{
// x | - | - - | x | - - | - | x - | - | -
// - | x | - - | x | - - | x | - x | x | x
// - | - | x - | x | - x | - | - - | - | -
if
(
current_game
.
board
[
4
]
==
1
)
{
return
current_game
.
host
;
}
else
if
(
current_game
.
board
[
4
]
==
2
)
{
return
current_game
.
challenger
;
}
}
else
if
((
current_game
.
board
[
0
]
==
current_game
.
board
[
1
]
&&
current_game
.
board
[
1
]
==
current_game
.
board
[
2
])
||
(
current_game
.
board
[
0
]
==
current_game
.
board
[
3
]
&&
current_game
.
board
[
3
]
==
current_game
.
board
[
6
]))
{
// x | x | x x | - | -
// - | - | - x | - | -
// - | - | - x | - | -
if
(
current_game
.
board
[
0
]
==
1
)
{
return
current_game
.
host
;
}
else
if
(
current_game
.
board
[
0
]
==
2
)
{
return
current_game
.
challenger
;
}
}
else
if
((
current_game
.
board
[
2
]
==
current_game
.
board
[
5
]
&&
current_game
.
board
[
5
]
==
current_game
.
board
[
8
])
||
(
current_game
.
board
[
6
]
==
current_game
.
board
[
7
]
&&
current_game
.
board
[
7
]
==
current_game
.
board
[
8
]))
{
// - | - | x - | - | -
// - | - | x - | - | -
// - | - | x x | x | x
if
(
current_game
.
board
[
8
]
==
1
)
{
return
current_game
.
host
;
}
else
if
(
current_game
.
board
[
8
]
==
2
)
{
return
current_game
.
challenger
;
}
}
else
{
bool
is_board_full
=
true
;
for
(
uint8_t
i
=
0
;
i
<
board_len
;
i
++
)
{
if
(
is_empty_cell
(
current_game
.
board
[
i
]))
{
is_board_full
=
false
;
break
;
}
}
if
(
is_board_full
)
{
return
N
(
draw
);
}
/**
* @brief Get winner of the game
* @detail Winner of the game is the first player who made three consecutive aligned movement
* @param current_game - the game which we want to determine the winner of
* @return winner of the game (can be either none/ draw/ account name of host/ account name of challenger)
*/
account_name
get_winner
(
const
tic_tac_toe
::
game
&
current_game
)
{
auto
&
board
=
current_game
.
board
;
bool
is_board_full
=
true
;
// Use bitwise AND operator to determine the consecutive values of each column, row and diagonal
// Since 3 == 0b11, 2 == 0b10, 1 = 0b01, 0 = 0b00
vector
<
uint32_t
>
consecutive_column
(
tic_tac_toe
::
game
::
board_width
,
3
);
vector
<
uint32_t
>
consecutive_row
(
tic_tac_toe
::
game
::
board_height
,
3
);
uint32_t
consecutive_diagonal_backslash
=
3
;
uint32_t
consecutive_diagonal_slash
=
3
;
for
(
uint32_t
i
=
0
;
i
<
board
.
size
();
i
++
)
{
is_board_full
&=
is_empty_cell
(
board
[
i
]);
uint16_t
row
=
uint16_t
(
i
/
tic_tac_toe
::
game
::
board_width
);
uint16_t
column
=
uint16_t
(
i
%
tic_tac_toe
::
game
::
board_width
);
// Calculate consecutive row and column value
consecutive_row
[
column
]
=
consecutive_row
[
column
]
&
board
[
i
];
consecutive_column
[
row
]
=
consecutive_column
[
row
]
&
board
[
i
];
// Calculate consecutive diagonal \ value
if
(
row
==
column
)
{
consecutive_diagonal_backslash
=
consecutive_diagonal_backslash
&
board
[
i
];
}
// Calculate consecutive diagonal / value
if
(
row
+
column
==
tic_tac_toe
::
game
::
board_width
-
1
)
{
consecutive_diagonal_slash
=
consecutive_diagonal_slash
&
board
[
i
];
}
return
N
(
none
);
}
/**
* @brief Apply create action
* @param c - action to be applied
*/
void
on
(
const
create
&
c
)
{
require_auth
(
c
.
host
);
eosio_assert
(
c
.
challenger
!=
c
.
host
,
"challenger shouldn't be the same as host"
);
// Check if game already exists
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
)
{
g
.
challenger
=
c
.
challenger
;
g
.
host
=
c
.
host
;
g
.
turn
=
c
.
host
;
});
// Inspect the value of all consecutive row, column, and diagonal and determine winner
vector
<
uint32_t
>
aggregate
=
{
consecutive_diagonal_backslash
,
consecutive_diagonal_slash
};
aggregate
.
insert
(
aggregate
.
end
(),
consecutive_column
.
begin
(),
consecutive_column
.
end
());
aggregate
.
insert
(
aggregate
.
end
(),
consecutive_row
.
begin
(),
consecutive_row
.
end
());
for
(
auto
value
:
aggregate
)
{
if
(
value
==
1
)
{
return
current_game
.
host
;
}
else
if
(
value
==
2
)
{
return
current_game
.
challenger
;
}
}
// Draw if the board is full, otherwise the winner is not determined yet
return
is_board_full
?
N
(
draw
)
:
N
(
none
);
}
/**
* @brief Apply restart action
* @param r - action to be applied
*/
void
on
(
const
restart
&
r
)
{
require_auth
(
r
.
by
);
// Check if game exists
games
existing_host_games
(
code_account
,
r
.
host
);
auto
itr
=
existing_host_games
.
find
(
r
.
challenger
);
eosio_assert
(
itr
!=
existing_host_games
.
end
(),
"game doesn't exists"
);
// Check if this game belongs to the action sender
eosio_assert
(
r
.
by
==
itr
->
host
||
r
.
by
==
itr
->
challenger
,
"this is not your game!"
);
// Reset game
existing_host_games
.
modify
(
itr
,
itr
->
host
,
[](
auto
&
g
)
{
g
.
reset_game
();
});
}
/**
* @brief Apply create action
*/
void
tic_tac_toe
::
create
(
const
account_name
&
challenger
,
const
account_name
&
host
)
{
require_auth
(
host
);
eosio_assert
(
challenger
!=
host
,
"challenger shouldn't be the same as host"
);
// Check if game already exists
games
existing_host_games
(
_self
,
host
);
auto
itr
=
existing_host_games
.
find
(
challenger
);
eosio_assert
(
itr
==
existing_host_games
.
end
(),
"game already exists"
);
existing_host_games
.
emplace
(
host
,
[
&
](
auto
&
g
)
{
g
.
challenger
=
challenger
;
g
.
host
=
host
;
g
.
turn
=
host
;
});
}
/**
* @brief Apply close action
* @param c - action to be applied
*/
void
on
(
const
close
&
c
)
{
require_auth
(
c
.
host
);
/**
* @brief Apply restart action
*/
void
tic_tac_toe
::
restart
(
const
account_name
&
challenger
,
const
account_name
&
host
,
const
account_name
&
by
)
{
require_auth
(
by
);
// Check if game exists
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"
);
// Check if game exists
games
existing_host_games
(
_self
,
host
);
auto
itr
=
existing_host_games
.
find
(
challenger
);
eosio_assert
(
itr
!=
existing_host_games
.
end
(),
"game doesn't exists"
);
// Remove game
existing_host_games
.
erase
(
itr
);
}
// Check if this game belongs to the action sender
eosio_assert
(
by
==
itr
->
host
||
by
==
itr
->
challenger
,
"this is not your game!"
);
/**
* @brief Apply move action
* @param m - action to be applied
*/
void
on
(
const
move
&
m
)
{
require_auth
(
m
.
by
);
// Check if game exists
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"
);
// Check if this game hasn't ended yet
eosio_assert
(
itr
->
winner
==
N
(
none
),
"the game has ended!"
);
// Check if this game belongs to the action sender
eosio_assert
(
m
.
by
==
itr
->
host
||
m
.
by
==
itr
->
challenger
,
"this is not your game!"
);
// Check if this is the action sender's turn
eosio_assert
(
m
.
by
==
itr
->
turn
,
"it's not your turn yet!"
);
// Check if user makes a valid movement
eosio_assert
(
is_valid_movement
(
m
.
mvt
,
*
itr
),
"not a valid movement!"
);
// Fill the cell, 1 for host, 2 for challenger
const
uint8_t
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
;
//check to see if we have a winner
g
.
winner
=
get_winner
(
g
);
});
}
// Reset game
existing_host_games
.
modify
(
itr
,
itr
->
host
,
[](
auto
&
g
)
{
g
.
reset_game
();
});
}
/// 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
))
{
impl
::
on
(
eosio
::
unpack_action_data
<
tic_tac_toe
::
create
>
());
}
else
if
(
action
==
N
(
restart
))
{
impl
::
on
(
eosio
::
unpack_action_data
<
tic_tac_toe
::
restart
>
());
}
else
if
(
action
==
N
(
close
))
{
impl
::
on
(
eosio
::
unpack_action_data
<
tic_tac_toe
::
close
>
());
}
else
if
(
action
==
N
(
move
))
{
impl
::
on
(
eosio
::
unpack_action_data
<
tic_tac_toe
::
move
>
());
}
}
}
/**
* @brief Apply close action
*/
void
tic_tac_toe
::
close
(
const
account_name
&
challenger
,
const
account_name
&
host
)
{
require_auth
(
host
);
};
// Check if game exists
games
existing_host_games
(
_self
,
host
);
auto
itr
=
existing_host_games
.
find
(
challenger
);
eosio_assert
(
itr
!=
existing_host_games
.
end
(),
"game doesn't exists"
);
// Remove game
existing_host_games
.
erase
(
itr
);
}
/**
* The apply() methods 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
)
{
impl
().
apply
(
receiver
,
code
,
action
);
}
* @brief Apply move action
*/
void
tic_tac_toe
::
move
(
const
account_name
&
challenger
,
const
account_name
&
host
,
const
account_name
&
by
,
const
uint16_t
&
row
,
const
uint16_t
&
column
)
{
require_auth
(
by
);
// Check if game exists
games
existing_host_games
(
_self
,
host
);
auto
itr
=
existing_host_games
.
find
(
challenger
);
eosio_assert
(
itr
!=
existing_host_games
.
end
(),
"game doesn't exists"
);
// Check if this game hasn't ended yet
eosio_assert
(
itr
->
winner
==
N
(
none
),
"the game has ended!"
);
// Check if this game belongs to the action sender
eosio_assert
(
by
==
itr
->
host
||
by
==
itr
->
challenger
,
"this is not your game!"
);
// Check if this is the action sender's turn
eosio_assert
(
by
==
itr
->
turn
,
"it's not your turn yet!"
);
// Check if user makes a valid movement
eosio_assert
(
is_valid_movement
(
row
,
column
,
itr
->
board
),
"not a valid movement!"
);
// Fill the cell, 1 for host, 2 for challenger
const
uint8_t
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
[
row
*
tic_tac_toe
::
game
::
board_width
+
column
]
=
cell_value
;
g
.
turn
=
turn
;
g
.
winner
=
get_winner
(
g
);
});
}
}
// extern "C"
EOSIO_ABI
(
tic_tac_toe
,
(
create
)(
restart
)(
close
)(
move
))
contracts/tic_tac_toe/tic_tac_toe.hpp
浏览文件 @
38e7a078
...
...
@@ -42,102 +42,63 @@
* @{
*/
namespace
tic_tac_toe
{
static
const
account_name
games_account
=
N
(
games
);
static
const
account_name
code_account
=
N
(
tic
.
tac
.
toe
);
/**
* @brief Data structure to hold game information
*/
static
const
uint32_t
board_len
=
9
;
struct
game
{
game
()
{
initialize_board
();
}
game
(
account_name
challenger_account
,
account_name
host_account
)
:
challenger
(
challenger_account
),
host
(
host_account
),
turn
(
host_account
)
{
// 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
[
board_len
];
// Initialize board with empty cell
void
initialize_board
()
{
for
(
uint8_t
i
=
0
;
i
<
board_len
;
i
++
)
{
board
[
i
]
=
0
;
class
tic_tac_toe
:
public
eosio
::
contract
{
public:
tic_tac_toe
(
account_name
self
)
:
contract
(
self
){}
/**
* @brief Information related to a game
* @abi table games i64
*/
struct
game
{
static
const
uint16_t
board_width
=
3
;
static
const
uint16_t
board_height
=
board_width
;
game
()
{
initialize_board
();
}
account_name
challenger
;
account_name
host
;
account_name
turn
;
// = account name of host/ challenger
account_name
winner
=
N
(
none
);
// = none/ draw/ name of host/ name of challenger
std
::
vector
<
uint8_t
>
board
;
// Initialize board with empty cell
void
initialize_board
()
{
board
=
std
::
vector
<
uint8_t
>
(
board_width
*
board_height
,
0
);
}
}
// Reset game
void
reset_game
()
{
initialize_board
();
turn
=
host
;
winner
=
N
(
none
);
}
auto
primary_key
()
const
{
return
challenger
;
}
EOSLIB_SERIALIZE
(
game
,
(
challenger
)(
host
)(
turn
)(
winner
)(
board
)
)
};
/**
* @brief Action to create new game
*/
struct
create
{
account_name
challenger
;
account_name
host
;
EOSLIB_SERIALIZE
(
create
,
(
challenger
)(
host
)
)
};
/**
* @brief Action to restart new game
*/
struct
restart
{
account_name
challenger
;
account_name
host
;
account_name
by
;
// the account who wants to restart the game
EOSLIB_SERIALIZE
(
restart
,
(
challenger
)(
host
)(
by
)
)
};
/**
* @brief Action to close new game
*/
struct
close
{
account_name
challenger
;
account_name
host
;
EOSLIB_SERIALIZE
(
close
,
(
challenger
)(
host
)
)
};
/**
* @brief Data structure for movement
*/
struct
movement
{
uint32_t
row
;
uint32_t
column
;
EOSLIB_SERIALIZE
(
movement
,
(
row
)(
column
)
)
};
/**
* @brief Action to make movement
*/
struct
move
{
account_name
challenger
;
account_name
host
;
account_name
by
;
// the account who wants to make the move
movement
mvt
;
EOSLIB_SERIALIZE
(
move
,
(
challenger
)(
host
)(
by
)(
mvt
)
)
};
// Reset game
void
reset_game
()
{
initialize_board
();
turn
=
host
;
winner
=
N
(
none
);
}
/**
* @brief table definition, used to store existing games and their current state
*/
typedef
eosio
::
multi_index
<
games_account
,
game
>
games
;
}
auto
primary_key
()
const
{
return
challenger
;
}
EOSLIB_SERIALIZE
(
game
,
(
challenger
)(
host
)(
turn
)(
winner
)(
board
))
};
/**
* @brief The table definition, used to store existing games and their current state
*/
typedef
eosio
::
multi_index
<
N
(
games
),
game
>
games
;
/// @abi action
/// Create a new game
void
create
(
const
account_name
&
challenger
,
const
account_name
&
host
);
/// @abi action
/// Restart a game
/// @param by the account who wants to restart the game
void
restart
(
const
account_name
&
challenger
,
const
account_name
&
host
,
const
account_name
&
by
);
/// @abi action
/// Close an existing game, and remove it from storage
void
close
(
const
account_name
&
challenger
,
const
account_name
&
host
);
/// @abi action
/// Make movement
/// @param by the account who wants to make the move
void
move
(
const
account_name
&
challenger
,
const
account_name
&
host
,
const
account_name
&
by
,
const
uint16_t
&
row
,
const
uint16_t
&
column
);
};
/// @}
unittests/tic_tac_toe_tests.cpp
浏览文件 @
38e7a078
...
...
@@ -41,12 +41,6 @@ struct game {
FC_REFLECT
(
game
,
(
challenger
)(
host
)(
turn
)(
winner
)(
board
));
struct
movement
{
uint32_t
row
;
uint32_t
column
;
};
FC_REFLECT
(
movement
,
(
row
)(
column
));
struct
ttt_tester
:
TESTER
{
void
get_game
(
game
&
game
,
account_name
scope
,
account_name
key
)
{
auto
*
maybe_tid
=
find_table
(
N
(
tic
.
tac
.
toe
),
scope
,
N
(
games
));
...
...
@@ -84,84 +78,68 @@ BOOST_AUTO_TEST_CASE( tic_tac_toe_game ) try {
chain
.
produce_blocks
();
auto
mvt
=
mutable_variant_object
()
(
"row"
,
1
)
(
"column"
,
1
);
chain
.
push_action
(
N
(
tic
.
tac
.
toe
),
N
(
move
),
N
(
player1
),
mutable_variant_object
()
(
"challenger"
,
"player2"
)
(
"host"
,
"player1"
)
(
"by"
,
"player1"
)
(
"mvt"
,
mvt
)
(
"row"
,
1
)
(
"column"
,
1
)
);
mvt
=
mutable_variant_object
()
(
"row"
,
0
)
(
"column"
,
1
);
BOOST_CHECK_EXCEPTION
(
chain
.
push_action
(
N
(
tic
.
tac
.
toe
),
N
(
move
),
N
(
player1
),
mutable_variant_object
()
(
"challenger"
,
"player2"
)
(
"host"
,
"player1"
)
(
"by"
,
"player1"
)
(
"mvt"
,
mvt
)
(
"row"
,
0
)
(
"column"
,
1
)
),
eosio_assert_message_exception
,
eosio_assert_message_starts_with
(
"it's not your turn yet"
));
mvt
=
mutable_variant_object
()
(
"row"
,
1
)
(
"column"
,
1
);
BOOST_CHECK_EXCEPTION
(
chain
.
push_action
(
N
(
tic
.
tac
.
toe
),
N
(
move
),
N
(
player2
),
mutable_variant_object
()
(
"challenger"
,
"player2"
)
(
"host"
,
"player1"
)
(
"by"
,
"player2"
)
(
"mvt"
,
mvt
)
(
"row"
,
1
)
(
"column"
,
1
)
),
eosio_assert_message_exception
,
eosio_assert_message_starts_with
(
"not a valid movement"
));
mvt
=
mutable_variant_object
()
(
"row"
,
0
)
(
"column"
,
1
);
chain
.
push_action
(
N
(
tic
.
tac
.
toe
),
N
(
move
),
N
(
player2
),
mutable_variant_object
()
(
"challenger"
,
"player2"
)
(
"host"
,
"player1"
)
(
"by"
,
"player2"
)
(
"mvt"
,
mvt
)
(
"row"
,
0
)
(
"column"
,
1
)
);
mvt
=
mutable_variant_object
()
(
"row"
,
0
)
(
"column"
,
0
);
chain
.
push_action
(
N
(
tic
.
tac
.
toe
),
N
(
move
),
N
(
player1
),
mutable_variant_object
()
(
"challenger"
,
"player2"
)
(
"host"
,
"player1"
)
(
"by"
,
"player1"
)
(
"mvt"
,
mvt
)
(
"row"
,
0
)
(
"column"
,
0
)
);
mvt
=
mutable_variant_object
()
(
"row"
,
0
)
(
"column"
,
2
);
chain
.
push_action
(
N
(
tic
.
tac
.
toe
),
N
(
move
),
N
(
player2
),
mutable_variant_object
()
(
"challenger"
,
"player2"
)
(
"host"
,
"player1"
)
(
"by"
,
"player2"
)
(
"mvt"
,
mvt
)
(
"row"
,
0
)
(
"column"
,
2
)
);
mvt
=
mutable_variant_object
()
(
"row"
,
2
)
(
"column"
,
2
);
chain
.
push_action
(
N
(
tic
.
tac
.
toe
),
N
(
move
),
N
(
player1
),
mutable_variant_object
()
(
"challenger"
,
"player2"
)
(
"host"
,
"player1"
)
(
"by"
,
"player1"
)
(
"mvt"
,
mvt
)
(
"row"
,
2
)
(
"column"
,
2
)
);
mvt
=
mutable_variant_object
()
(
"row"
,
2
)
(
"column"
,
0
);
BOOST_CHECK_EXCEPTION
(
chain
.
push_action
(
N
(
tic
.
tac
.
toe
),
N
(
move
),
N
(
player2
),
mutable_variant_object
()
(
"challenger"
,
"player2"
)
(
"host"
,
"player1"
)
(
"by"
,
"player2"
)
(
"mvt"
,
mvt
)
(
"row"
,
2
)
(
"column"
,
0
)
),
eosio_assert_message_exception
,
eosio_assert_message_starts_with
(
"the game has ended"
));
game
current
;
...
...
@@ -173,14 +151,12 @@ BOOST_AUTO_TEST_CASE( tic_tac_toe_game ) try {
(
"host"
,
"player1"
)
);
mvt
=
mutable_variant_object
()
(
"row"
,
2
)
(
"column"
,
0
);
BOOST_CHECK_EXCEPTION
(
chain
.
push_action
(
N
(
tic
.
tac
.
toe
),
N
(
move
),
N
(
player2
),
mutable_variant_object
()
(
"challenger"
,
"player2"
)
(
"host"
,
"player1"
)
(
"by"
,
"player2"
)
(
"mvt"
,
mvt
)
(
"row"
,
2
)
(
"column"
,
0
)
),
eosio_assert_message_exception
,
eosio_assert_message_starts_with
(
"game doesn't exists"
));
BOOST_CHECK_EXCEPTION
(
chain
.
push_action
(
N
(
tic
.
tac
.
toe
),
N
(
restart
),
N
(
player2
),
mutable_variant_object
()
...
...
@@ -201,25 +177,21 @@ BOOST_AUTO_TEST_CASE( tic_tac_toe_game ) try {
);
// making a move and ...
mvt
=
mutable_variant_object
()
(
"row"
,
1
)
(
"column"
,
1
);
chain
.
push_action
(
N
(
tic
.
tac
.
toe
),
N
(
move
),
N
(
player2
),
mutable_variant_object
()
(
"challenger"
,
"player1"
)
(
"host"
,
"player2"
)
(
"by"
,
"player2"
)
(
"mvt"
,
mvt
)
(
"row"
,
1
)
(
"column"
,
1
)
);
// ... repeating to get exception to ensure restart above actually did something
mvt
=
mutable_variant_object
()
(
"row"
,
0
)
(
"column"
,
1
);
BOOST_CHECK_EXCEPTION
(
chain
.
push_action
(
N
(
tic
.
tac
.
toe
),
N
(
move
),
N
(
player2
),
mutable_variant_object
()
(
"challenger"
,
"player1"
)
(
"host"
,
"player2"
)
(
"by"
,
"player2"
)
(
"mvt"
,
mvt
)
(
"row"
,
0
)
(
"column"
,
1
)
),
eosio_assert_message_exception
,
eosio_assert_message_starts_with
(
"it's not your turn yet"
));
}
FC_LOG_AND_RETHROW
()
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录