ナンプレ(数独)・ゲーム

ナンプレ(数独)は、9×9の81マスのプレートがあり、プレートは更に3×3の9マスの小プレートに分かれています。
全ての縦・横・小プレートに1~9が一つずつ入るように、数字を入力するゲームです。
HTML と JavaScript でスマホでも実行できるナンプレ(数独)・ゲームを作成します。

スマホのゲームは スマホ・ゲームの実行 を参照して下さい。

  1. リソースの説明






    (先頭に透明色の m0.gif)

    メニューアイコンの画像
    メニューアイコンの画像
    メニューアイコンの画像
    メニューアイコンの画像

    ゲームで使うリソースです。
    back.gif のマス(39*39*81個)には、ヒントの設定で 3*3=9個 の小さな数字を表示します。
    リソース 説明
    back.gif 351*351 ピクセルの盤です
    num.gif マスに表示する 39*39 ピクセルの数字
    number.gif マウスで選択する 32*32 ピクセルの数字
    n0.gif~n9.gif プレイで表示する 39*39 ピクセルの数字
    m0.gif~m9.gif ヒントに表示する 16*16 ピクセルの数字
    hint.gif~return.gif メニューアイコンの画像
  2. Counter Class を使ってマスに数字を表示します。
    1. <head> 内で Counter Class を定義します。
      <script type="text/javascript">
      function Counter(img, sw, sh)
      {   this.Img= img;  //Image File(0~9の画像)
          this.Sw = sw;   //Sprite の幅
          this.Sh = sh;   //Sprite の高さ
      
          //「上, 右, 下, 左」の順
          this.View_Num = function(num, x, y)
          {   var pos = num*this.Sw;
              var s1= 'style="clip:rect(0px,' + (pos+this.Sw) + 'px,' + this.Sh + 'px,' + pos + 'px);';
              var s2 = 'position:absolute;left:' + (x-pos) + 'px;top:' + y + 'px;';
              var s = '<img src="' + this.Img + '"' + s1 + s2 + '">';
              document.write(s);
          }
      }
      </script>
      
    2. new で Counter Class を生成します。
      引数で「画像ファイル名とスプライトの幅と高さ」を渡します。
          var cls = new Counter("num.gif", 39, 39);
          var mcls = new Counter("mini.gif", 16, 16);
      
    3. Counter Class を使って数字を描画します。
      0の数字は背景色を設定するため使います。
          cls.View_Num(1, 0, 50);
          cls.View_Num(0, 40, 50);
          cls.View_Num(2, 40, 50);
          cls.View_Num(3, 80, 50);
          cls.View_Num(4, 120, 50);
      
    4. 小さい数字の描画です。
          mcls.View_Num(5, 16, 100);
          mcls.View_Num(6, 32, 100);
          mcls.View_Num(0, 48, 100);
          mcls.View_Num(7, 48, 100);
          mcls.View_Num(8, 64, 100);
      
  3. 問題(Data)をプログラムで定義してプレイします。
    マウスでマスに数字を置こうとすると、新規画面に切り替わり数字だけが単独に表示されます。
    現画面でプレイするには、画像の id を取得して画像を切り替える方法しか無いようです。
    <!DOCTYPE html> 
    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <link rel="stylesheet" href="javascript.css" type="text/css">
    
    <script type="text/javascript">
    var cls = new Counter("num.gif", 39, 39);
    var mcls = new Counter("mini.gif", 16, 16);
    
    function Counter(img, sw, sh)
    {   this.Img= img;  //Image File(0~9の画像)
        this.Sw = sw;   //Sprite の幅
        this.Sh = sh;   //Sprite の高さ
    
        //「上, 右, 下, 左」の順
        this.View_Num = function(num, y, x)
        {   var pos = num*this.Sw;
            var s1= 'style="clip:rect(0px,' + (pos+this.Sw) + 'px,' + this.Sh + 'px,' + pos + 'px);';
            var s2 = 'position:absolute;left:' + (x-pos) + 'px;top:' + y + 'px;';
            var s = '<img src="' + this.Img + '"' + s1 + s2 + '">';
            document.write(s);
        }
    }
    
    //v,h:0~9
    function Num(num, v, h)
    {   var y,x;
        y= v*39-1;
        x= h*39+9;
        cls.View_Num(num, y, x); 
    }
    function Mnum(num, v, h)
    {   var y,x,n;
        n= num-1;
        y= (v-1)*39+Math.floor(n/3)*13-3;
        x= (h-1)*39+6+(n%3)*13;
        mcls.View_Num(num, y, x); 
    }
    
    // number.gif Click  num=1~9
    function NumClick(e)
    {
        if (!e)
        { e= window.event;
          var xp = e.clientX;
          var yp = e.clientY;
          //window.alert("YP:" + yp + "  XP:" + xp);
          num= Math.floor((xp-10)/39)+1;
          window.alert("num:" + num);
        }
    }
    
    // back.gif Click  xp,yp=0~8
    function Click(e)
    {   var yp,xp;
        if (!e)
        { e= window.event;
          var yp = e.clientY;
          var xp = e.clientX;
          window.alert("YP:" + yp + "  XP:" + xp);
          xp = Math.floor((e.clientX-10)/39);
          yp = Math.floor((e.clientY)/39);
          window.alert("YP:" + yp + "  XP:" + xp + "  num:" + num);
          Num(num,yp,xp);
        }
      }
    
    function View()
    {   var i,j,c;
        var Data= "....2..8.7...8.......5.16.33.8...1..9..4....725..76..81.........3...974.......2..";
        for(i=0; i<9; i++)
        {   for(j=0; j<9; j++)
            {   c= Data.charAt(i*9+j);
                if (c>='1' && c<='9')   Num(c,i,j);
            }
        }
    }
    </script>
    </head>
    
    <body>
    <img src="back.gif" id="back" onclick= Click()><br>
    <img src="number.gif" id="num" onclick= NumClick()><br>
    
    <script type="text/javascript">
        View();
    </script>
    
    </body>
    </html>
    
  4. num_start.html で問題作成または、ナンプレゲームファイルを選んで start(this) を呼び出します。
    <h2>ナンプレ(数独)・ゲーム</h2>
    問題(action list)を選択して下さい。<br>
    問題を作成では、複数の正解が存在することがあります。<br>
    <form>
    <select name="action" onChange="start(this)">
    <option value="dumy">action list
    <option value="auto1">初級問題を作成
    <option value="auto2">中級問題を作成
    <option value="auto3">上級問題を作成
    <option value="input">問題ファイルを入力
    </select>
    </form>
    
    start(this) では配列を初期化して、問題の作成またはゲームファイルを入力して num_play.html でプレイします。
      function start(parts)
      {   var i,j;
          for(i=0; i<9; i++)
          {   m_t[i]= new Array(9);
              restcol[i]= new Array(10);
          }
          for(i=0; i<3; i++)
          {   restblock[i]= new Array(3);
              for(j=0; j<3; j++)
                  restblock[i][j]= new Array(10);
          }
          var sel= parts.options[parts.selectedIndex].value;
          switch(sel)
          {   case "auto1":
                   auto1(); break; 
              case "auto2":
                   auto2(); break;
              case "auto3":
                   auto3(); break;
              case "input":
                   input(); break;
          }
      }
      function auto1()
      {   makeMahoujin();
          Generate(40);
          location.href= "num_play.html?data=" + data;
      }      
      function auto2()
      {   makeMahoujin();
          Generate(50);
          location.href= "num_play.html?data=" + data;
      }
      function auto3()
      {   makeMahoujin();
          Generate(60);
          location.href= "num_play.html?data=" + data;
      }
    
  5. ナンプレ(数属)ゲーム α版の完成です。
    num_play.html では num_start.html から渡された data を取得してプレイします。
    window.onload= getdata;
    
    function getdata()
    {   var i,j;
        var str= window.location.search;
        console.log(str);
        i= str.indexOf('data=');
        Data= str.substring(i+5);
        console.log(Data);
        for(i=0; i<9; i++)
            TT[i]= new Array(9);
        for(i=0; i<9; i++)
            for(j=0; j<9; j++) TT[i][j]= 0;
        document.write('<img src="back.gif">');
        document.write('<img src="number.gif" id="num" onclick=NumClick() style="position:absolute;left:20px;top:364px;">');
        document.write('<img src="hint.gif" onclick=Hint() style="position:absolute;left:20px;top:400px;">');
        document.write('<img src="ok.gif" onclick=Ok() style="position:absolute;left:100px;top:400px;">');
        document.write('<img src="save.gif" onclick=Save() style="position:absolute;left:180px;top:400px;">');
        document.write('<img src="return.gif" onclick=Ret() style="position:absolute;left:260px;top:400px;">');
        View();
    }
    
    数独ゲームの詳しい説明は下記のサイトを参照して下さい。
    超初心者のプログラム入門(C#) から C# Game Program 入門を参照して下さい。

前田稔の超初心者のプログラム入門
超初心者のプログラム入門(JavaScript)