Last active
December 13, 2015 23:39
-
-
Save Dawenster/4993396 to your computer and use it in GitHub Desktop.
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
class AI | |
attr_reader :already_guessed | |
def initialize | |
@already_guessed = [] | |
@coordinates = {} | |
end | |
def choose_coordinates | |
@coordinates = {} | |
col = rand(COL_RANGE) | |
row = ROW_RANGE.to_a.sample | |
@coordinates = {row: row, column: col} | |
if already_guessed.include?(@coordinates) | |
choose_coordinates | |
else | |
already_guessed << @coordinates | |
@coordinates | |
end | |
end | |
end |
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
COL_RANGE = 1..10 | |
ROW_RANGE = "A".."J" | |
SHIPS = [1,2,3,4,5] | |
DIRECTIONS = [:row, :column] | |
class Board | |
attr_reader :playing_field, :ships_sunk | |
def initialize | |
set_blank_board | |
@ships_sunk = [] | |
end | |
def playing_field_values | |
playing_field.values.flatten | |
end | |
def set_blank_board | |
@playing_field = {} | |
letter = 'A' | |
ROW_RANGE.to_a.each do |row_letter| | |
@playing_field[row_letter] = Array.new(10) { "." } | |
@playing_field[row_letter].unshift(letter) | |
letter = letter.succ | |
end | |
@playing_field | |
end | |
def place_all_the_ships | |
begin | |
SHIPS.each do |ship_value| | |
place_ship(ship_value) | |
end | |
rescue CannotBeDrawn | |
set_blank_board | |
place_all_the_ships | |
end | |
end | |
def place_ship(ship_value) | |
spot = random_starting_point | |
ship_direction = DIRECTIONS.sample | |
increment_direction = DIRECTIONS.find {|d| d != ship_direction} | |
increment_value = spot[increment_direction] | |
ship_value.times do | |
coordinates = { | |
ship_direction => spot[ship_direction], | |
increment_direction => increment_value | |
} | |
draw(coordinates, ship_value) | |
increment_value = increment_value.succ | |
end | |
end | |
def draw(coordinates, value) | |
row = coordinates[:row] | |
column = coordinates[:column] | |
row_values = playing_field[row] # sometimes this will be K, L, M... (if it goes off the map on a column boat) | |
raise CannotBeDrawn unless row_values | |
coordinate_value = row_values[column - 1] | |
raise CannotBeDrawn unless coordinate_value == '.' | |
playing_field[coordinates[:row]][coordinates[:column] - 1] = value | |
end | |
def draw_attack(coordinates, interface, boards, board) | |
if playing_field[coordinates[:row]][coordinates[:column]] == '.' | |
playing_field[coordinates[:row]][coordinates[:column]] = 'O' | |
interface.miss(boards, board, coordinates) | |
else | |
playing_field[coordinates[:row]][coordinates[:column]] = 'X' | |
interface.hit(boards, board, coordinates) | |
end | |
end | |
def random_starting_point | |
col = rand(COL_RANGE) | |
row = ROW_RANGE.to_a.sample | |
{row: row, column: col} | |
end | |
def check_sunk_ship(interface, boards, board) | |
current_player = '' | |
boards[0] == board ? current_player = 'Your' : current_player = "AI\'s" | |
SHIPS.each do |ship| | |
unless playing_field_values.include?(ship) | |
ships_sunk << ship | |
interface.sunk_ship(ship, current_player) if ships_sunk.count(ship) == 1 | |
end | |
end | |
end | |
def all_sunk?(board) | |
board.ships_sunk.uniq.length == 5 | |
end | |
end |
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
class Game | |
attr_reader :interface, :ai, :user, :players, :boards | |
attr_accessor :user_board, :ai_board | |
def initialize(user_board, ai_board) | |
@interface = Interface.new | |
@ai = AI.new | |
@user = User.new | |
@players = [user, ai] | |
@user_board = user_board | |
@ai_board = ai_board | |
@boards = [user_board, ai_board] | |
@user_attack_coords = {} | |
@ai_attack_coords = {} | |
end | |
def run | |
user_board.place_all_the_ships | |
ai_board.place_all_the_ships | |
interface.display_boards(boards) | |
until all_ships_sunk? | |
take_turns | |
draw_attacks | |
interface.display_boards(boards) | |
check_sunk_ships? | |
end | |
end | |
def take_turns | |
players.each do |player| | |
if player == user | |
@user_attack_coords = attack(player) | |
else | |
@ai_attack_coords = attack(player) | |
end | |
end | |
end | |
def attack(player) | |
if player == user | |
user.choose_coordinates(interface) | |
else | |
ai.choose_coordinates | |
end | |
end | |
def draw_attacks | |
boards.each do |board| | |
if board == user_board | |
boards.find {|b| b != board }.draw_attack(@user_attack_coords, interface, boards, board) | |
else | |
boards.find {|b| b != board }.draw_attack(@ai_attack_coords, interface, boards, board) | |
end | |
end | |
end | |
def check_sunk_ships? | |
boards.each do |board| | |
board.check_sunk_ship(interface, boards, board) | |
end | |
end | |
def all_ships_sunk? | |
boards.each do |board| | |
if board.all_sunk?(board) | |
interface.game_over(boards, board) | |
exit | |
end | |
end | |
false | |
end | |
end |
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
class User | |
attr_reader :already_guessed | |
def initialize | |
@already_guessed = [] | |
@coordinates = {} | |
end | |
def choose_coordinates(interface) | |
@coordinates = {} | |
interface.enter_letter | |
letter_entry = gets.chomp.upcase | |
until letter_legit?(letter_entry, interface) | |
interface.enter_letter | |
letter_entry = gets.chomp.upcase | |
end | |
interface.enter_number | |
number_entry = gets.chomp.to_i | |
until number_legit?(number_entry, interface) | |
interface.enter_number | |
number_entry = gets.chomp.to_i | |
end | |
@coordinates = {row: letter_entry, column: number_entry} | |
duplicate_check(interface) | |
end | |
def letter_legit?(letter_entry, interface) | |
if !!(letter_entry =~ /^[a-jA-J]$/) | |
true | |
else | |
interface.wrong_letter | |
false | |
end | |
end | |
def number_legit?(number_entry, interface) | |
if number_entry <= 10 && number_entry >= 1 | |
true | |
else | |
interface.wrong_number | |
false | |
end | |
end | |
def duplicate_check(interface) | |
if already_guessed.include?(@coordinates) | |
interface.guess_again | |
choose_coordinates(interface) | |
else | |
already_guessed << @coordinates | |
@coordinates | |
end | |
end | |
end |
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
require_relative 'controller - board' | |
require_relative 'controller - game' | |
require_relative 'controller - user' | |
require_relative 'controller - ai' | |
require_relative 'view' | |
class CannotBeDrawn < StandardError | |
end | |
user_board = Board.new | |
ai_board = Board.new | |
game = Game.new(user_board, ai_board) | |
game.run |
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
class Interface | |
ASTERIX_DIVIDER = '*' * 22 | |
def display_boards(boards) | |
clear_screen | |
move_to_home | |
boards.each do |board| | |
puts ASTERIX_DIVIDER | |
puts board == boards[0] ? ' Your board' : " AI\'s board" | |
puts ASTERIX_DIVIDER | |
puts ' 1 2 3 4 5 6 7 8 9 10' | |
board.playing_field.each do |k, v| | |
if board == boards[0] | |
puts v.join(' ') | |
else | |
hide_nums = [] | |
v.each do |e| | |
if e.class == Fixnum | |
hide_nums << '.' | |
else | |
hide_nums << e | |
end | |
end | |
puts hide_nums.join(' ') | |
end | |
end | |
puts '' | |
puts board == boards[0] ? 'Your remaining ships' : "AI\'s remaining ships" | |
p board.playing_field_values.select { |v| v.is_a?(Integer) }.uniq.sort | |
puts '' | |
letter = 'A' | |
end | |
end | |
def clear_screen | |
print "\e[2J" | |
end | |
def move_to_home | |
print "\e[H" | |
end | |
def enter_letter | |
puts 'Enter a letter:' | |
end | |
def enter_number | |
puts 'Enter a number:' | |
end | |
def guess_again | |
puts 'You have already guessed that - try again!' | |
end | |
def wrong_letter | |
puts "Please only put in one valid letter." | |
end | |
def wrong_number | |
puts "Please only put in one valid number between 1-10." | |
end | |
def miss(boards, board, coordinates) | |
pronoun = '' | |
boards[0] == board ? pronoun = 'You have' : pronoun = 'AI has' | |
puts "#{pronoun} missed at #{coordinates[:row]}#{coordinates[:column]}..." | |
sleep(1.0) | |
end | |
def hit(boards, board, coordinates) | |
pronoun = '' | |
boards[0] == board ? pronoun = 'You have hit AI' : pronoun = 'AI has hit you' | |
puts "#{pronoun} at #{coordinates[:row]}#{coordinates[:column]}!" | |
sleep(1.0) | |
end | |
def sunk_ship(ship, current_player) | |
puts "#{current_player} ship #{ship} has been sunk!" | |
end | |
def game_over(boards, board) | |
winning_message = '' | |
board == boards[0] ? winning_message = 'AI wins!' : winning_message = 'You win!' | |
puts "Game over! #{winning_message}" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment