view source

JavaScript


document.title = 'ナンプレ';

//https://ja.wikipedia.org/wiki/%E6%95%B0%E7%8B%AC

var numAry = [1,2,3,4,5,6,7,8,9];
var max = 9
var ary = Array.from(Array(max), () => new Array(max));
var ary2 = Array.from(Array(max), () => new Array(max));
var p = 0;

var hideCount = 3;

var setClear = function(x,y){
  for(let i=0;i<max;i++){
    var lineAry = _.shuffle(numAry);
    for(let j=0;j<max;j++){
      ary[i][j] = 0;
      ary2[i][j] = 0;
    }
  }
}

var setBlock3 = function(x,y){
  var randAry1 = _.shuffle(numAry);
  var randAry2 = _.shuffle(numAry);
  var randAry3 = _.shuffle(numAry);
  for(let i=0;i<9;i++){
    if(randAry2[i] === randAry1[i]){
      randAry2 = _.shuffle(numAry);
      i = 0;
    }
  }
  for(let i=0;i<9;i++){
    if(randAry3[i] === randAry1[i] || randAry3[i] === randAry2[i]){
      randAry3 = _.shuffle(numAry);
      i = 0;
    }
  }
  setBlock(0,0,randAry1);
  setBlock(3,3,randAry2);
  setBlock(6,6,randAry3);
}


var setBlock = function(x,y, randAry){
  //var randAry = _.shuffle(numAry);
  //console.log(randAry);
  for(let i=0;i<3;i++){
    for(let j=0;j<3;j++){
      ary[x+i][y+j] = randAry[j*3+i];
      ary2[x+i][y+j] = randAry[j*3+i];
    }
  }
}

//重複チェック
var checkRow = function(i,j,v){
  for(let k=0;k<max;k++){
    if(ary[i][k] === v){
      return false;
    }
  }
  return true;
}

var checkCol = function(i,j,v){
  for(let k=0;k<max;k++){
    if(ary[k][j] === v){
      return false;
    }
  }
  return true;
}

var checkBlock = function(i,j,v){
  var ii = Math.floor(i/3)*3;
  var jj = Math.floor(j/3)*3;

  for(let x=0;x<3;x++){
    for(let y=0;y<3;y++){
      if(ary[ii+x][jj+y] === v){
        return false;
      }
    }
  }
  return true;
}

//使わない
var checkOnlyPos = function(i,j,v){
  var ii = i%3;
  var jj = j%3;
  for(let x=0;x<9;x=x+3){
    for(let y=0;y<9;y=y+3){
      if(ary[ii+x][jj+y] === v){
        return false;
      }
    }
  }
  return true;
}

var setNumber = function(i,j){
  var randAry = _.shuffle(numAry);
  randAry.some(function(v){
    if(
      checkRow(i,j,v) &&
      checkCol(i,j,v) && 
      checkBlock(i,j,v)
    ){
      ary[i][j] = v;
      return true;
    }
  });
  return ary[i][j];
}

var setRetake = function(i){
  console.log('setRetake;'+i)
  for(let k=0;k<9;k++){
    ary[i][k] = 0;
  }
}

var setNumbers = function(x,y){
  var reTakeCount = 0;
  for(let i=0;i<max;i++){
    var isRetake = false;
    for(let j=0;j<max;j++){
      if(ary[i][j] !== 0){continue;}
      setNumber(i,j);
    }
    
    for(let j=0;j<max;j++){
      if(ary[i][j] === 0){
        isRetake = true;
      }
    }
    if(isRetake && reTakeCount < 30){
      reTakeCount++;
      setRetake(i);
      i--;
    }
  }
  console.log(ary);
}

