Translate

Minesweeper
Minesweeper in Crystal
class Minesweeper
  def initialize(@board : Array(String))
  end

  def annotate
    @board.map_with_index do |row, y|
      row.chars.map_with_index do |cell, x|
        cell.to_s.tr(" ", annotated_space(x, y))
      end.join
    end
  end

  private def annotated_space(x, y)
    ([y - 1, 0].max..[y + 1, @board.size - 1].min).sum do |y|
      ([x - 1, 0].max..[x + 1, @board[0].size - 1].min).count do |x|
        @board[y][x] == '*'
      end
    end.to_s.tr("0", " ")
  end
end

What makes this approach interesting is the use of the tr method, which allows us to have a concise solution that doesn't use conditionals. This approach starts with defining a initialize method that takes an Array(String) as an argument and assigns it to an instance variable @board. The annotate method starts with mapping over the @board array with the index y for each row. Then, it converts each row into an array of characters and maps over it with the index x for each cell. It converts each cell from a Char to a String and then uses the method tr.

The tr method allows you to replace a set of characters with another set of characters in a string. This is useful since it allows us to replace only the space character with the result of the annotated_space method.

The annotated_space method takes the x and y coordinates of the cell and calculates the number of mines around it. It then creates a range representing the area's height to check for mines. Since the index is 0, taking minus 1 would make the value -1, which would be valid in Crystal but would represent the last element. We don't want this behavior, so we use the max method to ensure that the value is at least 0. The same is done for the min value, but here we want to ensure that the value is, at most, the last index.

Then, we use the sum method to sum the total number of mines returned by the inner loop. The inner loop creates a range representing the area's width to check for mines. As before, we use the max and min methods to ensure that the values are within the board's bounds. Then, we use the count method to count how many times the inner condition is true, which indicates whether the cell is a mine or not.

Finally, we convert the sum to a string and use the tr method to replace all the zeros with spaces.

13th Nov 2024 · Found it useful?