老師,為何【贏法統計數組初始化】寫到【贏法種類索引】前面(24--27行)會出現白棋只在(0,0)處下一步,后續不再下棋的狀況?鞠躬感謝?。?/h1>
? ? ? ?
? ? ? ? 按照教程中老師的寫法:將【贏法統計數組初始化】寫在【贏法種類索引】后面(67-71行),本代碼可以正常運行。但我發現將【贏法統計數組初始化】寫在【贏法種類索引】前面時(24-27行),白棋只會在(0,0)處下第一步,后續無動作,且不會彈框。如下圖一所示:
? ? ? ?贏法統計數組myWin[i],computerWin[i]明明只會在【贏法種類索引】后續(139行以后)才會用到,為何在【贏法種類索引】前初始化會對程序造成影響??

? ? ? ? ? ? ? ? ? ? ?圖一:【贏法統計數組初始化】寫在24-27行,錯誤結果
對應錯誤代碼如下:
var?me=true;//下棋方為我方黑棋
var?chessboard=[];//棋盤狀態
var?over=false;//棋局未結束
var?wins=[];//贏法數組
var?myWin=[];//我方贏法統計數組
var?computerWin=[];//電腦方贏法統計數組
for?(var?i=0;i<15;i++)?{
chessboard[i]=[];
for?(var?j=0;?j<15;j++)?{
chessboard[i][j]=0;
}
}//棋盤未落子初始化
for(var?i?=?0;?i?<?15;?i++)?{
wins[i]=[];
for(var?j?=?0;?j?<?15;?j++)?{
wins[i][j]=[];
}
}//贏法數組初始化
for(var?i=0;i<count;i++){
myWin[i]=0;
computerWin[i]=0;
}//贏法統計數組初始化【錯誤位置】
var?count=0;//贏法種類索引
for(var?i=0;i<15;i++){
for(var?j=0;j<11;j++){
for(var?k=0;k<5;k++){
wins[i][j+k][count]=true;
}
count++;
}
}//所有橫向贏法
for(var?i?=?0;?i?<?15;?i++)?{
for(var?j?=?0;?j?<?11;?j++)?{
for(var?k?=?0;?k?<?5;?k++)?{
wins[j+k][i][count]?=?true;
}
count++;
}
}//所有縱向贏法
for(var?i?=?0;?i?<?11;?i++)?{
for(var?j?=?0;?j?<?11;?j++)?{
for(var?k?=?0;?k?<?5;?k++)?{
wins[i+k][j+k][count]?=?true;
}
count++;
}
}//所有斜線贏法
for(var?i?=?0;?i?<?11;?i++)?{
for(var?j?=?14;?j?>?3;?j--)?{
for(var?k?=?0;?k?<?5;?k++)?{
wins[i+k][j-k][count]?=?true;
}
count++;
}
}//所有反斜線贏法
console.log(count);//
/*
for(var?i=0;i<count;i++){
myWin[i]=0;
computerWin[i]=0;
}//贏法統計數組初始化【正確位置】
*/
var?chess=document.getElementById('chess');
var?context=chess.getContext('2d');//返回2D畫布繪圖的環境
context.strokeStyle="#BFBFBF";//設置繪制顏色#BFBFBF
var?logo=new?Image();
logo.src="images/GoBang.png";
logo.onload=function?()?{
context.drawImage(logo,0,0,450,450);//?圖片加載http://www.w3school.com.cn/tags/canvas_drawimage.asp
drawChessBoard();//先logo后棋盤網格,避免網格覆蓋
//test:oneStep(0,0,true);oneStep(1,1,false);
}
var?drawChessBoard=function(){//畫棋盤網格
for?(var?i?=?0;i<15;?i++)?{
context.moveTo(15+i*30,15);
context.lineTo(15+i*30,435);//畫橫線
context.stroke();//貌似可刪除
context.moveTo(15,15+i*30);
context.lineTo(435,15+i*30);//交換XY坐標,畫縱線
context.stroke();
}
}
var?oneStep?=?function(i,j,me){//棋盤索引?下棋方
//以下畫棋子輪廓---------
context.beginPath();
context.arc(15+i*30,15+j*30,13,0,2*Math.PI);//畫弧/圓(圓心X/Y,半徑,起始/終止弧度)
context.closePath();//用弦封閉弧,可刪除
context.stroke();//畫輪廓線,原文刪除
//以下漸變填充棋子--------
var?gradient=context.createRadialGradient(15+i*30+2,15+j*30-2,13,15+i*30+1,15+j*30-1,0);
//返回漸變對象,a圓x/y/R?b圓x/y/R
if(me){
gradient.addColorStop(0,"#0A0A0A");//a圓邊緣顏色#0A0A0A
gradient.addColorStop(1,"#636766");//b圓邊緣顏色#636766
}else{
gradient.addColorStop(0,"#D1D1D1");//a圓邊緣顏色#D1D1D1
gradient.addColorStop(1,"#F9F9F9");//b圓邊緣顏色#F9F9F9
}
//判斷下棋是否為我方(黑)
context.fillStyle=gradient;
//改變純色填充樣式?context.fillStyle="#636766";
context.fill();//填充,默認黑色??
}
chess.onclick=function(e){
if(over){
return;
}//棋局已結束
if(!me){
return;
}
var?x=e.offsetX;
var?y=e.offsetY;//
var?i=Math.floor(x/30);//算出索引
var?j=Math.floor(y/30);
if(chessboard[i][j]==0){//避免在已落子位置?再次落子
oneStep(i,j,me);
chessboard[i][j]=1;
for(var?k=0;k<count;k++){
if(wins[i][j][k]){
myWin[k]++;
computerWin[k]=6;
if(myWin[k]==5){
window.alert("黑棋勝");
over=true;
}
}
}
if(!over){
me=!me;
computerAI();
}
}
}
var?computerAI=function(){
var?myScore=[];
var?computerScore=[];//得分數組
var?max=0;//最高分數
var?u=0,v=0;//最高分數坐標
for(var?i=0;i<15;i++){
myScore[i]=[];
computerScore[i]=[];
for(var?j=0;j<15;j++){
myScore[i][j]=0;
computerScore[i][j]=0;
}
}//得分數組初始化
for(var?i=0;i<15;i++){
for(var?j=0;j<15;j++){
if(chessboard[i][j]==0){//遍歷棋盤上所有未落子的點
for(var?k=0;k<count;k++){//遍歷所有贏法
if(wins[i][j][k]){
if(myWin[k]==1){
myScore[i][j]+=200;
}else?if(myWin[k]==2){
myScore[i][j]+=400;
}else?if(myWin[k]==3){
myScore[i][j]+=2000;
}else?if(myWin[k]==4){
myScore[i][j]+=10000;
}
if(computerWin[k]==1){
computerScore[i][j]+=220;
}else?if(computerWin[k]==2){
computerScore[i][j]+=420;
}else?if(computerWin[k]==3){
computerScore[i][j]+=2100;
}else?if(computerWin[k]==4){
computerScore[i][j]+=20000;
}
}
}
if(myScore[i][j]>max){
max=myScore[i][j];
u=i;
v=j;
}else?if(myScore[i][j]==max){
if(computerScore[i][j]>computerScore[u][v]){
u=i;
v=j;
}
}
if(computerScore[i][j]>max){
max=computerScore[i][j];
u=i;
v=j;
}else?if(computerScore[i][j]==max){
if(myScore[i][j]>myScore[u][v]){
u=i;
v=j;
}
}
}
}
}
oneStep(u,v,false);
chessboard[u][v]=2;
for(var?k=0;k<count;k++){
if(wins[u][v][k]){
computerWin[k]++;
myWin[k]=6;
if(computerWin[k]==5){
? window.alert("白棋勝");
over=true;
}
}
}
if(!over){
me=!me;//輪流下棋
}
}
/*無法判斷勝負????????????
chess.onclick=function(e){
if(over){
return;
}//棋局已結束
var?x=e.offsetX;
var?y=e.offsetY;//?
var?i=Math.floor(x/30);//算出索引
var?j=Math.floor(y/30);
if(chessboard[i][j]==0){//避免在已落子位置?再次落子
oneStep(i,j,me);
if(me){
chessboard[i][j]=1;
for(var?k=0;k<count;k++){
if(wins[i][j][k]){
myWin[k]++;
computerWin[k]=6;//黑子可能占用該種贏法,白子不可能用該種方法贏,顧設為異常值
if(myWin[k]==5){
window.alert("黑棋勝");
over=true;
}
}
}
}else{
chessboard[i][j]=2;
for(var?k=0;k<count;k++){
if(wins[i][j][k]){
computerWin[k]++;
myWin[k]=6;
if(computerWin[k]==5){
window.alert("白棋勝");
over=true;
}
}
}
}
me=!me;//輪流下棋
}
}
*/
? ? ? ?
? ? ? ? 按照教程中老師的寫法:將【贏法統計數組初始化】寫在【贏法種類索引】后面(67-71行),本代碼可以正常運行。但我發現將【贏法統計數組初始化】寫在【贏法種類索引】前面時(24-27行),白棋只會在(0,0)處下第一步,后續無動作,且不會彈框。如下圖一所示:
? ? ? ?贏法統計數組myWin[i],computerWin[i]明明只會在【贏法種類索引】后續(139行以后)才會用到,為何在【贏法種類索引】前初始化會對程序造成影響??
? ? ? ? ? ? ? ? ? ? ?圖一:【贏法統計數組初始化】寫在24-27行,錯誤結果
對應錯誤代碼如下:
var?me=true;//下棋方為我方黑棋 var?chessboard=[];//棋盤狀態 var?over=false;//棋局未結束 var?wins=[];//贏法數組 var?myWin=[];//我方贏法統計數組 var?computerWin=[];//電腦方贏法統計數組 for?(var?i=0;i<15;i++)?{ chessboard[i]=[]; for?(var?j=0;?j<15;j++)?{ chessboard[i][j]=0; } }//棋盤未落子初始化 for(var?i?=?0;?i?<?15;?i++)?{ wins[i]=[]; for(var?j?=?0;?j?<?15;?j++)?{ wins[i][j]=[]; } }//贏法數組初始化 for(var?i=0;i<count;i++){ myWin[i]=0; computerWin[i]=0; }//贏法統計數組初始化【錯誤位置】 var?count=0;//贏法種類索引 for(var?i=0;i<15;i++){ for(var?j=0;j<11;j++){ for(var?k=0;k<5;k++){ wins[i][j+k][count]=true; } count++; } }//所有橫向贏法 for(var?i?=?0;?i?<?15;?i++)?{ for(var?j?=?0;?j?<?11;?j++)?{ for(var?k?=?0;?k?<?5;?k++)?{ wins[j+k][i][count]?=?true; } count++; } }//所有縱向贏法 for(var?i?=?0;?i?<?11;?i++)?{ for(var?j?=?0;?j?<?11;?j++)?{ for(var?k?=?0;?k?<?5;?k++)?{ wins[i+k][j+k][count]?=?true; } count++; } }//所有斜線贏法 for(var?i?=?0;?i?<?11;?i++)?{ for(var?j?=?14;?j?>?3;?j--)?{ for(var?k?=?0;?k?<?5;?k++)?{ wins[i+k][j-k][count]?=?true; } count++; } }//所有反斜線贏法 console.log(count);// /* for(var?i=0;i<count;i++){ myWin[i]=0; computerWin[i]=0; }//贏法統計數組初始化【正確位置】 */ var?chess=document.getElementById('chess'); var?context=chess.getContext('2d');//返回2D畫布繪圖的環境 context.strokeStyle="#BFBFBF";//設置繪制顏色#BFBFBF var?logo=new?Image(); logo.src="images/GoBang.png"; logo.onload=function?()?{ context.drawImage(logo,0,0,450,450);//?圖片加載http://www.w3school.com.cn/tags/canvas_drawimage.asp drawChessBoard();//先logo后棋盤網格,避免網格覆蓋 //test:oneStep(0,0,true);oneStep(1,1,false); } var?drawChessBoard=function(){//畫棋盤網格 for?(var?i?=?0;i<15;?i++)?{ context.moveTo(15+i*30,15); context.lineTo(15+i*30,435);//畫橫線 context.stroke();//貌似可刪除 context.moveTo(15,15+i*30); context.lineTo(435,15+i*30);//交換XY坐標,畫縱線 context.stroke(); } } var?oneStep?=?function(i,j,me){//棋盤索引?下棋方 //以下畫棋子輪廓--------- context.beginPath(); context.arc(15+i*30,15+j*30,13,0,2*Math.PI);//畫弧/圓(圓心X/Y,半徑,起始/終止弧度) context.closePath();//用弦封閉弧,可刪除 context.stroke();//畫輪廓線,原文刪除 //以下漸變填充棋子-------- var?gradient=context.createRadialGradient(15+i*30+2,15+j*30-2,13,15+i*30+1,15+j*30-1,0); //返回漸變對象,a圓x/y/R?b圓x/y/R if(me){ gradient.addColorStop(0,"#0A0A0A");//a圓邊緣顏色#0A0A0A gradient.addColorStop(1,"#636766");//b圓邊緣顏色#636766 }else{ gradient.addColorStop(0,"#D1D1D1");//a圓邊緣顏色#D1D1D1 gradient.addColorStop(1,"#F9F9F9");//b圓邊緣顏色#F9F9F9 } //判斷下棋是否為我方(黑) context.fillStyle=gradient; //改變純色填充樣式?context.fillStyle="#636766"; context.fill();//填充,默認黑色?? } chess.onclick=function(e){ if(over){ return; }//棋局已結束 if(!me){ return; } var?x=e.offsetX; var?y=e.offsetY;// var?i=Math.floor(x/30);//算出索引 var?j=Math.floor(y/30); if(chessboard[i][j]==0){//避免在已落子位置?再次落子 oneStep(i,j,me); chessboard[i][j]=1; for(var?k=0;k<count;k++){ if(wins[i][j][k]){ myWin[k]++; computerWin[k]=6; if(myWin[k]==5){ window.alert("黑棋勝"); over=true; } } } if(!over){ me=!me; computerAI(); } } } var?computerAI=function(){ var?myScore=[]; var?computerScore=[];//得分數組 var?max=0;//最高分數 var?u=0,v=0;//最高分數坐標 for(var?i=0;i<15;i++){ myScore[i]=[]; computerScore[i]=[]; for(var?j=0;j<15;j++){ myScore[i][j]=0; computerScore[i][j]=0; } }//得分數組初始化 for(var?i=0;i<15;i++){ for(var?j=0;j<15;j++){ if(chessboard[i][j]==0){//遍歷棋盤上所有未落子的點 for(var?k=0;k<count;k++){//遍歷所有贏法 if(wins[i][j][k]){ if(myWin[k]==1){ myScore[i][j]+=200; }else?if(myWin[k]==2){ myScore[i][j]+=400; }else?if(myWin[k]==3){ myScore[i][j]+=2000; }else?if(myWin[k]==4){ myScore[i][j]+=10000; } if(computerWin[k]==1){ computerScore[i][j]+=220; }else?if(computerWin[k]==2){ computerScore[i][j]+=420; }else?if(computerWin[k]==3){ computerScore[i][j]+=2100; }else?if(computerWin[k]==4){ computerScore[i][j]+=20000; } } } if(myScore[i][j]>max){ max=myScore[i][j]; u=i; v=j; }else?if(myScore[i][j]==max){ if(computerScore[i][j]>computerScore[u][v]){ u=i; v=j; } } if(computerScore[i][j]>max){ max=computerScore[i][j]; u=i; v=j; }else?if(computerScore[i][j]==max){ if(myScore[i][j]>myScore[u][v]){ u=i; v=j; } } } } } oneStep(u,v,false); chessboard[u][v]=2; for(var?k=0;k<count;k++){ if(wins[u][v][k]){ computerWin[k]++; myWin[k]=6; if(computerWin[k]==5){ ? window.alert("白棋勝"); over=true; } } } if(!over){ me=!me;//輪流下棋 } } /*無法判斷勝負???????????? chess.onclick=function(e){ if(over){ return; }//棋局已結束 var?x=e.offsetX; var?y=e.offsetY;//? var?i=Math.floor(x/30);//算出索引 var?j=Math.floor(y/30); if(chessboard[i][j]==0){//避免在已落子位置?再次落子 oneStep(i,j,me); if(me){ chessboard[i][j]=1; for(var?k=0;k<count;k++){ if(wins[i][j][k]){ myWin[k]++; computerWin[k]=6;//黑子可能占用該種贏法,白子不可能用該種方法贏,顧設為異常值 if(myWin[k]==5){ window.alert("黑棋勝"); over=true; } } } }else{ chessboard[i][j]=2; for(var?k=0;k<count;k++){ if(wins[i][j][k]){ computerWin[k]++; myWin[k]=6; if(computerWin[k]==5){ window.alert("白棋勝"); over=true; } } } } me=!me;//輪流下棋 } } */
2016-04-20
javascript的執行順序是從上到下,for(var i=0; i<count; i++)里的count是在后面定義且經過循環自增的,你可以在這里alert(count)看下結果應該是undefiend.
2016-04-14
你把第24-27行刪掉就好了