检查器需要的一个功能是防止玩家在可能跳过对方检查器的情况下移动检查器。为此,我有一个算法,如下所示:
当我尝试实施第6步时,我的问题就出现了。我发现自己必须包含一个辅助函数,如:
def jump_location_finder_stack(board, x, y)
jump_locations = {}
opposing_checkers = opposing_checker_adjacent(determine_adjacent_positions_content(board,assign_adjacent_board_coords(x, y)))
jump_locations = jump_locations(board, x, y, opposing_checkers)
jump_locations
end
看到可笑的长对立的棋子分配(我本可以通过将其嵌入到jump_locations调用中使其更长)来调用整个“堆栈”的调用,因为每个调用都会从下一个调用开始。这是第六步方法:
def generate_jump_locations_list(board, current_player)
coordinates_list = []
@current_player = current_player
board.each do |row|
row.each do |loc|
if (loc != nil) and (loc.color == @current_player)
jump_locations = jump_location_finder_stack(board, loc.x_pos, loc.y_pos)
coordinates_list << coordinates_of_jump_landings(loc.x_pos, loc.y_pos, jump_locations)
end
end
end
coordinates_list.flatten
end
我可以在辅助方法中改进那个超长的“opposite_checkers”调用,或者换句话说,这种方法的长链接在代码中是“气味”吗?我已经包含了下面的完整列表,以防你好奇
class BoardSurvey
attr_accessor :board, :current_player
QUADRANTS = ["upper_left", "upper_right", "lower_left", "lower_right"]
def invert_array(array)
array.map! { |x| -x }
end
def normal_deltas
deltas = [1, 1, 1, -1, -1, 1, -1, -1]
@current_player == :red ? deltas : invert_array(deltas)
end
def edge?(x)
x > 7
end
def edge_adjust(hash)
@current_player == :red ? hash.merge({"upper_left" => nil, "upper_right" => nil}) : hash.merge({"lower_left" => nil, "lower_right" => nil})
end
def deltas_to_board_locations(deltas, x, y)
board_coords = []
deltas.each_slice(2) do |slice|
board_coords << x + slice[0]
board_coords << y + slice[1]
end
board_coords
end
def assign_adjacent_board_coords(x, y)
jump_positions = Hash[QUADRANTS.zip(deltas_to_board_locations(normal_deltas, x, y).each_slice(2))]
end
def determine_adjacent_positions_content(board, board_coords)
adjacent_content = {}
board_coords.each_pair { |quad, coords| adjacent_content[quad] = board[coords[0]][coords[1]] }
adjacent_content
end
def opposing_checker_adjacent(adjacent_content)
opposing_checker_adjacent = {}
adjacent_content.each_pair do |quad, content|
if content != nil
content.color != @current_player ? opposing_checker_adjacent[quad] = true : opposing_checker_adjacent[quad] = false
else
opposing_checker_adjacent[quad] = false
end
end
opposing_checker_adjacent
end
def not_outside_bounds?(x, y, dx, dy)
move_check = MoveCheck.new
not move_check.out_of_bounds?(x + dx, y + dy)
end
def jump_possible?(board, x, y, deltas)
(not_outside_bounds?(x, y, deltas[0], deltas[1]) and board[x + deltas[0]][y + deltas[1]] == nil) ? true : false
end
def delta_translator(quad, x, y, mag)
deltas = []
case quad
when "upper_left"
x += mag; y += mag
when "upper_right"
x += mag; y -= mag
when "lower_left"
x -= mag; y += mag
when "lower_right"
x -= mag; y -= mag
end
deltas << x << y
@current_player == :black ? deltas.reverse : deltas
end
def adjust_jump_locations_if_not_king(board, x, y, jump_locations)
unless board[x][y].is_king?
jump_locations["lower_left"] = false
jump_locations["lower_right"] = false
end
jump_locations
end
def jump_locations(board, x, y, opposing_checkers)
jump_locations = {}
opposing_checkers.each_pair do |quad, present|
if present
deltas = delta_translator(quad, x, y, 1)
jump_possible?(board, x, y, deltas) ? jump_locations[quad] = true : jump_locations[quad] = false
else
jump_locations[quad] = false
end
end
adjust_jump_locations_if_not_king(board, x, y, jump_locations)
jump_locations
end
def coordinates_of_jump_landings(x, y, jump_locations)
jump_coords = []
jump_locations.each_pair do |quad, jump|
if jump
jump_coords << delta_translator(quad, x, y, 2)
end
end
jump_coords
end
def jump_location_finder_stack(board, x, y)
jump_locations = {}
opposing_checkers = opposing_checker_adjacent(determine_adjacent_positions_content(board, assign_adjacent_board_coords(x, y)))
jump_locations = jump_locations(board, x, y, opposing_checkers)
jump_locations
end
def generate_jump_locations_list(board, current_player)
coordinates_list = []
@current_player = current_player
board.each do |row|
row.each do |loc|
if (loc != nil) and (loc.color == @current_player)
jump_locations = jump_location_finder_stack(board, loc.x_pos, loc.y_pos)
coordinates_list << coordinates_of_jump_landings(loc.x_pos, loc.y_pos, jump_locations)
end
end
end
coordinates_list.flatten
end
end
答案 0 :(得分:1)
长链方法通常被认为是一种不好的做法,因为它会降低代码的可读性。
首先,你可以在这里做的最简单的重构是'Extract Variable'。这将提高您方法的可读性:
def jump_location_finder_stack(board, x, y)
adj_board_coords = assign_adjacent_board_coords(x, y)
adj_position_content = determine_adjacent_positions_content(board, adj_board_coords)
opposing_checkers = opposing_checker_adjacent(adj_position_content)
jump_locations(board, x, y, opposing_checkers)
end
下一个链接方法的气味是你的班级BoardsSurvey太大而且做了很多不同的事情。这打破了Single Responsibility principle。你可以做的是应用'Extract Class'重构。在重构之后可以引入的可能类:Board,Location,PositionContext等。
启动后可能会有大量的重构工作,如果你不想破坏任何东西,我会建议你移动很小的步骤:确定代码气味,为你要重构的代码编写单元测试(如果现在没有测试),请进行小型重构。
希望这有帮助!