Cyzanfar
Cyzanfar

Reputation: 7136

undefined method `keys' for nil:NilClass in tic tac toe game RUBY

I'm trying to build a simple 2 player tic tac toe game in Ruby. Here is the code:

class Morpion

   def init
      create_grid
      get_player
      show_grid
   end
   def get_player
      puts "Let play some Tic Tac Toe"
      puts ""
      @player1 ='X'
      @player2='O'
          puts ""
          puts "Where would you like to move? (check out the grid below and type any number 1-9 to place your symbol): "
          puts " 1 | 2 | 3 "
          puts "---+---+---"
          puts " 4 | 5 | 6 "
          puts "---+---+---"
          puts " 7 | 8 | 9 "
   end

   def create_grid
        @grid = {
            '1' => ' ',
            '2' => ' ',
            '3' => ' ',
            '4' => ' ',
            '5' => ' ',
            '6' => ' ',
            '7' => ' ',
            '8' => ' ',
            '9' => ' '
        }
   end

    def show_grid
        puts ""
        puts "#{@grid['1']}|#{@grid['2']}|#{@grid['3']}"
        puts "-----"
        puts "#{@grid['4']}|#{@grid['5']}|#{@grid['6']}"
        puts "-----"
        puts "#{@grid['7']}|#{@grid['8']}|#{@grid['9']}"
        puts ""
    end

   def play
       number_turns=1
       while number_turns < 10
        number_turns.odd? ? player_turn(@player1) : player_turn(@player2)
        game_checker
        if game_checker
          break
        end
        number_turns+=1
       end  
   end

   def player_turn(player)
        puts player == 'X' ? "It's X's turn!" : "It's O's turn!"
        puts ""
        cell = gets.chomp
        unless @grid.keys.include?(cell) #check if the user entered a number corresponding to the grid
            puts ""
            puts "it has to be a number from 1 to 9"
            player_turn(player)
        end
        if @grid[cell] == ' ' #check if cell in grid is empty for user input
            @grid[cell] = player
        else
            puts ""
            puts "That cell is occupied. Choose again!"
            player_turn(player)
        end
        show_grid
   end

   def game_checker
        end_game = false
      if @grid['1'] != ' ' && @grid['5'] != ' ' && @grid['9'] != ' '
        if (@grid['1'] == @grid['2'] && @grid['1'] == @grid['3'])
            end_game = true
            victory = @grid['1']
          elsif (@grid['4'] == @grid['5'] && @grid['4'] ==@grid['6'])
            end_game = true
            victory = @grid['4']
          elsif (@grid['7'] == @grid['8'] && @grid['7'] == @grid['9'])
            end_game = true
            victory = @grid['7']
          elsif (@grid['1'] == @grid['4'] && @grid['1'] == @grid['7'])
            end_game = true
            victory = @grid['1']
          elsif (@grid['2'] == @grid['5'] && @grid['2'] == @grid['8'])
            end_game= true
            victory = @grid['2']
          elsif (@grid['3'] == @grid['6'] && @grid['3'] == @grid['9'])
            end_game = true
            victory = @grid['3']
          elsif (@grid['1'] == @grid['5'] && @grid['1'] == @grid['9'])
            end_game = true
            victory = @grid['1']
          elsif (@grid['3'] == @grid['5'] && @grid['3'] == @grid['7'])
            end_game = true
            victory = @grid['3']
          else
            end_game = false
        end
      end
        if end_game 
           puts "the winner of this game is #{victory}"
           return true
        end
   end


end


m=Morpion.new
m.play

So my issue is this: 1. I am asking a player to add his symbol (X or O) in the grid that ranges from 1 to 9 (because there is 9 cells)

  1. if I enter 1 for example, which is the upper left cell I get this error:

    (eval):187: undefined method `keys' for nil:NilClass (NoMethodError) from (eval):168:in `play' from (eval):245

If you want to run this program I suggest using THIS LINK

EDIT: The problem as @Paul and @August stated was that I used an incorrect constructor method init instead of using the correct one: initialize. Now my program works. Thanks to them.

Upvotes: 0

Views: 281

Answers (2)

Paul Richter
Paul Richter

Reputation: 11072

The problem is that your @grid variable is never being created; it is nil. Hence the error message, you're attempting to invoke a method on a nil object.

The cause of your woes is because you've misnamed the constructor method. In Ruby, constructors are named initialize, however you named it init. Rename it to the correct name, and it should work.

Upvotes: 1

August
August

Reputation: 12558

You initialize the @grid hash in a method called init. Ruby won't call this method when you construct a new instance of Game. You should instead rename the init method to initialize, which will be called automatically by Ruby.

Upvotes: 2

Related Questions