Idea to Code

アイデアをコードへ
独学でプログラミング関係にいろいろ手を出すサイト

hawk

HTA

ピクロス2017/08/13

HTAでピクロスを作ってみた。

picross.htamain.jsstyle.cssを同じフォルダに配置し、picross.htaを起動することで動作する。


起動するとマス数を入力するプロンプトが表示される。



数字を入力しOKを押下するとメイン画面が表示される。



マスを左クリックすると開けることができ、右クリックすると空白マスとして開けることができる。



checkボタンを押すと正解不正解の判定を行うことができる。



answerボタンを押すと正解を確認することができる。



rボタンを押すと、マス数を入力するプロンプトが表示され、再度新しく開始することができる。

picross.hta
<!DOCTYPE html>
<html="ja">
  <head>
    <HTA:APPLICATION  SCROLL="no" />
    <meta charset="utf-8">
    <title>picross</title>
    <script src="http://code.jquery.com/jquery-1.5.1.min.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css">
  </head>
  <body>
    <table border="0" cellspacing="0" cellpadding="2" id="field"></table>
    <input type="button" value="check" id="check"/>
    <input type="button" value="answer" id="answer" />
    <input type="button" value="r" id="reload" />
    <script type="text/javascript" language="JavaScript" src="main.js"></script>
  </body>
</html>
main.js
var tds = new Array();                    // tdタグ配列

var field = $("#field");                  // 表示フィールド
var tr;                            // trタグ生成用

var n;                            // 縦横のマス数

var masu_size = "22px";                    // マスの縦横のpx数
var batu = "×";                        // バツ印を設定

var color_gray = "#eee";                  // 灰色を定義

// 0~numまでの乱数を返す(整数)
var randNum = function(num){
  return(Math.floor(Math.random()*(num+1)));
}

n = prompt("n*nマスのnを入力してください。", 5);        // クリックする部分のマス数
var len = Math.ceil(n/2);                  // 数字部の最大マス数
var max_len = n*1 + len*1;                  // マスの最大長(*1で文字列から数値に変換している)
//max_len = parseInt(n) + parseInt(len);          // 本来はこうやる?

// タグ作成・初期化
for(var i=0; i<max_len; i++){                // 最大長分繰り返す
  tr = $("<tr/>");                    // trタグ生成
  tds[i] = new Array();                  // tdタブ用配列生成
  for(var j=0; j<max_len; j++){              // 最大長分繰り返す
    tds[i][j] = $("<td/>");                // tdタグ生成
    tds[i][j].css("background",color_gray);        // 背景を灰色に
    if(i>=len && j>=len){                // 描画フィールドなら(クリックできるマス)
      tds[i][j].value = randNum(2)>0?1:0;        // ランダム(66%)にマスを設定
      tds[i][j].css("border","1px solid #000")    // 線を表示
      .css("width", masu_size).css("height", masu_size)  // 縦横のサイズを設定
      .click(                      // 左クリックされたら
        (function(){                // 一時関数宣言
          var x = j;                // jを保持
          var y = i;                // iを保持
          tds[y][x].flag = false;          // クリックフラグを初期化
          return function(){            // クリックに反応するクロージャを返す
            tds[y][x].flag = !tds[y][x].flag;  // フラグを切り替え
            tds[y][x].css("background", tds[y][x].flag?"#aaf":color_gray)  // 背景をフラグが真なら青、偽なら灰色にする
            .html(" ");              // xが付いている場合があるので空白にする
          };
        })()
      ).bind('contextmenu',              // 右クリックされたら
        (function(){                // 一時関数宣言
          var x = j;                // jを保持
          var y = i;                // iを保持
          return function(){            // クリックに反応するクロージャを返す
            tds[y][x].flag = false;        // フラグを切り替え
            if(tds[y][x].html() == batu){    // バツが付いているなら
              tds[y][x].css("background", color_gray)  // 背景を灰色にする
              .html(" ");            // バツを取る
            }
            else {                // バツが付いていないなら
              tds[y][x].css("background", "#ee8")  // 背景を黄色にする
              .html(batu);          // バツを付ける
            }
            return false;            // 本来の右クリック抑止
          };
        })()
      ).html(" ");                  // 空白を設定
    }
    tr.append(tds[i][j]);                // trに追加
  }
  field.append(tr);                    // フィールドに追加
}

