汉诺塔的源程序

原创 2002年05月31日 10:01:00

    本程序是一个汉诺塔的游戏程序,用TURBO  C 2.0编写并编译成功,游戏可以让玩家选择盘子的个数(3到7个).并有三种游戏结果(YOU WIN;GAME OVER;YOU PLAY BAD),而且一局成功以后,玩家可以选择退出或继续(如果选择继续,则盘子的个数就会自动加一).
本游戏程序算法简单,界面友好,可玩性强,是第一款在DOS界面下的汉诺塔游戏程序.

作者E_MAIL:   bolm@etang.com

/*---------------------------HANOI TOWER V 1.0--------------------------*/
/*-----------------------------SOURCE PROGRAM---------------------------*/
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
#include "graphics.h"
#include "math.h"

#define O outtextxy
#define S setcolor
#define F setfillstyle
#define R rectangle
#define C circle
#define L line
#define B bar
#define B3D bar3d

#define X 200
#define Y 30

int step=0;
int record[5]={7,15,31,63,127},rec;
int disk,disknum;
char mark[15];

struct rod
       {
       int disk[8][5];
       int diskname[8];
       }tree[3];

/********************************************/
ntoa(int s)
{
 int b[15];
 int i,j;
 for (i=0;i<15;i++)
   mark[i]='/0';
 for (i=0;s>=10;i++)
   {b[i]=s%10;
   s/=10;}
 b[i]=s;
 for(j=i;j>=0;j--)
   mark[i-j]=b[j]+'0';
}

void drawrod()
{
 F(1,LIGHTBLUE);
 B(118,150,122,400);   /*ROD1*/
 B(318,150,322,400);   /*ROD2*/
 B(518,150,522,400);   /*ROD3*/
 F(6,BLUE);
 B(119,151,123,401);
 B(319,151,323,401);
 B(519,151,522,401);
}

void draw()
{
 S(LIGHTBLUE);
 R(10,10,629,469);
 L(10,30,629,30);      /*UP LINE1*/
 L(10,26,629,26);
 L(10,450,629,450);    /*BOTTOM LINE1*/
 L(10,446,629,446);
 S(GREEN);
 settextstyle(DEFAULT_FONT,HORIZ_DIR,2);
 O(200,452,"HANOI TOWER V1.0");
 S(LIGHTBLUE);
 O(201,453,"HANOI TOWER V1.0");
}

void showrecord()
{
 settextstyle(DEFAULT_FONT,HORIZ_DIR,1);
 F(1,BLACK);
 bar(58,11,80,22);
 ntoa(disk);
 S(RED);
 O(20,15,"DISK:");
 S(GREEN);
 O(60,15,mark);

 bar(318,11,350,22);
 ntoa(rec);
 S(RED);
 O(260,15,"RECORD:");
 S(GREEN);
 O(320,15,mark);

 bar(530,11,600,22);
 ntoa(step);
 S(RED);
 O(490,15,"STEP:");
 S(GREEN);
 O(532,15,mark);
}

void filldisk(int x1,int y1,int x2,int y2,int color,int color1)
{
 S(color);
 F(1,color);
 B3D(x1,y1,x2,y2,5,5);
 F(6,color1);
 B3D(x1+1,y1+1,x2+1,y2+1,5,5);
}

void action()  /**ANIMATION**/
{
 int i;
 S(BLACK);
 for (i=0;i<600;i=i+2)
 {R(i,0,i+40,479);
  delay(100);}
}

