Решение на Втора задача от Десислава Цветкова

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

Към профила на Десислава Цветкова

Резултати

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

Код

def move(snake, direction)
snake.drop(1) << new_head(snake, direction)
# snake[1..-1] << new_head(snake, direction)
end
def grow(snake, direction)
snake.dup << new_head(snake, direction)
end
def new_food(food, snake, dimensions)
free_positions(dimensions[:width],
dimensions[:height],
food,
snake).shuffle().first
end
def obstacle_ahead?(snake, direction, dimensions)
new_snake = move(snake, direction)
newly_head = new_snake.last
outside_x = outside_field?(newly_head[0], dimensions[:width])
outside_y = outside_field?(newly_head[1], dimensions[:height])
self_collision = new_snake[0...-1].include? newly_head
outside_x or outside_y or self_collision
end
def danger?(snake, direction, dimensions)
return true if obstacle_ahead?(snake, direction, dimensions)
obstacle_ahead?(move(snake, direction), direction, dimensions)
end
def new_head(snake, direction)
[snake.last[0] + direction[0], snake.last[1] + direction[1]]
end
def outside_field?(coordinate, length)
coordinate < 0 or coordinate >= length
end
def free_positions(dimension_x, dimension_y, food, snake)
all_positions = (0...dimension_x).to_a.product((0...dimension_y).to_a)
all_positions - food - snake
end

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

............F.......

Failures:

  1) #obstacle_ahead? returns true if snake body ahead
     Failure/Error: expect(
       
       expected: true
            got: false
       
       (compared using ==)
     # /tmp/d20151026-15631-5rh1ci/spec.rb:83:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.01479 seconds
20 examples, 1 failure

Failed examples:

rspec /tmp/d20151026-15631-5rh1ci/spec.rb:82 # #obstacle_ahead? returns true if snake body ahead

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

Десислава обнови решението на 13.10.2015 22:54 (преди над 9 години)

+def make_new_head(snake, direction)
+ [snake[-1][0] + direction[0], snake[-1][1] + direction[1]]
+end
+
+def generate_place(dimensions)
+ [rand(dimensions[:width]), rand(dimensions[:height])]
+end
+
+def move(snake, direction)
+ head_new = make_new_head(snake, direction)
+ snake[1 .. -1] << head_new
+end
+
+def grow(snake, direction)
+ head_new = make_new_head(snake, direction)
+ snake << head_new
+end
+
+def new_food(food, snake, dimensions)
+ busy_places = food + snake
+ new_food = generate_place(dimensions)
+ new_food = generate_place(dimensions) while busy_places.include? new_food
+ new_food
+end
+
+def obstacle_ahead?(snake, direction, dimensions)
+ snake_new = move(snake, direction)
+ head_new = snake_new[-1]
+ # snake_new[-1] is its new head
+
+ # Checking if it's outside the field or if it's bitten itself
+ outside_width = head_new[0] < 0 or head_new[0] >= dimensions[:width]
+ outside_height = head_new[1] < 0 or head_new[1] >= dimensions[:height]
+ snake_on_itself = snake_new.include? head_new
+ outside_width or outside_height or snake_on_itself
+end
+
+def danger?(snake, direction, dimensions)
+ danger_one_move = obstacle_ahead?(snake, direction, dimensions)
+ # If its first move is dangerous, we return immediately true
+ return true if danger_one_move
+
+ # Else we see what happens on the next move - with a new snake
+ # which has moved in the appropriate direction
+ snake_new = move(snake, direction)
+ obstacle_ahead?(snake_new, direction, dimensions)
+end
+

Десислава обнови решението на 14.10.2015 23:25 (преди над 9 години)

def make_new_head(snake, direction)
[snake[-1][0] + direction[0], snake[-1][1] + direction[1]]
end
def generate_place(dimensions)
[rand(dimensions[:width]), rand(dimensions[:height])]
end
def move(snake, direction)
head_new = make_new_head(snake, direction)
snake[1 .. -1] << head_new
end
def grow(snake, direction)
head_new = make_new_head(snake, direction)
- snake << head_new
+ snake.dup << head_new
end
def new_food(food, snake, dimensions)
busy_places = food + snake
new_food = generate_place(dimensions)
new_food = generate_place(dimensions) while busy_places.include? new_food
new_food
end
def obstacle_ahead?(snake, direction, dimensions)
snake_new = move(snake, direction)
head_new = snake_new[-1]
# snake_new[-1] is its new head
# Checking if it's outside the field or if it's bitten itself
outside_width = head_new[0] < 0 or head_new[0] >= dimensions[:width]
outside_height = head_new[1] < 0 or head_new[1] >= dimensions[:height]
snake_on_itself = snake_new.include? head_new
outside_width or outside_height or snake_on_itself
end
def danger?(snake, direction, dimensions)
danger_one_move = obstacle_ahead?(snake, direction, dimensions)
# If its first move is dangerous, we return immediately true
return true if danger_one_move
# Else we see what happens on the next move - with a new snake
# which has moved in the appropriate direction
snake_new = move(snake, direction)
obstacle_ahead?(snake_new, direction, dimensions)
-end
-
+end
  • Индентирай с два space-a.
  • Погледни документацията на Array за методи, с които можеш да вземеш първи/последен елемент на масив. Ще елеминира нуждата от индексиране. Същото за копие на масив без първия елемент.
  • Защо беше този недетерминистичен алгоритъм. Ако се чувстваме особено зли можем да stub-нем Kernel.rand така, че постоянно да връща едно и също число и решението ти ще tl. :)
  • Коментарите бяха малко излишни. Стига имената да са добри и да оставиш някой друг празен ред се разбира какво става и без тях.
  • Някои междинни променливи изглеждат ненужни. Например danger_one_move в danger? и head_new в move/grow.
  • Дребен трик за малко естетическо подобрение - опитай да подравниш =-тата на съседните редове в obstacle_ahead? и виж дали няма да ти хареса повече. Може да се прави и с други конструкции (примерно ключове на hash-ове).