var tmp_arr;                        // 数字部演算用
var temp_index;                        // 数字部演算用

// 左側数字部設定
for(var i=0; i<n; i++){                    // マス数繰り返す
  tmp_arr = new Array();                  // 配列を生成
  tmp_index = 0;                      // インデックスを初期化
  tmp_arr[0] = 0;                      // 先頭要素初期化
  for(var j=0; j<n; j++){                  // マス数繰り返す
    if(tds[len+i][len+j].value){            // 値が真(1)なら
      if(tmp_arr[tmp_index] == undefined)        // 未カウントなら
        tmp_arr[tmp_index] = 1;            // 1を設定
      else                      // カウントされているなら
        tmp_arr[tmp_index]++;            // 記録用配列インクリメント
    }else{                        // 値が偽(0)なら
      if(tmp_arr[tmp_index] > 0)            // tmp_index番目の値が0より大きいなら(すでにカウントされている)
        tmp_index++;                // tmp_indexをインクリメント
    }
  }
  for(var j=0; j<tmp_arr.length; j++){          // tmp_arrの要素数繰り返す
    tds[i+len][len-j-1].html(tmp_arr[tmp_arr.length-1-j]) // 数字を設定
    .css("width",masu_size);              // 横幅を設定
  }
}
// 上部数字部設定
for(var i=0; i<n; i++){                    // マス数繰り返す
  tmp_arr = new Array();                  // 配列を生成
  tmp_index = 0;                      // インデックスを初期化
  tmp_arr[0] = 0;                      // 先頭要素初期化
  for(var j=0; j<n; j++){                  // マス数繰り返す
    if(tds[len+j][len+i].value){            // 値が真(1)なら
      if(tmp_arr[tmp_index] == undefined)        // 未カウントなら
        tmp_arr[tmp_index] = 1;            // 1を設定
      else                      // カウントされているなら
        tmp_arr[tmp_index]++;            // 記録用配列インクリメント
    }else{                        // 値が偽(0)なら
      if(tmp_arr[tmp_index] > 0)            // tmp_index番目の値が0より大きいなら
        tmp_index++;                // tmp_indexをインクリメント
    }
  }
  for(var j=0; j<tmp_arr.length; j++){          // tmp_arrの要素数繰り返す
    tds[len-1-j][len+i].html(tmp_arr[tmp_arr.length-1-j])// 数字を設定
    .css("height",masu_size);              // 高さを設定
  }
}

// checkボタン設定
$("#check").click(                      // クリックされたら
  function(){                        // 一時関数宣言
    for(var i=0; i<n; i++){                // マス数繰り返す
      for(var j=0; j<n; j++){              // マス数繰り返す
        if(tds[len+i][len+j].value != tds[len+i][len+j].flag)  // 値とフラグが異なるなら(値は固定、フラグは左クリックで変わる)
          break;                  // 途中でブレイク
      }
      if(j<n)                      // 途中でブレイクしているなら
        break;                    // 途中でブレイク
    }
    alert((i==n && j==n)?"正解":"不正解");        // ループが最後まで回っていれば正解、途中で終わっていれば不正解
  }
);

// answerボタン設定
$("#answer").click(                      // クリックされたら
  (function(){                      // 一時関数宣言
    var f = false;                    // 表示フラグ初期化
    return(
      function(){                    // クロージャ
        f = !f;                    // フラグ切り替え
        for(var i=0; i<n; i++)
          for(var j=0; j<n; j++)
            if(tds[len+i][len+j].value){    // valueが1なら(1=true)
              tds[len+i][len+j].css("border",f?"4px solid #f22":"1px solid #000") // fが真なら赤太線、偽なら黒細線
              .css("width",f?(parseInt(masu_size)-6)+"px":masu_size).css("height",f?(parseInt(masu_size)-6)+"px":masu_size);  // 線分(2*(4px-1)=6px)変わる
            }
      }
    );
  })()
);

// rボタン設定
$("#reload").click(
  function(){
    location.reload();                  // リロードする
  }
);
style.css
#field{
  border:1px solid #555;
  margin:0px;
  padding:0px;
  background:#000;
  font-size:14px;
}
#field tr{
  margin:0px;
  padding:0px;
}
#field td{
  margin:0px;
  padding:0px;
  cursor: pointer;
  text-align:center;
  vertical-align:middle;
}
input {
  margin-top:5px;
}