var setStage  =function(){
  var hideAry = [...Array(max*max)].map((_, i) => i);
  hideAry = _.shuffle(hideAry);
  hideAry = hideAry.slice(0, hideCount);
  console.log(hideAry);

  var table = $('<div>',{id:'table'});
  $('#demo').empty();
  $('#demo').append(table);
  console.log(ary);
  ary.forEach(function(rows,i){
    var row = $('<div>');
    row.addClass('flex')
    table.append(row);
    rows.forEach(function(v,j){
      if(v===0){
        setTimeout(function(){
          setNextStage();
        },99);
      }
      //setNextStage();
      var input = $('<input>',{type:'text',min:0,max:9,pattern:'[0-9]'}).val(v)
      var col = $('<div>');
      col.append(input);
      col.addClass('v'+v);
      col.attr({i:i,j:j,v:v});
      row.append(col);
      col.css({width:'calc(90vmin / '+max+')',height:'calc(90vmin / '+max+')'})
      col.css({lineHeight:'calc(90vmin / '+max+')'});
      if(i%3===0 && i !== 0){
        col.css({borderTop:'2px solid #000'});
      }
      if(j%3===0 && j !== 0){
        col.css({borderLeft:'2px solid #000'});
      }

      var isHide = false;
      var ij = j*max+i;
      hideAry.some(function(h){
        if(h===ij){isHide = true;return true;}
      });
      if(isHide){
        col.addClass('hide');
        input.val('');
      } else {
        input.attr({readonly:'readonly'});
      }
      input.on('click', function(){
        if(p>0 && isHide){
          input.val(p).trigger('change');
        }
      });
      input.on('change', function(){
        var n = Number($(this).val());
        if(n === v){
          col.removeClass('hide');
          col.addClass('clear');
        }
        if(isNaN(n)){
          input.val('0');
        }
        if($('.hide').length === 0){
          setTimeout(function(){
            hideCount=hideCount+4;
            if(hideCount>40){hideCount=40;}
            setNextStage();
          },999);
        }
      });
    });
  });

  var ul = $('<ul>');
  [1,2,3,4,5,6,7,8,9].forEach(function(v){
    var li = $('<li>').text(v);
    ul.append(li);
    li.css({width:'calc(90vmin / '+max+')',height:'calc(90vmin / '+max+' - 8px)'})
    li.css({lineHeight:'calc(90vmin / '+max+' - 8px)'});
    li.on('click', function(){
      $('li').removeClass('on');
      li.addClass('on');
      p = v;
    });
  });
  $('#demo').append(ul);
}

var setNextStage  =function(){
  setClear();
  setNumbers();
  setStage();
}

setNextStage();

CSS

html,body{
  overflow:hidden;
}

#demo{
}
#table{
  width:90vmin;
  margin:0 auto;
}

#table.clear{
  background-color:#afa;
}


#table div div{
  box-sizing:border-box;
  border:1px solid #aaa;
  text-align:center;
}
#table input{
  box-sizing:border-box;
  border:0;
  height:100%;
  width:100%;
  text-align:center;
  -webkit-appearance: none;
  margin: 0;
  font-size:4vmin;
}

#table .hide input{
  background-color:#ccc;
}
#table .clear input{
  background-color:#afa;
}

.flex{
  display:flex;
}

.v0{
  background-color:#999;
}

ul{
  width:90vmin;
  margin:0 auto;
  display:flex;
  margin-top:8px;
}
li{
  box-sizing:border-box;
  border:1px solid #333;
  background-color:#ccc;
  text-align:center;
  border-radius:2vmin;
  cursor:pointer;
}
li.on{
  background-color:#eee;
}

HTML

ページのソースを表示 : Ctrl+U , DevTools : F12

view-source:https://hi0a.com/demo/-js/js-game-sudoku/

ABOUT

hi0a.com 「ひまアプリ」は無料で遊べるミニゲームや便利ツールを公開しています。

プログラミング言語の動作デモやWEBデザイン、ソースコード、フロントエンド等の開発者のための技術を公開しています。

必要な機能の関数をコピペ利用したり勉強に活用できます。

プログラムの動作サンプル結果は画面上部に出力表示されています。

環境:最新のブラウザ GoogleChrome / Windows / Android / iPhone 等の端末で動作確認しています。

画像素材や音素材は半分自作でフリー素材配布サイトも利用しています。LINK参照。

動く便利なものが好きなだけで技術自体に興味はないのでコードは汚いです。

途中放置や実験状態、仕様変更、API廃止等で動かないページもあります。