[Game] Javascriptでナンプレ、自動解答機能 レベル2

2016年12月22日

Javascript ゲーム テクノロジー プログラミング 特集

前回までナンプレの操作UIと低レベル自動解凍機能を搭載したが、少し何回な問題を解けなかったので、非常にストレスの残るシステムとなってしまった。 今回は、かなり複雑になったが、少しレベルの高い問題をクリアできるように機能追加を行なってみた。 今のところ手元にある問題はこれでFinishしているので、解けない問題が現れたらさらなるレベルアップを行うとしよう。

今回の機能概要

「中級の自動回答機能」として、以下の処理を実現してます。
縦、横、3x3の箱で比較してみて、有り得ない数値を除外
有り得ないというのを人間の頭で考えるとすぐにわかるのが、いかに計算で出せるかがポイントとなった。

ソースコード

今回の変更点は「numberplace.js」のみだけですが、とりあえず全てのソースコードを載せておきます。 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" /> <title>NumberPlace</title> <meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Cache-Control" content="no-cache"> <meta http-equiv="Expires" content="Thu, 01 Dec 1994 16:00:00 GMT"> <link type='text/css' rel='stylesheet' href='css/numberplace.css' /> <script type='text/javascript' src='js/lib.js'></script> <script type='text/javascript' src='js/numberplace.js'></script> </head> <body class='design_black' data-transition='scroll_stop'> <h1>NumberPlace</h1> <hr> <div id='game'> <table class="numberplace"> <tr><td></td><td></td><td></td> <td></td><td></td><td></td> <td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td> <td></td><td></td><td></td> <td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td> <td></td><td></td><td></td> <td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td> <td></td><td></td><td></td> <td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td> <td></td><td></td><td></td> <td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td> <td></td><td></td><td></td> <td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td> <td></td><td></td><td></td> <td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td> <td></td><td></td><td></td> <td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td> <td></td><td></td><td></td> <td></td><td></td><td></td></tr> </table> </div> <div id="key"> <table class="numberKey"> <tr> <td data-key="1">1</td> <td data-key="2">2</td> <td data-key="3">3</td> </tr> <tr> <td data-key="4">4</td> <td data-key="5">5</td> <td data-key="6">6</td> </tr> <tr> <td data-key="7">7</td> <td data-key="8">8</td> <td data-key="9">9</td> </tr> <tr> <td class="clear" data-key="" colspan="3">clear</td> </tr> </table> </div> <hr> <div> <button id="solve">Solve</button> </div> <div> <button id="clear">Clear</button> <button id="load">Load</button> <button id="save">Save</button> <button id="finish">Finish</button> </div> <hr> <ol id="lists"> </ol> </body> </html> ※CSSファイルは前回と同じです body,html{ width:100%; height:100%; } body{ text-align:center; } #game{ display:inline-block; box-shadow:4px 4px 4px rgba(0,0,0,0.4); margin:auto auto; } table{ border-collapse:collapse; } td{ padding:0; margin:0; } /*numberPlace*/ .numberplace td{ width:32px; height:32px; border:1px solid #666; cursor:pointer; text-align:center; vertical-align:middle; background-color:white; font-size:20px; font-weight:bold; } .numberplace td:hover{ background-color:#DDD; } .numberplace tr:nth-child(1){ border-top:2px solid #000; } .numberplace tr:nth-child(3){ border-bottom:2px solid #000; } .numberplace tr:nth-child(6){ border-bottom:2px solid #000; } .numberplace tr:nth-child(9){ border-bottom:2px solid #000; } .numberplace td:nth-child(1){ border-left:2px solid #000; } .numberplace td:nth-child(3){ border-right:2px solid #000; } .numberplace td:nth-child(6){ border-right:2px solid #000; } .numberplace td:nth-child(9){ border-right:2px solid #000; } /*action*/ #game .numberplace td{ background-color:#FFF; } #game .numberplace td[data-enable="false"]{ background-color:#EEE; } #game .numberplace td[data-enable="active"]{ background-color:#FEE; } #game .numberplace td[data-enable="target"]{ background-color:#FCC; } #game .numberplace td[data-enable="bad"]{ background-color:#CCF; } #game .numberplace td[data-enable="complete"]{ background-color:#FFC; } /*numberKey*/ #key{ position:absolute; display:none; box-shadow:10px 10px 10px rgba(0,0,0,0.4); margin:8px; } .numberKey td{ width:40px; height:40px; background-color:blue; color:white; cont-weight:bold; text-align:center; vertical-align:middle; font-size:32px; border:1px solid white; cursor:pointer; } .numberKey td.clear{ width:auto; background-color:#666; font-size:24px; } .numberKey td:hover{ background-color:red; } .numberKey td:active{ background-color:black; } /*etc*/ button{ margin:8px; font-size:12px; font-weight:bold; cursor:pointer; border:1px solid #CCC; border-radius:4px; padding:8px; } button:hover{ opacity:0.5; } #lists li{ text-align:left; cursor:pointer; font-size:24px; } ※JSライブラリも前回と同じ・・・ !(function(){ var $$={}; /** * Library --------------------- */ /** * Event-Set * param @ t : Target-element * param @ m : mode ["onload"->"load" , "onclick"->"click"] * param @ f : function **/ $$.eventAdd=function(t, m, f){ //other Browser if (t.addEventListener){t.addEventListener(m, f, false)} //IE else{ if(m=='load'){ var body = document.body; if(typeof(body)!='undefined'){body = w;} if((typeof(onload)!='undefined' && typeof(body.onload)!='undefined' && onload == body.onload) || typeof(eval(onload))=='object'){ t.attachEvent('on' + m, function() { f.call(t , window.event); }); } else{f.call(t, w.event)} } else{t.attachEvent('on' + m, function() { f.call(t , window.event); })} } }; /** * Get URL-property * return @ [url , domain , querys{}]; **/ $$.urlProperty=function(url){ if(!url){url=location.href} var res = {}; var urls = url.split("?"); res.url = urls[0]; res.domain = urls[0].split("/")[2]; res.querys={}; if(urls[1]){ var querys = urls[1].split("&"); for(var i=0;i<querys.length;i++){ var keyValue = querys[i].split("="); if(keyValue.length!=2||keyValue[0]===""){continue} res.querys[keyValue[0]] = keyValue[1]; } } return res; }; /** * Ajax * $$.ajax.set({ * url:"**", * method:"POST", * async:true, * query:{}, * querys:[], * onSuccess:function(){} * }); **/ $$.ajax = { createHttpRequest:function(){ //Win ie用 if(window.ActiveXObject){ //MSXML2以降用; try{return new ActiveXObject("Msxml2.XMLHTTP")} catch(e){ //旧MSXML用; try{return new ActiveXObject("Microsoft.XMLHTTP")} catch(e2){return null} } } //Win ie以外のXMLHttpRequestオブジェクト実装ブラウザ用; else if(window.XMLHttpRequest){return new XMLHttpRequest()} else{return null} }, //XMLHttpRequestオブジェクト生成 set:function(options){ if(!options){return} var httpoj = new $$.ajax.createHttpRequest(); if(!httpoj){return;} //open メソッド; option = $$.ajax.setOption(options); httpoj.open( option.method , option.url , option.async ); //type //httpoj.setRequestHeader('Content-Type', option.type); if(typeof option.type != "undefined"){ httpoj.setRequestHeader('Content-Type', option.type); } else{ httpoj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); } //onload-check // httpoj.onreadystatechange = this.readystate(httpoj,option); httpoj.onreadystatechange = function(){ //readyState値は4で受信完了; if (httpoj.readyState==4){ //コールバック option.onSuccess(httpoj.responseText); } }; //query整形 var data = $$.ajax.setQuery(option); //send メソッド if(data.length){ httpoj.send(data.join("&")); } else{ httpoj.send(); } }, dataOption:{ url:"", query:{}, // same-key Nothing querys:[], // same-key OK data:{}, // ETC-data event受渡用 async:"true", // [trye:非同期 false:同期] method:"POST", // [POST / GET] type:"application/x-www-form-urlencoded", // [text/javascript]... //call-back onSuccess:function(res){console.log("Success:"+res)}, onError:function(res){console.log("Error:"+res)} }, setOption:function(options){ var option = {}; for(var i in $$.ajax.dataOption){ if(typeof options[i] != "undefined"){ option[i] = options[i]; } else{ option[i] = $$.ajax.dataOption[i]; } } return option; }, setQuery:function(option){ var data = []; if(typeof option.query != "undefined"){ for(var i in option.query){ data.push(i+"="+encodeURIComponent(option.query[i])); } } if(typeof option.querys != "undefined"){ for(var i=0;i<option.querys.length;i++){ if(typeof option.querys[i] == "Array"){ data.push(option.querys[i][0]+"="+encodeURIComponent(option.querys[i][1])); } else{ var sp = option.querys[i].split("="); data.push(sp[0]+"="+encodeURIComponent(sp[1])); } } } return data; }, _:0 }; //path-info Ex):p=location.href $$.pathinfo = function(p){ var basename="", dirname=[], filename=[], ext=""; var p2 = p.split("?"); var urls = p2[0].split("/"); for(var i=0; i<urls.length-1; i++){ dirname.push(urls[i]); } basename = urls[urls.length-1]; var basenames = basename.split("."); for(var i=0;i<basenames.length-1;i++){ filename.push(basenames[i]); } ext = basenames[basenames.length-1]; return { "hostname":urls[2], "basename":basename, "dirname":dirname.join("/"), "filename":filename.join("."), "extension":ext, "query":(p2[1])?p2[1]:"", "path":p2[0] }; }; $$.urlinfo=function(uri){ if(!uri){uri = location.href} var url = uri; //URLとクエリ分離分解; var query={}; // set-query if(uri.indexOf("?")!=-1){ var sp1 = uri.split("?"); url = sp1[0]; query = $$.getQuery(sp1[1],"&","="); } // semi-colon-split else if(uri.indexOf(";")!=-1){ var sp = uri.split(";"); url = sp[0]; query = $$.getQuery(sp1[1],";","="); } //基本情報取得; var sp = url.split("/"); var selfpath = ""; for(var i=3;i<sp.length;i++){ //selfpaths.push(sp[i]); selfpath += "/"+sp[i]; } var data={ url:url, dirname:this.pathinfo(url).dirname, domain:sp[2], protocol:sp[0].replace(":",""), selfpath:selfpath, query:query }; return data; }; // ex) $$.getQuery("a=1&b=2&c=3","&","="); $$.getQuery = function(data, splitValue, keyValueSplit){ var query = {}; var sp = data.split(splitValue); for(var i=0; i<sp.length; i++){ var sp2 = sp[i].split(keyValueSplit); query[sp2[0]] = sp2[1]; } return query; }; //cookie $$.cookie = { //init-data options:{ name : 'temporary_cookie', day : 0, hour : 0, min : 1, sec : 0 }, //expires date : function(add) { if(!add){add = 0} var exp = new Date(); if(add){ exp.setTime(exp.getTime()+ add); } else{ exp.setTime(exp.getTime() + (this.options.day * 1000 * 60 * 60 * 24) + (this.options.hour * 1000 * 60 * 60) + (this.options.min * 1000 * 60) + (this.options.sec * 1000)); } return exp.toGMTString(); }, //secure-check checkSecure : function() { if (location.href.match(/^https:/)) {return true} else {return false} }, set : function(name, val, addTime) { if(!addTime){addTime = 3600;} if(!name){name = this.options.name} val = this.encode(val); if (this.checkSecure()) { document.cookie = name + "=" + val + ";expires=" + this.date(addTime) + ";secure"; } else { document.cookie = name + "=" + val + ";expires=" + this.date(addTime); } }, del : function(name){ if(!name){name = this.options.name} var exp = new Date(); exp.setTime(exp.getTime()-1); var d = exp.toGMTString(); if (this.checkSecure()) { document.cookie = name + "='';expires=" + d + ";secure"; } else { document.cookie = name + "='';expires=" + d; } }, get : function(name){ return this.val(name); }, val : function(name) { var ck0 = document.cookie.split(" ").join(""); var ck1 = ck0.split(";"); for ( var i = 0; i < ck1.length; i++) { var ck2 = ck1[i].split("="); if (ck2[0] == name) { ck2[1] = this.encode(ck2[1]); return ck2[1]; } } return ''; }, encode:function(val){ if (!val) {return ""} val = val.split("¥r") .join(""); val = val.split("¥n") .join(""); val = val.split("<") .join("-"); val = val.split("%3c").join("-"); val = val.split("%3C").join("-"); val = val.split(">") .join("-"); val = val.split("%3e").join("-"); val = val.split("%3E").join("-"); return val; } }; /** // set-value -> element [ex) $$.getElement("id","#sample")] // type @ [id , class , querySelector] // caution issue return multi-element **/ $$.getElement = function(type , str , num){ //single if(type == "id"){ return document.getElementById(str); } //multi var elements; if(type == "class"){ elements = document.getElementsByClassName(str); } else if(type == "name"){ elements = document.getElementsByName(str); } else if(type == "querySelector"){ elements = document.querySelector(str); } // return-- if(num == "multi"){ return elements; } else if(num == "first"){ return elements[0]; } }; $$.getScriptTag = function(){ var protechScript = document.getElementById("ProtechScript"); if(protechScript == null){return null} return __PROTECH_COMMON.urlinfo(protechScript.src); }; $$.getServiceData = function(service , srcInfo){ if(typeof(__PROTECH_INFO)=="undeifned" || typeof(__PROTECH_INFO.services)=="undeifned"){return null} var data = null; for(var i=0; i<__PROTECH_INFO.services.length; i++){ if(typeof __PROTECH_INFO.services[i] == "undefined"){continue} if(service && service != __PROTECH_INFO.services[i].api){continue} // solid-id if(typeof srcInfo.query.p != "undefined"){ if(typeof __PROTECH_INFO.services[i].pid == "undefined"){continue} if(srcInfo.query.p == __PROTECH_INFO.services[i].pid){ data = __PROTECH_INFO.services[i]; break; } else{continue} } // url-match if(typeof __PROTECH_INFO.services[i]["url"] == "undefined"){continue} if(__PROTECH_INFO.services[i]["url"] == location.href){ data = __PROTECH_INFO.services[i]; break; } } return data; }; /** * Servide Use Function **/ $$.getCookie = function(name){ if(!name || typeof __PROTECH != "undefined" || typeof __PROTECH.cookieName != "undefined" ){name = __PROTECH.cookieName} var cookieData = $$.cookie.get(name); if(!cookieData){ return {"pv":"","uu":"","su":""}; } else{ var sp = cookieData.split("."); return {"uu":sp[0],"su":sp[1],"pv":sp[2]}; } } /** * Log write */ $$.logWrite = function(data){ var uidCookie = $$.getCookie(); var q = [ 'mode=' + 'log', 'd=' + escape(__PROTECH[service].uKey), 'pv=' + escape(uidCookie["pv"]), 'su=' + escape(uidCookie["su"]), 'uu=' + escape(uidCookie["uu"]), 'data=' + escape(data) ]; var sc = document.createElement('script'); sc.src = __PROTECH[service].scriptPath + 'load.php'+'?t='+ (+new Date()) + "&" +q.join("&"); sc.type = 'text/javascript'; sc.async = true; document.body.appendChild(sc); console.log(sc.src); } /** * 62進数 **/ $$.hex62 = { chars:function(){ var str = ""; str += "0123456789"; str += "abcdefghijklmnopqrstuvwxyz"; str += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; return str; }, encode:function(num){ var chars = this.chars(); var cn = chars.length; var str = []; var a1 , a2; while (num != 0) { a1 = parseInt(num / cn); a2 = num - (a1 * cn); str.unshift(chars.substr(a2,1)); num = a1; } var res = str.join(""); res = (!res)?"0":res; return res; }, decode:function(num){ var chars = this.chars(); var char2 = {}; var cn = chars.length; for (var i=0; i< cn; i++) { char2[chars[i]] = i; } var str = 0; for (var i=0; i<num.toString().length; i++) { str += char2[num.substr((i+1)*-1, 1)] * Math.pow(cn, i); } return str; } }; /** * 100進数 **/ $$.digit100 = { chars:function(){ var str = ""; str += "0123456789"; str += "abcdefghijklmnopqrstuvwxyz"; str += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // -+*/@_?,.;:^!#$%&'()[]{}<>=~|`¥ //str += "!"; return str; }, encode:function(num){ var chars = this.chars(); var cn = chars.length; var str = []; var a1 , a2; while (num != 0) { a1 = parseInt(num / cn); a2 = num - (a1 * cn); str.unshift(chars.substr(a2,1)); num = a1; } var res = str.join(""); res = (!res)?"0":res; return res; }, decode:function(num){ var chars = this.chars(); var char2 = {}; var cn = chars.length; for (var i=0; i< cn; i++) { char2[chars[i]] = i; } var str = 0; for (var i=0; i<num.toString().length; i++) { str += char2[num.substr((i+1)*-1, 1)] * Math.pow(cn, i); } return str; } }; // Transformation $$.getPos = function(elm){ //エレメント確認処理 if(!elm){return;} //途中指定のエレメントチェック(指定がない場合はbody) var target = document.body; //デフォルト座標 var pos={x:0,y:0}; do{ //指定エレメントでストップする。 if(elm == target){break} //対象エレメントが存在しない場合はその辞典で終了 if(typeof(elm)=='undefined' || elm==null){break} //座標を足し込む pos.x += elm.offsetLeft; pos.y += elm.offsetTop; } //上位エレメントを参照する while(elm = elm.offsetParent); //最終座標を返す return pos; }; //targetの中心座標にelmの中心座標を移動する。 $$.getPosCenter = function(elm,target){ var pos1 = $$.getPos(target); var size1 = $$.getSize(target); var size2 = $$.getSize(elm); return { x:(pos1.x+(size1.x/2)-(size2.x/2)), y:(pos1.y+(size1.y/2)-(size2.y/2)) }; }; $$.getSize = function(elm){ //対象element if(typeof(elm)=='undefined'){ if (navigator.userAgent.match("MSIE")&&document.compatMode!='BackCompat'){ elm = document.documentElement; } else{ elm = document.getElementsByTagName("body")[0]; } } //サイズ取得; var size={ x:elm.offsetWidth, y:elm.offsetHeight }; //子階層依存※下に1つのみの子を持つ場合サイズチェックを行う; if(elm.childNodes.length==1 && elm.tagName=='A'){ var chk ={ x:elm.childNodes[0].offsetWidth, y:elm.childNodes[0].offsetHeight }; if(chk.x > size.x){ size.x = chk.x; } if(chk.y > size.y){ size.y = chk.y; } } return size; }; //Emveronment $$.getWindowSize = function(){ var d={x:0,y:0}; var e; if(window.innerWidth){ document.x = window.innerWidth; document.y = window.innerHeight; } else if(navigator.userAgent.indexOf("MSIE")!=-1&&document.compatMode=='BackCompat'){ document.x = document.body.clientWidth; document.y = document.body.clientHeight; } else{ document.x = document.documentElement.clientWidth; document.y = document.documentElement.clientHeight; } return d; }; //mouse $$.getMouse = { pos:{x:0,y:0}, proc:function(e){ //IE以外のブラウザ; if(e){ this.pos={ x:e.clientX, y:e.clientY }; } //IE処理; else{ this.pos={ x:event.x, y:event.y }; } } }; window.$$LIB = $$; })(); ※今回の変更点はこのJSファイルのみです。 !(function(){ $$={}; $$.data = { game:null, key :null }; $$.datas = []; $$.targetElm = null; $$.__construct = function(){ // numberplace $$.data.game = document.getElementById("game"); if($$.data.game===null){return} var table = $$.getNumberPlace(); if(table.className !== "numberplace"){return} $$.setClassName(table); $$.setInputEvent(table); // key $$.data.key = document.getElementById("key"); if(key===null){return} var keyTables = $$.data.key.getElementsByTagName("table"); if(!keyTables.length){return} $$.setKeyEvent(keyTables[0]); // Button $$.setButtonLoad(); $$.setButtonSave(); $$.setButtonProgramSave(); $$.setButtonProgramLoad(); $$.setButtonClear(); $$.setButtonFinish(); $$.setButtonSolve(); //load-sample $$.loadSample(); //$$.getCache(); }; $$.setClassName = function(table){ //cells var td = table.getElementsByTagName("td"); // set-array for(var i=0; i<td.length; i++){ td[i].setAttribute("data-num" , i); var classes = []; var row = parseInt(i/9 , 10); classes.push("row-" + row); var col = (i%9); classes.push("col-" + col); var box = Number(parseInt(i/27)*3 ,10) + Number(parseInt(parseInt(i%9 ,10)/3 ,10)); classes.push("box-" + box); td[i].className = classes.join(" "); td[i].setAttribute("data-row" , row); td[i].setAttribute("data-col" , col); td[i].setAttribute("data-box" , box); } }; // Button $$.setButtonClear = function(){ var elm = document.getElementById("clear"); if(elm===null){return} elm.onclick = function(){ $$.clearPazzle(); }; }; $$.setButtonLoad = function(){ var elm = document.getElementById("load"); if(elm===null){return} elm.onclick = function(){ //$$.setLoad(); $$.getCache(); }; }; $$.setButtonSave = function(){ var elm = document.getElementById("save"); if(elm===null){return} elm.onclick = function(){ $$.setSave(); }; }; $$.setButtonProgramSave = function(){ var elm = document.getElementById("programSave"); if(elm===null){return} elm.onclick = function(){ $$.setProgramSave(); }; }; $$.setButtonProgramLoad = function(){ var elm = document.getElementById("programLoad"); if(elm===null){return} elm.onclick = function(){ $$.setProgramLoad(); }; }; $$.clearPazzle = function(){ var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); for(var i=0; i<td.length; i++){ td[i].innerHTML = ""; td[i].setAttribute("data-enable" , ""); } }; $$.setComplete = function(){ var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); for(var i=0; i<td.length; i++){ td[i].setAttribute("data-enable" , "complete"); } }; $$.setSave = function(){ var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); var data = []; var emptyFlg = 0; for(var i=0; i<td.length; i++){ var num = td[i].innerHTML; if(num === ""){ data[i] = "-"; } else{ data[i] = Number(num); } if(td[i].innerHTML!==""){emptyFlg++;} } if(emptyFlg > 0){ var str = $$.getSave_arr2str(data); localStorage.setItem("numberplace", str); } else{ localStorage.removeItem("numberplace"); } }; $$.setProgramSave = function(){ var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); var data = []; var emptyFlg = 0; for(var i=0; i<td.length; i++){ var num = td[i].innerHTML; if(num === ""){ data[i] = "-"; } else{ data[i] = Number(num); } if(td[i].innerHTML!==""){emptyFlg++;} } if(emptyFlg > 0){ var str = $$.getSave_arr2str(data); localStorage.setItem("numberplace_program", str); } else{ localStorage.removeItem("numberplace_program"); } }; $$.setProgramLoad = function(){ var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); var ls = localStorage.getItem("numberplace_program"); if(!ls){return} var data = $$.getSave_str2arr(ls); for(var i=0; i<td.length; i++){ //if(!data[i] || !data[i].match(/[1-9]/)){data[i] = ""} if(!data[i].toString().match(/[1-9]/)){data[i] = ""} td[i].innerHTML = data[i]; } }; $$.getCache = function(){ var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); var ls = localStorage.getItem("numberplace"); if(!ls){return} var data = $$.getSave_str2arr(ls); for(var i=0; i<td.length; i++){ // if(data[i] === 0){data[i] = ""} // if(data[i] === "-"){data[i] = ""} if(!data[i].toString().match(/[1-9]/)){data[i] = ""} td[i].innerHTML = data[i]; } }; $$.getProgramData = function(){ var ls = localStorage.getItem("numberplace_program"); if(!ls){return ""} return $$.getSave_str2arr(ls); }; /** * LocalStorage-Save Value * condition : Numeric (1-digit) */ $$.getSave_arr2str = function(arr){ var str=""; for(var i=0; i<arr.length; i++){ str += arr[i].toString(); } return str; }; $$.getSave_str2arr = function(str){ str = str.replace(/\"/g , ''); var arr=[]; for(var i=0; i<str.length; i++){ arr.push(Number(str.charAt(i))); } return arr; }; $$.loadSample = function(){ $$LIB.ajax.set({ url:"./data/sample.json", method:"GET", async:"true", //type:"text/javascript", //query:{}, onSuccess:function(res){ if(!res){return} var json = JSON.parse(res); var lists = document.getElementById("lists"); for(var i=0; i<json.length; i++){ var li = document.createElement("li"); li.innerHTML = json[i].name; li.setAttribute("data-np" , json[i].data); li.onclick = $$.clickDataLists; lists.appendChild(li); } } }); }; $$.clickDataLists = function(event){ var elm = event.target; var data = elm.getAttribute("data-np"); if(!data){return} $$.setData_list2view(data); } $$.setData_list2view = function(data_np){ if(!data_np){return} var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); var data = $$.getSave_str2arr(data_np); for(var i=0; i<td.length; i++){ if(data[i].toString().match(/[1-9]/)){ td[i].innerHTML = data[i]; td[i].setAttribute("data-enable","false"); } else{ td[i].innerHTML = ""; td[i].setAttribute("data-enable","true"); } } // cache localStorage.setItem("numberplace_program" , data_np); }; /** * Input */ $$.setInputEvent = function(table){ var td = table.getElementsByTagName("td"); for(var i=0; i<td.length; i++){ td[i].onclick = $$.viewKeyElement; } }; $$.viewKeyElement = function(event){ var elm = event.target; if(elm.getAttribute("data-enable") === "false"){return} $$.setCellsColorOn(elm); $$.targetElm = elm; var key = document.getElementById("key"); $$.setKeyPosition(key , elm); }; $$.setKeyPosition = function(key , elm){ var win = $$LIB.getWindowSize(); var pos = $$LIB.getPos(elm); if(pos.x < win.x/2){ key.style.setProperty("right","0",""); key.style.setProperty("left","auto",""); } else{ key.style.setProperty("right","auto",""); key.style.setProperty("left","16px",""); } key.style.setProperty("display","block",""); }; $$.setKeyEvent = function(table){ var td = table.getElementsByTagName("td"); for(var i=0; i<td.length; i++){ td[i].onclick = $$.clickKey; } }; $$.clickKey = function(event){ if($$.targetElm === null){return} //$$.cancelSolveError(); $$.cancelPazzleCheck(); var elm = event.target; var key = document.getElementById("key"); key.style.setProperty("display","none",""); $$.targetElm.innerHTML = elm.getAttribute("data-key"); $$.setCellsColorOff($$.targetElm); $$.targetElm = null; }; $$.setCellsColorOn = function(elm){ if($$.targetElm !== null){ $$.setCellsColorOff($$.targetElm); } // cross var row = elm.getAttribute("data-row"); var rows = $$.data.game.getElementsByClassName("row-"+row); for(var i=0; i<rows.length; i++){ if(rows[i].getAttribute("data-enable") === "false"){continue} if(rows[i] === elm){continue} rows[i].setAttribute("data-enable" , "active"); } var col = elm.getAttribute("data-col"); var cols = $$.data.game.getElementsByClassName("col-"+col); for(var i=0; i<cols.length; i++){ if(cols[i].getAttribute("data-enable") === "false"){continue} if(cols[i] === elm){continue} cols[i].setAttribute("data-enable" , "active"); } //target elm.setAttribute("data-enable" , "target"); }; $$.setCellsColorOff = function(elm){ //cross + target var row = elm.getAttribute("data-row"); var rows = $$.data.game.getElementsByClassName("row-"+row); for(var i=0; i<rows.length; i++){ if(rows[i].getAttribute("data-enable") === "false"){continue} if(rows[i] === elm){continue} rows[i].setAttribute("data-enable" , "true"); } var col = elm.getAttribute("data-col"); var cols = $$.data.game.getElementsByClassName("col-"+col); for(var i=0; i<cols.length; i++){ if(cols[i].getAttribute("data-enable") === "false"){continue} if(cols[i] === elm){continue} cols[i].setAttribute("data-enable" , "true"); } //target elm.setAttribute("data-enable" , "true"); }; /** * Finish */ $$.setButtonFinish = function(){ var elm = document.getElementById("finish"); if(elm===null){return} elm.onclick = function(){ if(!$$.checkPazzle()){ $$.setComplete(); //alert("complete"); } else{ //alert("not fix"); //$$.checkSolve(); } }; }; // return error-count $$.checkPazzle = function(){ var table = $$.getNumberPlace(); //flg var flg = 0; for(var i=0; i<9; i++){ //check-row var rows = table.getElementsByClassName("row-"+i); var arrRow = []; for(var j=0; j<rows.length; j++){ if(rows[i].getAttribute("data-enable") === "false"){continue} var num = rows[j].innerHTML; if(num===""){ flg++; continue; } if(arrRow.indexOf(num)!==-1){ flg++; } arrRow.push(num); } //overlap arrRow = arrRow.filter(function (x, i, self) { return self.indexOf(x) === i && i !== self.lastIndexOf(x); }); for(var j=0; j<rows.length; j++){ var val = rows[j].innerHTML; if(val === ""){ rows[j].setAttribute("data-enable" , "bad"); } else if(arrRow.indexOf(val) != -1){ rows[j].setAttribute("data-enable" , "bad"); } } //check-col var cols = table.getElementsByClassName("col-"+i); var arrCol = []; for(var j=0; j<cols.length; j++){ if(cols[i].getAttribute("data-enable") === "false"){continue} var num = cols[j].innerHTML; if(num===""){ flg++; continue; } if(arrCol.indexOf(num)!==-1){ flg++; } arrCol.push(num); } //overlap arrCol = arrCol.filter(function (x, i, self) { return self.indexOf(x) === i && i !== self.lastIndexOf(x); }); for(var j=0; j<cols.length; j++){ var val = cols[j].innerHTML; if(val === ""){ cols[j].setAttribute("data-enable" , "bad"); } else if(arrCol.indexOf(val) !== -1){ cols[j].setAttribute("data-enable" , "bad"); } } //check-box var boxs = table.getElementsByClassName("box-"+i); var arrBox = []; for(var j=0; j<boxs.length; j++){ if(boxs[i].getAttribute("data-enable") === "false"){continue} var num = boxs[j].innerHTML; if(num===""){ flg++; continue; } if(arrBox.indexOf(num)!==-1){ flg++; } arrBox.push(num); } //overlap arrBox = arrBox.filter(function (x, i, self) { return self.indexOf(x) === i && i !== self.lastIndexOf(x); }); for(var j=0; j<boxs.length; j++){ var val = boxs[j].innerHTML; if(val === ""){ boxs[j].setAttribute("data-enable" , "bad"); } else if(arrBox.indexOf(val) !== -1){ boxs[j].setAttribute("data-enable" , "bad"); } } } return flg; }; $$.clearEnable = function(){ var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); for(var i=0; i<td.length; i++){ if(td[i].getAttribute("data-enable") === "bad"){ td[i].removeAttribute("data-enable"); } } }; $$.cancelPazzleCheck = function(){ var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); for(var i=0; i<td.length; i++){ if(td[i].getAttribute("data-enable")!==null){ td[i].removeAttribute("data-enable"); } } }; /** * Solve */ $$.setButtonSolve = function(){ var elm = document.getElementById("solve"); elm.onclick = $$.solve.action; }; $$.solve = { action:function(){ // Empty-Check if($$.solve.checkAllEmpty()===true){ alert("All empty !!!"); return false; } // First-set $$.solve.setDataTemp(); // Loop-Check var cnt = 0; cnt += $$.solve.loop(1); //$$.solve.debugDataView(); if(!$$.checkPazzle()){ console.log("level1 :" + cnt ); $$.setComplete(); return; } // loop2 cnt += $$.solve.loop2(1); if(!$$.checkPazzle()){ console.log("level2 :" + cnt ); $$.setComplete(); return; } }, // Inition-only setDataTemp:function(){ var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); // set 9.length for(var i=0; i<td.length; i++){ if(td.innerHTML !== ""){ td[i].setAttribute("data-temp","123456789"); } } // temp-data-remove $$.solve.checkFirstAll(); }, checkAllEmpty:function(){ var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); var empty = 0; for(var i=0; i<td.length; i++){ if(td[i].innerHTML!==""){empty++} } if(empty===0){return true}else{return false} }, loop:function(num){ if(!num){num=0} while($$.solve.check()!==0){ num++; } return num; }, loop2:function(num){ if(!num){num=0} while($$.solve.check2()!==0){ num++; } //console.log(num); return num; }, check:function(){ $$.solve.checkFirstAll(); $$.solve.checkUniqueGroupAll(); $$.solve.setTitle_dataTemp(); var cnt = $$.solve.checkUnique(); // remove $$.solve.rmCellDataCheck("row"); $$.solve.rmCellDataCheck("col"); $$.solve.rmCellDataCheck("box"); return cnt; }, check2:function(){ $$.clearEnable(); $$.solve.checkSecond(); $$.solve.checkUniqueGroupAll(); //$$.selve.setDataTempAdjust(); $$.solve.setTitle_dataTemp(); var cnt = 0; cnt += $$.solve.checkUnique(); // remove $$.solve.rmCellDataCheck("row"); $$.solve.rmCellDataCheck("col"); $$.solve.rmCellDataCheck("box"); if(cnt === 0){ cnt += $$.solve.check3(); // remove $$.solve.rmCellDataCheck("row"); $$.solve.rmCellDataCheck("col"); $$.solve.rmCellDataCheck("box"); } return cnt; }, check3:function(){ $$.clearEnable(); $$.solve.checkThird(); $$.solve.checkUniqueGroupAll(); $$.solve.setTitle_dataTemp(); var cnt = 0; cnt += $$.solve.checkUnique(); // remove $$.solve.rmCellDataCheck("row"); $$.solve.rmCellDataCheck("col"); $$.solve.rmCellDataCheck("box"); return cnt; }, rmCellDataCheck:function(key){ var table = $$.getNumberPlace(); // blocks for(var cellNum=0;cellNum<9;cellNum++){ var cell = table.getElementsByClassName(key+"-"+cellNum); // get number var numbers = []; for(var j=0; j<cell.length; j++){ var num = cell[j].innerHTML; if(num !== ""){ numbers.push(num); } } // remove number to data-check for(var j=0; j<cell.length; j++){ if(cell[j].getAttribute("data-temp") == null){continue} else if(cell[j].innerHTML != "" && cell[j].getAttribute("data-temp")!==null){ cell[j].removeAttribute("data-temp"); cell[j].removeAttribute("title"); } else{ var checkNum = cell[j].getAttribute("data-temp"); for(var k=0; k<numbers.length; k++){ checkNum = checkNum.replace(numbers[k] , ""); } cell[j].setAttribute("data-temp" , checkNum); cell[j].setAttribute("title" , checkNum); } } } }, checkFirstAll:function(){ $$.solve.checkFirst("row"); $$.solve.checkFirst("col"); $$.solve.checkFirst("box"); }, checkFirst:function(key){ for(var i=0; i<9; i++){ var tempValues = $$.solve.getGroupValues(key,i); $$.solve.setTemp(key,i,tempValues); } }, // boxを基準にrowとcolの3blockずつのいらない数値削除 checkSecond:function(){ var table = $$.getNumberPlace(); var row = [ ["","",""],["","",""],["","",""], ["","",""],["","",""],["","",""], ["","",""],["","",""],["","",""]]; var col = [ ["","",""],["","",""],["","",""], ["","",""],["","",""],["","",""], ["","",""],["","",""],["","",""]]; var uniqueRow = []; var uniqueCol = []; //getTemp for(var i=0; i<9; i++){ var cells = table.getElementsByClassName("box-"+i); for(var j=0; j<cells.length; j++){ var temp = cells[j].getAttribute("data-temp"); temp = (temp === null)?"":temp; //console.log(i+"="+(parseInt(j/3,10))+"/"+(j%3)); row[i][(parseInt(j/3,10))] += temp; col[i][j%3] += temp; } } //Unique-str for(var i=0; i<9; i++){ for(var j=0; j<3; j++){ row[i][j] = $$.getStrUnique(row[i][j]); col[i][j] = $$.getStrUnique(col[i][j]); } } //Unique-block for(var i=0; i<9; i++){ uniqueRow[i] = $$.getArrayUnique(row[i]); uniqueCol[i] = $$.getArrayUnique(col[i]); } }, //box単位の不要数値検出 checkThird:function(){ var table = $$.getNumberPlace(); var row = [ ["","",""],["","",""],["","",""], ["","",""],["","",""],["","",""], ["","",""],["","",""],["","",""]]; var col = [ ["","",""],["","",""],["","",""], ["","",""],["","",""],["","",""], ["","",""],["","",""],["","",""]]; var uniqueRow = []; var uniqueCol = []; //getTemp for(var i=0; i<9; i++){ var cells = table.getElementsByClassName("box-"+i); for(var j=0; j<cells.length; j++){ var temp = cells[j].getAttribute("data-temp"); temp = (temp === null)?"":temp; row[i][(parseInt(j/3,10))] += temp; col[i][j%3] += temp; } } //Unique-str for(var i=0; i<9; i++){ for(var j=0; j<3; j++){ row[i][j] = $$.getStrUnique(row[i][j]); col[i][j] = $$.getStrUnique(col[i][j]); } } //Unique-block for(var i=0; i<9; i++){ uniqueRow[i] = $$.getArrayUnique(row[i]); uniqueCol[i] = $$.getArrayUnique(col[i]); } // console.log("row2 : "+JSON.stringify(uniqueRow)); // console.log("col2 : "+JSON.stringify(uniqueCol)); //Delete-other-block for(var x=0; x<9; x++){ for(var y=0; y<3; y++){ $$.solve.removeDataTempRow(uniqueRow[x][y],x,y); $$.solve.removeDataTempCol(uniqueCol[x][y],x,y); } } }, // Box -> row|col removeDataTempRow:function(str,x,y){ if(str===""){return} var table = $$.getNumberPlace(); var cells = table.getElementsByClassName("row"+"-"+ (parseInt(x/3,10) *3 +y)); var from = (x%3*3); var to = (x%3*3)+3; for(var i=0; i<cells.length; i++){ if(from<=i && i<to){continue} $$.solve.setSharpen(cells[i],str); } // Multi Cells Check if(str.length>1){ var blankCellsCount = $$.solve.getBlankCellsCountRow(x,y); if(blankCellsCount === str.length){ $$.solve.removeDataTempMultiRow(x,y,str); } } }, // [x:box y:box-line] removeDataTempCol:function(str,x,y){ if(str===""){return} var table = $$.getNumberPlace(); var cells = table.getElementsByClassName("col"+"-"+ (x%3*3 +y)); var from = (parseInt(x/3,10)*3); var to = (parseInt(x/3,10)*3)+3; for(var i=0; i<cells.length; i++){ if(from<=i && i<to){continue} $$.solve.setSharpen(cells[i],str); } // Multi Cells Check if(str.length>1){ var blankCellsCount = $$.solve.getBlankCellsCountCol(x,y); if(blankCellsCount === str.length){ $$.solve.removeDataTempMultiCol(x,y,str); } } }, getBlankCellsCountRow:function(x,y){ var num1 = (parseInt(x/3,10) *3 +y); var from = (x%3*3); var to = (x%3*3)+3; var table = $$.getNumberPlace(); var cells = table.getElementsByClassName("row"+"-"+ num1); var cnt = 0; for(var i=0; i<cells.length; i++){ if(from<=i && i<to){ if(cells[i].innerHTML === ""){cnt++} } } return cnt; }, getBlankCellsCountCol:function(x,y){ var num1 = (x%3*3+y); var from = (parseInt(x/3,10)*3); var to = (parseInt(x/3,10)*3)+3; var table = $$.getNumberPlace(); var cells = table.getElementsByClassName("col"+"-"+ num1); var cnt = 0; for(var i=0; i<cells.length; i++){ if(from<=i && i<to){ if(cells[i].innerHTML === ""){cnt++} } } return cnt; }, removeDataTempMultiRow:function(x,y,str){ var table = $$.getNumberPlace(); var cells = table.getElementsByClassName("box"+"-"+x); for(var i=0; i<cells.length; i++){ if(parseInt(i/3,10)==y){ $$.solve.setExclusion(cells[i],str); } else{ $$.solve.setSharpen(cells[i],str); } } }, removeDataTempMultiCol:function(x,y,str){ var table = $$.getNumberPlace(); var cells = table.getElementsByClassName("box"+"-"+x); for(var i=0; i<cells.length; i++){ if((i%3)==y){ $$.solve.setExclusion(cells[i],str); } else{ $$.solve.setSharpen(cells[i],str); } } }, checkUniqueGroupAll:function(){ $$.solve.checkUniqueGroup("row"); $$.solve.checkUniqueGroup("col"); $$.solve.checkUniqueGroup("box"); }, checkUniqueGroup:function(key){ if(!key){return} var table = $$.getNumberPlace(); // block別に処理 for(var cnt=0; cnt<9; cnt++){ var cells = table.getElementsByClassName(key+"-"+cnt); // Search for single numerical value.(単一数字を探す) for(var num=1; num<=9; num++){ var flg = 0; var elm = null; var targetValue = ""; for(var i=0; i<cells.length; i++){ if(cells[i].innerHTML!==""){continue} var tempValue = cells[i].getAttribute("data-temp"); if(tempValue===null){continue} if(tempValue.indexOf(num)!==-1){ flg++; elm = cells[i]; targetValue = num; } } if(flg!==1 || elm===null || targetValue===""){continue} for(var i=0; i<cells.length; i++){ if(cells[i].innerHTML!==""){continue} var tempValue = cells[i].getAttribute("data-temp"); if(tempValue===null){continue} //対象elm if(cells[i]===elm){ cells[i].setAttribute("data-temp" , targetValue); } //周辺elm(row/col/box) else{ var newValue = tempValue.replace(targetValue,""); cells[i].setAttribute("data-temp" , newValue); } } } } }, checkUnique:function(){ var cnt = 0; var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); for(var i=0; i<td.length; i++){ if(td[i].innerHTML!==""){continue} var temp = td[i].getAttribute("data-temp"); if(temp === null){continue} if(temp && temp.length === 1){ td[i].innerHTML = temp; td[i].removeAttribute("data-temp"); td[i].removeAttribute("title"); //console.log(temp+"/"+td[i].className); cnt++; } } return cnt; }, getGroupValues:function(key,num){ var table = $$.getNumberPlace(); var cells = table.getElementsByClassName(key+"-"+num); var values = ""; for(var i=0; i<cells.length; i++){ var str = cells[i].innerHTML; if(!str){continue} values += str; } values = $$.getStrUnique(values); return values; }, setTemp:function(key,num,values){ var table = $$.getNumberPlace(); var cells = table.getElementsByClassName(key+"-"+num); for(var i=0; i<cells.length; i++){ var str = cells[i].innerHTML; if(str){ $$.solve.removeElementTempData(cells[i]); } else{ $$.solve.setSharpen(cells[i],values); } } }, removeElementTempData:function(elm){ elm.removeAttribute("data-temp"); }, setSharpen:function(elm,delValue){ if(elm.innerHTML!==""){return} var currentValue = elm.getAttribute("data-temp"); if(currentValue===null){return} var newValue = ""; for(var i=0; i<currentValue.length; i++){ var char = currentValue.charAt(i); if(delValue.indexOf(char)!==-1){continue} newValue += char; } newValue = $$.getStrUnique(newValue); //console.log(newValue+"/"+currentValue+"/"+delValue); elm.setAttribute("data-temp" , newValue); }, setExclusion:function(elm,leaveValue){ elm.setAttribute("data-temp" , leaveValue); }, setTitle_dataTemp:function(){ var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); for(var i=0;i<td.length; i++){ var temp = td[i].getAttribute("data-temp"); temp = (temp == null)?"":temp; td[i].title = temp; } }, debugDataView:function(){ var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); var arr=[]; for(var i=0;i<td.length; i++){ var temp = td[i].getAttribute("data-temp"); temp = (temp == null)?"":temp; arr[i] = i+":"+temp; } console.log(JSON.stringify(arr)); } }; /** * Common */ $$.getNumberPlace = function(){ var tables = $$.data.game.getElementsByTagName("table"); return tables[0]; }; $$.getData = function(){ var table = $$.getNumberPlace(); var td = table.getElementsByTagName("td"); var data = []; for(var i=0; i<td.length; i++){ var num = td[i].innerHTML; if(num === ""){ data[i] = "-"; } else{ data[i] = Number(num); } } return $$.getSave_arr2str(data); }; $$.getStrUnique = function(str){ if(str==="" || str===null || str==="undefined" || typeof str !== "string"){return ""} var newStr=[]; for(var i=0; i<str.length; i++){ var char = str.charAt(i); if(newStr.indexOf(char)===-1){ newStr.push(char); } } //sort newStr = newStr.sort(function(a,b){ if( a < b ) return -1; if( a > b ) return 1; return 0; }); return newStr.join(""); }; $$.getArrayUnique = function(arr){ var unique = []; for(var i=0; i<arr.length; i++){ unique[i] = ""; if(arr[i]===""){continue} // currentStr var currentStr = arr[i]; var otherStr = (function(arr,num){ var str = ""; for(var i=0; i<arr.length; i++){ if(num == i){continue} str += arr[i]; } return str; })(arr,i); for(var j=0; j<currentStr.length; j++){ //var flg = 0; var char = currentStr.charAt(j); if(otherStr.indexOf(char)==-1){ unique[i] += char; } } } return unique; }; $$.getRowStr = function(lineNumber){//console.log(lineNumber); var table = $$.getNumberPlace(); var rows = table.getElementsByClassName("row-"+lineNumber); var data = ""; for(var i=0; i<rows.length; i++){ var str = rows[i].innerHTML; if(str!==""){data += str;} } return data; }; $$LIB.eventAdd(window , "load" , $$.__construct); })(); ※12番の問題を追加したのだが、初級レベルで解答できてしまった・・・ [ { "name":"sample-1", "data":"--7---2-----6-4---4----2--8-----1--52---5--1---6-8--7--8-------1--59-8-372-4-----" }, { "name":"sample-2", "data":"--1---3-----9-1--423---7-69--8-6--71---------19----------8-9--6---3---4-42-------" }, { "name":"sample-3", "data":"--2---6-----3-895-7-8--5-------56--8-7--9--2--8----5-----92----5-3----------431--" }, { "name":"sample-4", "data":"--4---3---9---867-12---9--8------725--------49---2-------5----7----6-94-2-8-1--3-" }, { "name":"sample-5", "data":"--2---5---86---------5--71-89--5---2--4-8--3-2--------4----2---7---4--8---9--826-" }, { "name":"sample-6", "data":"--7---3--8------4956------12-3-9-----7---3--6--5--1----8-1--5----4----9-71-2-----" }, { "name":"sample-7", "data":"--9---6--4--2--9------------754--------9-2-8-6------25-4----1979---3-----1--8----" }, { "name":"sample-8", "data":"--6---1--4--1-8-597--2------5-9--4-------6391-67-4-2------7---81------7----4-----" }, { "name":"sample-9", "data":"--6---5--3-1-8--699----5-1-5--6--8----8---1---6-87---------1953---496----1------2" }, { "name":"sample-10", "data":"--9---6--61-----2--5--3-1---7-5-826--62--4--------14-52---6--5-18-----9-9----5---" }, { "name":"sample-11", "data":"6--4-----5----7-9--1--8-3----27----4-5-----6-1----95----9-7--4--8-3----2-----6--3" }, { "name":"sample-12", "data":"2-1---9-7---1-4-----8-3-2--3-------1-5--7--3-9-------8--9-1-6-----2-5---4-7---3-2" } ]

解説

今回は前回の処理$$.solve.check()関数に加えて$$.solve.check2()というのを追加している。 そして、これに付随する関数を山ほど追加しているので、ソースコードから解析するのはなかなか時間がかかると思う。 とりあえず、コードに沿って解説します。 まず概要は以下の通り、ちなみに、6番までは前回と同じで7番からが今回追加した処理。
1. 解凍ボタンを押した時に処理を実行 2. 空欄に対して1~9の数字を仮登録 3. 仮登録した数字の縦、横、3x3の箱、の部分に重複のある数値を仮登録の数値から除外する 4. 縦、横、3x3箱の中で重複する数値の内値を拾って確定数値にする(この時点では仮登録するだけ) 5. 仮登録されている数値のうち、1つしかないものを確定数値として、反映させる。(この時仮登録は削除する) 6. 完了していない場合、3番に戻ってさらに処理をすすめる。※変更点が無くなったら7番に進む 7. 縦よ横の列を3つを1つのブロックとして、単一ブロック以外に値が無い場合に確定ブロックとして、値とセットのデータを作成(※配列「row」と「col」) 8. 確定ブロックを箱単位で縦、横毎に、同じ行と列に同一文字がある場合は、仮登録の値から除外する。 9. この場合変更点が0になるまで7番に戻って繰り返す
8番のBOX毎のユニーク値判定が2段階あり、非常に複雑になっていますが、とりあえず現時点でうまく行っているので、このままGOします。 ※おそらくもう一段階レベルアップする時はリファクタリングすると思います。

ポイント

解説の8番について、図解しておきます。

ブロック数値確定サンプル

次への課題

現時点である程度の難易度レベルの自動解答ができたんですが、ランダムに問題を作成できる機能が作れると、無限にナンプレを楽しめるツールが作成できます。 しかも、難易度の指定もできる問題作成機能があれば、かなり便利だと思いませんか? 毎日ナンプレにTRYして、朝の通勤時などに、脳みそを解すことができそうです。

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。