Class: SlidingPuzzle

Inherits:
Object
  • Object
show all
Defined in:
lib/sliding_puzzle/base.rb,
lib/sliding_puzzle/oracle.rb

Defined Under Namespace

Classes: BlankError, InvalidMoveError, NotRectangularError, Oracle

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*tiles) ⇒ SlidingPuzzle

Returns a new instance of SlidingPuzzle.



14
15
16
17
18
19
20
21
# File 'lib/sliding_puzzle/base.rb', line 14

def initialize(*tiles)
  self.tiles = flatten_tiles(tiles)
  self.max_row = @tiles.size - 1
  self.max_column = @tiles.first.size - 1

  must_be_rectangular!
  must_contain_one_blank!
end

Instance Attribute Details

#tilesObject



76
77
78
# File 'lib/sliding_puzzle/base.rb', line 76

def tiles
  JSON.parse(JSON.generate(@tiles))
end

Class Method Details

.oracle(goal_state) ⇒ Object



2
3
4
# File 'lib/sliding_puzzle/base.rb', line 2

def self.oracle(goal_state)
  Oracle.lookup(goal_state)
end

.precompute(goal_state, **options) ⇒ Object



6
7
8
# File 'lib/sliding_puzzle/base.rb', line 6

def self.precompute(goal_state, **options)
  Oracle.precompute(goal_state, **options)
end

.read(path) ⇒ Object



10
11
12
# File 'lib/sliding_puzzle/base.rb', line 10

def self.read(path)
  Oracle.read(path)
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



94
95
96
# File 'lib/sliding_puzzle/base.rb', line 94

def ==(other)
  tiles == other.tiles
end

#cloneObject



44
45
46
# File 'lib/sliding_puzzle/base.rb', line 44

def clone
  self.class.new(*tiles)
end

#find(number) ⇒ Object



84
85
86
87
88
89
90
91
92
# File 'lib/sliding_puzzle/base.rb', line 84

def find(number)
  tiles.each.with_index do |numbers, row|
    numbers.each.with_index do |n, column|
      return [row, column] if n == number
    end
  end

  nil
end

#get(row, column) ⇒ Object



80
81
82
# File 'lib/sliding_puzzle/base.rb', line 80

def get(row, column)
  @tiles[row][column]
end

#hashObject



100
101
102
# File 'lib/sliding_puzzle/base.rb', line 100

def hash
  tiles.hash
end

#movesObject



52
53
54
55
56
57
58
59
60
61
62
# File 'lib/sliding_puzzle/base.rb', line 52

def moves
  row, column = find(0)
  moves = []

  moves.push(:left) unless column == max_column
  moves.push(:right) unless column.zero?
  moves.push(:up) unless row == max_row
  moves.push(:down) unless row.zero?

  moves
end


48
49
50
# File 'lib/sliding_puzzle/base.rb', line 48

def print
  Kernel.print @tiles.map(&:inspect).join("\n")
end

#scramble(moves: 100) ⇒ Object



72
73
74
# File 'lib/sliding_puzzle/base.rb', line 72

def scramble(moves: 100)
  clone.scramble!(moves: moves)
end

#scramble!(moves: 100) ⇒ Object



64
65
66
67
68
69
70
# File 'lib/sliding_puzzle/base.rb', line 64

def scramble!(moves: 100)
  moves.times do
    slide!(self.moves.sample)
  end

  self
end

#slide(direction) ⇒ Object



40
41
42
# File 'lib/sliding_puzzle/base.rb', line 40

def slide(direction)
  clone.slide!(direction)
end

#slide!(direction) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/sliding_puzzle/base.rb', line 23

def slide!(direction)
  unless moves.include?(direction)
    raise InvalidMoveError, "unable to slide #{direction}"
  end

  x1, y1 = find(0)
  x2, y2 = x1, y1

  y2 += 1 if direction == :left
  y2 -= 1 if direction == :right
  x2 += 1 if direction == :up
  x2 -= 1 if direction == :down

  @tiles[x1][y1], @tiles[x2][y2] = @tiles[x2][y2], @tiles[x1][y1]
  self
end