Адриана обнови решението на 16.10.2015 10:34 (преди над 9 години)
+def move(snake, direction)
+ moved_snake = snake.clone
+ moved_snake.delete_at(0)
+ add_new_head(moved_snake, direction)
+end
+
+def grow(snake, direction)
+ grown_snake = snake.clone
+ add_new_head(grown_snake, direction)
+end
+
+def new_food(food, snake, dimensions)
+ busy = snake.clone
+ busy += food
+
+ possible_new_food = get_random_place(dimensions)
+
+ while busy.include? possible_new_food do
+ possible_new_food = get_random_place(dimensions)
+ end
+
+ possible_new_food
+end
+
+def obstacle_ahead?(snake, direction, dimensions)
+ new_snake = snake.clone
+ out_of_bounds(new_snake, direction, dimensions)
+end
+
+def danger?(snake, direction, dimensions)
+ new_snake = snake.clone
+ new_snake = add_new_head(snake, direction)
+ out_of_bounds(new_snake, direction, dimensions)
+end
+
+def get_new_head(snake, direction)
+ current_head = snake[-1].clone
+ new_head = current_head
+
+ new_head.zip(direction).map {|element| element.inject(:+)}
+end
+
+def add_new_head(snake, direction)
+ snake << get_new_head(snake, direction)
+end
+
+def get_random_place(dimensions)
+ [Random.rand(dimensions[:width]), Random.rand(dimensions[:height])]
+end
+
+def out_of_bounds(snake, direction, dimensions)
+ head = get_new_head(snake, direction)
+
+ x_out_of_bounds = head[0] < 0 || head[0] >= dimensions[:width]
+ y_out_of_bounds = head[1] < 0 || head[1] >= dimensions[:height]
+ snake.include?(head) || x_out_of_bounds || y_out_of_bounds
+end
Забелязвам common pattern в решението ти. Правиш някои неща ненужно постъпково. Като резултат решението ти става малко по-дълго и ти трябват малко повече променливи, за които да мислиш имена. И си им дала имена, които ще отразяват съдържанието им след края на изпълнението, не на мястото, където се срещат за първи път. Например:
grown_snake = snake.clone
Тук grown_snake
всъщност не е grown. Става grown на следващия ред. По принцип би следвало да я кръстиш snake_duplicate
. А тук можеш изцяло да избегнеш променливата, като направиш целия grow
one-liner:
add_new_head(snake.clone, direction)
Някои други идеи:
-
danger?
трябваше да проверява за опасност след 1 или два хода. -
new_head.zip(direction).map {|element| element.inject(:+)}
e overkill. Искаше просто[x1 + y1, x2 + y2]
. Не е нужно да се ограничаваш до един ред. - Във форума сме обсъдили малко темата с
generate_new_position until position.satisfies?(condition)
. - Има методи
Array#first
/Array#last
, изглеждат по-ясно от индексирането. -
do
-то наwhile
е излишно.
Още неща откъм имена:
-
out_of_bounds
е леко объркващо. От името очаквах да проверява дали текущата змия е извън ограниченията. Без да я мърда и без да гледа дали се е самозахапала.head
ми звучи като текущата, не "мръдналата" глава. - Избягвай
get_x
/set_x
имена в Ruby.get_new_head
като име не дава друга информация, която вече не се съдържа вnew_head
. В случая ще имаш колизия с имената, съответно би следвало да помислиш за нещо друго.