我试图克隆板,因为每次运行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 in Player(board, ai)最初是我在播放器中注入的一个param。调用者只是简单地为该param发送Board()。
我的minMax函数利用这个副本,操作它来做一些分析。该副本再次是一个副本的董事会,所以它是工作的任何当前的董事会状态,而不影响原来的董事会。
在完成minMax之后,我的makeMove被调用:const moved = Move.makeMove(nextMove.index, currentPlayer, board);
问题是,这里的board应该使用发送给Player的原始板。但我注意到,不知何故,它丢失了该引用,现在正在引用minMaxBoard。为什么?
我也尝试过const minMaxBoard = Board();而不是const minMaxBoard = Object.create(board);,但这导致了problem..which,即minMax函数最终得到了一个全新的板,即empty...which,这不是我希望发送给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是发送到Player的实例Board()。
我也尝试过const minMaxBoard = Board(board.getBoard().slice()),但仍然没有在新板中获得当前板数组的副本。
发布于 2018-07-15 22:17:34
Object.create并不克隆传递给它的对象,而是创建一个新对象,其内部原型是传递的对象。然后,如果您继续引用(并可能发生变异)一个恰好位于原型上的属性,那么它确实会改变原始原型。
如果希望拥有多个独立的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());https://stackoverflow.com/questions/51352568
复制相似问题