// ■3D迷路 // 乱数で方向を選びながらブロックを置いていきます。 // ブロックが置かれた位置が壁になります。 // 処理を進める過程で、ブロックを置ける可能性がある座標を // X[],Y[]に登録しておきます。 // ブロックを置けなくなったら、X[],Y[]から1箇所を選んで、 // 再度、プロックを置いていきます。 // X[],Y[]が空になったら迷路完成です。 // 【実行】 // @実行後、迷路が表示されます。 // A左ボタンをダブルクリックすると、新たな迷路が表示されます。 // B左ボタンを上方向にドラッギングすると進みます。 // C左ボタンを下方向にドラッギングすると振り返ります。 // D左ボタンを左方向にドラッギングすると左を向きます。 // E左ボタンを右方向にドラッギングすると右を返ります。 // #include "myWin.h" #include "time.h" #include "stdlib.h" #include "math.h" #define frand() ((double) rand()/(RAND_MAX+1)) #define XMAX 16 // X方向の数(偶数とする) #define YMAX 16 // 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,downX, downY,pDir; POINT pTab[4]={{0,-1},{1,0},{0,1}, {-1,0}}, curPos; int cTab[4]={0x77FF77, 0xFF7777,0x7777FF,0x77FFFF}; 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); } } int leftPos(int dir){ dir--; if(dir<0) dir=3; return dir; } int rightPos(int dir){ dir++; if(dir>3) dir=0; return dir; } void drawLeftWall(HDC hdc, int L, int X, int Y, int C){ POINT P1[4]; P1[0].x=X ; P1[0].y=Y; P1[1].x=X+15; P1[1].y=Y+5; P1[2].x=X+15; P1[2].y=Y+L-25; P1[3].x=X ; P1[3].y=Y+L; HBRUSH hbrush=CreateSolidBrush(cTab[C]); SelectObject(hdc,hbrush); Polygon(hdc,P1,4); DeleteObject(hbrush); } void drawLeftOpen(HDC hdc, int L, int X, int Y, int C){ POINT P1[4]; P1[0].x=X ; P1[0].y=Y+5; P1[1].x=X+15; P1[1].y=Y+5; P1[2].x=X+15; P1[2].y=Y+L-25; P1[3].x=X ; P1[3].y=Y+L-25; HBRUSH hbrush=CreateSolidBrush(cTab[C]); SelectObject(hdc,hbrush); Polygon(hdc,P1,4); DeleteObject(hbrush); } void drawRightWall(HDC hdc, int L, int X, int Y,int C){ POINT P1[4]; P1[0].x=X+L ; P1[0].y=Y; P1[1].x=X+L-15; P1[1].y=Y+5; P1[2].x=X+L-15; P1[2].y=Y+L-25; P1[3].x=X+L ; P1[3].y=Y+L; HBRUSH hbrush=CreateSolidBrush(cTab[C]); SelectObject(hdc,hbrush); Polygon(hdc,P1,4); DeleteObject(hbrush); } void drawRightOpen(HDC hdc, int L, int X, int Y,int C){ POINT P1[4]; P1[0].x=X+L ; P1[0].y=Y+5; P1[1].x=X+L-15; P1[1].y=Y+5; P1[2].x=X+L-15; P1[2].y=Y+L-25; P1[3].x=X+L ; P1[3].y=Y+L-25; HBRUSH hbrush=CreateSolidBrush(cTab[C]); SelectObject(hdc,hbrush); Polygon(hdc,P1,4); DeleteObject(hbrush); } 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) ; } int XX=(curPos.x-1)*10, YY=(curPos.y-1)*10; if((pDir % 2)==0) { MoveToEx(hdc, XX+5,YY+2,NULL);LineTo(hdc, XX+5,YY+8); if(pDir==2) LineTo(hdc, XX+2,YY+5); else { MoveToEx(hdc, XX+5,YY+2,NULL); LineTo(hdc, XX+2,YY+7); } } else{ MoveToEx(hdc, XX+2,YY+5,NULL);LineTo(hdc, XX+8,YY+5); if(pDir==1) LineTo(hdc, XX+5,YY+2); else { MoveToEx(hdc, XX+2,YY+5,NULL); LineTo(hdc, XX+7,YY+2); } } DeleteObject(hb); POINT p=curPos;int L=400,X=10,Y=200; int LDir=leftPos(pDir), RDir=rightPos(pDir); int Ldx=pTab[LDir].x, Ldy=pTab[LDir].y; int Rdx=pTab[RDir].x, Rdy=pTab[RDir].y; do{ if(map[p.x+Ldx][p.y+Ldy]) drawLeftWall(hdc, L, X, Y, LDir); else drawLeftOpen(hdc, L, X, Y,pDir); if(map[p.x+Rdx][p.y+Rdy]) drawRightWall(hdc, L, X, Y, RDir); else drawRightOpen(hdc, L, X, Y,pDir); p.x+=pTab[pDir].x; p.y+=pTab[pDir].y; L-=30; X+=15; Y+=5; }while(!map[p.x][p.y]); if(p.x>=(XMAX-1) && p.y>=(YMAX-3)){ SetTextColor(hdc,0xFF); TextOut(hdc, X+3,Y,TEXT("出口"),2); } else { HBRUSH hbrush=CreateSolidBrush(cTab[pDir]); SelectObject(hdc,hbrush); Rectangle(hdc,X,Y, X+L+1,Y+L+1); DeleteObject(hbrush); } EndPaint(hw,&ps); } void procLButtonDblClk(HWND hw, WPARAM wp,LPARAM lp){ pDir=1;curPos.x=2;curPos.y=3; init(); genMap(); InvalidateRect(hw,NULL,TRUE); } void procLButtonDown(HWND hw, WPARAM wp,LPARAM lp){ downX=LOWORD(lp); downY=HIWORD(lp); } void turnLf(){pDir=leftPos(pDir);} void turnRt(){pDir=rightPos(pDir);} void turnRv(){pDir=leftPos(leftPos(pDir));} void proceed(){ if(map[curPos.x+pTab[pDir].x][curPos.y+pTab[pDir].y]) MessageBox(NULL,TEXT("進めません"),TEXT("3次元迷路"),MB_OK); else { curPos.x+=pTab[pDir].x; curPos.y+=pTab[pDir].y;} } void procLButtonUp(HWND hw, WPARAM wp,LPARAM lp){ int X=LOWORD(lp), Y=HIWORD(lp); if(abs(downX-X)<5 && abs(downY-Y)<5)return; if(abs(downX-X)>abs(downY-Y)){ if(X=(XMAX-2) && curPos.y>=(YMAX-3)){ MessageBox(NULL,TEXT("出口です"),TEXT("3次元迷路"),MB_OK); procLButtonDblClk(hw,wp,lp); } } void procCreate(HWND hw, WPARAM wp,LPARAM lp){ SetWindowText(hw,TEXT("迷路")); MoveWindow(hw,0,0,500,700,TRUE); srand((unsigned int)time(NULL)); procLButtonDblClk(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_LBUTTONDBLCLK : procLButtonDblClk(hw,wp,lp); return 0; case WM_LBUTTONDOWN : procLButtonDown(hw,wp,lp) ; return 0; case WM_LBUTTONUP : procLButtonUp(hw,wp,lp) ; return 0; } return DefWindowProc(hw,msg,wp,lp); }