<p>您的复制函数实际上可以很好地复制列表的<em>结构</em>,尽管可以通过使用列表理解来简化它:
<code>new = [[x for x in row] for row in array]</code></p>
<p>问题是<code>copy.deepcopy</code>与<code>copy.deepcopy</code>的区别在于,它没有复制像<code>Rook('black', [0,0])</code>那样的实际游戏片段。
从各种评论中,我得出以下结论:</p>
<ul>
<li>这些片段没有实现^{<cd4>,因此<code>==</code>只是比较内存地址,因此您的副本被认为与<code>deepcopy</code>“不同”(但可能<em>等于</em>原件,事实上,<code>deepcopy</code><em>与原件不同</em>)</li>
<li>工件包括其当前位置,例如<code>[0,0]</code>,移动工件时更新/修改此位置</li>
<li>因此,当向棋盘副本添加对同一棋子的引用时,你的极小极大算法将“移动”所有状态下的棋子,从而创建大量无效的游戏状态</li>
</ul>
<p>以下是一些可能的解决方案,它们增加了所需重构的复杂性,但也增加了(假定的)好处:</p>
<ul>
<li>添加一个<code>copy</code>函数,并在创建“手动”副本时调用该方法,例如在我上面的列表中<code>new = [[copy(x) for x in row] for row in array]</code>;在这里,<code>copy</code>不是一个方法,因为在这些列表中有<code>str</code>和游戏块,并且<code>copy</code>必须对这两个都起作用(对于<code>str</code>,它可以只返回原始的)</li>
<li>与每次复制状态时使用<code>copy</code>函数不同,只在移动<em>游戏块之前创建游戏块的副本,其他所有游戏块可以保持不变;这样,您只需创建一个拷贝,而不是每次移动64个拷贝(不过,您仍然需要创建实际板的拷贝)</li>
<li>完全删除<code>Rook</code>等类,只使用类似<code>"Rb"</code>的字符串表示法来表示“black Rook”或元组<code>("Rook", "black")</code>,不要冗余地包含它们的当前位置,而是在计算可能的移动时从网格本身获取它(这将是一个函数,而不是不再存在的类的方法)</li>
</ul>
<p>前两种方法中使用的<code>copy</code>函数可能看起来很简单:</p>
<pre><code>def copy(piece):
if isinstance(piece, str):
return piece
else:
return type(piece)(piece.color, list(piece.position))
</code></pre>
<p>您还可以在循环/列表理解中的各个部分上使用<code>copy.deepcopy</code>,这可能比使用它复制整个电路板要快一些,但要比定制的<code>copy</code>函数慢得多</p>