Question

I wrote a tic-tac-toe program. The problem is that when a user enters an invalid coordinate, the user is notified however, it skips his turn. For example: if player "x" enters valid coordinates, and player "o" enters valid coordinates, player "o" is notified but his/her turn gets skipped and player "x" goes again. How do I fix this so that player "o" gets another chance to enter in valid coordinates?

Here is my code:

class Game

  def initialize
    @board=Array.new
    @board[1]="1  __|"
    @board[2]="__"
    @board[3]="|__"
    @board[4]="\n2  __|"
    @board[5]="__"
    @board[6]="|__"
    @board[7]="\n3    |"
    @board[8]="  "
    @board[9]="|  "
    @turn="o"
    @win_status = false
  end

  def turn
    @turn
  end

  def show_board
    puts "   1  2  3"
    @board.each do |i|
      print i
    end
    puts ""
  end

  def set_turn #switches turns
    if @turn == "x"
      @turn = "o"
    else @turn == "o"
      @turn = "x"
    end
  end

  def make_move
    puts "Enter x coordinate"
    x=gets.to_i
    puts "Enter y coordinate"
    y=gets.to_i
    if y==1 && x==1
      @board[1]="1  _"+@turn+"|"
    elsif y==2 && x==1
      @board[2]="_"+@turn
    elsif  y==3 && x==1
      @board[3]="|_"+@turn
    elsif y==1 && x==2
      @board[4]="\n2  _"+@turn+"|"
    elsif y==2 && x==2
      @board[5]="_"+@turn
    elsif y==3 && x==2
      @board[6]="|_"+@turn
    elsif y==1 && x==3
      @board[7]="\n3   "+@turn+"|"
    elsif y==2 && x==3
      @board[8]=" "+@turn
    elsif y==3 && x==3
      @board[9]="| "+@turn+" \n"
    else
      puts "you entered an invalid coordinate"
    end

  end

  def win_combo
    return [[@board[1][4] + @board[2][1] + @board[3][2]], [@board[4][5] + @board[5][1] + @board[6][2]], [@board[7][5] + @board[8][1] + @board[9][2]],[@board[1][4] + @board[4][5] + @board[7][5]], [@board[2][1] + @board[5][1] + @board[8][1]], [@board[3][2] + @board[6][2] + @board[9][2]], [@board[1][4] + @board[5][1] + @board[9][2]], [@board[3][2] + @board[5][1] + @board[7][5]]]
  end

  def check_win
    #if some row or column or diagonal is "xxx" or "ooo" then set @win_status = true
    self.win_combo.each do |arr|
      str = arr.join
      if str == "xxx"
        puts "X Wins!"
        return true
      elsif str == "ooo"
        puts "O Wins!"
        return true
      end
    end
    return false
  end
  g = Game.new
  while g.check_win != true
    g.show_board
    g.set_turn
    g.make_move
  end
end
Was it helpful?

Solution

You could call make_move again to prompt for the user to enter new coordinates.

puts "you entered an invalid coordinate"
make_move

OTHER TIPS

You could call make_move from within your else clause once you know that a player has entered an invalid move.

else
  puts "you entered an invalid coordinate"
  make_move
end

Look at the condition in make_move that is triggered when the user enters an invalid coordinate. After that code is triggered, make_move's execution is over, so it steps out into your g.check_win loop.

Think about your functions as pieces that can be reused. make_move is called whenever you want the current user to make a move. How can you execute this functionality again, after make_move tells the user their input was invalid?

I'll give you a hint: functions can call themselves.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top