int ifwin()
{
  int i,step_sub_rec;
  disknum=0;
  for (i=0;i<disk;i++)
   { if(tree[2].disk[i][0]==1) disknum++;}
  step_sub_rec=step-rec;
  if (disknum==disk)
    { if (step_sub_rec<=10) /**WIN**/
       { action();
  cleardevice();
  S(GREEN);
  settextstyle(DEFAULT_FONT,HORIZ_DIR,3);
  O(230,200,"YOU WIN");
  S(RED);
  O(231,201,"YOU WIN"); }
      else if (step_sub_rec<=20)
       { action();
  cleardevice();
  S(RED);
  settextstyle(DEFAULT_FONT,HORIZ_DIR,3);
  O(220,200,"GAME OVER");
  S(LIGHTBLUE);
  O(221,201,"GAME OVER"); }
       else
       { action();
  cleardevice();
  S(LIGHTBLUE);
  settextstyle(DEFAULT_FONT,HORIZ_DIR,3);
  O(175,200,"YOU PLAY BAD");
  S(CYAN);
  O(176,201,"YOU PLAY BAD"); }

  for (i=0;i<3000;i=i+50)
   {sound(i);
    delay(300);
    nosound();}
  S(RED);
  settextstyle(DEFAULT_FONT,HORIZ_DIR,2);
  O(180,240,"THANK YOU TO PLAY");
  S(GREEN);
  O(181,241,"THANK YOU TO PLAY");
  S(RED);
  R(168,298,473,309);
  settextstyle(DEFAULT_FONT,HORIZ_DIR,1);
  O(170,300,"PRESS ANY KEY TO CONTINUE(ESC TO QUIT)");
  S(YELLOW);
  O(171,301,"PRESS ANY KEY TO CONTINUE(ESC TO QUIT)");

  if(getch()==27) {closegraph();exit(0);}
  else return(1);
    }
    return(0);
}

void helpmessage()
{
 S(BLUE);
 R(20,258,619,405);
 L(20,260,619,260);
 L(20,376,619,376);
 S(RED);
 O(124,230,">>>");
 settextstyle(SANS_SERIF_FONT,HORIZ_DIR,1);
 O(23,265,"HELP MESSAGE:");
 settextstyle(DEFAULT_FONT,HORIZ_DIR,1);
 S(LIGHTBLUE);
 O(30,290,"1). KEY: <-,->,A,D :MOVE THE RED BALL TO SELECT A ROD");
 O(30,315,"2). KEY: UP,W      :TO SELECT THE TOP DISK");
 O(30,340,"3). KEY: DOWN,S    :TO GET DOWN THE DISK WHICH SELECT");
 O(30,365,"4). KEY: ESC       :QUIT THE GAME");
 S(RED);
 O(30,382,"5). IF   STEP-RECORD<10  THAN  :YOU WIN");
 O(30,393,"6). ELSE                       :GAME OVER");
}

