diff --git a/week7/homework/features/step_definitions/tic-tac-toe-steps.rb b/week7/homework/features/step_definitions/tic-tac-toe-steps.rb index b353120..6a6f7b4 100644 --- a/week7/homework/features/step_definitions/tic-tac-toe-steps.rb +++ b/week7/homework/features/step_definitions/tic-tac-toe-steps.rb @@ -1,5 +1,8 @@ require 'rspec/mocks/standalone' +current_dir = File.expand_path(File.dirname(__FILE__)) +require "#{current_dir}/../../lib/tic_tac_toe.rb" + Given /^I start a new Tic\-Tac\-Toe game$/ do @game = TicTacToe.new end @@ -13,7 +16,7 @@ end Then /^randomly chooses who goes first$/ do - [@game.player, "Computer"].should include @game.current_player + [@game.player, "Computer"].should include @game.current_player.name end Then /^who is X and who is O$/ do @@ -26,7 +29,7 @@ end Given /^it is my turn$/ do - @game.current_player.should eq "Renee" + @game.current_player.name.should eq "Renee" end Given /^the computer knows my name is Renee$/ do @@ -35,7 +38,7 @@ Then /^the computer prints "(.*?)"$/ do |arg1| @game.should_receive(:puts).with(arg1) - @game.indicate_palyer_turn + @game.indicate_player_turn end Then /^waits for my input of "(.*?)"$/ do |arg1| @@ -45,7 +48,7 @@ Given /^it is the computer's turn$/ do @game = TicTacToe.new(:computer, :O) - @game.current_player.should eq "Computer" + @game.current_player.name.should eq "Computer" end Then /^the computer randomly chooses an open position for its move$/ do @@ -74,11 +77,11 @@ end When /^"(.*?)" is not taken$/ do |arg1| - @old_pos.should eq " " + @old_pos.should eq nil end Then /^it is now the computer's turn$/ do - @game.current_player.should eq "Computer" + @game.current_player.name.should eq "Computer" end When /^there are three X's in a row$/ do @@ -118,7 +121,7 @@ end Then /^computer should ask me for another position "(.*?)"$/ do |arg1| - @game.board[arg1.to_sym] = ' ' + @game.board[arg1.to_sym] = nil @game.should_receive(:get_player_move).twice.and_return(@taken_spot, arg1) @game.player_move.should eq arg1.to_sym end diff --git a/week7/homework/lib/tic_tac_toe.rb b/week7/homework/lib/tic_tac_toe.rb new file mode 100644 index 0000000..c550b13 --- /dev/null +++ b/week7/homework/lib/tic_tac_toe.rb @@ -0,0 +1,209 @@ +require 'pry' + +class Player + attr_accessor :name, :symbol, :winner +end + + +class TicTacToe + + SYMBOLS = [:X, :O] + + attr_accessor :board + + def initialize(first_player = nil, player_symbol = nil) + @computer_player = Player.new + @computer_player.name = "Computer" + + @human_player = Player.new + + @players = {:player => @human_player, :computer => @computer_player} + + # player_order is an array like [:player, :computer] + if first_player + @player_order = [] + player_names = @players.keys + + @player_order << player_names.delete(first_player) + @player_order << player_names[0] + else + @player_order = @players.keys.shuffle + end + + # Randomize the symbol order + symbols = SYMBOLS.dup.shuffle + + if player_symbol + @players[:player].symbol = symbols.delete(player_symbol) + end + + # Iterate over all the players that don't yet have symbols, and assign them one + @players.values.select { |player| !player.symbol }.each_with_index do |player, index| + player.symbol = symbols[index] + end + + @current_player_index = 0 + + @board = { + :A1 => nil, :A2 => nil, :A3 => nil, + :B1 => nil, :B2 => nil, :B3 => nil, + :C1 => nil, :C2 => nil, :C3 => nil + } + end + + def player_for_symbol(symbol) + @players.values.find { |player| player.symbol == symbol } + end + + def player=(name) + @human_player.name = name + end + + def player + @human_player.name + end + + def player_symbol + @human_player.symbol + end + + def computer_symbol + @computer_player.symbol + end + + def welcome_player + "Welcome #{@human_player.name}" + end + + def current_player + key = @player_order[@current_player_index] + @players[key] + end + + def advance_player + @current_player_index = (@current_player_index + 1) % 2 + end + + def indicate_player_turn + puts "#{@human_player.name}'s Move:" + end + + def get_player_move + gets.chomp + end + + def open_spots + @board.keys.select { |key| @board[key] == nil } + end + + def open?(position) + open_spots.include?(position) + end + + def taken?(position) + !open?(position) + end + + def computer_move + + puts "Computer's Move:" + + position = open_spots.shuffle.first # :A2 + + puts position + + @board[position] = computer_symbol + + advance_player + + position + end + + def player_move + position = nil + + begin + if position + puts "That spot is taken, please choose another:" + else + puts "It's your turn, please make a move:" + end + + position = get_player_move.to_sym + end until open?(position) + + @board[position] = player_symbol + + advance_player + + position + end + + def determine_winner + win_scenarios = [ + %w[A1 A2 A3], + %w[B1 B2 B3], + %w[C1 C2 C3], + %w[A1 B1 C1], + %w[A2 B2 C2], + %w[A3 B3 C3], + %w[A3 B2 C1], + %w[A1 B2 C3] + ].map { |array| array.map(&:to_sym) } + + # Find the winning scenenario + win = win_scenarios.find do |scenario| + board_state = scenario.map { |c| @board[c] } + + board_state.all? { |i| i == :O } || board_state.all? { |i| i == :X } + end + + # Figure out which player won + if win + # [:B1, :B2, :B3] + winning_symbol = @board[win.first] + winning_player = player_for_symbol(winning_symbol) + winning_player.winner = true + @winner = winning_player + end + + end + + def player_won? + @human_player.winner + end + + def computer_won? + @computer_player.winner + end + + def spots_open? + open_spots.any? + end + + def over? + @winner || !spots_open? + end + + def draw? + over? && !@winner + end + + def current_state +<<-BOARD + A B C + ------------- +1 | #{present_board_at(:A1)} | #{present_board_at(:B1)} | #{present_board_at(:C1)} | + ------------- +2 | #{present_board_at(:A2)} | #{present_board_at(:B2)} | #{present_board_at(:C2)} | + ------------- +3 | #{present_board_at(:A3)} | #{present_board_at(:B3)} | #{present_board_at(:C3)} | + ------------- + +BOARD + end + + def present_board_at(slot) + @board[slot] || " " + end +end \ No newline at end of file diff --git a/week7/homework/play_game.rb b/week7/homework/play_game.rb index cf7847f..75824e5 100644 --- a/week7/homework/play_game.rb +++ b/week7/homework/play_game.rb @@ -1,15 +1,24 @@ -require './features/step_definitions/tic-tac-toe.rb' +current_dir = File.expand_path(File.dirname(__FILE__)) +require "#{current_dir}/lib/tic_tac_toe.rb" @game = TicTacToe.new + +puts "What's your name player?" + +name = gets.chomp +@game.player = name + puts @game.welcome_player until @game.over? - case @game.current_player + case @game.current_player.name when "Computer" @game.computer_move when @game.player - @game.indicate_palyer_turn + @game.indicate_player_turn @game.player_move + else + raise "It's nobody's move!" end puts @game.current_state @game.determine_winner