如何从保存的 yaml 文件继续井字游戏?

How do I continue tic-tac-toe game from saved yaml file?

我有以下井字游戏:(我是菜鸟,请无视class的设计,游戏能玩,我暂时只关心这些。)

#a tic tac toe game
class TicTacToe
    require "yaml"
    attr_accessor :player1, :player2
    #crates playes and a game board to play tic tac toe
    def initialize()
        @player1 = Player.new("Player One", "x")
        @player2 = Player.new("Player Two", "o")
        @game_board = Board.new
    end

    #prints the board
    def print_board
        @game_board.board.each_with_index do |row, index| 
            puts "#{row.join(" | ")}"
            puts "---------" unless index == 2
        end
        puts
    end

    #determines whose move it is
    def move
        if @turn % 2 == 1
            player_one_turn
        else
            player_two_turn
        end
        @turn += 1
    end

    def valid_move?(row, col)
        if @game_board.board[row][col] == " "
            return true
        else
            return false
        end
    end

    #player ones turn
    def player_one_turn
        print_board
        puts "#{@player1.name} it's your turn:"
        puts "Enter a row (0-2)"
        row = gets.chomp.to_i
        puts "Enter a column (0-2)"
        col = gets.chomp.to_i
        if valid_move?(row, col)
            @game_board.board[row][col] = @player1.shape
        else
            puts "There's already a shape at that position."
            player_one_turn
        end

        if win?(@player1.shape)
            winner(@player1.name)
            @winner = true
        end
    end

    #player two's turn
    def player_two_turn
        print_board
        puts "#{@player2.name} it's your turn:"
        puts "Enter a row (0-2)"
        row = gets.chomp.to_i
        puts "Enter a column (0-2)"
        col = gets.chomp.to_i
        if valid_move?(row, col)
            @game_board.board[row][col] = @player2.shape
        else
            puts "There's already a shape at that position."
            player_two_turn
        end

        if win?(@player2.shape)
            winner(@player2.name)
            @winner = true
        end
    end

    def win?(shape)
        if (@game_board.board[0][0] == shape) && (@game_board.board[0][1] == shape) && (@game_board.board[0][2] == shape)
            return true
        elsif (@game_board.board[1][0] == shape) && (@game_board.board[1][1] == shape) && (@game_board.board[1][2] == shape)
            return true
        elsif (@game_board.board[2][0] == shape) && (@game_board.board[2][1] == shape) && (@game_board.board[2][2] == shape)
            return true
        elsif (@game_board.board[0][0] == shape) && (@game_board.board[1][0] == shape) && (@game_board.board[2][0] == shape)
            return true
        elsif (@game_board.board[0][1] == shape) && (@game_board.board[1][1] == shape) && (@game_board.board[2][1] == shape)
            return true
        elsif (@game_board.board[0][2] == shape) && (@game_board.board[1][2] == shape) && (@game_board.board[2][2] == shape)
            return true
        elsif (@game_board.board[0][0] == shape) && (@game_board.board[1][1] == shape) && (@game_board.board[2][2] == shape)
            return true
        elsif (@game_board.board[0][2] == shape) && (@game_board.board[1][1] == shape) && (@game_board.board[2][0] == shape)
            return true
        else
            return false
        end
    end

    def draw?
        if @turn > 9
            print_board
            puts "The game ended in a draw. :)"
            @winner = true
            return true
        end
        false
    end

    def winner(winner_name)
        puts "#{winner_name}, YOU WIN!!!"
    end

    def play
        @turn = 1
        @winner = false

        until @winner
            move unless draw?
            save
        end
    end


    #a class that generates an empty board
    class Board
    attr_accessor :board
        def initialize
            @board = [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]
        end
    end

    #a class that assigns creates plaers and assigns them a shape "x" or "o"
    class Player
        attr_accessor :name, :shape
        def initialize(name, shape)
            @name = name
            @shape = shape
        end
    end

    def save
        yaml = YAML::dump(self)
        File.open("save.txt", "w"){|file| file.write(yaml)}
    end

    def self.load
        file = File.read("save.txt")
        YAML::load_file(file)
    end
end

game = TicTacToe.new
game.play

我想开始玩游戏,游戏中途退出程序,等我调用TicTacToe.load后再回来完成。但是,当我现在执行此操作时,YAML 文件已加载,但程序不会在应有的位置恢复。

有人可以告诉我是否有办法做我想做的事情吗?

我认为像 YAML::load(self) 这样的操作会通过某种魔法自动加载我所指文件的保存状态。但是,我已经了解到,我设计 class 的方式和 "play" 函数中的依赖项不允许我加载以前的状态,如果我的文件。

加载 YAML 文件时,必须将文件加载到一个变量,然后手动将对象值分配给 class 的值。这样,变量的当前状态几乎是手动分配给 class 的实例变量。例如,我可以这样做:file = YAML.load("file_name"),然后为变量赋值:@board = file.board.

如果我之前知道这一点,我会设计我的 class 以减少依赖性,这样它就可以以更干净、更方便的方式加载。