我正在尝试在Ruby中构建一个简单的tic tac toe程序。我遇到一个问题,在一个类实例上调用一个方法更新另一个类实例。问题出在我的Game类中,如下所示:
class Game
attr_accessor :turn_count, :all_positions_occupied, :winner, :rows, :columns, :diagonals
def initialize
@turn_count = 0
@all_positions_occupied = {1 => "*", 2 => "*", 3 => "*",
4 => "*", 5 => "*", 6 => "*",
7 => "*", 8 => "*", 9 => "*"}
@winner = nil
@rows = { 1 => [1, 2, 3], 2 => [4, 5, 6], 3 => [7, 8, 9] }
@columns = { 1 => [1, 4, 7], 2 => [2, 5, 8], 3 => [3, 6, 9] }
@diagonals = { 1 => [1, 5, 9], 2 => [3, 5, 7] }
end
def refresh_line(line, item, symbol)
line.each do |key, value|
if value.include?(item)
value[(value.index(item))] = symbol
end
end
end
def occupy_selected(selection, symbol)
@all_positions_occupied[selection] = symbol
# Refresh rows, columns, and diagonals
refresh_line(@rows, selection, symbol)
refresh_line(@columns, selection, symbol)
refresh_line(@diagonals, selection, symbol)
end
def copy_onto_virtual_board(virtual_game)
virtual_game.all_positions_occupied = @all_positions_occupied.clone
virtual_game.rows = @rows.clone
virtual_game.columns = @columns.clone
virtual_game.diagonals = @diagonals.clone
end
end
我正在尝试创建试图阻止玩家获胜的计算机行为。在我的主代码中,我想创建一个“real_game”和一个“virtual_game”。每当计算机轮到我的时候,我想运行以下方法:
def block_win(virtual_game)
# Copy Real Board Onto Virtual Board Using 'copy_onto_virtual_board(virtual_game)'
# Create Array of Available Positions
# Cycle Through Array of Available -> 'available_positions.each do |position|'
# Occupy 'position' on the Virtual Board with 'X' using 'occupy_selected(position, 'X')
# If 'virtual_game.check_for_winner' is not nil
# Have Computer Occupy that Position with 'O', effectively blocking 'X' from taking that position and winning
# Else
# Re-Copy Real Board Onto the Virtual Board Using 'copy_onto_virtual_board(virtual_game)'
end
但是,一旦我使用real_game.copy_onto_virtual_board(virtual_game)
,real_game
和virtual_game
会以某种方式链接起来,这样无论何时我在virtual_game上使用occupy_selected(position, "X")
,它都会将相同的方法应用于real_game同样。这违背了将virtual_game与real_game分开的全部目的。只要我不使用copy_onto_virtual_board
方法,这两个游戏就会分开运作。
关于为什么会发生这种情况的任何想法?我知道这是一个令人费解的解释,所以请告诉我您可能需要的其他信息。
感谢您的帮助。
更新-----------
根据以下engineermnky给出的答案,我更新了以下方法:
def copy_onto_virtual_board(virtual_game)
virtual_game.all_positions_occupied = @all_positions_occupied.clone
virtual_game.rows = @rows.keys.zip(@rows.values.map(&:clone)).to_h
virtual_game.columns = @columns.keys.zip(@columns.values.map(&:clone)).to_h
virtual_game.diagonals = @diagonals.keys.zip(@diagonals.values.map(&:clone)).to_h
end
设置block_win方法以返回阻塞位置(如果有)。否则,它会根据available_positions数组返回一个随机位置。
答案 0 :(得分:0)
原因是你没有深刻复制哈希。这意味着通过使用#clone
,您创建一个新哈希,其键指向相同的数组。
您可以使用Marshal.load(Marshal.dump(hash))
代替hash.clone
在ruby中制作深层副本。这将创建所有引用对象的完整副本。
但我不能推荐它,并鼓励你检查你的设计,以便你不需要。