Решение на Втора задача от Георги Киряков

Обратно към всички решения

Към профила на Георги Киряков

Резултати

  • 6 точки от тестове
  • 0 бонус точки
  • 6 точки общо
  • 20 успешни тест(а)
  • 0 неуспешни тест(а)

Код

def next_position(position, direction)
[position[0] + direction[0], position[1] + direction[1]]
end
def move(snake, direction)
new_head = next_position(snake.last, direction)
snake.drop(1).push(new_head)
end
def grow(snake, direction)
new_head = next_position(snake.last, direction)
snake.dup.push(new_head)
end
def new_food(food, snake, dimensions)
map = [*0..dimensions[:width]-1].product([*0..dimensions[:height]-1])
(map - (snake | food)).sample
end
def obstacle_ahead?(snake, direction, dimensions)
next_x, next_y = next_position(snake.last, direction)
wall_ahead = (next_x < 0 || next_y < 0) ||
(next_x == dimensions[:width]) ||
(next_y == dimensions[:height])
snake.include?([next_x, next_y]) or wall_ahead
end
def danger?(snake, direction, dimensions)
obstacle_ahead?(snake, direction, dimensions) or
obstacle_ahead?(move(snake, direction), direction, dimensions)
end

Лог от изпълнението

....................

Finished in 0.01846 seconds
20 examples, 0 failures

История (3 версии и 3 коментара)

Георги обнови решението на 16.10.2015 00:29 (преди над 9 години)

+def next_position(position, direction)
+ direction.map.with_index { |e, i| e + position[i]}
+end
+
+def rand_tile(dimensions)
+ [rand(dimensions[:width]), rand(dimensions[:height])]
+end
+
+def move(snake, direction)
+ new_head = next_position(snake.last, direction)
+ snake.drop(1).push(new_head)
+end
+
+def grow(snake, direction)
+ new_head = next_position(snake.last, direction)
+ snake.dup.push(new_head)
+end
+
+def new_food(food, snake, dimensions)
+ new_food_tile = rand_tile(dimensions)
+
+ while food.include?(new_food_tile) or snake.include?(new_food_tile)
+ new_food_tile = rand_tile(dimensions)
+ end
+
+ new_food_tile
+end
+
+def obstacle_ahead?(snake, direction, dimensions)
+ next_tile = next_position(snake.last, direction)
+ wall_ahead = (next_tile[0] < 0 || next_tile[1] < 0) ||
+ (next_tile[0] == dimensions[:width]) ||
+ (next_tile[1] == dimensions[:height])
+
+ snake.include?(next_tile) or wall_ahead
+end
+
+def danger?(snake, direction, dimensions)
+ danger_in_move_one = obstacle_ahead?(snake, direction, dimensions)
+
+ moved_snake = move(snake, direction)
+ danger_in_move_two = obstacle_ahead?(moved_snake, direction, dimensions)
+
+ danger_in_move_one or dager_in_move_two
+end

Георги обнови решението на 16.10.2015 00:33 (преди над 9 години)

def next_position(position, direction)
direction.map.with_index { |e, i| e + position[i]}
end
def rand_tile(dimensions)
[rand(dimensions[:width]), rand(dimensions[:height])]
end
def move(snake, direction)
new_head = next_position(snake.last, direction)
snake.drop(1).push(new_head)
end
def grow(snake, direction)
new_head = next_position(snake.last, direction)
snake.dup.push(new_head)
end
def new_food(food, snake, dimensions)
new_food_tile = rand_tile(dimensions)
while food.include?(new_food_tile) or snake.include?(new_food_tile)
new_food_tile = rand_tile(dimensions)
end
new_food_tile
end
def obstacle_ahead?(snake, direction, dimensions)
next_tile = next_position(snake.last, direction)
wall_ahead = (next_tile[0] < 0 || next_tile[1] < 0) ||
(next_tile[0] == dimensions[:width]) ||
(next_tile[1] == dimensions[:height])
snake.include?(next_tile) or wall_ahead
end
def danger?(snake, direction, dimensions)
danger_in_move_one = obstacle_ahead?(snake, direction, dimensions)
moved_snake = move(snake, direction)
danger_in_move_two = obstacle_ahead?(moved_snake, direction, dimensions)
- danger_in_move_one or dager_in_move_two
+ danger_in_move_one or danger_in_move_two
end

