- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我想知道是否有人可以帮我解决这个问题……我敢肯定这是拍额头的事情之一……但我不知道如何擦干这部分。
我正在制作井字棋程序作为学习练习。我实际上已经完成了,但是有一点困扰我,因为它看起来显然很笨拙。当我为计算机的移动做 AI 时,这部分就来了。其运作方式是,您测试八个条件中的每一个以寻找可能的移动。你看第一个条件;如果它导致移动,则返回该移动并跳过其余条件。如果这八个条件都没有引发移动,那么游戏就结束了(棋盘已满)。
嗯,条件非常复杂,每个条件都需要一个单独的方法。因此,为了执行逻辑,我简单地说 1.times
(叹气),然后在一个一次性 block 中,一个接一个地执行这些方法。在检查该方法是否返回移动后,我说 break if move
,即跳出 block 。很明显我不应该在每个 项之后使用break if move
。违反干。我想过使用 if...elsif...
或 switch
语句,但这行不通,因为所有的方法都必须经过,直到一个其中的一个返回一个移动,并且这些方法不只是返回 true 或 false;它们实际上返回移动的索引号或 false
。
(unless skip_rule == n
位是一种让 AI 变笨的方法;如果玩家希望 AI 可以被打败,另一种方法是选择要跳过的规则。)
如果您想深入了解,请在此处查看第 96 行以上的代码:https://github.com/globewalldesk/tictactoe2/blob/master/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
更新(12/3/2016):我不太能理解下面的建议。但是一位线下的 friend 看了这个问题并建议我制作一个方法数组并对其进行迭代......那是我的手碰到我额头的声音。我知道有一种(相对)简单的方法可以做到这一点。无论如何,在 Ruby 中可能不可能有一个方法数组,但是可以创建一个包含方法的过程数组。所以这就是我所做的。这是更正/改进的代码:
# 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
漂亮,不是吗?据我所知,这段代码干涸了。 Here是程序的更新源文件。顺便说一句,该程序可以设置为无与伦比,但用户可以让它“忘记”随机规则,从而使其成为可击败的。
感谢所有回复的人。下次我会试试 Code Review.SE。
最佳答案
只需将 1.times
block 中的代码重构为它自己的方法即可。而不是 break if move
使用显式 return
运算符以相同的方式:return if move
。
关于ruby - 我怎样才能在我的井字游戏中干掉这段 Ruby 代码? (使用 1.times block !),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40797849/
我的 blockly.js 文件中有以下代码 Blockly.Blocks['account_number'] = { // Other type. init: function() {
首先抱歉我的英语不好,我正在开发 Image Splitter 应用程序并且已经完成,但是现在的要求是当图像被分割(分成几 block /chunks)那么图像 block 的每一 block (ch
#value: 消息的返回值,当发送到一个 block 时,是该 block 中最后一句话的值。所以 [ 1 + 2. 3 + 4. ] value 计算结果为 7。我发现有时很难使用。有没有办法显式
我想构建一个包含 3 div 的响应式导航栏相同的 width和 height . 我申请了 inline-block到每个 block ,我得到一个我不理解的行为。 问题是,第三 block 由 2
我希望使用 Blockly 来允许非技术人员用户指定测试脚本。 它的一部分需要一个文件选择器,但是,我看不到 Blockly 有一个。是吗? 实际上,我找不到完整的标准 block 列表。谁有网址?
仅当您位于父 block 内部时,父 block 的 props.isSelected 才为 true,但当您在该 block 的 innerBlocks 内进行编辑时则不然。 如何从父 block
仅当您位于父 block 内部时,父 block 的 props.isSelected 才为 true,但当您在该 block 的 innerBlocks 内进行编辑时则不然。 如何从父 block
我想创建一个具有不同背景颜色 block 和不同悬停颜色 block 的导航栏 block 。我可以分别创建不同的悬停颜色 block 或不同的背景颜色 block ,但不能一起创建。所以请告诉我如何
我正在使用看到的代码 here定期执行代码: #define DELAY_IN_MS 1000 __block dispatch_time_t next = dispatch_time(DISPATC
为什么 block 必须被复制而不是保留?两者在引擎盖下有什么区别?在什么情况下不需要复制 block (如果有)? 最佳答案 通常,当您分配一个类的实例时,它会进入堆并一直存在,直到它被释放。但是,
我想弄清楚我这样做是否正确: 如果我有一个 block ,我会这样做: __weak MyClass *weakSelf = self; [self performBlock:^{
我想制作一个 4 block 导航菜单,虽然我已经显示了一个 block ,然后单击打开第二个 block ,从第二个开始选择并再次单击出现第三个 block ,第四个 block 相同...这是我的
例如,这样更好吗? try { synchronized (bean) { // Write something } } catch (Int
我想让一只乌龟检查前方小块的颜色并决定移动到哪里。如果前面的补丁不是白色的,那么乌龟向左或向右旋转并移动。我的 If 决策结构中出现错误,显示“此处应为 TRUE?FALSE,而不是 block 列表
我想创建一个 block 对角矩阵,其中对角 block 重复一定次数,非对角 block 都是零矩阵。例如,假设我们从一个矩阵开始: > diag.matrix [,1] [,2] [
我是区 block 链新手。突然我有一个问题,我们是否可以通过区 block 号来访问以太坊区 block 链上之前的区 block 数据。 例如我创建了一个block1、block2。 block
我是区 block 链新手。突然我有一个问题,我们是否可以通过区 block 号来访问以太坊区 block 链上之前的区 block 数据。 例如我创建了一个block1、block2。 block
我创建了一个等距环境,全部使用 Javascript 和 HTML5 (2D Canvas),大部分情况下工作正常。我面临的问题是使用不同高度的图 block ,然后对图 block 上的对象索引进行
这是令我困惑的代码: public Integer getInteger(BlockingQueue queue) { boolean interrupted = false; try
我有一个基于 TPL 数据流的应用程序,它仅使用批处理 block 和操作 block 就可以正常工作。 我已经添加了一个 TransformBlock 以尝试在发布到批处理 block 之前从源中转
我是一名优秀的程序员,十分优秀!