如何在TIC-TAC-toe游戏中弄干此红宝石代码?(使用1.Times Block!)



我想知道是否有人可以帮助我……我敢肯定这是那些额头打滑的东西之一...但是我不知道如何将这个点晾干。

我正在制作一项学习练习的TIC-TAC节目。我实际上已经完成了,但是有点困扰我,因为这显然笨拙。当我为计算机移动进行AI时,该部分就到了。此操作的方式是,您测试八个条件中的每一个,寻找可能的举动。您看第一个条件;如果导致移动,请返回并跳过其余条件。如果八个条件都没有引起举动,那么游戏已经结束(板已经满)。

好吧,条件足够复杂,每个人都需要单独的方法。因此,要执行逻辑,我说简单地说1.times(叹气),然后在一个曾经一次的一次块中,一一仔细研究这些方法。检查该方法是否返回移动后,我说break if move,即突破块。很明显,我不必在每个项目之后使用break if move。违反干。我想到使用if...elsif...switch语句,但这是行不通的,因为所有方法都必须通过,直到其中一个方法返回移动,而这些方法不仅返回true或false;他们实际上返回移动的索引号,或者否则false

unless skip_rule == n位是愚蠢的AI的一种方式;如果玩家希望AI可以击败AI,则选择一个规则要跳过。)

如果您想潜入潜水,请在此处查看第96列以下的代码:https://github.com/globewalldesk/tictactoe2/blob/master/master/lib/lib/board.rb

# Test each set of conditions, until a move is found
move = false
1.times do
  # Win: If you have two in a row, play the third to get three in a row.
  # puts "Trying 1"
  move, length = are_there_two_tokens_in_a_row(@ctoken) unless skip_rule == 0
  break if move # skip to end if move is found
  # Block: If the opponent has two in a row, play the third to block them.
  # puts "Trying 2"
  move, length = are_there_two_tokens_in_a_row(@ptoken) unless skip_rule == 1
  break if move
  # Fork: Create an opportunity where you can win in two ways (a fork).
  # puts "Trying 3"
  move = discover_fork(@ctoken) unless skip_rule == 2
  break if move
  # Block Opponent's Fork: If opponent can create fork, block that fork.
  # puts "Trying 4"
  move = discover_fork(@ptoken) unless skip_rule == 3
  break if move
  # Center: Play the center.
  # puts "Trying 5"
  unless skip_rule == 4
    move = 4 if @spaces[4].c == " " # if the center is open, move there
  end
  break if move
  # Opposite Corner: If the opponent is in the corner, play the opposite corner.
  # puts "Trying 6"
  move = try_opposite_corner unless skip_rule == 5
  break if move
  # Empty Corner: Play an empty corner.
  # puts "Trying 7"
  move = try_empty_corner
  break if move
  # Empty Side: Play an empty side.
  # puts "Trying 8"
  move = play_empty_side
  # If move is still false, game is over!
end # of "do" block
# Make the change to @spaces; this edits the individual space and hence also
# the triads and the board, which use it.
@spaces[move].c = @ctoken if move
end # of computer_moves

更新(2016年12月3日):我无法完全理解我在下面得到的建议。但是一个朋友离线看了这个问题,并建议我制作一系列方法并迭代这一问题……这就是我的手击中我的额头的声音。我知道有一种(相对)的简单方法可以做到这一点。无论如何,Ruby中可能不可能进行一系列方法,但是可以制作包含方法的一系列procs。这就是我所做的。这是校正/改进的代码:

# Initialize array of procs for each step of algorithm
rules = [
  # Win: If you have two in a row, play the third to get three in a row.
  Proc.new { are_there_two_tokens_in_a_row(@ctoken) },
  # Block: If the opponent has two in a row, play the third to block them.
  Proc.new { are_there_two_tokens_in_a_row(@ptoken) },
  # Fork: Create an opportunity where you can win in two ways (a fork).
  Proc.new { discover_fork(@ctoken) },
  # Block Opponent's Fork: If opponent can create fork, block that fork.
  Proc.new { discover_fork(@ctoken) },
  # Center: Play the center.
  Proc.new {
    unless skip_rule == 4
      move = 4 if @spaces[4].c == " " # if the center is open, move there
    end
  },
  # Opposite Corner: If the opponent is in the corner, play the opposite corner.
  Proc.new { try_opposite_corner },
  # Empty Corner: Play an empty corner.
  Proc.new { try_empty_corner },
  # Empty Side: Play an empty side.
  Proc.new { play_empty_side }
]
# Iterates over rule procs, and breaks out of iteration when move != false
(0..7).each do |rule_index|
  move, length = rules[rule_index].call unless skip_rule == rule_index
  break if move
end

漂亮,n'est-ce pas?据我所知,这一点代码干燥了。这是程序的更新源文件。顺便说一句,该程序可以设置为无与伦比的,但是用户可以将其"忘记"随机规则,这使其可击败。

感谢所有回答的人。下次我将尝试代码评论。

只需将1.times块内部的代码重构为自己的方法即可。而不是break if move以相同的方式使用显式return操作员: return if move

最新更新