纯JS实现五子棋

棋盘界面十分简单,不怎么美观,主要实现一下功能。


五子棋界面

首先画20*20的棋盘(横竖都可以放20个棋子),全部可放400颗棋子,每个棋子都对应一个位置(x,y),可以命名一个二维数组,需注意x为列,y为行;每个位置是一个小盒子,盒子有横竖两条线,可以用before和after伪类添加;

var arr=[];
var isBlackFirst=true;
var isGameOver=false;
  //画棋盘
 var element=document.getElementById("content"); 
  //找到id为content的盒子,现在是个空盒子
 for(var n=0;n<400;n++){   //这个棋盘可以下400个棋子
     var y=Math.floor(n/20),x=n%20;  
   //每个棋子都对应一个位置(x,y),可以命名一个二维数组
     //需注意x为行,y为列;
     arr[x]=[];
     arr[x][y]=0;
    //画棋盘网格
     var child=document.createElement("div"); //每个棋子位置是一个小盒子,
       //给小盒子添加样式,用伪元素before和after添加横竖线
         child.className="small";  
         element.appendChild(child);    //为大盒子添加小盒子
伪类添加网格线

棋盘
(function(child,n){
    child.onclick=function(){  
        var y=Math.floor(n/20),x=n%20;  
      /判断游戏是否结束                 
      if(isGameOver)return;//如果游戏结束就直接返回;
     //判断点击位置是否已落子
         //没有落子:arr[x][y]=0;落黑子:arr[x][y]=1;落白子:arr[x][y]=2; 
        if(arr[x][y]==1||arr[x][y]==2){   
               alert("不能重复落子");
        return; //已落子直接返回;
     }
     //判断是否是黑子下,是加黑子,不是就加白子
    if(isBlackFirst){
        arr[x][y]=1;
        child.className=child.className+" small-black";
    }else{
        arr[x][y]=2;
        child.className=child.className+" small-white";
    }
    //用函数checkSuccess(x,y)判断是否赢了
    if(checkSuccess(x,y)){
          var str=isBlackFirst?"黑子赢":"白子赢";   
             //是黑子赢就弹窗黑子赢,不是就弹白子赢
         alert(str);
         isGameOver=true;
    }
    isBlackFirst=!isBlackFirst;//取反;如果是真就变成假;
  }
})(child,n);

落子时需要考虑的几个问题:
1、游戏是否已经结束,如果游戏结束就直接返回;
2、点击位置是否已落子:没有落子:arr[x][y]=0;落黑子:arr[x][y]=1;落白子:arr[x][y]=2; 已落子直接返回;;
3、判断是否是黑子下,是加黑子,不是就加白子;通过增加类名添样式,需要注意层级的设置要比横竖线的层级高,才可以显示在最上面;
4、输赢判断:用函数checkSuccess(x,y)判断是否赢了;是黑子赢就弹窗黑子赢,不是就弹白子赢;若还没有赢,下一次落子的颜色与当前的相反,即 isBlackFirst=!isBlackFirst;取反;如果是真就变成假。

落子位置

不能重复落子

输赢的判断
共有四种情况: 横、竖、左斜、右斜
每落一次子都要判断当前颜色的棋子是否赢了(举个横向判断的例子):
1、横向判断的时候,当前落的子记作左1右0,向左找没有找到边界,并且向左找到的颜色与自己相同,左边的棋子数加1;
2、找到边界或不是相同颜色就向右找,向右找没到边界,并且颜色一样,右边的棋子数加1,如果向右没有找到,则跳出循环;
3、如果向左找到的同颜色的棋子数加上向右找到的同颜色棋子数等于5,说明该颜色的棋子游戏赢了,直接返回游戏结果,后面的情况不用再判断 ;否则继续判断其他三种情况,原理相同。

 function checkSuccess(x,y){
      var isSuccess=false;
      var  cur_play=isBlackFirst?1:2;
      //四种情况  横、竖、左斜、右斜
      //一:判横;
      var  leftNum=1;
      var  rightNum=0;
      var  isLeft=true;  
      for(var n=1;n<=5;n++){
         if(isLeft){    //向左找
            if(x-n>=0&&arr[x-n][y]==cur_play){ 
               //向左找没有找到边界,并且向左找到的颜色与自己相同;
                leftNum++;   //左边的棋子数加1
            }else{    //否则向右找
                    isLeft=false;
                 }
        }else{   //如果isLeft=false,就向右找
              if(x+(n-leftNum)<=19&&arr[x+(n-leftNum)][y]==cur_play){ 
                //向右找没到边界,并且颜色一样;
             rightNum++;   //右边的棋子数加1
              }else{    //如果向右没有找到,跳出循环
                     break;
              }
         }
        if(leftNum+rightNum==5){  
          //如果向左找到的棋子数加上向右找到的棋子数等于5,说明该颜色游戏赢了
         isSuccess=true;
         return isSuccess; //直接返回游戏结果,后面的情况不用再判断          
        }
  }
      //二:判竖(判断方法同上);
      var  topNum=1;
      var  bottomNum=0;
      var isTop=true;
      for(var n=1;n<=5;n++){ 
            if(isTop){
                 if(y-n>=0&&arr[x][y-n]==cur_play){
                     topNum++;
                 }else{
                    isTop=false;
                 }
             }else{
                 if(y+(n-topNum)<=19&&arr[x][y+(n-topNum)]==cur_play){
                         bottomNum++;
                     }else{
                          break;
                     }
             }
            if(topNum+bottomNum==5){
               isSuccess=true;
               return isSuccess;
            }
      }
      //三:判左斜(判断方法同上);
      var  lTopNum=1;
      var  rBottomNum=0; 
      var islTop=true;
      for(var n=1;n<=5;n++){
             if(islTop){
                 if(x-n>=0&&y-n>=0&&arr[x-n][y-n]==cur_play){
                     lTopNum++;
                 }else{
                    islTop=false;
                 }
             }else{
                 if(x+(n-lTopNum)<=19&&y+(n-lTopNum)<=19
                 &&arr[x+(n-lTopNum)][y+(n-lTopNum)]==cur_play){
                         rBottomNum++;
                     }else{
                          break;
                     }
             }
            if(lTopNum+rBottomNum==5){
               isSuccess=true;
               return isSuccess; 
            }
      }
      //四:判右斜(判断方法同上);
      var  rTopNum=1;
      var  lBottomNum=0;
      var isrTop=true;
      for(var n=1;n<=5;n++){
             if(isrTop){
                 if(x+n<=19&&y-n>=0&&arr[x+n][y-n]==cur_play){
                     rTopNum++;
                 }else{
                    isrTop=false;
                 }
             }else{
                 if(x-(n-rTopNum)>=0&&y+(n-rTopNum)<=19
                 &&arr[x-(n-rTopNum)][y+(n-rTopNum)]==cur_play){
                         lBottomNum++;
                     }else{
                          break;
                     }
             }
            if(rTopNum+lBottomNum==5){
               isSuccess=true;
               return isSuccess;
            }
      }
}

外部css样式

body {
    margin:50px;    
    text-align:center;
    background-color:#92CEA4;
    }
h1{
    color: rgba(23, 22, 22, 0.57);
    font-weight:bold;
    line-height:30px;
    font-size:20px;
    font-family:Arial,times;
    }
#content{
    width:800px;
    height:800px;
    border:1px solid #000;
    margin:10px auto;
    padding:0;
    text-align:left;    
    overflow: hidden;
    }   

.small{
     width:40px;
     height:40px;
     border:0px solid #000;
     float:left;
     position:relative;
     display:inline-block;
     }
.small:before{
     left:0;
     position: absolute;    
     top:20px;      
     width:40px;    
     height:1px;    
     background:#000;       
     content:"";    
     z-index:-1;
     }  
.small:after{
     position: absolute;    
     top:0px;   
     left:20px;         
     width:1px;     
     height:40px;   
     background:#000;           
     content:"";
     z-index:-1;
     }  
.small:hover:after, .small:hover:before {
     background-color: yellow;
     }
.small-white{
     border-radius:20px;
     background:radial-gradient(10px 10px at 10px 10px,#fff,#e2e2e2);
     box-shadow:2px 2px 4px rgba(0,0,0,0.3);
    }
.small-black{
     border-radius:20px;
     background:radial-gradient(10px 10px at 10px 10px,#fff,#333);
     box-shadow:2px 2px 4px rgba(0,0,0,0.4);
    }     

好了,可以开始游戏了。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容