class ConnectNGame::Rack

The class of game racks. That is a matrix of cells

Attributes

channel_names[R]

The names of the channels

depth[R]

The depth of the playable area.

order[R]

The number in a row needed for victory.

rack[R]

The raw playable area.

weights[R]

The column weight values.

width[R]

The width of the playable area.

Public Class Methods

new(order) click to toggle source

Create a rack of the appropriate order.
Parameters

  • order - The order of the game, that is the winning number of pieces in a row.

# File lib/connect_n_game/game/rack.rb, line 30
def initialize(order)
  unless (4..8).include?(order)
    fail "Invalid game dimension #{order} not (4 .. 8)"
  end

  @order = order
  @depth = @order + (order >> 1)
  @width = @depth + (@depth.odd? ? 2 : 1)

  @weights = [0.5]
  weight = 4

  (@width/2).times do
    @weights << 1.0/weight
    weight *= 2
    @weights.insert(0, 1.0/weight)
    weight *= 2
  end

  @channel_names = %w(A B C D E F G H I J K L M).first(width)

  @rack = Array.new(@width) { [ ] }
end

Public Instance Methods

channel_full?(channel) click to toggle source

Is the selected channel full?
Parameters

  • channel - The channel number 1 .. width


Returns

  • true if full else false.

# File lib/connect_n_game/game/rack.rb, line 68
def channel_full?(channel)
  get_channel(channel).length >= depth
end
channel_to_row(channel) click to toggle source

Get the free row for the specified channel.
Parameters

  • channel - The channel number 1 .. width


Returns

  • The row number or nil.

# File lib/connect_n_game/game/rack.rb, line 154
def channel_to_row(channel)
  channel_full?(channel) ? nil : rack[channel-1].length + 1
end
cli_display() click to toggle source

Display the rack via a command line interface.

# File lib/cli/cli_rack.rb, line 12
def cli_display
  #Show the title line.
  puts " " + channel_names.join(" ")

  #Show the body
  (1..depth).reverse_each do |row|
    (1..width).each do |channel|
      print "|#{CLI_MAP[get_cell(channel,row)]}"
    end

    puts "|"
  end
end
count_pieces(channel, row, dx, dy, piece) click to toggle source

Count the pieces along the designated path.
Parameters

  • channel - The starting channel

  • row - The starting row

  • dx - The channel step value

  • dy - The row step value

  • piece - The piece we are looking for.


Returns

  • The score for that play 0 .. n

# File lib/connect_n_game/game/rack.rb, line 135
def count_pieces(channel, row, dx, dy, piece)
  result = 0

  while result < width
    channel, row = channel+dx, row+dy

    return result unless piece == get_cell(channel, row)

    result += 1
  end

  fail "Looping error"
end
deep_clone() click to toggle source

Clone the internal array.

# File lib/connect_n_game/game/rack.rb, line 169
def deep_clone
  @rack = @rack.clone

  (0...@width).each do |index|
    @rack[index] = @rack[index].clone
  end

  self
end
get_cell(channel, row) click to toggle source

Get the specified cell.
Parameters

  • channel - The channel number 1 .. width

  • row - The row number 1 .. depth


Returns

  • The contents of the cell or nil

# File lib/connect_n_game/game/rack.rb, line 89
def get_cell(channel, row)
  return nil unless valid_channel?(channel)
  return nil unless valid_row?(row)

  rack[channel-1][row-1]
end
get_channel(channel) click to toggle source

Get the required play channel
Parameters

  • channel - The channel number 1 .. width


Returns

  • The requested channel (array) or nil for invalid channels.

# File lib/connect_n_game/game/rack.rb, line 59
def get_channel(channel)
  rack[channel-1]
end
play_channel(channel, piece) click to toggle source

Play a specified channel.
Parameters

  • channel - The channel number 1 .. width

  • piece - The piece to be played.


Returns

  • The score of the move or raises GameInvalidMove exception.

# File lib/connect_n_game/game/rack.rb, line 102
def play_channel(channel, piece)
  score = score_move(channel, piece)
  rack[channel-1] << piece if score > 0
  score
end
rack_full?() click to toggle source

Is the rack full?
Returns

  • true if full (or invalid) else false.

# File lib/connect_n_game/game/rack.rb, line 75
def rack_full?
  rack.each do |channel|
    return false if channel.length < depth
  end

  true
end
score_move(channel, piece) click to toggle source

Determine the score obtained for moving to a specified channel
Parameters

  • channel - The channel number 1 .. width

  • piece - The piece to be played.


Returns

  • The score for that play 0 .. n

# File lib/connect_n_game/game/rack.rb, line 114
def score_move(channel, piece)
  return -9 if channel_full?(channel)

  row = channel_to_row(channel)

  ([[0,1], [1,1], [1,0], [1,-1]].map do |delta|
    dx, dy = delta
    count_pieces(channel, row,  dx,  dy, piece) + 1 +
    count_pieces(channel, row, -dx, -dy, piece)
  end).max
end
valid_channel?(channel) click to toggle source

Is this a valid channel?

# File lib/connect_n_game/game/rack.rb, line 159
def valid_channel?(channel)
  (1..width).include?(channel)
end
valid_row?(row) click to toggle source

Is this a valid row?

# File lib/connect_n_game/game/rack.rb, line 164
def valid_row?(row)
  (1..depth).include?(row)
end