class ConnectNGame::Rack
The class of game racks. That is a matrix of cells
Attributes
The names of the channels
The depth of the playable area.
The number in a row needed for victory.
The raw playable area.
The column weight values.
The width of the playable area.
Public Class Methods
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
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
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
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 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
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 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 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 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
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
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
Is this a valid channel?
# File lib/connect_n_game/game/rack.rb, line 159 def valid_channel?(channel) (1..width).include?(channel) end
Is this a valid row?
# File lib/connect_n_game/game/rack.rb, line 164 def valid_row?(row) (1..depth).include?(row) end