Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a battleship game in ruby

Tags:

ruby

I'm leaning coding Ruby and trying to make a battleship game. Now I have some difficulties (found a lot of implementations at Github, but could not understand them).

I have a 10*10 board and now I'm trying to implement the algorithm of walking on the field. For example: I'm in x-position on the field, how to check the availability of A1 cell? So here is a variant... but how to make a universal method? (when I choose a position, I need to check 8 cells around for free space for the next cell).

def test(postition)
letter = position[0]

#   1 2 3
# A O . .
# B x . .
# C . . .

keys = board.keys
index = keys.find_index(letter)
prev_key = keys[index - 1] #up-down
unless prev_key.nil?
    is_ship_placed = board[prev_key][postition[1]] #left-right
end

#   1 2 3
# A O . .
# B . . .
# C . . .

end

All my code for now is in ideone.com

I will be very grateful if someone will help me!

P.S. Excuse my english, pls.

like image 752
k1r8r0wn Avatar asked Jul 05 '26 10:07

k1r8r0wn


1 Answers

I have expanded @JustinWood's great advice into this answer. You will find it easier to represent your board as an Array instead of a Hash.

So change

board = { a: [false, false, false, false, false, false, false, false, false, false], \
          b: [false, false, false, false, false, false, false, false, false, false], etc.

to something like this two-dimensional Array. (A list of lists.)

board = [[false, false, false, false, false, false, false, false, false, false],
         [false, false, false, false, false, false, false, false, false, false],
                                     ..........                               ]]

Naturally you can populate it automatically instead of copy-pasting 10 rows of false into your source code. This works:

blank_row = Array.new(10,false)
board = Array.new(10) { blank_row.clone }

Then you can navigate around the board with arithmetic, to check the 8 surrounding squares. You would do something like this:

def test (position)
  x, y = position 
  return true if board[y][x]
  return true if board[y-1][x-1]
  return true if board[y-1][x]
  ....
  false
end

Add in suitable guards to deal with the edges, and automate it instead of typing out all 9 cases.

As you noticed, when you changed the Hash to an Array, it means you have to change other parts of your game that use the board. For example, you already know how to iterate through your Hash (for example to change it)

board.each do |key, row|
  row.each do |v|
    # do something with cell v and build a new row
  end
  # insert the new row at board[key] 
end

You can iterate a 2D Array like this example

board.each.with_index do |row, y|
  row.each.with_index do |v, x|
    # change a true cell to 'S' and false to '.'
    if v
      board[y][x] = 'S'
    else
      board[y][x] = '.'
    end
  end
end
like image 131
dcorking Avatar answered Jul 07 '26 09:07

dcorking