思考関数(DLL)の解説

Logic Puzzle の思考関数について解説します。

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

  1. 思考関数は Level_0 から Level_9 の段階に分かれています。
    Level_0 には、初歩のパズルを解くことができるソースコードが格納されています。
    また Level_9 には関数に渡されるパラメータを確認するソースコードが格納されています。
    これらのソースコードを変更するのは自由ですが、Level の番号が大きくなるほど難しいパズルを 解くことができるようにして下さい。
    どのレベルの関数を使用するかはメニューから選択できるようになっています。
    DLL が正常に終了したときはゼロをリターンして下さい。
    ゼロ以外の値が返されると、返された値が MessageBox に表示されます。
  2. Logic Puzzle の最も基本的なマークの方法に付いて説明します。
    例として10個の列に6個マークする場合を考えます。
    6個マークを左詰めで格納すると次のようになります。
            ■■■■■■・・・・     左に詰めたとき
        
    6個マークを右詰めで格納すると次のようになります。
            ■■■■■■・・・・     左に詰めたとき
            ・・・・■■■■■■     右に詰めたとき
        
    このとき中央の重なった2個のマークが確定できます。
            ■■■■■■・・・・     左に詰めたとき
            ・・・・■■■■■■     右に詰めたとき
        
  3. それでは次の場合はどうでしょう。
    10個の列に4個と3個をマークします。
            ■■■■・■■■・・     左に詰めたとき
        
    中央の重なった2個と1個のマークが確定できます。
            ■■■■・■■■・・     左に詰めたとき
            ・・■■■■・■■■     右に詰めたとき
        
  4. ここで説明した解法を Level_0 の関数に追加して下さい。
    この処理を追加してもマークが少し増えるだけ、新たに完成するパズルは無いかもしれません。
    Puzzle を解くには人間が考えられるあらゆるケースを根気良くプログラムに組み込んで行って下さい。
    コンピュータの特徴を利用した別の方法もあるのですが、それでは腕を磨くことにはなりません。


エラーコード

渡された行(列)にマークや空白を設定してリターンすると、メインプログラム側で明らかな矛盾をチェックして、 エラーが見つかれば MessageBox で知らせてくれます。
MessageBox には「修正前の状態」と「設定値された値」と「エラーコード」が表示されます。
エラーコードは次のようになっています。


DLL の例

上で説明した処理を組み込んだ Level_0 のプログラムです。
関数に渡されるパラメータを確認するときは Level_9 に設定して下さい。
short   sum;    //列に割り当てられた全ての数字の合計
short   dcnt;   //列に割り当てられた数字の個数
short   mx;     //列に割り当てられた数字の中の最大値
short   nul;    //ゼロの個数(nul, mk 以外の個数)
short   mk;     //マークされている数
short   sp;     //空白の個数
short   i,j;

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    return TRUE;
}

// マークと数値のカウント
void  Count(short data[16], short len, short tbl[])
{
    sum=mx= 0;
    for(dcnt=0; dcnt<16 && data[dcnt]; dcnt++)
    {   sum+= data[dcnt];
        if(mx<data[dcnt])    mx=data[dcnt];
    }
    nul=mk=sp= 0;
    for(i=0; i<len; i++)
    {   switch(tbl[i])
        {   case 0: nul++;  break;  //NULL
            case 1: mk++;   break;  //マーク
            case 2: sp++;   break;  //空白
        }
    }
}

// Level-0 思考関数
EXPORT short Level_0(LOGIC *App, short data[16], short len, short tbl[])
{   short   wk,mkn,pos;

    Count(data,len,tbl);
    //残り全て空白
    if(sum==mk)
    {   for(i=0; i<len; i++)
            if(tbl[i]!=1)   tbl[i]= 2;
        return(0);
    }
    //残り NULL を全てマーク
    if(sum==mk+nul)
    {   for(i=0; i<len; i++)
        {   if(tbl[i]==0 || tbl[i]==1)  tbl[i]= 1;
            else                        tbl[i]= 2;
        }
        return(0);
    }
    //左右から重なる部分をマーク
    wk= sum-mx+dcnt-1;
    mkn= mx*2-len+wk;
    if(mkn<=0)  return(0);
    for(wk=i=0; i<dcnt; i++)
    {   wk+= data[i]+1;
        if (data[i]==mx)
        {   pos= wk-mkn-1;
            for(j=0; j<mkn; j++,pos++)  tbl[pos]= 1;
        }
    }
    return 0;
}
    

[Next Chapter ↓] Logic Puzzle Object Class の説明
[Previous Chapter ↑] Logic Puzzle の説明

超初心者のプログラム入門(Win32API C++)