// ■迷路作成 // 乱数で方向を選びながらブロックを置いていきます。 // ブロックが置かれた位置が壁になります。 // 処理を進める過程で、ブロックを置ける可能性がある座標を // X[],Y[]に登録しておきます。 // ブロックを置けなくなったら、X[],Y[]から1箇所を選んで、 // 再度、プロックを置いていきます。 // X[],Y[]が空になったら迷路完成です。 // 【実行】 // 実行後、迷路が表示されます。 // 左ボタンをクリックすると、新たな迷路が表示されます。 #include "myWin.h" #include "time.h" #include "stdlib.h" #define frand() ((double) rand()/(RAND_MAX+1)) #define XMAX 40 // X方向の数(偶数とする) #define YMAX 20 // Y方向の数(偶数とする) #define XDIV XMAX / 2 - 2 #define YDIV YMAX / 2 - 2 #define MAXBLK 200 // ブロック配列大きさ(XMAX*YMAX/4以下とする) int map[XMAX+1][YMAX+1]; int X[MAXBLK+1], Y[MAXBLK+1]; int dir[][2]={{ 2, 0}, { 0, 2},{ -2, 0},{ 0, -2}}; int nBlk, nDir; void insBlk(int i, int j){ nBlk++; X[nBlk]=i; Y[nBlk]=j; } void init(){//初期設定 int i,j; for(i=0; i<=XMAX;i++) for(j=0; j<=YMAX;j++) {map[i][j] = true;} for(i=3; i<=(XMAX-3);i++) for(j=3; j<=(YMAX-3);j++) {map[i][j] = false;} map[2][3] = false; map[XMAX-2][YMAX-3] = false; nBlk=0; for(i=2;i<=XDIV;i++){ insBlk(i*2,2); insBlk(i*2,YMAX-2);} for(j=2;i<=YDIV;i++){ insBlk(2,j*2); insBlk(XMAX-2,j*2);} } void selBlk(int *i, int *j){//ブロック位置の選択 int R=(int)(frand()*nBlk)+1; *i = X[R]; *j = Y[R]; X[R] = X[nBlk]; Y[R] = Y[nBlk]; nBlk--; } void selDir(int *i, int *j){//方向の選択 int R=(int)(frand()*nDir); *i = dir[R][0]; *j=dir[R][1]; dir[R][0]=dir[nDir-1][0];dir[R][1]=dir[nDir-1][1]; dir[nDir-1][0]=*i;dir[nDir-1][1]=*j; nDir--; } void genMap(){//迷路作成 int i,j,dI,dJ,OK; while(nBlk>0){ selBlk(&i, &j); do{ nDir=4; do{ selDir(&dI, &dJ); OK= !map[i+dI][j+dJ]; }while((!OK) &&( nDir!=0)); if(OK){ map[i+dI/2][j+dJ/2]=true;i+=dI; j+=dJ;map[i][j]=true; insBlk(i,j); } }while(OK); } } void procPaint(HWND hw, WPARAM wp,LPARAM lp){ PAINTSTRUCT ps; HDC hdc=BeginPaint(hw, &ps); HBRUSH hb=CreateSolidBrush(0x77FF); SelectObject(hdc,hb); for(int j=2,Y=10; j<=(YMAX-2);j++, Y+=10){ for(int i=2, X=10; i<=(XMAX-2);i++,X+=10) if(map[i][j]) Rectangle(hdc,X,Y,X+11,Y+11) ; } DeleteObject(hb); EndPaint(hw,&ps); } void procLButtonDown(HWND hw, WPARAM wp,LPARAM lp){ init(); genMap(); InvalidateRect(hw,NULL,TRUE); } void procCreate(HWND hw, WPARAM wp,LPARAM lp){ SetWindowText(hw,TEXT("迷路(左クリックで再生成)")); MoveWindow(hw,0,0,500,300,TRUE); srand((unsigned int)time(NULL)); procLButtonDown(hw,wp,lp); } LRESULT CALLBACK WndProc(HWND hw, UINT msg, WPARAM wp,LPARAM lp){ switch(msg){ case WM_DESTROY : PostQuitMessage(0) ; return 0; case WM_CREATE : procCreate(hw,wp,lp) ; return 0; case WM_PAINT : procPaint(hw,wp,lp) ; return 0; case WM_LBUTTONDOWN : procLButtonDown(hw,wp,lp); return 0; } return DefWindowProc(hw,msg,wp,lp); }