Малко идеи с имената:

  • make-ът в make_new_head е излишен. Не носи информация, която вече да не се съдържа в new_head.
  • generate_place звучи като да разширява игралната дъска. Вероятно си искала да избереш, не да генерираш.
  • Консистентност - защо new_food/make_new_head, но snake_new/head_new? По-добре е new да е от същата страна.
  • outside_width/outside_height - външна широчина/външна височина. Може нещо по-недвусмислено. Например отвън хоризонтално/вертикално.
  • В момента и аз не мога да се сетя за нещо по-добро, но snake_on_itself звучи интересно. Алтернативно може би self_collision или нещо със самоухапване.

Като цяло добра идея и сравнително чисто решение.

Десислава обнови решението на 17.10.2015 15:27 (преди над 9 години)

-def make_new_head(snake, direction)
- [snake[-1][0] + direction[0], snake[-1][1] + direction[1]]
-end
-
-def generate_place(dimensions)
- [rand(dimensions[:width]), rand(dimensions[:height])]
-end
-
def move(snake, direction)
- head_new = make_new_head(snake, direction)
- snake[1 .. -1] << head_new
+ snake.drop(1) << new_head(snake, direction)
+ # snake[1..-1] << new_head(snake, direction)
end
def grow(snake, direction)
- head_new = make_new_head(snake, direction)
- snake.dup << head_new
+ snake.dup << new_head(snake, direction)
end
def new_food(food, snake, dimensions)
- busy_places = food + snake
- new_food = generate_place(dimensions)
- new_food = generate_place(dimensions) while busy_places.include? new_food
- new_food
+ free_positions(*dimensions.values, food, snake).shuffle().first
end
def obstacle_ahead?(snake, direction, dimensions)
- snake_new = move(snake, direction)
- head_new = snake_new[-1]
- # snake_new[-1] is its new head
+ new_snake = move(snake, direction)
+ newly_head = new_snake.last
- # Checking if it's outside the field or if it's bitten itself
- outside_width = head_new[0] < 0 or head_new[0] >= dimensions[:width]
- outside_height = head_new[1] < 0 or head_new[1] >= dimensions[:height]
- snake_on_itself = snake_new.include? head_new
- outside_width or outside_height or snake_on_itself
+ outside_x = outside_field?(newly_head[0], dimensions[:width])
+ outside_y = outside_field?(newly_head[1], dimensions[:height])
+ self_collision = new_snake.include? newly_head
+ outside_x or outside_y or self_collision
end
def danger?(snake, direction, dimensions)
- danger_one_move = obstacle_ahead?(snake, direction, dimensions)
- # If its first move is dangerous, we return immediately true
- return true if danger_one_move
+ return true if obstacle_ahead?(snake, direction, dimensions)
+ obstacle_ahead?(move(snake, direction), direction, dimensions)
+end
- # Else we see what happens on the next move - with a new snake
- # which has moved in the appropriate direction
+def new_head(snake, direction)
- snake_new = move(snake, direction)
+ [snake.last[0] + direction[0], snake.last[1] + direction[1]]
- obstacle_ahead?(snake_new, direction, dimensions)
+end
-end
+
+def outside_field?(coordinate, length)
+ coordinate < 0 or coordinate >= length
+end
+
+def free_positions(dimension_x, dimension_y, food, snake)
+ all_positions = (0...dimension_x).to_a.product((0...dimension_y).to_a)
+ all_positions - food - snake
+end

