-
Notifications
You must be signed in to change notification settings - Fork 0
/
board.rb
106 lines (89 loc) · 2.09 KB
/
board.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# frozen_string_literal: true
require_relative './square'
# creates boards
class Board
def initialize
@squares = build
end
def knight_moves(start, stop)
unless valid_input?(start) && valid_input?(stop)
puts 'enter valid coordinates'
return
end
result = bfs(start, stop)
move_count = result.pop
puts "Nice! You made it in #{move_count} moves \nHere's your path:"
result.each { |move| p move }
nil
end
private
def build
result = []
(0..7).to_a.repeated_permutation(2) do |perm|
square = Square.new(perm)
square.adjacents = add_adj(perm)
result << square
end
result
end
def bfs(start, stop)
reset_sqs
look_for(start).distance = 0
queue = [look_for(start)]
until queue.empty?
current = queue.shift
break if current.coordinate == stop
current.adjacents.each do |adj|
square = look_for(adj)
next unless square.distance.nil?
square.distance = current.distance + 1
square.predecessor = current
queue << square
end
end
trace(current)
end
def trace(stop)
arr = []
move_count = stop.distance
queue = [stop.coordinate]
until queue.empty?
current = look_for(queue.shift)
current.predecessor && queue << current.predecessor.coordinate
arr.unshift(current.coordinate)
end
arr << move_count
end
def add_adj(coor)
arr = []
[
[-2, -1], [+2, -1], [-2, +1], [+2, +1],
[-1, +2], [-1, -2], [+1, +2], [+1, -2]
].each do |move|
x = coor[0] + move[0]
y = coor[1] + move[1]
arr << [x, y]
end
validate_adj(arr)
end
def validate_adj(adj_list)
adj_list.select do |el|
el => [x, y]
x.between?(0, 7) && y.between?(0, 7)
end
end
def look_for(coor)
@squares.find { |sq| sq.coordinate == coor }
end
def reset_sqs
@squares.each do |sq|
sq.predecessor = nil
sq.distance = nil
end
end
def valid_input?(cood)
return unless cood.is_a?(Array)
cood => [x, y]
x.between?(0, 7) && y.between?(0, 7)
end
end