/************************---GAME---**************************/
void game()
{
 int movedisk[4],updiskname1,updiskname2,updisknum1,updisknum2,havemove=0,i,j,rn=0;
 int stage,stage1,stage2,rn1,rn2;
 int x1,y1,x2,y2;
 int a=0,b=0;
 int name=1;
 char c;
 rec=record[disk-3];
 draw();
 drawrod();
 showrecord();

for (i=0;i<3;i++)         /*****---EXIST BIT=0---********/
  for (j=0;j<7;j++)
    {tree[i].disk[j][0]=0;
     tree[i].diskname[j]=0;}


for (i=0;i<disk;i++)     /****DRAW THE DISKS OF THE FIRST ROD***/
 {
  tree[rn].diskname[i]=name;
  tree[rn].disk[i][0]=1;      /*DISK i-----exist bit*/
  tree[rn].disk[i][1]=40+a;   /*--X1--*/
  tree[rn].disk[i][2]=380-b;  /*--y1--*/
  tree[rn].disk[i][3]=200-a;  /*--X2--*/
  tree[rn].disk[i][4]=400-b;  /*--y2--*/

  name=name+1;
  a=a+10;
  b=b+30;
 }

for (i=0;i<disk;i++)     /*********DRAW THE DISKS***********/
    filldisk(tree[rn].disk[i][1],tree[rn].disk[i][2],tree[rn].disk[i][3],tree[rn].disk[i][4],9,1);
for (i=0;i<4;i++)
    movedisk[i]=0;
 drawrod();
/*-----------------------------------------------------------------*/

F(1,BLACK);
       B(20,100,609,130);
       F(1,RED);
       S(RED);
       C(118+(rn*200),115,10);
       floodfill(118+(rn*200),115, RED);

while(1)
    {if(kbhit())
      switch(c=getch())
       {case 75:     /**left**/
        case 'A':
        case 'a':
           rn=((rn==0)?2:rn-1);
    break;

 case 77:     /**right**/
        case 'D':
        case 'd':
           rn=((rn==2)?0:rn+1);
    break;

 case 72:     /**up**/
        case 'W':
 case 'w':
    for (i=0;tree[rn].disk[i][0]!=0;i++);
    if (i<1) break;
    else
      {
        updiskname1=tree[rn].diskname[i-1];
        updisknum1=i-1;
        stage1=i-1;
        rn1=rn;
    for (i=0;i<4;i++)
        movedisk[i]=tree[rn].disk[updisknum1][i+1];
        havemove=0;
    /*    tree[rn].diskname[updisknum1]=0;
   tree[rn].disk[updisknum1][0]=0;   */
       }
    break;

 case 80:     /**down**/
        case 'S':
 case 's':
    if (movedisk[0]==0) break;
    for (i=0;tree[rn].disk[i][0]!=0;i++);
    if (i<1)
      {  if (havemove==1) break;
        stage2=0;rn2=rn;
        tree[rn].diskname[0]=updiskname1;
        tree[rn].disk[0][0]=1;      /**exist bit-->1**/
  tree[rn1].diskname[updisknum1]=0;
  tree[rn1].disk[updisknum1][0]=0;
        stage=stage1-stage2;
        x1=movedisk[0]+(rn2-rn1)*X;
        y1=movedisk[1]+stage*Y;
        x2=movedisk[2]+(rn2-rn1)*X;
        y2=movedisk[3]+stage*Y;

        tree[rn].disk[0][1]=x1;
        tree[rn].disk[0][2]=y1;
        tree[rn].disk[0][3]=x2;
        tree[rn].disk[0][4]=y2;
      }
     else
      {
        updiskname2=tree[rn].diskname[i-1];
        updisknum2=i;
        stage2=i;
        rn2=rn;
        if (updiskname1>updiskname2)
    {
    if (havemove==1) break;
      tree[rn].diskname[updisknum2]=updiskname1;
      tree[rn].disk[updisknum2][0]=1; /**exist bit-->1**/
       tree[rn1].diskname[updisknum1]=0;
       tree[rn1].disk[updisknum1][0]=0;
      stage=stage1-stage2;
      x1=movedisk[0]+(rn2-rn1)*X;
      y1=movedisk[1]+stage*Y;
      x2=movedisk[2]+(rn2-rn1)*X;
      y2=movedisk[3]+stage*Y;

      tree[rn].disk[updisknum2][1]=x1;
      tree[rn].disk[updisknum2][2]=y1;
      tree[rn].disk[updisknum2][3]=x2;
      tree[rn].disk[updisknum2][4]=y2;
    }
    else
      {sound(1000);
       delay(300);
       nosound();
       break;     }
      }
      filldisk(movedisk[0],movedisk[1],movedisk[2],movedisk[3],7,9);
      delay(2000);
      filldisk(movedisk[0],movedisk[1],movedisk[2],movedisk[3],0,0);
      filldisk(x1,y1,x2,y2,9,1);
      step=step+1;
      showrecord();
      drawrod();

      for(i=0;i<4;i++)
         movedisk[i]=0;
         havemove=1;
     if (ifwin()==1) return;       /****check if moves are finished****/
    break;

 case 27:closegraph(); exit(0);
 default:break;
       }
F(1,BLACK);
       B(20,100,609,130);
       F(1,RED);
       S(RED);
       C(118+(rn*200),115,10);
       floodfill(118+(rn*200),115, RED);

}
}

