Search code examples
rubymethodstic-tac-toe

Tic Tac Toe Help fixing method that checks if square has already been chosen. Game board is structured as empty array


I'm creating a tic tac toe game in the command line using Ruby. I have a method display_board that displays my array as a game board in the command line and when I play the game players can choose between 1-9 and populate the square with their "symbol". I created a method check_square to verify if one of the squares in the grid has already been taken but it's not working properly for me. I start up the game and everything works, up until it asks me to choose my first number on the grid. It immediately responds and tells me the number is already taken even though it's the first move of the game. It asks me to choose another number and on the second try it populates the grid. It does this on every player move. The logic seems to make sense to me and I've been trying to figure it out for an hour but I'm clearly overlooking something. Any pushes in the right direction would be helpful!

class Players
    attr_accessor :name, :symbol
    def initialize(name, symbol)
        @name = name
        @symbol = symbol
    end
end

class Game 
    @@board = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
    @@count = 0

    def initialize
        puts "Tic Tac Toe!"
    end

    def display_board
        puts "  #{@@board[0]}  |  #{@@board[1]}  |  #{@@board[2]}"
        puts seperator = "-----+-----+-----"
        puts "  #{@@board[3]}  |  #{@@board[4]}  |  #{@@board[5]}"
        puts seperator
        puts "  #{@@board[6]}  |  #{@@board[7]}  |  #{@@board[8]}"
        puts "\n"
    end

    def game_start
        puts "Time for some Tic Tac Toe! Enter your name player 1: \n"
        player1 = gets.chomp
        puts "Would you like to be X or O #{player1}?"
        symbol1 = gets.chomp.upcase
        player_one = Players.new(player1, symbol1)
        puts "And a name for player 2: \n"
        player2 = gets.chomp
        symbol2 = player_one.symbol == "X" ? "O" : "X"
        player_two = Players.new(player2, symbol2)
        puts "\n"
        puts "Okay #{player_one.name}, you're up. Make a move."
        display_board
        make_moves(player_one, player_two)
    end

    def make_moves(player_one, player_two)
        until @@count == 9

            puts "Pick a number from the grid above #{player_one.name}"
            move = gets.chomp.to_i - 1
            check_square(move, player_one, player_two)
            @@board[move] = player_one.symbol
            @@count += 1
            display_board

            puts "Pick a number from the grid above #{player_two.name}"
            move = gets.chomp.to_i - 1
            check_square(move, player_one, player_two)
            @@board[move] = player_two.symbol
            @@count += 1
            display_board
        end
    end

    def check_square(move, player_one, player_two)
        if @@board[move] == "#{player_one.symbol}" || "#{player_two.symbol}"
            puts "That number is taken, pick another!"
            move = gets.chomp.to_i - 1
        else
            return
        end
    end

end

game = Game.new
game.game_start

Solution

  • The problem you're running into is the conditional logic in your check_square method.

    @@board[move] == "#{player_one.symbol}" || "#{player_two.symbol}"
    

    This logic is suppose to check if either of the players' symbols is stored on the board at the selected position. However, what it is really doing is checking if player one's symbol is stored on the board at that position and if it's not then the string literal for player two's symbol is being evaluated as truthy. This results in check_square always returning true

    Try this instead:

    @@board[move] == "#{player_one.symbol}" || @@board[move] == "#{player_two.symbol}"
    

    For more idiomatic ruby you can remove the interpolation which isn't necessary since symbol is already a string.

    @@board[move] == player_one.symbol || @@board[move] == player_two.symbol