#define DISKS_NUM 6 #define PEDESTAL_HEIGHT 20 #define DISK_HEIGHT 7 #define DISK_UNIT_WIDTH 5 I64 poles_x[3]; I64 disks_x[DISKS_NUM], disks_y[DISKS_NUM], disks_pole[DISKS_NUM]; I64 OtherPole(I64 pole1, I64 pole2) { return 3 - pole1 - pole2; } I64 TopDisk(I64 pole) { I64 i; for (i = 0; i < DISKS_NUM; i++) if (disks_pole[i] == pole) return i; return -1; } I64 PosInStack(I64 pole, I64 disk) { I64 res = 0, i; for (i = DISKS_NUM - 1; i > disk; i--) if (disks_pole[i] == pole) res++; return res; } U0 SetDisksRestXY() { I64 i; for (i = 0; i < DISKS_NUM; i++) { disks_x[i] = poles_x[disks_pole[i]]; disks_y[i] = Fs->pix_height - PEDESTAL_HEIGHT - (DISK_HEIGHT + 1) / 2 - 1 - (DISK_HEIGHT + 1) * PosInStack(disks_pole[i], i); } } U0 DrawIt(CTask *task, CDC *dc) { I64 i; for (i = 0; i < 3; i++) poles_x[i] = (1 + i) * task->pix_width / 4; dc->color = BLACK; GrRect(dc, poles_x[0] - 50, task->pix_height - PEDESTAL_HEIGHT, poles_x[2] - poles_x[0] + 100, PEDESTAL_HEIGHT - FONT_HEIGHT); dc->color = DKGRAY; GrRect(dc, poles_x[0] - 49, task->pix_height - PEDESTAL_HEIGHT + 1, poles_x[2] - poles_x[0] + 98, PEDESTAL_HEIGHT - FONT_HEIGHT - 2); for (i = 0; i < 3; i++) { dc->color = BLACK; GrRect(dc, poles_x[i] - 3, task->pix_height - PEDESTAL_HEIGHT - (DISKS_NUM + 1) * (DISK_HEIGHT + 1), 7, (DISKS_NUM + 1) * (DISK_HEIGHT + 1)); dc->color = YELLOW; GrRect(dc, poles_x[i] - 2, task->pix_height - PEDESTAL_HEIGHT + 1 - (DISKS_NUM + 1) * (DISK_HEIGHT + 1), 5, (DISKS_NUM + 1) * (DISK_HEIGHT + 1) - 1); } for (i = 0; i < DISKS_NUM; i++) { dc->color = BLACK; GrRect(dc, disks_x[i] - (i + 1) * DISK_UNIT_WIDTH, disks_y[i] - DISK_HEIGHT / 2, (i + 1) * (DISK_UNIT_WIDTH * 2) + 1, DISK_HEIGHT); dc->color = gr_rainbow_10[i]; GrRect(dc, disks_x[i] - (i + 1) * DISK_UNIT_WIDTH + 1, disks_y[i] - DISK_HEIGHT / 2 + 1, (i + 1) * (DISK_UNIT_WIDTH * 2) - 1, DISK_HEIGHT - 2); } } U0 MySleep() { if (CharScan) throw; Sleep(3); } U0 MoveDisks(I64 src_pole, I64 dst_pole, I64 num) { I64 top, x, y; if (num > 1) MoveDisks(src_pole, OtherPole(src_pole, dst_pole), num - 1); DocClear; "$CM+BY,0,0$Disk:%d from %d to %d\n", TopDisk(src_pole), src_pole, dst_pole; top = TopDisk(src_pole); for (y = disks_y[top]; y > Fs->pix_height - PEDESTAL_HEIGHT - (DISK_HEIGHT + 1) / 2 - (DISK_HEIGHT + 1) * (DISKS_NUM + 2); y--) { disks_y[top] = y; MySleep; } if (src_pole < dst_pole) for (x = poles_x[src_pole]; x <= poles_x[dst_pole]; x++) { disks_x[top] = x; MySleep; } else for (x = poles_x[src_pole]; x >= poles_x[dst_pole]; x--) { disks_x[top] = x; MySleep; } disks_pole[top] = dst_pole; for (y = disks_y[top]; y < Fs->pix_height - PEDESTAL_HEIGHT - (DISK_HEIGHT + 1) / 2 - 1 - (DISK_HEIGHT + 1) * PosInStack(dst_pole, top); y++) { disks_y[top] = y; MySleep; } SetDisksRestXY; if (num > 1) MoveDisks(OtherPole(src_pole, dst_pole), dst_pole, num - 1); } U0 Init() { I64 i; for (i = 0; i < 3; i++) poles_x[i] = (1 + i) * Fs->pix_width / 4; for (i = 0; i < DISKS_NUM; i++) disks_pole[i] = 0; SetDisksRestXY; } U0 Hanoi() { SettingsPush; //See SettingsPush Init; DocClear; Fs->draw_it = &DrawIt; Sleep(1000); try { MoveDisks(0, 2, DISKS_NUM); Beep; Beep; DocClear; DocBottom; PressAKey; } catch PutExcept; DocClear; SettingsPop; } Hanoi;