我已经看到了JavaScript中最奇怪的行为,并希望能够深入了解造成这种情况的原因。我做了一个小数独求解器应用程序(下面的代码,也可以在wellsjohnston.com/projects上看到),其中一部分有一个板生成器。当你点击'生成板'或'解决'时,jQuery应该改变按钮来说“创建随机板......”或“解决......”。但是,当它们被点击时,没有任何反应。你会认为这根本不起作用 - 但事实并非如此。当我删除代码以更改按钮(即,删除$('。submit_sudoku_board')。text('solve')时,它突然起作用,并且在单击时发生更改(当然不会返回)。任何人都知道发生了什么事?
TL; DR:代码似乎是异步执行的。当求解/板生成递归函数正在运行时,脚本的其余部分将执行。为什么??
谢谢!
编辑:也添加了HTML代码。对不起,如果它很难看......
$(function(){
$('.submit_sudoku_board').click(function(){
$('.submit_sudoku_board').text('Solving...');
sudoku();
$('.submit_sudoku_board').text('Solve');
});
$('.clear_board').click(function(){
$('.board_input').val('');
});
$('.generate_board').click(function(){
$('.board_input').val('');
$('.generate_board').text('Creating Random Board...');
console.log('creating random board...')
generate_random_board();
console.log('------done creating board-----');
});
});
function sudoku()
{
var sudoku_board = new Array(9);
for(var i = 0; i < 9; i++){
sudoku_board[i] = new Array(9);
}
var cell, valid = true;
for(i = 0; i < 9; ++i)
{
for(var j = 0; j < 9; ++j)
{
cell = '#r' + i + 'c' + j;
if($(cell).val())
{
if(!($(cell).val() > 0 && $(cell).val() < 10))
{
$('.sudoku_message_box').text("Illegal characer found");
valid = false;
break;
}
sudoku_board[i][j] = ($(cell).val());
}else{
sudoku_board[i][j] = 0;
}
}
}
if(valid)
{
var start = new Date().getTime();
var solved = sudoku_solver(sudoku_board, 0, 0);
var end = new Date().getTime();
var solve_time = (end - start)/1000.0;
if(solved)
{
fill_board(sudoku_board);
$('.sudoku_message_box').text("Solve time: " + solve_time + " seconds");
$('.submit_sudoku_board)').text('Solve');
}else{
$('.sudoku_message_box').text("Sudoku puzzle not solvable");
}
}
}
function sudoku_solver(board, row, col){
if(row == 9)
{
return true;
}else if(col == 9)
{
return sudoku_solver(board, row + 1, 0);
}else if(board[row][col] != 0)
{
return sudoku_solver(board, row, col + 1);
}
for(var i = 1; i < 10; i++)
{
if(can_go(board, row, col, i))
{
board[row][col] = i;
if(sudoku_solver(board, row, col + 1))
{
return true;
}
}
}
board[row][col] = 0;
return false;
}
function can_go(board, row, col, val){
for(var i = 0; i < 9; i++)
{
if(board[row][i] == val || board[i][col] == val)
{
return false;
}
}
var subgrid_row;
var subgrid_col;
if(row < 3)
{
subgrid_row = 0;
}else if(row > 5)
{
subgrid_row = 6;
}else{
subgrid_row = 3;
}
if(col < 3)
{
subgrid_col = 0;
}else if(col > 5)
{
subgrid_col = 6;
}else{
subgrid_col = 3;
}
for(i = subgrid_row; i <= subgrid_row + 2; i++)
{
for(var j = subgrid_col; j <= subgrid_col + 2; j++)
{
if(board[i][j] == val)
{
return false;
}
}
}
return true;
}
function fill_board(board){
var cell;
for(i = 0; i < 9; ++i)
{
for(j = 0; j < 9; ++j)
{
if(board[i][j] != 0)
{
cell = '#r' + i + 'c' + j;
($(cell).val(board[i][j]));
}
}
}
}
function generate_random_board(){
var sudoku_board = new Array(9), dummy_board = new Array(9);
for(var i = 0; i < 9; i++){
sudoku_board[i] = new Array(9);
dummy_board[i] = new Array(9);
}
for(i = 0; i < 9; ++i)
{
for(var j = 0; j < 9; ++j)
{
sudoku_board[i][j] = 0;
dummy_board[i][j] = 0;
}
}
var random_range = Math.floor(Math.random()*10)+ 30;
for(i = 0; i < random_range; i++)
{
var random_x=Math.floor(Math.random()*8) + 1; // generate a random number 1-9
var random_y =Math.floor(Math.random()*8) + 1;
var random_val =Math.floor(Math.random()*8) + 1;
if(can_go(sudoku_board, random_x, random_y, random_val))
{
sudoku_board[random_x][random_y] = random_val;
dummy_board[random_x][random_y] = random_val;
}
}
console.log('solving test board');
var solvable = sudoku_solver(dummy_board, 0, 0);
console.log('iteration complete');
if(solvable)
{
console.log('found board');
$('.generate_board').text('Generate Solvable Board');
fill_board(sudoku_board);
}else{
console.log('board failed');
$('.generate_board').text('board not found');
$('.board_input').val('');
generate_random_board();
}
}
<div class="sudoku">
<div class="sudoku_title">
Sudoku Solver in JavaScript
</div>
<form style="position:relative; left:20%; top:25px;">
<table cellspacing=0 cellpadding=0 border=1 style="background-color:#FFFFFF;">
<!-- row 0 -->
<tr>
<td class="board"><input class ="board_input" maxlength="1" maxlength="1" type="text" id="r0c0" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r0c1" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r0c2" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r0c3" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r0c4" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r0c5" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r0c6" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r0c7" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r0c8" size="20" /></td>
</tr>
<!-- row 1 -->
<tr>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r1c0" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r1c1" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r1c2" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r1c3" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r1c4" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r1c5" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r1c6" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r1c7" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r1c8" size="20" /></td>
</tr>
<!-- row 2 -->
<tr>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r2c0" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r2c1" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r2c2" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r2c3" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r2c4" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r2c5" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r2c6" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r2c7" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r2c8" size="20" /></td>
</tr>
<!-- row 3 -->
<tr>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r3c0" size="20" /></td>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r3c1" size="20" /></td>
<td class="board board_horizontal board_vertical"><input class ="board_input" maxlength="1" type="text" id="r3c2" size="20" /></td>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r3c3" size="20" /></td>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r3c4" size="20" /></td>
<td class="board board_horizontal board_vertical"><input class ="board_input" maxlength="1" type="text" id="r3c5" size="20" /></td>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r3c6" size="20" /></td>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r3c7" size="20" /></td>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r3c8" size="20" /></td>
</tr>
<!-- row 4 -->
<tr>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r4c0" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r4c1" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r4c2" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r4c3" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r4c4" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r4c5" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r4c6" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r4c7" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r4c8" size="20" /></td>
</tr>
<!-- row 5 -->
<tr>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r5c0" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r5c1" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r5c2" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r5c3" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r5c4" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r5c5" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r5c6" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r5c7" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r5c8" size="20" /></td>
</tr>
<!-- row 6 -->
<tr>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r6c0" size="20" /></td>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r6c1" size="20" /></td>
<td class="board board_horizontal board_vertical"><input class ="board_input" maxlength="1" type="text" id="r6c2" size="20" /></td>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r6c3" size="20" /></td>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r6c4" size="20" /></td>
<td class="board board_horizontal board_vertical"><input class ="board_input" maxlength="1" type="text" id="r6c5" size="20" /></td>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r6c6" size="20" /></td>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r6c7" size="20" /></td>
<td class="board board_horizontal"><input class ="board_input" maxlength="1" type="text" id="r6c8" size="20" /></td>
</tr>
<!-- row 7 -->
<tr>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r7c0" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r7c1" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r7c2" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r7c3" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r7c4" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r7c5" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r7c6" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r7c7" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r7c8" size="20" /></td>
</tr>
<!-- row 8 -->
<tr>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r8c0" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r8c1" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r8c2" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r8c3" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r8c4" size="20" /></td>
<td class="board board_vertical"><input class ="board_input" maxlength="1" type="text" id="r8c5" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r8c6" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r8c7" size="20" /></td>
<td class="board"><input class ="board_input" maxlength="1" type="text" id="r8c8" size="20" /></td>
</tr>
<!-- end rows -->
</table>
</form>
<div class="sudoku_bottom">
<div class="submit_sudoku_board">
Solve
</div>
<div class="sudoku_message_box">
Enter a Sudoku puzzle into the board
</div>
</div>
<div class="clear_board">
Clear Board
</div>
<div class="generate_board">
Generate Solvable Board
</div>
</div>
答案 0 :(得分:5)
在大多数浏览器中,Javascript在GUI线程上运行。如果您的脚本正在运行,则在您的函数返回之前,GUI不会更新。
允许GUI重新获得控制权并重新绘制此类内容,这会延迟执行实际解决,直到GUI更新为止:
$('.submit_sudoku_board').click(function(){
$('.submit_sudoku_board').text('Solving...');
window.setTimeout(function() {
sudoku();
$('.submit_sudoku_board').text('Solve');
}, 10);
});