На втори ред трябва да има място преди затварящата скоба на блока.

Следват няколко не-толкова-дребнави-коментара :bowtie: :

Начина, по който намираш новата позиция за храна е малко проблемен. Представи си, че имаш дъска 1000 на 1000 и змията е станала толкова голяма, че заема 80% от дъската. Тогава шанса условието на while цикъла на 22 ред да е false също е ~ 80%. И тъй като имаш 1 000 000 възможни позиции този while цикъл ще трябва да направи средно 800 000 итерации докато стигне до свободна клетка. Принципно в курса не целим бързодействие на алгоритмите, но просто този подход към проблема не е добър.

Можеш да мислиш за проблема така - имаш някакво множество от свободни позиции, избираш на произволен принцип една от тях.

Освен това избор на произволен елемент от колекция се използва често, тъй че може да провериш за някакъв подходящ метод от Array примерно.

В obstacle_ahead? можеш вместо да достъпваш с [] нужните координати всеки път, подавайки някакъв индекс, би било по-готино да си направиш някакви променливи за координатите по x и y и да си ползваш тях при сравненията. Можеш също да извадиш wall_ahead? като отделена функция и да направиш подобна функция и за проверката дали има змия на следващата позиция, а obstacle_ahead? да вика въпросните функции.

В danger? малко си се престарал с използването на променвили. Пробвай без тях :smile:.

Супер яко е, че си видял как се ползва map с индекс, но конкретно за целите на next_position функцията се опитай да подходиш по-просто. Освен това имена на променливи e и i ще ти костват точки.

Георги обнови решението на 18.10.2015 19:29 (преди над 9 години)

def next_position(position, direction)
- direction.map.with_index { |e, i| e + position[i]}
+ [position[0] + direction[0], position[1] + direction[1]]
end
-def rand_tile(dimensions)
- [rand(dimensions[:width]), rand(dimensions[:height])]
-end
-
def move(snake, direction)
new_head = next_position(snake.last, direction)
snake.drop(1).push(new_head)
end
def grow(snake, direction)
new_head = next_position(snake.last, direction)
snake.dup.push(new_head)
end
def new_food(food, snake, dimensions)
- new_food_tile = rand_tile(dimensions)
-
- while food.include?(new_food_tile) or snake.include?(new_food_tile)
- new_food_tile = rand_tile(dimensions)
- end
-
- new_food_tile
+ map = [*0..dimensions[:width]-1].product([*0..dimensions[:height]-1])
+ (map - (snake | food)).sample
end
def obstacle_ahead?(snake, direction, dimensions)
- next_tile = next_position(snake.last, direction)
- wall_ahead = (next_tile[0] < 0 || next_tile[1] < 0) ||
- (next_tile[0] == dimensions[:width]) ||
- (next_tile[1] == dimensions[:height])
+ next_x, next_y = next_position(snake.last, direction)
+ wall_ahead = (next_x < 0 || next_y < 0) ||
+ (next_x == dimensions[:width]) ||
+ (next_y == dimensions[:height])
- snake.include?(next_tile) or wall_ahead
+ snake.include?([next_x, next_y]) or wall_ahead
end
def danger?(snake, direction, dimensions)
- danger_in_move_one = obstacle_ahead?(snake, direction, dimensions)
-
- moved_snake = move(snake, direction)
- danger_in_move_two = obstacle_ahead?(moved_snake, direction, dimensions)
-
- danger_in_move_one or danger_in_move_two
+ obstacle_ahead?(snake, direction, dimensions) or
+ obstacle_ahead?(move(snake, direction), direction, dimensions)
end