使用H5編寫網頁版象棋(原始碼)
阿新 • • 發佈:2019-01-25
//車馬相士將士相馬車 8*11
var qzName=["車","馬","相","仕","將","仕","相","馬","車","炮","炮","兵","兵","兵","兵","兵"];//
var qzRedArray=new Array();
var qzBlackArray=new Array();
var qzArray=new Array();
var body_w=document.body.clientWidth;
var gameType=0;
body_w=body_w%9==0?body_w:body_w-body_w%9 ;//讓座標為整數
body_w=body_w<810?body_w:810;
console.log(document.body.clientWidth+"|"+body_w);
/////////////////////////////////////////////////////
// var b=document.getElementsByTagName('body')[0];
var b=document.getElementById('content');
b.style.textAlign='center';
var np=document.createElement('div');
var nbut=document.createElement('div' );
if(body_w==810){
np.style.width='1.1em';
np.style.float='right';
nbut.style.width='2.5em';
nbut.style.float='right';
nbut.style.padding='1em';
}else{
np.style.width='50%';
np.style.float='right';
nbut.style.width='40%';
nbut.style.float='right' ;
}
np.innerHTML='Good luck';
nbut.innerHTML='重新開始遊戲';
nbut.fontSize=body_w/16+'px';
nbut.style.border='solid 2px red';
nbut.style.borderRadius='20%';
nbut.style.cursor='pointer';
nbut.style.fontWeight='bold';
nbut.style.color='red';
nbut.onclick=function () {
newGameStart();
};
np.id='mark';
np.style.fontFamily='微軟雅黑';
np.style.fontSize=body_w/16+'px';
b.appendChild(nbut);
b.appendChild(np);
///////////////////////////////
//var w=800,h=900;
var w=body_w/9*8,h=w/8*9;
var c=document.createElement('canvas');
var wh=w/2; var hh=h/2; var cell=w/8; var cellh=cell/2;
c.width=w+cell; c.height=h+cell; c.id="can";
b.appendChild(c);
var cxt=c.getContext("2d");
cxt.strokeStyle="#ff0000";
cxt.font=cell*0.8+"px 微軟雅黑";
//座標原點為中心,右下為正,左上為負
cxt.translate(wh+cellh,hh+cellh);
////////////////////////////////////////////////////
var mouseClickCount=0;
var qzRunTime=0;
c.onclick=function(event)
{
mouseClickCount+=1;
console.log("滑鼠點選了 "+mouseClickCount+" 次_____________________________________________________");
var e = event || window.event;
var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
var x = e.pageX || e.clientX + scrollX;
var y = e.pageY || e.clientY + scrollY;
x=x-c.offsetLeft-cellh-wh;y=y-c.offsetTop-cellh-hh;
x=Math.abs(x%cell)>cellh?(x>0?x-x%cell+cell:x-x%cell-cell):x-x%cell;
y=y>0?y-y%cell+cellh:y-y%cell-cellh;
if(gameType==1){
clickHere(x,y);
}else {
np.innerHTML="勝負已分莫強求";
}
console.log ('滑鼠點選的座標x:'+x+' y:'+y);
};
function clickHere(x,y) {
var qzHere=checkXYisEmpty(x,y);//空是true,有則返回棋子obj
var qzChoose=null;
for(i in qzArray){
if(qzArray[i].isChoose==true){
qzChoose=qzArray[i];
}
}
console.log(typeof qzHere);
if(qzHere===true){//點選的地方是空的
if(qzChoose===null){//沒有選中的棋子
console.log("點選的地方是空的,沒有選中的棋子");
}else{//選中的棋子為qzChoose
if(qzChoose.go(x,y)===true){///////////////////////// 完成- 走!////////////////////////////////
qzRunTime+=1;
if(gameType==1){
np.innerHTML="棋局第"+qzRunTime+"步";
}
isJiangJun(qzChoose);
qzChoose.isChoose=false;
}
}
}else {//點選的地方是object
if(qzChoose===null){//沒有選中的棋子
if(qzRunTime%2==0 && qzHere.side=='紅方'){
console.log("紅:之前沒有選中棋子,所以選中點選的棋子,下choose");
qzHere.choose();
}else if(qzRunTime%2==1 && qzHere.side=='黑方'){
console.log("黑:之前沒有選中棋子,所以選中點選的棋子,下choose");
qzHere.choose();
}else{
if(qzRunTime%2==0){
console.log("warn:到紅方了");
np.innerHTML="紅方回合";
}else{
console.log("warn:到黑方了");
np.innerHTML="黑方回合";
}
}
}else{//選中的棋子為qzChoose,點選的是object
if(qzChoose.side==qzHere.side){
console.log("點選的棋子和之前選中的棋子同一邊,所以,選中此棋子");
qzChoose.noChoose();
console.log("typeof qzHere:"+typeof qzHere+',下choose');
qzHere.choose();
}else {
console.log("點選的棋子和之前選中的棋子敵對,所以,嘗試 吃子");
if(qzChoose.go(x,y)===true){///////////////////////// 完成- 走!////////////////////////////////
qzRunTime+=1;
if(gameType==1){
np.innerHTML="棋局第"+qzRunTime+"步";
}
isJiangJun(qzChoose);
qzChoose.isChoose=false;
}
}
}
}
rePut();
}
newGameStart();
function isJiangJun(obj) {
var html='';
for(i in qzBlackArray){
var o=qzBlackArray[i],a=o.x,b=o.y;
if(o.go(qzRedArray[4].x,qzRedArray[4].y,true)===true){
html+='黑方';
o.x=a;o.y=b; rePut();
break;
}
}
for(i in qzRedArray){
var o=qzRedArray[i],a=o.x,b=o.y;
if(o.go(qzBlackArray[4].x,qzBlackArray[4].y,true)===true){
html+='紅方';
o.x=a;o.y=b; rePut();
break;
}
}
if(html!==''){np.innerHTML=html+' :將軍 !'; }
}
function rePut() {
console.log('repout()');
createQiPan();
for(index in qzArray){
var a=qzArray[index];
if(a.isDead){continue;}
createQZ(a.x,a.y,a.name,a.side,a.isChoose);
putQiZi(a);
}
}
function gameOver(side) {
gameType=0;
np.innerHTML=side+'輸了 !';
}
function createQZ(x,y,name,side,ischoose,isDead) {
var qz=new Object();
qz.side=side;
qz.x=x;qz.y=y;
qz.name=name;
qz.isChoose=ischoose?ischoose:false;
qz.isDead=isDead?isDead:false;
qz.goDead=function () {
qz.isDead=true;
if(qz.name=='將'){gameOver(qz.side);}
console.log('createQZ:'+qz.name+' dead')
};
qz.go=function (a,b,c) {
var tryJiangJun=c?c:false;
var theWayCanGo=way(qz,a,b,tryJiangJun);
var is_empty=checkXYisEmpty(a,b);
console.log("createQZ_theWayCanGo:"+theWayCanGo);
if(theWayCanGo===true) {
if (is_empty == true) {
qz.x = a;
qz.y = b;
console.log("createQZ_function_把" + qz.side + "的【" + qz.name + "】移到座標(" + qz.x + "," + qz.y + "】)");
rePut();
return true;
} else if (is_empty.side===qz.side){
console.log('createQZ_function_go_不能這麼走!');
if(!tryJiangJun)np.innerHTML="同陣營 !";
return false;
}else{
if(qz.name=='炮'){
console.log('createQZ_function_go_不能這麼吃,要隔一個子!');
if(!tryJiangJun)np.innerHTML="隔空打炮 !";
return false;
}else{
if(!tryJiangJun)is_empty.goDead();
qz.x = a;
qz.y = b;
console.log("createQZ_function_go_把" + qz.side + "的【" + qz.name + "】移到座標(" + qz.x + "," + qz.y + "】)");
rePut();
return true;
}
}
}else if(theWayCanGo===1&&qz.name=='炮'){
if(is_empty!==true && is_empty.side!==qz.side){
if(!tryJiangJun)is_empty.goDead();
qz.x = a;
qz.y = b;
console.log("createQZ_function_PaoGo_" +is_empty.name+" Dead;把"+ qz.side + "的【" + qz.name + "】移到座標(" + qz.x + "," + qz.y + "】)");
rePut();
return true;
}else {
if(!tryJiangJun)np.innerHTML="禁止打空炮 !";
}
}else {
console.log('warn:go else ????????');
if(!tryJiangJun)np.innerHTML="你走遠了 !";
return false;
}
};
qz.choose=function () {
cxt.beginPath();
cxt.lineWidth=cell/20;
cxt.strokeStyle="#ffff00";
cxt.arc(qz.x,qz.y,cell/2.2,0,Math.PI*2,true);
cxt.stroke();
cxt.closePath();
cxt.lineWidth=1;
qz.isChoose=true;
console.log('createQZ_fun_choose_'+qz.side+" 的 【"+qz.name+"】被選中,座標是:("+qz.x+","+qz.y+")");
};
qz.noChoose=function () {
qz.isChoose=false;
console.log('createQZ_fun_noChoose_'+qz.side+" 的 【"+qz.name+"】被取消選中,原座標是:("+qz.x+","+qz.y+")");
};
// console.log(qz.side+" 已建立:"+qz.name+",座標是:("+qz.x+","+qz.y+")");
return qz;
}
function way(obj,a,b,c){
var tryJiangJun=c?c:false;
var x=obj.x,
y=obj.y,
k=obj.name,
wayResult,
countQiziOnRoad=0;
if(x==a&&y==b){return false}//在原來的位置,沒有移動
console.log("【"+k+"】("+x+","+y+") 在走");
switch (k){
case "車":
if(x==a){//y-b有沒有其它棋子
console.log("沿y軸:現在y="+y+"; 目標y=b("+b);
if(Math.abs(y-b)==cell){return true}
if(b<y){
console.log("b<y往上走,x不變,y減小");
for(var f=y-cell;f>b;f-=cell){
console.log("沿y軸:現在y="+f+"; 目標y=b("+b);
if(checkXYisEmpty(a,f)!==true){//路徑座標上有其它棋子
wayResult=false; //不能走
console.log("不能走");
if(!tryJiangJun)np.innerHTML="車步錯誤";
break;
}else {
wayResult=true; //能走
console.log("能走");
}
}
}else{
console.log("b>y往下走,x不變,y增大");
for(var f=y+cell;f<b;f+=cell){
console.log("沿y軸:現在y="+f+"; 目標y=b("+b);
if(checkXYisEmpty(a,f)!==true){//路徑座標上有其它棋子
wayResult=false; //不能走
console.log("不能走");
if(!tryJiangJun)np.innerHTML="車步錯誤";
break;
}else {
wayResult=true; //能走
console.log("能走");
}
}
}
}
else if(y==b){//x-a有沒有其它棋子
console.log("沿x軸:現在x="+x+"; 目標x=a("+a);
if(Math.abs(x-a)==cell){return true}
if(a<x){
console.log("a<x往左走,y不變,x減小");
for(var f=x-cell;f>a;f-=cell){
console.log("沿x軸:現在x="+f+"; 目標x=a("+a);
if(checkXYisEmpty(f,b)!==true){//路徑座標上有其它棋子
wayResult=false; //不能走
console.log("不能走");
if(!tryJiangJun)np.innerHTML="車步錯誤";
break;
}else {
wayResult=true; //能走
console.log("能走");
}
}
}else{
console.log("a>x往右走,y不變,x增大");
for(var f=x+cell;f<a;f+=cell){
console.log("沿y軸:現在x="+f+"; 目標x=a("+a);
if(checkXYisEmpty(f,b)!==true){//路徑座標上有其它棋子
wayResult=false; //不能走
console.log("不能走");
if(!tryJiangJun)np.innerHTML="車步錯誤";
break;
}else {
wayResult=true; //能走
console.log("能走");
}
}
}
}
else{
wayResult=false; //不能走
// console.log("??不能走");
if(!tryJiangJun)np.innerHTML="車步錯誤 !";
}
break;
case "馬"://xy---ab
if(Math.abs(x-a)==2*cell && Math.abs(y-b)==cell){
if(x<a&&checkXYisEmpty(x+cell,y)===true){
wayResult=true; //能走
}else if(x>a&&checkXYisEmpty(x-cell,y)===true){
wayResult=true; //能走
}else{
wayResult=false; //不能走
if(!tryJiangJun)np.innerHTML="馬步錯誤";
}
}else if(Math.abs(x-a)==cell && Math.abs(y-b)==2*cell){
if(y<b&&checkXYisEmpty(x,y+cell)===true){
wayResult=true; //能走
}else if(y>b&&checkXYisEmpty(x,y-cell)===true){
wayResult=true; //能走
}else{
wayResult=false; //不能走
if(!tryJiangJun)np.innerHTML="馬步錯誤";
}
}
break;
case "相":
if((obj.side=="紅方" && b<0)||(obj.side=="黑方"&&b>0)){
wayResult=false; //不能走
console.log('提示:相不能過河');
if(!tryJiangJun)np.innerHTML="相不能過河";
return wayResult;
}
console.log('相腳:'+(x+a)/2+","+(y+b)/2);
if((Math.abs(x-a)==2*cell )&&( Math.abs(y-b)==2*cell)&&(checkXYisEmpty((x+a)/2,(y+b)/2)===true)){
wayResult=true; //能走
}else{
wayResult=false; //不能走
if(!tryJiangJun)np.innerHTML="相步錯誤";
}
break;
case "仕":
if(Math.abs(x-a)==cell && Math.abs(y-b)==cell&&Math.abs(a)<=cell&&Math.abs(b)>=2.5*cell){
wayResult=true; //能走
}else{
wayResult=false; //不能走
if(!tryJiangJun)np.innerHTML="仕步錯誤";
}
break;
case "將":
if(a==x){
if(Math.abs(y-b)==cell&&Math.abs(a)<=cell&&Math.abs(b)>=2.5*cell){
wayResult=true; //能走
}else{
wayResult=false; //不能走
if(!tryJiangJun)np.innerHTML="將步錯誤";
}
}else if(b==y){
if(Math.abs(a-x)==cell&&Math.abs(a)<=cell&&Math.abs(b)>=2.5*cell){
wayResult=true; //能走
}else{
wayResult=false; //不能走
if(!tryJiangJun)np.innerHTML="將步錯誤";
}
}
break;
case "炮":
if(x==a){//y-b有沒有其它棋子
console.log("沿y軸:現在y="+y+"; 目標y=b("+b);
if(Math.abs(y-b)==cell){return true}
if(b<y){
console.log("b<y往上走,x不變,y減小");
for(var f=y-cell;f>b;f-=cell){
console.log("沿y軸:現在y="+f+"; 目標y=b("+b);
if(checkXYisEmpty(a,f)!==true){//路徑座標上有其它棋子
wayResult=false; //不能走
console.log("不能走");
countQiziOnRoad+=1;
if(countQiziOnRoad==2){
if(!tryJiangJun)np.innerHTML="炮步錯誤";
break;
}
}else {
wayResult=true; //能走
console.log("能走");
}
}
}else{
console.log("b>y往下走,x不變,y增大");
for(var f=y+cell;f<b;f+=cell){
console.log("沿y軸:現在y="+f+"; 目標y=b("+b);
if(checkXYisEmpty(a,f)!==true){//路徑座標上有其它棋子
wayResult=false; //不能走
console.log("不能走");
countQiziOnRoad+=1;
if(countQiziOnRoad==2){
if(!tryJiangJun)np.innerHTML="炮步錯誤";
break;
}
}else {
wayResult=true; //能走
console.log("能走");
}
}
}
}
else if(y==b){//x-a有沒有其它棋子
console.log("沿x軸:現在x="+x+"; 目標x=a("+a);
if(Math.abs(x-a)==cell){return true}
if(a<x){
console.log("a<x往左走,y不變,x減小");
for(var f=x-cell;f>a;f-=cell){
console.log("沿x軸:現在x="+f+"; 目標x=a("+a);
if(checkXYisEmpty(f,b)!==true){//路徑座標上有其它棋子
wayResult=false; //不能走
console.log("不能走");
countQiziOnRoad+=1;
if(countQiziOnRoad==2){
if(!tryJiangJun)np.innerHTML="炮步錯誤";
break;
}
}else {
wayResult=true; //能走
console.log("能走");
}
}
}else{
console.log("a>x往右走,y不變,x增大");
for(var f=x+cell;f<a;f+=cell){
console.log("沿y軸:現在x="+f+"; 目標x=a("+a);
if(checkXYisEmpty(f,b)!==true){//路徑座標上有其它棋子
wayResult=false; //不能走
console.log("不能走");
countQiziOnRoad+=1;
if(countQiziOnRoad==2){
if(!tryJiangJun)np.innerHTML="炮步錯誤";
break;
}
}else {
wayResult=true; //能走
console.log("能走");
}
}
}
}
else{
wayResult=false; //不能走
if(!tryJiangJun)np.innerHTML="炮步錯誤 !";
// console.log("??不能走");
}
break;
case "兵":
if(obj.side=="紅方"){
if(y>0){//未過河
if(x==a&&y-b==cell){
wayResult=true; //能走
}else {
wayResult=false; //不能走
console.log('紅方兵未過河,只能向前走一步!');
if(!tryJiangJun)np.innerHTML="兵步錯誤";
}
}else{//過河
if((Math.abs(x-a)==cell&&y==b)||(a==x&&y-b==cell)){
wayResult=true; //能走
}else {
wayResult=false; //不能走
console.log('紅方兵未過河,只能向 前、左、右 方向走一步!');
if(!tryJiangJun)np.innerHTML="兵步錯誤";
}
}
}else{
if(y<0){//未過河
if(x==a&&y-b==-cell){
wayResult=true; //能走
console.log('黑方兵未過河,能走!');
}else {
wayResult=false; //不能走
console.log('黑方兵未過河,只能向前走一步!');
if(!tryJiangJun)np.innerHTML="兵步錯誤";
}
}else{//過河
if((Math.abs(x-a)==cell&&y==b)||(a==x&&y-b==-cell)){
wayResult=true; //能走
}else {
wayResult=false; //不能走
console.log('黑方兵未過河,只能向 前、左、右 方向走一步!');
if(!tryJiangJun)np.innerHTML="兵步錯誤";
}
}
}
break;
default:
}
if(countQiziOnRoad===1){
return countQiziOnRoad;
}else{
console.log("wayResult:"+wayResult);
return wayResult;
}
}
function checkXYisEmpty(x,y) {
//指定座標上 是否為空,空則true,有棋子則返回棋子的;
// console.log("指定座標上 是否為空,空則true,有棋子則返回棋子的side");
var re;
for(i in qzArray){
if(qzArray[i].isDead===true){re=true;continue}
// console.log("檢測座標:"+x+","+y+" 上有沒有"+qzArray[i].name);
if(qzArray[i].x==x && qzArray[i].y==y){
re= qzArray[i].side+"_"+qzArray[i].name+"_"+qzArray[i].x+","+qzArray[i].y;
console.log(re);
re=qzArray[i];
break;
}else {
re=true;
}
}
console.log("re:"+re);
return re;
}
function putQiZi(object) {
cxt.beginPath();
cxt.arc(object.x,object.y,cell/2,0,Math.PI*2,true);
cxt.fillStyle="#DEB887";
cxt.fill();
cxt.fillStyle=(object.side=="紅方")?"red":"black";
cxt.fillText(object.name,object.x-cell*0.4,object.y+cell*0.3);
cxt.closePath();
if(object.isChoose===true){object.choose()}
// console.log(object.side+""+object.name+",已到位");
}
function newGameStart() {
gameType=1;
createQiPan();
for(index in qzName){
// if(qzName[index]=='兵'){continue}
switch (qzName[index]){
case '炮':
var a=(index==10)?-1:1;
qzRedArray[index]=createQZ(-3*cell*a,2.5*cell,qzName[index],"紅方");
qzBlackArray[index]=createQZ(-3*cell*a,-2.5*cell,qzName[index],"黑方");
break;
case '兵':
qzRedArray[index]=createQZ(-wh+(index-11)*2*cell,1.5*cell,qzName[index],"紅方");
qzBlackArray[index]=createQZ(-wh+(index-11)*2*cell,-1.5*cell,qzName[index],"黑方");
break;
default:
qzRedArray[index]=createQZ(-wh+index*cell,hh,qzName[index],"紅方");
qzBlackArray[index]=createQZ(-wh+index*cell,-hh,qzName[index],"黑方");
}
qzArray=qzRedArray.concat(qzBlackArray);
putQiZi(qzRedArray[index]);
putQiZi(qzBlackArray[index]);
}
console.log('------------紅方先走!(Red First)-------------');
np.innerHTML="紅方先走";
}
function clearCanvas() {
cxt.clearRect(-c.width/2,-c.height/2,c.width,c.height);
}
function createQiPan() {
clearCanvas();
cxt.strokeStyle="#ff0000";
cxt.lineWidth=1;
//橫線
for(var i=0;i<=9;i++){
cxt.moveTo(-wh,-hh+cell*i);
cxt.lineTo(wh,-hh+cell*i);
}
//豎線
for(var i=0;i<=8;i++){
cxt.moveTo(-wh+cell*i,-hh);
if(i!=0 && i!=8){//除兩端外,中間豎線 分為兩段
cxt.lineTo(-wh+cell*i,-cellh);
cxt.moveTo(-wh+cell*i,cellh);
}
cxt.lineTo(-wh+cell*i,hh);
}
//下方‘米’格
cxt.moveTo(-cell,hh);
cxt.lineTo(cell,hh-2*cell);
cxt.moveTo(-cell,hh-2*cell);
cxt.lineTo(cell,hh);
//上方‘米’格
cxt.moveTo(-cell,-hh);
cxt.lineTo(cell,-hh+2*cell);
cxt.moveTo(-cell,-hh+2*cell);
cxt.lineTo(cell,-hh);
cxt.stroke();
//兵位
for(var i=0;i<5;i++){
cxt.beginPath();
cxt.arc(-wh+2*cell*i,1.5*cell,cell/4,0,Math.PI*2,true);
cxt.stroke();
cxt.beginPath();
cxt.arc(wh-2*cell*i,-1.5*cell,cell/4,0,Math.PI*2,true);
cxt.stroke();
}
//炮位
cxt.beginPath();
cxt.arc(-3*cell,2.5*cell,cell/4,0,Math.PI*2,true);
cxt.stroke();
cxt.beginPath();
cxt.arc(3*cell,2.5*cell,cell/4,0,Math.PI*2,true);
cxt.stroke();
cxt.beginPath();
cxt.arc(-3*cell,-2.5*cell,cell/4,0,Math.PI*2,true);
cxt.stroke();
cxt.beginPath();
cxt.arc(3*cell,-2.5*cell,cell/4,0,Math.PI*2,true);
cxt.stroke();
cxt.closePath();
//楚河 漢界
cxt.fillStyle='#ff0000';
cxt.beginPath();
cxt.fillText('楚河',-2.5*cell,0.6*cellh);
cxt.fillText('漢界',1*cell,0.6*cellh);
cxt.closePath();
}