【发布时间】:2015-01-19 12:29:46
【问题描述】:
我正在用 Erlang 实现一个国际象棋游戏(中国象棋,准确的说是象棋)。
一块由{Color, Type} 元组表示,一个点(即位置)由{File, Rank} 元组表示。棋盘由一个点到一块的地图表示(即#{point() => piece()})。
有查询棋盘上某个点是否被棋子占据的功能:
is_point_occupied_simple(Board, Point) ->
ensure_is_point(Point),
case maps:find(Point, Board) of
{ok, _} ->
true;
error ->
false
end.
但是,我想添加一个可选参数来检查棋子的颜色-如果该点被指定颜色的棋子占据,则该函数返回true;否则返回false。如果我不关心这件作品的颜色,我可以将'_' 放入TargetColor 参数中(或者,等效地调用is_point_occupied/2):
is_point_occupied(Board, Point) ->
is_point_occupied(Board, Point, '_').
is_point_occupied(Board, Point, '_') ->
ensure_is_point(Point),
case maps:find(Point, Board) of
{ok, _} ->
true;
error ->
false
end;
is_point_occupied(Board, Point, TargetColor) ->
ensure_is_point(Point),
ensure_is_color(TargetColor),
case maps:find(Point, Board) of
{ok, {TargetColor, _}} ->
true;
{ok, _} ->
false;
error ->
false
end.
我不喜欢上面的实现,因为复制粘贴的比例很大,所以我把上面的函数简化成这样:
is_point_occupied_2(Board, Point) ->
is_point_occupied_2(Board, Point, '_').
is_point_occupied_2(Board, Point, TargetColor) ->
ensure_is_point(Point),
ensure_is_color_or_wildcard(TargetColor),
case maps:find(Point, Board) of
{ok, {TargetColor, _}} ->
true;
{ok, _} ->
is_wildcard(TargetColor);
error ->
false
end.
函数is_wildcard/1 只是单行:
is_wildcard(Wildcard) -> Wildcard =:= '_'.
现在,我想进一步将TargetColor 替换为TargetPiece,这是一个{TargetColor, TargetType} 元组。无,一个或两个元组元素可以是通配符 ('_')。我发现编写case 子句很困难。我还注意到,要以这种方式匹配允许“不关心”的 n 元组,需要 2n 子句。所以显然这不是实现这一点的正确方法。
有人有更好的想法吗?
PS:我没有包含所有函数的来源,因为我认为我没有包含的那些实现起来很简单。如果您有兴趣,请在下方留言。谢谢!
【问题讨论】: