Last active
December 16, 2015 15:39
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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