hanoi.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:9k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /* hanoi.c - written by Greg Humphreys while an intern at SGI */
  2. #include <GL/glut.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. double WIDTH = 800;
  7. double HEIGHT = 800;
  8. GLboolean motion = GL_TRUE;
  9. GLboolean back_wall = GL_FALSE;
  10. GLint xangle = 0, yangle = 0;
  11. GLint xlangle = 0, ylangle = 0;
  12. #define other(i,j) (6-(i+j))
  13. #define wallz -(WIDTH/2)
  14. #define DISK_HEIGHT 20
  15. int NUM_DISKS = 11;
  16. #define CONE NUM_DISKS+1
  17. #define WALL CONE + 1
  18. #define HANOI_SOLVE 0
  19. #define HANOI_QUIT 1
  20. #define HANOI_LIGHTING 2
  21. #define HANOI_WALL 3
  22. #define HANOI_FOG 4
  23. GLfloat lightOneDirection[] =
  24. {0, 0, -1};
  25. GLfloat lightOnePosition[] =
  26. {200, 100, 300, 1};
  27. GLfloat lightOneColor[] =
  28. {1.0, 1.0, 0.5, 1.0};
  29. GLfloat lightTwoDirection[] =
  30. {0, 0, -1};
  31. GLfloat lightTwoPosition[] =
  32. {600, 100, 300, 1};
  33. GLfloat lightTwoColor[] =
  34. {1.0, 0.0, 0.3, 1.0};
  35. GLfloat lightZeroPosition[] =
  36. {400, 200, 300, 1};
  37. GLfloat lightZeroColor[] =
  38. {.3, .3, .3, .3};
  39. GLfloat diskColor[] =
  40. {1.0, 1.0, 1.0, .8}, poleColor[] =
  41. {1.0, 0.2, 0.2, .8};
  42. typedef struct stack_node {
  43.   int size;
  44.   struct stack_node *next;
  45. } stack_node;
  46. typedef struct stack {
  47.   struct stack_node *head;
  48.   int depth;
  49. } stack;
  50. stack poles[4];
  51. void 
  52. push(int which, int size)
  53. {
  54.   stack_node *node = malloc(sizeof(stack_node));
  55.   if (!node) {
  56.     fprintf(stderr, "out of memory!n");
  57.     exit(-1);
  58.   }
  59.   node->size = size;
  60.   node->next = poles[which].head;
  61.   poles[which].head = node;
  62.   poles[which].depth++;
  63. }
  64. int 
  65. pop(int which)
  66. {
  67.   int retval = poles[which].head->size;
  68.   stack_node *temp = poles[which].head;
  69.   poles[which].head = poles[which].head->next;
  70.   poles[which].depth--;
  71.   free(temp);
  72.   return retval;
  73. }
  74. typedef struct move_node {
  75.   int t, f;
  76.   struct move_node *next;
  77.   struct move_node *prev;
  78. } move_node;
  79. typedef struct move_stack {
  80.   int depth;
  81.   struct move_node *head, *tail;
  82. } move_stack;
  83. move_stack moves;
  84. void 
  85. init(void)
  86. {
  87.   int i;
  88.   for (i = 0; i < 4; i++) {
  89.     poles[i].head = NULL;
  90.     poles[i].depth = 0;
  91.   }
  92.   moves.head = NULL;
  93.   moves.tail = NULL;
  94.   moves.depth = 0;
  95.   for (i = 1; i <= NUM_DISKS; i++) {
  96.     glNewList(i, GL_COMPILE);
  97.     {
  98.       glutSolidTorus(DISK_HEIGHT / 2, 5 * i, 15, 15);
  99.     }
  100.     glEndList();
  101.   }
  102.   glNewList(CONE, GL_COMPILE);
  103.   {
  104.     glutSolidCone(10, (NUM_DISKS + 1) * DISK_HEIGHT, 20, 20);
  105.   }
  106.   glEndList();
  107. }
  108. void 
  109. mpop(void)
  110. {
  111.   move_node *temp = moves.head;
  112.   moves.head = moves.head->next;
  113.   free(temp);
  114.   moves.depth--;
  115. }
  116. void 
  117. mpush(int t, int f)
  118. {
  119.   move_node *node = malloc(sizeof(move_node));
  120.   if (!node) {
  121.     fprintf(stderr, "Out of memory!n");
  122.     exit(-1);
  123.   }
  124.   node->t = t;
  125.   node->f = f;
  126.   node->next = NULL;
  127.   node->prev = moves.tail;
  128.   if (moves.tail)
  129.     moves.tail->next = node;
  130.   moves.tail = node;
  131.   if (!moves.head)
  132.     moves.head = moves.tail;
  133.   moves.depth++;
  134. }
  135. /* ARGSUSED1 */
  136. void 
  137. keyboard(unsigned char key, int x, int y)
  138. {
  139.   switch (key) {
  140.   case 27:             /* ESC */
  141.   case 'q':
  142.   case 'Q':
  143.     exit(0);
  144.   }
  145. }
  146. void 
  147. update(void)
  148. {
  149.   glutPostRedisplay();
  150. }
  151. void 
  152. DrawPost(int xcenter)
  153. {
  154.   glPushMatrix();
  155.   {
  156.     glTranslatef(xcenter, 0, 0);
  157.     glRotatef(90, -1, 0, 0);
  158.     glCallList(CONE);
  159.   } glPopMatrix();
  160. }
  161. void 
  162. DrawPosts(void)
  163. {
  164.   glColor3fv(poleColor);
  165.   glLineWidth(10);
  166.   glMaterialfv(GL_FRONT, GL_DIFFUSE, poleColor);
  167.   DrawPost((int) WIDTH / 4);
  168.   DrawPost(2 * (int) WIDTH / 4);
  169.   DrawPost(3 * (int) WIDTH / 4);
  170. }
  171. void 
  172. DrawDisk(int xcenter, int ycenter, int size)
  173. {
  174.   glPushMatrix();
  175.   {
  176.     glTranslatef(xcenter, ycenter, 0);
  177.     glRotatef(90, 1, 0, 0);
  178.     glCallList(size);
  179.   } glPopMatrix();
  180. }
  181. void 
  182. DrawDooDads(void)
  183. {
  184.   int i;
  185.   stack_node *temp;
  186.   int xcenter, ycenter;
  187.   glColor3fv(diskColor);
  188.   glMaterialfv(GL_FRONT, GL_DIFFUSE, diskColor);
  189.   for (i = 1; i <= 3; i++) {
  190.     xcenter = i * WIDTH / 4;
  191.     for (temp = poles[i].head, ycenter = DISK_HEIGHT * poles[i].depth - DISK_HEIGHT / 2; temp; temp = temp->next, ycenter -= DISK_HEIGHT) {
  192.       DrawDisk(xcenter, ycenter, temp->size);
  193.     }
  194.   }
  195. }
  196. #define MOVE(t,f) mpush((t),(f))
  197. static void
  198. mov(int n, int f, int t)
  199. {
  200.   int o;
  201.   if (n == 1) {
  202.     MOVE(t, f);
  203.     return;
  204.   }
  205.   o = other(f, t);
  206.   mov(n - 1, f, o);
  207.   mov(1, f, t);
  208.   mov(n - 1, o, t);
  209. }
  210. GLfloat wallcolor[] =
  211. {0, .3, 1, 1};
  212. void 
  213. DrawWall(void)
  214. {
  215.   int i;
  216.   int j;
  217.   glColor3fv(wallcolor);
  218.   for (i = 0; i < WIDTH; i += 10) {
  219.     for (j = 0; j < HEIGHT; j += 10) {
  220.       glBegin(GL_POLYGON);
  221.       {
  222.         glNormal3f(0, 0, 1);
  223.         glVertex3f(i + 10, j, wallz);
  224.         glVertex3f(i + 10, j + 10, wallz);
  225.         glVertex3f(i, j + 10, wallz);
  226.         glVertex3f(i, j, wallz);
  227.       }
  228.       glEnd();
  229.     }
  230.   }
  231. }
  232. void 
  233. draw(void)
  234. {
  235.   int t, f;
  236.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  237.   if (back_wall) {
  238.     glMaterialfv(GL_FRONT, GL_DIFFUSE, wallcolor);
  239.     DrawWall();
  240.   }
  241.   glPushMatrix();
  242.   {
  243.     glTranslatef(WIDTH / 2, HEIGHT / 2, 0);
  244.     glRotatef(xlangle, 0, 1, 0);
  245.     glRotatef(ylangle, 1, 0, 0);
  246.     glTranslatef(-WIDTH / 2, -HEIGHT / 2, 0);
  247.     glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
  248.   }
  249.   glPopMatrix();
  250.   glPushMatrix();
  251.   {
  252.     glTranslatef(WIDTH / 2, HEIGHT / 2, 0);
  253.     glRotatef(xangle, 0, 1, 0);
  254.     glRotatef(yangle, 1, 0, 0);
  255.     glTranslatef(-WIDTH / 2, -HEIGHT / 2, 0);
  256.     DrawPosts();
  257.     DrawDooDads();
  258.   }
  259.   glPopMatrix();
  260.   if (motion && moves.depth) {
  261.     t = moves.head->t;
  262.     f = moves.head->f;
  263.     push(t, pop(f));
  264.     mpop();
  265.   }
  266.   glutSwapBuffers();
  267. }
  268. void 
  269. hanoi_menu(int value)
  270. {
  271.   switch (value) {
  272.   case HANOI_SOLVE:
  273.     motion = !motion;
  274.     if(motion) {
  275.       glutIdleFunc(update);
  276.     } else {
  277.       glutIdleFunc(NULL);
  278.     }
  279.     break;
  280.   case HANOI_LIGHTING:
  281.     if (glIsEnabled(GL_LIGHTING))
  282.       glDisable(GL_LIGHTING);
  283.     else
  284.       glEnable(GL_LIGHTING);
  285.     break;
  286.   case HANOI_WALL:
  287.     back_wall = !back_wall;
  288.     break;
  289.   case HANOI_FOG:
  290.     if (glIsEnabled(GL_FOG))
  291.       glDisable(GL_FOG);
  292.     else {
  293.       glEnable(GL_FOG);
  294.       glFogi(GL_FOG_MODE, GL_EXP);
  295.       glFogf(GL_FOG_DENSITY, .01);
  296.     }
  297.     break;
  298.   case HANOI_QUIT:
  299.     exit(0);
  300.     break;
  301.   }
  302.   glutPostRedisplay();
  303. }
  304. int oldx, oldy;
  305. GLboolean leftb = GL_FALSE, middleb = GL_FALSE;
  306. void 
  307. hanoi_mouse(int button, int state, int x, int y)
  308. {
  309.   if (button == GLUT_LEFT_BUTTON) {
  310.     oldx = x;
  311.     oldy = y;
  312.     if (state == GLUT_DOWN)
  313.       leftb = GL_TRUE;
  314.     else
  315.       leftb = GL_FALSE;
  316.   }
  317.   if (button == GLUT_MIDDLE_BUTTON) {
  318.     oldx = x;
  319.     oldy = y;
  320.     if (state == GLUT_DOWN)
  321.       middleb = GL_TRUE;
  322.     else
  323.       middleb = GL_FALSE;
  324.   }
  325. }
  326. void 
  327. hanoi_visibility(int state)
  328. {
  329.   if (state == GLUT_VISIBLE && motion) {
  330.     glutIdleFunc(update);
  331.   } else {
  332.     glutIdleFunc(NULL);
  333.   }
  334. }
  335. void 
  336. hanoi_motion(int x, int y)
  337. {
  338.   if (leftb) {
  339.     xangle -= (x - oldx);
  340.     yangle -= (y - oldy);
  341.   }
  342.   if (middleb) {
  343.     xlangle -= (x - oldx);
  344.     ylangle -= (y - oldy);
  345.   }
  346.   oldx = x;
  347.   oldy = y;
  348.   glutPostRedisplay();
  349. }
  350. int 
  351. main(int argc, char *argv[])
  352. {
  353.   int i;
  354.   glutInit(&argc, argv);
  355.   for(i=1; i<argc; i++) {
  356.     if(!strcmp("-n", argv[i])) {
  357.       i++;
  358.       if(i >= argc) {
  359. printf("hanoi: number after -n is requiredn");
  360. exit(1);
  361.       }
  362.       NUM_DISKS = atoi(argv[i]);
  363.     }
  364.   }
  365.   glutInitWindowSize((int) WIDTH, (int) HEIGHT);
  366.   glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  367.   glutCreateWindow("Hanoi");
  368.   glutDisplayFunc(draw);
  369.   glutKeyboardFunc(keyboard);
  370.   glViewport(0, 0, (GLsizei) WIDTH, (GLsizei) HEIGHT);
  371.   glMatrixMode(GL_PROJECTION);
  372.   glLoadIdentity();
  373.   glOrtho(0, WIDTH, 0, HEIGHT, -10000, 10000);
  374.   glMatrixMode(GL_MODELVIEW);
  375.   glLoadIdentity();
  376.   glClearColor(0, 0, 0, 0);
  377.   glClearDepth(1.0);
  378.   glEnable(GL_CULL_FACE);
  379.   glEnable(GL_DEPTH_TEST);
  380. /*  glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);  */
  381.   glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);
  382.   glLightfv(GL_LIGHT1, GL_DIFFUSE, lightOneColor);
  383.   glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 10);
  384.   glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, lightOneDirection);
  385.   glEnable(GL_LIGHT1);
  386.   glLightfv(GL_LIGHT2, GL_POSITION, lightTwoPosition);
  387.   glLightfv(GL_LIGHT2, GL_DIFFUSE, lightTwoColor);
  388. /*  glLightf(GL_LIGHT2,GL_LINEAR_ATTENUATION,.005); */
  389.   glLightf(GL_LIGHT2, GL_SPOT_CUTOFF, 10);
  390.   glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, lightTwoDirection);
  391.   glEnable(GL_LIGHT2);
  392.   glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
  393.   glEnable(GL_LIGHT0);
  394.   glEnable(GL_LIGHTING);
  395.   glutMouseFunc(hanoi_mouse);
  396.   glutMotionFunc(hanoi_motion);
  397.   glutVisibilityFunc(hanoi_visibility);
  398.   glutCreateMenu(hanoi_menu);
  399.   glutAddMenuEntry("Solve", HANOI_SOLVE);
  400.   glutAddMenuEntry("Lighting", HANOI_LIGHTING);
  401.   glutAddMenuEntry("Back Wall", HANOI_WALL);
  402.   glutAddMenuEntry("Fog", HANOI_FOG);
  403.   glutAddMenuEntry("Quit", HANOI_QUIT);
  404.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  405.   init();
  406.   for (i = 0; i < NUM_DISKS; i++)
  407.     push(1, NUM_DISKS - i);
  408.   mov(NUM_DISKS, 1, 3);
  409.   glutMainLoop();
  410.   return 0;             /* ANSI C requires main to return int. */
  411. }