Десислава обнови решението на 19.10.2015 11:06 (преди над 9 години)

def move(snake, direction)
snake.drop(1) << new_head(snake, direction)
# snake[1..-1] << new_head(snake, direction)
end
def grow(snake, direction)
snake.dup << new_head(snake, direction)
end
def new_food(food, snake, dimensions)
- free_positions(*dimensions.values, food, snake).shuffle().first
+ free_positions(dimensions[:width],
+ dimensions[:height],
+ food,
+ snake).shuffle().first
end
def obstacle_ahead?(snake, direction, dimensions)
new_snake = move(snake, direction)
newly_head = new_snake.last
outside_x = outside_field?(newly_head[0], dimensions[:width])
outside_y = outside_field?(newly_head[1], dimensions[:height])
self_collision = new_snake.include? newly_head
outside_x or outside_y or self_collision
end
def danger?(snake, direction, dimensions)
return true if obstacle_ahead?(snake, direction, dimensions)
obstacle_ahead?(move(snake, direction), direction, dimensions)
end
def new_head(snake, direction)
[snake.last[0] + direction[0], snake.last[1] + direction[1]]
end
def outside_field?(coordinate, length)
coordinate < 0 or coordinate >= length
end
def free_positions(dimension_x, dimension_y, food, snake)
all_positions = (0...dimension_x).to_a.product((0...dimension_y).to_a)
all_positions - food - snake
end
+

Десислава обнови решението на 19.10.2015 15:49 (преди над 9 години)

def move(snake, direction)
snake.drop(1) << new_head(snake, direction)
# snake[1..-1] << new_head(snake, direction)
end
def grow(snake, direction)
snake.dup << new_head(snake, direction)
end
def new_food(food, snake, dimensions)
free_positions(dimensions[:width],
- dimensions[:height],
- food,
- snake).shuffle().first
+ dimensions[:height],
+ food,
+ snake).shuffle().first
end
def obstacle_ahead?(snake, direction, dimensions)
new_snake = move(snake, direction)
newly_head = new_snake.last
outside_x = outside_field?(newly_head[0], dimensions[:width])
outside_y = outside_field?(newly_head[1], dimensions[:height])
- self_collision = new_snake.include? newly_head
+ self_collision = new_snake[0...-1].include? newly_head
outside_x or outside_y or self_collision
end
def danger?(snake, direction, dimensions)
return true if obstacle_ahead?(snake, direction, dimensions)
obstacle_ahead?(move(snake, direction), direction, dimensions)
end
def new_head(snake, direction)
[snake.last[0] + direction[0], snake.last[1] + direction[1]]
end
def outside_field?(coordinate, length)
coordinate < 0 or coordinate >= length
end
def free_positions(dimension_x, dimension_y, food, snake)
all_positions = (0...dimension_x).to_a.product((0...dimension_y).to_a)
all_positions - food - snake
end