Skip to content

Instantly share code, notes, and snippets.

@WhereIsX
Last active August 6, 2019 19:29
Show Gist options
  • Save WhereIsX/96ae80ffd4679619ffb5803186a442f0 to your computer and use it in GitHub Desktop.
Save WhereIsX/96ae80ffd4679619ffb5803186a442f0 to your computer and use it in GitHub Desktop.
Yana's OO TicTacToe: first attempt, a bit wet in some places, but in working order.
class Game_Master
attr_accessor :player1, :player2, :board, :winner, :whose_turn
def initialize
@player1 = nil
@player2 = nil
@board = Board.new(3,3)
@winner = nil
@whose_turn = nil
end
def start_game
self.prompt_start
self.prompt_new_players
until @winner
self.play_game
end
@board.display
puts "Congrats #{winner.name}! You won!"
end
def prompt_start
puts "Welcome to Yana's Tic Tac Toe!"
# TODO: add sleep for dramatic effect
end
def prompt_new_players
# TODO: players can choose own tokens, validate tokens, whos first
puts "Now who wants to be 'X'?"
player1_name = gets.strip
puts "is X a computer?"
is_computer = gets.strip
if is_computer == "true"
@player1 = Player.new(name: player1_name, token: 'X', is_computer: true)
else
@player1 = Player.new(name: player1_name, token: 'X')
end
p @player1.is_computer
puts "And who's stuck with 'O'?"
@player2 = Player.new(name: gets.strip, token: 'O')
@whose_turn = player1
puts "Remember to enter your response in x- y- coordinates separated by a space. For example, if you'd like to place your piece in the upper right corner of a 3x3 board, please enter 'x3 y1'. "
end
def play_game
@board.display
puts "Ok, #{@whose_turn.name}, you're up!\nWhere would you like to place your #{@whose_turn.token}?"
@board.add_a_move(@whose_turn, gets.strip)
if @board.winning_move?
@winner = @whose_turn
else
@whose_turn = @whose_turn == @player1 ? @player2 : @player1
end
end
end
class Board
attr_accessor :state, :current_move
attr_reader :row_size, :column_size
def initialize(row_size, column_size)
@row_size = row_size
@column_size = column_size
@state = generate_positions(row_size, column_size)
@current_move = nil
end
def display
rows = []
horizontal_separator_line = '-' * (@row_size * 3) + "\n"
@column_size.times do |column_index|
single_row = []
@row_size.times do |row_index|
single_row << @state["x#{row_index + 1} y#{column_index + 1}"]
end
rows.push( single_row.join(' | ') + "\n" )
end
displayed_board = rows.join(horizontal_separator_line)
puts displayed_board
end
def add_a_move(player, move)
@current_move = move
if valid_move?
@state[@current_move] = player.token
else
puts "Sorry, that's not a valid move, try again"
display
add_a_move(player, gets.strip)
end
end
def winning_move?
current_move_token = @state[@current_move]
vertical = generate_vertical_keys()
horizontal = generate_horizontal_keys()
forward = generate_forward_slant_keys()
backward = generate_backward_slant_keys()
all_possible_winning_paths = [vertical, horizontal, forward, backward]
p "forward"
p forward
all_possible_winning_paths.each do |path|
tokens_in_a_row_so_far = 0
path.each do |position|
if @state[position] == current_move_token
tokens_in_a_row_so_far += 1
if tokens_in_a_row_so_far == 3
return true
end
else
tokens_in_a_row_so_far = 0
end
end
end
return false
end
# TODO
# dry up key gen...
# vertical: -X, ^Y
# horizontal: ^X, -Y
# backward slant: ^X, ^Y
# forward slant: ^X, vY
def generate_vertical_keys
x, y = current_move_as_array_of_integers()
y_start = y - 2
y_end = y + 2
y_range = *y_start..y_end
return y_range.collect { |y_value| "x#{x} y#{y_value}"}
end
def generate_horizontal_keys
x, y = current_move_as_array_of_integers()
x_start = x - 2
x_end = x + 2
x_range = *x_start..x_end
return x_range.collect { |x_value| "x#{x_value} y#{y}"}
end
def generate_backward_slant_keys
x, y = current_move_as_array_of_integers()
x_start = x - 2
x_end = x + 2
x_range = *x_start..x_end
y_start = y - 2
y_end = y + 2
y_range = *y_start..y_end
coordinates = x_range.collect.with_index do |x_value, index|
"x#{x_value} y#{y_range[index]}"
end
return coordinates
end
def generate_forward_slant_keys
x, y = current_move_as_array_of_integers()
x_start = x - 2
x_end = x + 2
x_range = *x_start..x_end
y_start = y + 2
y_end = y - 2
y_range = *y_end..y_start
# the above is because splatting a range in decreasing order yields empty array
y_range.reverse!
coordinates = x_range.collect.with_index do |x_value, index|
"x#{x_value} y#{y_range[index]}"
end
return coordinates
end
def current_move_as_array_of_integers
return @current_move.split(' ').collect { |axis_and_num| axis_and_num[1..-1].to_i }
end
def generate_positions(row_size, column_size)
all_positions = {}
column_size.times do |column_index|
row_size.times do |row_index|
all_positions["x#{row_index+1} y#{column_index+1}"] = ' '
end
end
return all_positions
end
def valid_move?
return @state[@current_move] == ' '
end
end
class Player
attr_reader :name, :token, :is_computer
def initialize(name:, token:, is_computer: false)
@name = name
@token = token
@is_computer = is_computer
end
end
Game_Master.new.start_game
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment