// ■ハノイの塔問題をアニメーションで表示 #include "myWin.h" #include "math.h" #define RED(X) ( X & 0xFF) #define GREEN(X) ((X>> 8) & 0xFF) #define BLUE(X) ((X>>16) & 0xFF) #define MAX 9 #define HMAX 1000 typedef struct{ int disk, from, to; }moveData; static int colDisk[3][MAX]; static int numDisk[3]; static int pHist, pHtimer; static moveData history[HMAX]; static int Nst; static HDC hBuff; static HBITMAP hBM; int colorBright(int color, double BR){ if(BR>1)BR=1; int R = (int)(BR*RED(color)), G=(int)(BR*GREEN(color)),B=(int)(BR*BLUE(color)); return RGB(R,G,B); } void drawLine(int X1, int Y1, int X2, int Y2, int color){ HPEN pen=CreatePen(PS_SOLID, 1, color); SelectObject(hBuff, pen); MoveToEx(hBuff,X1,Y1,NULL); LineTo(hBuff,X2,Y2); DeleteObject(pen); } void drawRectangle(int X1, int Y1, int X2, int Y2, int color){ HPEN pen=CreatePen(PS_SOLID, 1, 0); SelectObject(hBuff, pen); HBRUSH brush=CreateSolidBrush(color); SelectObject(hBuff, brush); Rectangle(hBuff,X1,Y1,X2,Y2); DeleteObject(brush);DeleteObject(pen); } void drawDisk(int X0, int Y0, int R, int TH, int color){ double DR = R, RR =DR*DR; int X1=X0-R, X2=X0+R, Y2=Y0-TH; for(int X=X1; X<=X2; X++){ double XX=X-X0;double Bright=sqrt((double)(RR-XX*XX))/R; drawLine(X, Y0, X, Y0 - TH, colorBright(color, Bright)); } drawLine(X1,Y0, X1,Y2, 0);drawLine(X1,Y2, X2,Y2, 0); drawLine(X2,Y2, X2,Y0, 0);drawLine(X2,Y0, X1,Y0, 0); } int diskColor(int N){ switch(N%10){ case 0: return 0xFF77FF; case 1: return 0xFFFF; case 2: return 0xFF00; case 3: return 0xFF; case 4: return 0xFF5555; case 5: return 0xFFFF00; case 6: return 0x7777FF; case 7: return 0xFFFF77; case 8: return 0x77FF77; case 9: return 0xFF00FF; } return 0xFF77FF; } void crearBitmap(){ SelectObject(hBuff,GetStockObject(NULL_PEN)); PatBlt(hBuff,0, 0,1000,400,WHITENESS); } void drawState(){ int DX=Nst*20,XST=Nst*15, poleH=10*Nst+10, Xed=70*Nst, Yed=20*Nst+40; crearBitmap(); drawRectangle(5, Yed, Xed, Yed+20, 0x5577); for(int i=0; i<3;i++) drawDisk(i*DX+XST, Yed,3, poleH, 0x225577); for(int i=0;i<3;i++)for(int j=0; j=HMAX) {MessageBox(NULL,TEXT("ヒストリ領域オーバ"), TEXT("Error"), MB_OK); return 1;} history[pHist].disk = n; history[pHist].from = x;history[pHist].to = y; pHist++; return 0; } int hanoi(int n, int x, int y){ if(n<=0) return 0; if(hanoi( n-1,x, 3-x-y)) return 1; if(moveTo( n,x,y))return 1; if(hanoi( n-1,3-x-y,y)) return 1;; return 0; } void procTimer(HWND hw, WPARAM wp,LPARAM lp){ if(pHtimer>=pHist){ KillTimer(hw,1);return;} int D=history[pHtimer].disk, fr=history[pHtimer].from, to=history[pHtimer].to; numDisk[fr]--; colDisk[to][numDisk[to]++]=D; drawState(); InvalidateRect(hw,NULL,TRUE); pHtimer++; } void procLButtonDown(HWND hw, WPARAM wp,LPARAM lp){ int N=4; pHist=0; MoveWindow(hw,0,0,80*N,20*N+150,TRUE); initState(N);drawState(); hanoi(N,0, 2); initState(N); pHtimer=0; SetTimer(hw,1,500, NULL); drawState(); InvalidateRect(hw,NULL,FALSE); } void initBitmap(HWND hw){ HDC hdc=GetDC(hw); hBM=CreateCompatibleBitmap(hdc,1000,400); hBuff=CreateCompatibleDC(hdc); SelectObject(hBuff,hBM); crearBitmap(); ReleaseDC(hw,hdc); } void procCreate(HWND hw, WPARAM wp,LPARAM lp){ SetWindowText(hw,TEXT("ハノイの塔")); MoveWindow(hw,0,0,800,300,TRUE); initBitmap(hw); } void procPaint(HWND hw, WPARAM wp,LPARAM lp){ PAINTSTRUCT ps; HDC hdc=BeginPaint(hw, &ps); BitBlt(hdc, 0,0,1000,400,hBuff,0,0,SRCCOPY); EndPaint(hw,&ps); } 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_TIMER : procTimer(hw,wp,lp) ; return 0; case WM_LBUTTONDOWN : procLButtonDown(hw,wp,lp) ; break; } return DefWindowProc(hw,msg,wp,lp); }