/********************MAIN*******************/
void main()
{
  int gd=DETECT,gm=0;
  int input,i;
  initgraph(&gd,&gm,"");
  setbkcolor(BLACK);
  S(YELLOW);
  settextstyle(DEFAULT_FONT,HORIZ_DIR,4);
  O(150,204,"HANOI TOWER");
  S(LIGHTBLUE);
  O(149,203,"HANOI TOWER");
  S(YELLOW);
  settextstyle(DEFAULT_FONT,HORIZ_DIR,3);
  O(267,254,"V 1.0");
  S(LIGHTBLUE);
  O(266,253,"V 1.0");
  S(LIGHTBLUE);
  settextstyle(DEFAULT_FONT,HORIZ_DIR,1);
  O(243,300,"--MADE BY CHENCHENG--");
  S(CYAN);
  O(242,299,"--MADE BY CHENCHENG--");
  sleep(2);
  cleardevice();
  helpmessage();
  S(GREEN);
  settextstyle(DEFAULT_FONT,HORIZ_DIR,1);
for (i=1;i<75;i++)
  {delay(500);          /*SPEED OF THE SENTENCE*/
  setviewport(0,0,50+i*8,479,1);
  O(155,230,"PLEASE INPUT THE NUMBERS OF DISKS(3..7):");
  }
while((input=getch())<'3'||input>'7');
  input=input-48;
  disk=input;
  delay (1000);
  action();
  cleardevice();
ag:
  game();              /********GAME*******/
  cleardevice();
  if (disk<7) disk++;
  step=0;
  goto ag;
}



汉诺塔递归C语言代码实现

#include int c=0; void move(int disk,char start,char end) { printf("step:%d,move %c to %c\n",++...
  • gl486546
  • gl486546
  • 2016年10月29日 16:39
  • 1326

汉诺塔的Java 源程序

刚写的:package mooonsoft.j2se;public class Hannoi {  public Hannoi()  {  }  public static void main(Str...
  • sylmoon
  • sylmoon
  • 2005年09月07日 10:13
  • 1711

汉诺塔递归分析和非递归算法

一位法国数学家曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这...
  • z294155673
  • z294155673
  • 2016年08月01日 10:12
  • 1223

算法学习-类似汉诺塔的问题

题目: 汉诺塔问题比较经典,这里修改一下游戏规则: 现在限制不能从最左侧的塔直接移动到最右 侧,也不能从最右侧直接移动到最左侧,而是必须经过中间。求当塔有 N 层的时候,打印 最优移动过程和最优...
  • Luxia_24
  • Luxia_24
  • 2016年09月02日 15:51
  • 673

java实现汉诺塔算法

package com.ywx.count; import java.util.Scanner; /**  * @author Vashon  * date:20150410  *   * 题...
  • yangwenxue_admin
  • yangwenxue_admin
  • 2015年04月10日 14:14
  • 3559

汉诺塔非递归算法分析与实现

汉诺塔的递归算法很容易理解,也非常容易实现。下面,本文讨论了汉诺塔问题的非递归算法,核心内容就是栈的使用技巧。 首先,对于每个柱子来说,就是一个栈,这个栈有个特点就是,大数放在下面,小数放在上面。在...
  • feihongchen
  • feihongchen
  • 2015年07月21日 22:37
  • 5854

汉诺塔问题(+递推公式)

 汉诺塔问题是使用递归解决问题的经典范例。   汉诺(Hanoi)塔问题:古代有一个梵塔,塔内有三个座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上(如图)。有一个和尚想把这...
  • haut_ykc
  • haut_ykc
  • 2016年08月24日 18:37
  • 2088

四根柱子处理汉诺塔问题的最少次数

经典的汉诺塔问题经常作为一个递归的经典例题存在。可能有人并不知道汉诺塔问题的典故。汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上...
  • qq_34576910
  • qq_34576910
  • 2016年12月11日 19:35
  • 1031

汉诺塔 经典递归算法 in python

#coding:utf-8#coding:utf-8 #汉诺塔问题 n = int(input("输入初始化时A塔上盘子的个数n:\n")) def move( n , A , B ,C ): if...
  • u014496330
  • u014496330
  • 2015年03月25日 14:00
  • 3356

算法详解--汉诺塔

算法由来 小故事 汉诺塔(Towers of Hanoi)是法国人M.Claus(Lucas)于1883年从泰国带至法国的,河内为越战时北越的首都,即现在的胡志明市;1883年法国数学家...
  • baidu_23086307
  • baidu_23086307
  • 2017年03月09日 10:24
  • 450
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:汉诺塔的源程序
举报原因:
原因补充:

(最多只允许输入30个字)