Javascript:范围效果尽管执行顺序

时间:2015-12-29 18:21:54

标签: javascript jquery scope

请注意:这不是关于范围的问题本身。我理解为了使代码工作,我应该对变量板进行深度复制,而不是分配var tboard = board。但是,我不清楚为什么制作浅拷贝具有我在下面描述的效果。

我遇到了令人困惑的事情。基本上,全局变量(板)会被改变,我不知道如何。 board在函数NewGame()(从select()调用)中初始化为空数组。在初始化之后,在用户单击板上的方块之前不会调用任何其他内容(假设用户为简单起见选择了X)。当发生这种情况时,调用函数playerMove()。令人困惑的是,playerMove()顶部的console.log(board)打印出一个数组,其中x是点击位置,os是其他地方(即非空)。这很奇怪,因为在select()(称为NewGame())结束时,该板是空的,其间不会发生任何其他事情。为了演示这一点,我打印出每个函数顶部的函数名称,并在select()函数和playerMove()函数中打印出board变量,以显示它在没有其他任何调用的情况下发生了变化。请注意,要获得此行为,请刷新页面(否则board变量将从os开始)。我认为这在某种程度上必须是范围问题(因为我没有制作一个深层的董事会副本),但这很奇怪,因为我不知道被调用的是什么,在变量被播放到playerMove的顶部之前更改变量( )。

以下是我的笔和代码的链接:http://codepen.io/joshlevy89/pen/MKjxop?editors=101

$(document).ready(function() {
var pSym; // player's symbol
var cSym; // computer's symbol
var board;
var whosMove; // can be "player" or "computer" or "neither"
var gameOver;

setup();

$("#newgame").on('click', '#X', select);
$("#newgame").on('click', '#O', select);
$("#restart").on('click', setup);
$("table").on('click', 'td', playerMove);

function playerMove()
{
  console.log('playerMove');
  console.log(board);
  if (whosMove === "player")
  {
   var val = $(this).data('value');
   $('#g' + val).text(pSym);
   var arr = PositionToCoords(val);
   board[arr[0]][arr[1]] = pSym;
   var tboard = board;
   var gc = gameCheck(tboard);
  if (gc>=0)
  {
   endGame(gc);
   setTimeout(function(){setup();}, 1000);
   return;
  }
  whosMove = "computer";
  computerMove();


 }
 }

function computerMove() {
console.log('computerMove');
//var p1 = Math.floor(Math.random() * 3);
//var p2 = Math.floor(Math.random() * 3);
var tboard = board;
var pos = chooseMove(tboard);
var arr = PositionToCoords(pos);
board[arr[0]][arr[1]] = cSym;
DrawPosition(arr[0], arr[1], cSym);
var tboard = board;
var gc = gameCheck(tboard);
if (gc>=0) {
endGame(gc);
setTimeout(function(){setup();}, 1000);
return;
}
whosMove = "player";
}

function chooseMove(inboard) {
console.log('chooseMove');
// get the possible moves
var moves=[];
var scores = [];
for (var i=1;i<10;i++) {
var arr = PositionToCoords(i);
if (inboard[arr[0]][arr[1]] === undefined) {
moves.push(i);
var tboard = inboard;
tboard[arr[0]][arr[1]] = cSym;
var gc = gameCheck(tboard);
scores.push(gc);
}
}
//console.log(moves);    
//console.log(scores);
return moves[0]; // TEMPORARY
}

function endGame(gc) {
console.log('endGame');
var str;
if (gc===1) { // somebody won
if (whosMove==="player"){
str = "You Won!"
}
else {
str = "You Lost :(";
}
}
else if (gc === 0){//draw
str = "It's a draw."
}

html = '<div id="closer">' + str + '</div>';
$('#endgame').html(html);
}

function gameCheck(tboard) {
console.log('gameCheck');
// get symbol to check for
var sym;
if (whosMove === "player") {
sym = pSym;
} else {
sym = cSym;
}

// check if in a row
var hrow;
var vrow;
// check for horizonal row
for (var i = 0; i < 3; i++) {
hrow = true;
vrow = true;
for (var j = 0; j < 3; j++) {
if (tboard[i][j] !== sym) {
hrow = false;
}
if (tboard[j][i] !== sym) {
vrow = false;
}
}
if ((hrow) || (vrow)) {
return 1;
}
}

var fdrow = true;
var bdrow = true;
for (var i = 0; i < 3; i++) {
if (tboard[i][i] !== sym) {
fdrow = false;
}
if (tboard[i][2 - i] !== sym) {
bdrow = false;
}
}
if ((fdrow) || (bdrow)) {
return 1;
}
// otherwise, check if board is full 
var full = true;
for (var i = 1; i < 10; i++) {
var arr = PositionToCoords(i);
if (tboard[arr[0]][arr[1]] === undefined) {
full = false;
break;
}
}
if (full === true) {
  return 0;
} 
// if neither 0 (tie) or win (1), return -1 (game not over)
return -1;
}

function select() {
console.log('select');
pSym = $(this).data('value');
$('#newgame').html('');
NewGame();
console.log(board);
}

function setup() {
console.log('select');
$('#endgame').html('');
html = '<div id="opener">Xs or Os? <div id="buttons">';
html += '<div id="X" data-value="X" class="btn btn-default">Xs</div>';
html += '<div id="O" data-value="O" class="btn btn-default">Os</div>';
html += '</div></div>';
$('#newgame').html(html);
}

function NewGame() {
console.log('NewGame');
$('td').empty();

board = new Array(3);
for (i = 0; i < 3; i++) {
  board[i] = new Array(3)
};

if (pSym === "X") {
  cSym = "O";
  whosMove = "player";
} else {
  cSym = "X";
whosMove = "computer";
computerMove();
}
}

function DrawPosition(p1, p2, sym) {
console.log('DrawPosition');
var pos = p1 * 3 + (p2 + 1);
$("#g" + pos).text(sym)
}

function PositionToCoords(pos) {
console.log('PositionToCoords');
var p1 = Math.ceil(pos / 3) - 1;
var p2 = ((pos - 1) % 3);
var arr = [p1, p2];
return arr;
}
});

提前致谢。

1 个答案:

答案 0 :(得分:0)

只需在for循环中添加break就可以解决问题。我错过了什么吗?

function refreshMasterTable() {
    xhr = $.ajax({
        type: "GET",
        url: "tablefunctions.aspx?mode=showmastertable",
        success: function (html) {
            $("#tbl_master").html(html);
            prevAjaxReturned = true;
            $('input[type=button]').click(function () {
                var bid, trid;
                bid = (this.id);
                trid = $(this).closest('tr').attr('id');
                if ($("#detail_" + trid).length == 0) {
                    detailShow = true;
                    pointer = $(this).closest('tr');
                    pointer.after("<tr><td colspan=5><div id=detail_" + trid + "></div></td></tr>");
                    $.get("tablefunctions.aspx?mode=showdetailtable&id=" + trid, function (response) {
                        $('#detail_' + trid).html(response);
                    });
                    //need to unbind all the previously attached events
                    $(document).off('click', '#submitMasterData');
                    $(document).on('click', '#submitMasterData', function () {
                        value = $('#name').val();
                        $.get("tablefunctions.aspx?mode=mastertableupdate&id=" + trid + "&name=" + value);
                        refreshMasterTable();
                    });
                } else {
                    detailShow = false;
                    $(this).closest('tr').next("tr").remove();
                }
            });
        }
    });
};