Skip to content

Instantly share code, notes, and snippets.

@labe
Last active December 16, 2015 15:39
Show Gist options
  • Save labe/5457632 to your computer and use it in GitHub Desktop.
Save labe/5457632 to your computer and use it in GitHub Desktop.
Battleship!: The Console Game (as best conceived by someone who has never played a game of Battleship in real life and who never saw the movie, but who HAS actually BEEN on battleships, albeit retired ones)
# only 5 ships are placed
# Board is printed with headers and is formatted for spacing
# ability to manually place ships horizontally
# ability to manually choose coordinates for salvos
# ability to dictate player types (human vs human, human vs computer, computer vs computer)
# only show players' boards at end of game
# if player is human, show opponent's board with previous attack attempts marked // DONE
# update the board to show attempted tiles // DONE
# translate letters to values ("A1" should -> (0,0)) // DONE
# if either player is a human, enter key must be pressed between turns (makes gameplay easier to follow) // DONE
# ability to place (manually and automatically) ships vertically // BAM, DONE
# v2 (current) stores previous computer coordinate choices in an array to prevent players (human or computer) from repeating previous attack attempts.
# future features:
#
# -new method of counting ships needed to allow for multiples of same ship kind to be placed and accounted for...
COORD_EQUIVALENTS = {"A" => 1, "B" => 2, "C" => 3, "D" => 4, "E" => 5,
"F" => 6, "G" => 7, "H" => 8, "I" => 9, "J" => 10 }
class Battleship
def initialize(name)
@name = name
@attacks = 0
@x_coord = nil
@y_coord = nil
@layout_with_headers = []
@line = "---" * 12
@attempted_attack_coords = []
@ships = []
end
def establish_user_type
@user_type = ""
until @user_type == "human" || @user_type == "computer"
puts "#{@name} player: Are you a HUMAN or a COMPUTER?"
@user_type = gets.chomp.downcase
puts
end
end
def identify_user_name
@name
end
def identify_user_type
@user_type
end
def identify_opponent(opponent_type, opponent_name)
@opponent_type = opponent_type
@opponent_name = opponent_name
end
def define_board
@layout = [
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
]
@attack_attempts = [
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
["/","/","/","/","/","/","/","/","/","/"],
]
end
def show_board
puts @name + "\'s board:"
@row_header = "A"
@col_header = [" ","1","2","3","4","5","6","7","8","9","10"]
@col_header.each { |tile| print tile.center(2) }
puts
@layout.each do |row|
print @row_header + " "
@row_header = @row_header.next
row.each do |tile|
print tile.center(2)
end
puts
end
puts "Ships on #{@name}'s board: #{@ships.count}"
puts
end
def show_attack_attempts
puts "Your previous attack attempts on #{@name}:"
@row_header = "A"
@col_header = [" ","1","2","3","4","5","6","7","8","9","10"]
@col_header.each { |tile| print tile.center(2) }
puts
@attack_attempts.each do |row|
print @row_header + " "
@row_header = @row_header.next
row.each do |tile|
print tile.center(2)
end
puts
end
end
def format_x_coord(coord)
@x_coord = coord.split(//)
@x_coord.delete_at(0)
@x_coord.join.to_i
end
def format_y_coord(coord)
@y_coord = COORD_EQUIVALENTS[coord.split(//).delete_at(0)]
@y_coord.to_i
end
def choose_setup_coords
if @user_type == "computer"
@x_coord = rand(10)
@y_coord = rand(10)
elsif @user_type == "human"
show_board
puts "Please select the starting coordinate"
print "for your ship placement (e.g., A1): "
formatted_coords = gets.chomp.upcase
puts
@x_coord = format_x_coord(formatted_coords)
@y_coord = format_y_coord(formatted_coords)
if (@x_coord < 1 || @x_coord > 10) || (@y_coord < 1 || @y_coord > 10)
puts "Those coordinates are not valid."
puts "Please try again."
puts
choose_setup_coords
else
@x_coord -= 1
@y_coord -= 1
end
end
end
def choose_attack_coords
if @opponent_type == "computer"
@x_coord = rand(10)
@y_coord = rand(10)
if @attempted_attack_coords.include?([@x_coord,@y_coord])
choose_attack_coords
else
@attempted_attack_coords << [@x_coord, @y_coord]
puts "#{@opponent_name} has chosen to attack (#{@x_coord},#{@y_coord})"
end
elsif @opponent_type == "human"
show_attack_attempts
print "Which tile would you like to attack? (e.g. A1): "
formatted_coords = gets.chomp.upcase
@x_coord = format_x_coord(formatted_coords)
@y_coord = format_y_coord(formatted_coords)
if @x_coord < 1 || @x_coord > 10 || @y_coord < 1 || @y_coord > 10
puts "Those coordinates are not valid."
puts "Please try again."
puts
choose_attack_coords
elsif @attempted_attack_coords.include?([@x_coord, @y_coord])
puts
puts "You have already attacked #{formatted_coords}."
puts "Please choose a different tile."
puts
choose_attack_coords
else
@attempted_attack_coords << [@x_coord, @y_coord]
@x_coord -= 1
@y_coord -= 1
puts
end
end
end
def placement_error
if @user_type == "human"
puts "** Your ship can't fit there. ** "
puts "** Please try again. **"
puts
end
end
def choose_orientation
if @user_type == "computer"
@ship_orientation = rand(2)
@ship_orientation = "H" if @ship_orientation == 0
@ship_orientation = "V" if @ship_orientation == 1
elsif @user_type == "human"
puts "Choose your ship's direction"
print "(H for horizontal, V for vertical): "
@ship_orientation = gets.chomp.upcase
puts
if @ship_orientation == "H" || @ship_orientation == "V"
return @ship_orientation
else
puts "** You did not enter a valid choice. **"
puts
choose_orientation
end
end
end
def place_submarine
puts "Place your submarine (size: 1)" if @user_type == "human"
choose_setup_coords
if @layout[@y_coord][@x_coord] == "/"
@layout[@y_coord][@x_coord] = "s"
else
placement_error
place_submarine
end
end
def place_destroyer
puts "Place your destroyer (size: 2)" if @user_type == "human"
choose_setup_coords
choose_orientation
if @ship_orientation == "H"
if @x_coord < 9 && @layout[@y_coord][@x_coord] == "/" && @layout[@y_coord][@x_coord+1] == "/"
@layout[@y_coord][@x_coord] = "d"
@layout[@y_coord][@x_coord+1] = "d"
puts
else
placement_error
place_destroyer
end
elsif @ship_orientation == "V"
if @y_coord < 9 && @layout[@y_coord][@x_coord] == "/" && @layout[@y_coord+1][@x_coord] == "/"
@layout[@y_coord][@x_coord] = "d"
@layout[@y_coord+1][@x_coord] = "d"
puts
else
placement_error
place_destroyer
end
end
end
def place_cruiser
puts "Place your cruiser (size: 3)" if @user_type == "human"
choose_setup_coords
choose_orientation
if @ship_orientation == "H"
if @x_coord < 8 && @layout[@y_coord][@x_coord] == "/" && @layout[@y_coord][@x_coord+1] == "/" && @layout[@y_coord][@x_coord+2] == "/"
@layout[@y_coord][@x_coord] = "c"
@layout[@y_coord][@x_coord+1] = "c"
@layout[@y_coord][@x_coord+2] = "c"
puts
else
placement_error
place_cruiser
end
elsif @ship_orientation == "V"
if @y_coord < 8 && @layout[@y_coord][@x_coord] == "/" && @layout[@y_coord+1][@x_coord] == "/" && @layout[@y_coord+2][@x_coord] == "/"
@layout[@y_coord][@x_coord] = "c"
@layout[@y_coord+1][@x_coord] = "c"
@layout[@y_coord+2][@x_coord] = "c"
puts
else
placement_error
place_cruiser
end
end
end
def place_battleship
puts "Place your battleship (size: 4)" if @user_type == "human"
choose_setup_coords
choose_orientation
if @ship_orientation == "H"
if @x_coord < 7 && @layout[@y_coord][@x_coord] == "/" && @layout[@y_coord][@x_coord+1] == "/" && @layout[@y_coord][@x_coord+2] == "/" && @layout[@y_coord][@x_coord+3] == "/"
@layout[@y_coord][@x_coord] = "b"
@layout[@y_coord][@x_coord+1] = "b"
@layout[@y_coord][@x_coord+2] = "b"
@layout[@y_coord][@x_coord+3] = "b"
else
placement_error
place_battleship
end
elsif @ship_orientation == "V"
if @y_coord < 7 && @layout[@y_coord][@x_coord] == "/" && @layout[@y_coord+1][@x_coord] == "/" && @layout[@y_coord+2][@x_coord] == "/" && @layout[@y_coord+3][@x_coord] == "/"
@layout[@y_coord][@x_coord] = "b"
@layout[@y_coord+1][@x_coord] = "b"
@layout[@y_coord+2][@x_coord] = "b"
@layout[@y_coord+3][@x_coord] = "b"
else
placement_error
place_battleship
end
end
end
def place_aircraft
puts "Place your aircraft (size: 5)" if @user_type == "human"
choose_setup_coords
choose_orientation
if @ship_orientation == "H"
if @x_coord < 6 && @layout[@y_coord][@x_coord] == "/" && @layout[@y_coord][@x_coord+1] == "/" && @layout[@y_coord][@x_coord+2] == "/" && @layout[@y_coord][@x_coord+3] == "/" && @layout[@y_coord][@x_coord+4] == "/"
@layout[@y_coord][@x_coord] = "a"
@layout[@y_coord][@x_coord+1] = "a"
@layout[@y_coord][@x_coord+2] = "a"
@layout[@y_coord][@x_coord+3] = "a"
@layout[@y_coord][@x_coord+4] = "a"
else
placement_error
place_aircraft
end
elsif @ship_orientation == "V"
if @y_coord < 6 && @layout[@y_coord][@x_coord] == "/" && @layout[@y_coord+1][@x_coord] == "/" && @layout[@y_coord+2][@x_coord] == "/" && @layout[@y_coord+3][@x_coord] == "/" && @layout[@y_coord+4][@x_coord] == "/"
@layout[@y_coord][@x_coord] = "a"
@layout[@y_coord+1][@x_coord] = "a"
@layout[@y_coord+2][@x_coord] = "a"
@layout[@y_coord+3][@x_coord] = "a"
@layout[@y_coord+4][@x_coord] = "a"
else
placement_error
place_aircraft
end
end
end
def place_all_ships
place_aircraft
count_ships if @user_type == "human"
place_battleship
count_ships if @user_type == "human"
place_cruiser
count_ships if @user_type == "human"
place_destroyer
count_ships if @user_type == "human"
# place_destroyer
# count_ships if @user_type == "human"
# place_submarine
# count_ships if @user_type == "human"
place_submarine
count_ships if @user_type == "human"
end
def count_ships
@ships = []
for x in @layout
for y in x
if y != "/" && @ships.include?(y) != true && y != "x"
@ships << y
end
end
end
return @ships.count
end
def setup
establish_user_type
define_board
place_all_ships
count_ships
show_board if @user_type == "human"
end
def under_attack
@starting_num_of_ships = count_ships
puts @line
puts "It is #{@opponent_name}'s turn."
puts
@ships.count.times {
choose_attack_coords
if @layout[@y_coord][@x_coord] == "/"
@attack_attempts[@y_coord][@x_coord] = "M"
puts "#{@opponent_name} misses!"
else
@layout[@y_coord][@x_coord] = "x"
@attack_attempts[@y_coord][@x_coord] = "x"
puts "Battleship hit!"
puts
end
@attacks += 1
}
@ending_num_of_ships = count_ships
puts "#{@name} has lost a ship!" if @starting_num_of_ships > @ending_num_of_ships
puts "Ships on #{@name}'s board: #{@ships.count}"
# puts
# puts @name + "\'s board:"
# show_board
if @user_type == "human" || @opponent_type == "human"
puts @line
print "Press any key to continue: "
gets
end
end
def show_attack_count
@attacks
end
end
Home = Battleship.new("HOME")
Enemy = Battleship.new("ENEMY")
def play_game
Home.setup
Enemy.setup
Home.identify_opponent(Enemy.identify_user_type, Enemy.identify_user_name)
Enemy.identify_opponent(Home.identify_user_type, Home.identify_user_name)
while Home.count_ships > 0
Enemy.under_attack
if Enemy.count_ships == 0
puts
puts "HOME WINS after #{Home.show_attack_count} salvos!"
break
else
Home.under_attack
puts
puts "ENEMY WINS after #{Enemy.show_attack_count} salvos!" if Home.count_ships == 0
end
end
puts
Home.show_board
puts
Enemy.show_board
end
play_game
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment