# How to detect vertical and horizontal lines in a 2d Array?

I’ve been fiddling around with a little Sratch Ticket game but not entirely sure how to detect lines.
Crystal Playground

The part where I’m stuck at is in the `check_winners` method. I am not sure how to detect if a horizontal or vertical line is matched. For example:

``````         2   5  8  10
Prize 10 [0, 0, 1, 0]
Prize 20 [1, 1, 1, 1]
Prize 45 [1, 0, 1, 1]
Prize 50 [0, 0, 1, 0]
``````

Prize 20 and 8 would be the winners.

``````class Board
property rows = 4
property columns = 4
property board = Array(Array(Int32)).new
property prizes = {10, 20, 45, 50, 70, 90}
property prizes_top = {2, 5, 8, 10}

def initialize()
@board = create_matrix(rows, columns)

print_board
check_winners
end

def check_winners
puts "Winners:"

board.each_with_index do |c, column_i|
c.each_with_index do |r, row_i|
value = c[r]
if value == 1 # we matched something on the board!
# However.. not sure how to keep track of the values here to detect
# If a player has matched 1 all vertically or horizontally?
end
end
end
end

def print_board
puts "         #{prizes_top[0]}   #{prizes_top[1]}  #{prizes_top[2]}  #{prizes_top[3]}"

board.each_with_index do |c, i|
puts "Prize #{prizes[i]} #{c}"
end
puts "----------------------------------"
end

def create_matrix(rows, columns)
array = Array(Array(Int32)).new
columns.times do |i|
array << fill_array(rows)
end
array
end

def fill_array(a)
temp = Array(Int32).new
a.times do
temp << rand(0..1)
end
temp
end
end

Board.new
``````
``````    win_first_column = true
columns.times do |c_i|
win_first_column = false if board[c_i][0] == 0 # first column
end

puts win_first_column
``````

This only checks the first vertical column. I think I’m getting closer?

Here’s how I would do that: https://carc.in/#/r/6khk

``````require "spec"
require "bit_array"

struct Grid
Size = 4
property board : StaticArray(BitArray, Size)

def initialize(@board); end

def column_is_all_true?(column_number)
raise "board doesn't have that column" if column_number >= Size
board.all? { |row| row[column_number] } # (if the all rows is true at the given column number)
end

def row_is_all_true?(row_number)
raise "board doesn't have that row" if row_number >= Size
board[row_number].all? { |column| column } # if every column in this row is true
end
end

falsey_row = BitArray.new 4
falsey_row.toggle 1
truthy_row = BitArray.new 4, initial: true
grid = Grid.new StaticArray[
falsey_row,
truthy_row,
falsey_row,
falsey_row
]

describe Grid do
it "finds the all-true column" do
grid.column_is_all_true?(1).should be_true
end
it "rejects a column that is not all true" do
grid.column_is_all_true?(0).should be_false
end
it "finds the all-true row" do
grid.row_is_all_true?(1).should be_true
end
it "rejects a row that is not all true" do
grid.row_is_all_true?(2).should be_false
end
end
``````

Thanks for the fun challenge this morning

Edit: note that if the `Size` value isn’t a compile-time constant you need to use `Array` not `StaticArray` and if the values are larger than base two then obviously each row would be a `StaticArray` or `Array` of a type large enough to hold the data.

1 Like

@scott

Just curious, where is the

``````Finished in 155 microseconds
4 examples, 0 failures, 0 errors, 0 pending
``````

Text coming from?

edit: Oh, nvm, comes from require “spec”, just commented it out and it’s gone.

I will have to read more about Static and BitArray’s. Are they more performant than regular Arrays that use Int32 values? Instead of Int32 value types, they are “bits”? If I got that right.

https://crystal-lang.org/api/0.27.2/StaticArray.html
“fixed-size”, I guess that means immutable. So this wouldn’t really be used for an inventory matrix, where player’s can move items around, but for a board game with a fixed set of values to check rows and columns with… would be fine.

I think I am understanding it better

@girng sorry I didn’t see this sooner

StaticArray is an Array whose size is known at compile time (that is, it’s a constant value). It is much more efficient to know the size at compile time than to have to check or store that information as a variable. Just because the size is of a fixed/static value doesn’t mean that the values in the array are immutable.

A BitArray is an array of boolean values. Because computers can only index one byte at a time, a `Bool` type actually takes up a byte of space despite only representing a bit of data. If you are storing a list of `true` and `false` values, you should prefer `BitArray` over `Array(Bool)` or even `StaticArray(Bool, Size)` due to performance.

That said, if their use is appropriate, using a BitArray or StaticArray will be roughly equivalent to using an `Array(Bool)` or an array whose size is known at compile-time, respectively.

As far as the output, yes, I used specs to “describe” the way my code behaved, sorry if that wasn’t clear.

1 Like

So for your board game example, if you have a board of a size that is known at compile time, then you could use a `StaticArray`. If you wanted to give the user a setting or command-line argument where they could adjust the size of the board, you’d want to use an `Array`.

But in general, always use an Array unless you have a serious bottleneck or something. You’ll make your program much more complex if you don’t use Array. In 99.9% of programs you don’t need to know or care about static array or bit array.

1 Like

I see. Very cool. I actually always thought the lowest value we could go for an Array is 1_i8.

In fact, the scratch ticket I am inspired by is the Loteria Ticket here:

So, I would need to use something higher than a BitArray for this case, because there are going to be different items to match on the board. I should have mentioned that in my OP, my apologies! But then again, now I know about Static and BitArray’s, TIL!

Thanks!