我正在尝试克隆电路板,因为每次我运行minMax时,我的minMax函数都需要一个当前电路板状态的副本。
我最近将es6 Board.js模块从单例转换为(从中导出函数)到闭包(返回函数的函数,因为我想隐藏状态,并且还利用了能够调用函数工厂来创建函数的优势)新的董事会实例。
所以现在Board.js看起来像这样:
Board.js
function Board() {
let board = [
' ', ' ', ' ',
' ', ' ', ' ',
' ', ' ', ' '];
function slotIsOpen(position){
const open = board[position] === ' ';
return open;
}
function getOpenSlots(){
const openSlots = board.filter((slot) => {
return slot === ' '
});
return openSlots;
}
function getBoard() {
return board;
}
function isFull(board){
const emptySlots = board.filter(slot => { return slot === ' '});
return emptySlots.length === 0;
}
function addMoveToBoard(position, player){
board.splice(+position, 1, player.marker);
}
const api = {
addMoveToBoard,
isFull,
getBoard,
getOpenSlots,
slotIsOpen
};
return api;
}
export default Board;
我的 Player.js ,它带有Board()实例:
function Player(board, ai){
async function move({position = -1, currentPlayer = null}){
const minMaxBoard = Object.create(board),
nextMove = await ai.minMax(minMaxBoard, currentPlayer)
if(nextMove){
const moved = Move.makeMove(nextMove.openSpaceIndex, currentPlayer, board);
return moved;
}
}
const player = {
addPlayer
};
return player;
}
export default Player
这是怎么回事:
const minMaxBoard = Object.create(board)
-我创建了板工厂的克隆(或者我认为),然后将其作为Board()的副本发送到我的minMax函数中。 (请牢记board
中的Player(board, ai)
是我注入Player的参数。调用方只是在Board()中发送该参数)。
我的minMax函数利用该副本,操纵它进行一些分析。该副本还是木板的副本,因此无论当前木板的状态如何,它都可以使用,而不会影响原始木板。
完成minMax
之后,我的makeMove
被称为:
const moved = Move.makeMove(nextMove.index, currentPlayer, board);
问题是这里的board
应该与发送到Player的原始板一起使用。但是我注意到它以某种方式丢失了该引用,现在正在引用minMaxBoard。为什么?
我也尝试了const minMaxBoard = Board();
而不是const minMaxBoard = Object.create(board);
,但是这会导致一个问题..那就是minMax函数最终会得到一个全新的空板...这不是什么我想发送到minMax中。我想要发送的当前板的副本具有当前状态。
更新:
我已经对其进行了更改,以尝试提供克隆功能,但仍无法正常工作,每次调用克隆时,我仍然会得到一个新的空白板:
function _Board(board) {
function slotIsOpen(position){
const open = board[position] === EMPTY_CELL;
return open;
}
function getOpenSlots(){
const openSlots = board.filter((slot) => {
return slot === EMPTY_CELL
});
return openSlots;
}
function getBoard() {
return board;
}
function isFull(board){
const emptySlots = board.filter(slot => { return slot === EMPTY_CELL});
return emptySlots.length === 0;
}
function addMoveToBoard(position, marker){
board.splice(position, 1, marker);
}
function clone() {
return Board(board.slice());
}
return {
addMoveToBoard,
clone,
isFull,
getBoard,
getOpenSlots,
slotIsOpen
};
}
function Board() {
return _Board([
' ', ' ', ' ',
' ', ' ', ' ',
' ', ' ', ' ']);
}
export default Board;
然后在 Player.js 中:
const minMaxBoard = board.clone();
const nextMove = await ai.minMax(minMaxBoard, currentPlayer)
但我仍然遇到相同的问题,即克隆每次都以空板结尾,而不是board
的当前状态副本,board
仍然是实例{ {1}}发送到Board()
。
我也尝试了Player
,但是仍然没有在新的Board中获得当前Board阵列的副本。
答案 0 :(得分:0)
Object.create
不会克隆传递给它的对象-而是创建一个新的对象,其内部 prototype 是传递的对象。如果您随后继续引用(并可能变异)恰好在 prototype 上的属性,那么确实会变异原始原型。
如果要拥有Board
的多个独立副本,则每次都需要显式调用Board()
,例如:
function Player(board, ai){
async function move({position = -1, currentPlayer = null}){
// Create an entirely new Board:
const minMaxBoard = Board();
要制作现有电路板的副本,您可能需要Board
接受board
数组的参数才能使用:
const defaultBoard = [
' ', ' ', ' ',
' ', ' ', ' ',
' ', ' ', ' '];
function Board(board = defaultBoard) {
// ...
// other file:
function Player(board, ai){
async function move({position = -1, currentPlayer = null}){
const minMaxBoard = Board(board.getBoard().slice());