TicTacToe 无效移动方法问题

TicTacToe invalid move method issue

以下是我对 TicTacToe 游戏的看法。到目前为止它有效,但并不完美。我对其中一种方法有疑问 - Game#invalid_move_check?在游戏问你之后"where to:"一旦选择了新的目的地,游戏就会改变符号,就像是新的回合一样。事实上不是,假设在下一个回合之前保持相同的玩家符号。

P.S 代码可能需要一些重构。我正处于学习阶段。

class  Game

def initialize(symbol) 
    @board  = Array.new(3){Array.new(3)}
    # [0,1,2]
    # [3,4,5]
    # [6,7,8]
    @symbol = ["X", "O"]
end

WINNING_COMBO = [
  # Horizontal wins:
  [0, 1, 2], [3, 4, 5], [6, 7, 8],
  # Vertical wins:
  [0, 3, 6], [1, 4, 7], [2, 5, 8],
  # Diagonal wins:
  [0, 4, 8], [2, 4, 6]
]

def create_players
    # create both players 
    @names = []

    print "Please enter the name of the first player: "
    @player_1 =gets.chomp
    @names << @player_1

    print "Please enter the name of the second player: "
    @player_2 = gets.chomp
    @names << @player_2 

    puts "\n"
    puts"welcome #{@player_1.upcase} and #{@player_2.upcase}"
    puts"------------------------------------------------"
    puts"\n"

    puts "Randomizing who'll start..."
    puts"\n"
    # assign player by calling the player_assigment function that will determine who will start first
    player_assigment
    puts"\n"

end

def player_assigment
    # merge the names array and symbol array 
    # with the zip method and return a nested array with player and symbol.  
    @choice = @names.zip(@symbol)
    # iterate over the choice nested array and 
    # print out each player and their assigned symbol
    @choice.each do |player, symbol|
       puts "#{player.upcase} will use #{symbol}"
    end

end

def current
    @current = @names.first
    @current
end

def switch_turn
    @current = @names.last
    @current
end

def first_turn
    current
    puts "#{@current.upcase} turn"
    @marker = @symbol.first
    make_move(@marker)
end

def next_turn
    switch_turn
    puts "#{@current.upcase} turn"
    @marker = @symbol.last
    make_move(@marker)
end

def check_win?(first_arr, second_arr)
    WINNING_COMBO.select do |item|
        if 
            item == first_arr 
            puts"#{@player_1} won!!"
        elsif 
            item == second_arr
            puts "#{@player_2} won!!"
        end
    end

end

def mapping(move, marker)
     case move
        when 0
          arr_index = 0
          index = 0
          invalid_move_check?(arr_index,index)
          @board[0][0] = marker
        when 1
          arr_index = 0
          index = 1
          invalid_move_check?(arr_index,index)
          @board[0][1] = marker
        when 2
          arr_index = 0
          index = 2
          invalid_move_check?(arr_index,index)
          @board[0][2] = marker
        when 3
          arr_index = 1
          index = 0
          invalid_move_check?(arr_index,index)
          @board[1][0] = marker
        when 4
          arr_index = 1
          index = 1
          invalid_move_check?(arr_index,index)
          @board[1][1] = marker
        when 5
          arr_index = 1
          index = 2
          invalid_move_check?(arr_index,index)
          @board[1][2] = marker
        when 6
          arr_index = 2
          index = 0
          invalid_move_check?(arr_index,index)
          @board[2][0] = marker
        when 7
          arr_index = 2
          index = 1
          invalid_move_check?(arr_index,index)
          @board[2][1] = marker
        when 8
          arr_index = 2
          index = 2
          invalid_move_check?(arr_index,index)
          @board[2][2] = marker
    end
end

def invalid
    puts"move invalid"
end

def invalid_move_check?(arr_index, index)
    array = @board
    if array[arr_index][index]  == "X" || 
        array[arr_index][index]  == "O"
        invalid
        puts "Where to :"
        @move = gets.chomp.to_i
        mapping(@move,@marker)
    end
end

def make_move(marker)
    # after each turn the make_move method will called to place move on the board 
    puts "Where to :"
    @move = gets.chomp.to_i
    mapping(@move,@marker)
    print_board
end

# display board in a matrix format 
def print_board
    @board.each_slice(1) { |a| p a }
    puts"\n"
end

def instructions
    puts "Instructions :Enter your first move by entering  a number 1-9" 
    puts "corresponding to the grid on the bottom and press enter"
    puts"\n"
    puts "0 | 1 | 2 ",             
         "----------",              
         "3 | 4 | 5 ",             
         "----------",            
         "6 | 7 | 8 " 
    print"\n"

end

def self.start(symbol)
    # start a new game 
    new_game =Game.new(symbol)
    # create players
    new_game.create_players
    new_game.instructions
    new_game.print_board
    # Checking wining combo for matching patter if none 
    while new_game.check_win?(@move_first, @move_second) do
    new_game.first_turn
    # the player switch turn 
    new_game.next_turn
    end 
end

loop do
    puts"------------------------------------------------"
    puts"              Welcome to tictactoe              ".upcase
    puts"------------------------------------------------"
    print"\n"
     Game.start(@symbol)

end

end

这应该可以解决问题:

#will return true or false to check validity of move
def invalid_move_check?(arr_index, index)
    array = @board
    if array[arr_index][index]  == "X" || 
        array[arr_index][index]  == "O"
        invalid
        puts "Where to :"
        @move = gets.chomp.to_i
        mapping(@move,@marker)
        return true            
    end
return false
end

def mapping(move, marker)
     case move
        ...
        when 0
          arr_index = 0
          index = 0
          unless invalid_move_check?(arr_index,index) #change all cases
            @board[0][0] = marker #to have the assignment of board
                                  #only if the move is valid
          end
          ...
     end
end 

你的错误的原因是即使移动无效也会发生赋值。

这只是您当前问题的创可贴解决方案,至于重构,可以做一些事情来优化您的代码并使其变得更好:)但是您仍然必须先修复您的 'ending'.重构您自己的代码将是一个很好的做法。祝你旅途愉快ruby !

在草拟之前的代码并重新思考我提出这个解决方案的代码之后,虽然不像我希望的那样优雅,但它有效。我移动了 if/else 块代码中的符号分配因此,当一个动作无效时,下一步将使用当前玩家的符号

 def mapping(move, symbol)
         case move
            when 0
                if @board[0][0]=="X" || @board[0][0] == "O"
                   invalid
                   make_move
                else
                   @board[0][0] = symbol
                   track_move(@move)
                   print_board
                end
               ...
           end
  end