汇编网首页登录博客注册
youthangel的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
学习动态
文章收藏

[2012-10-12 18:16] 用C语言画图实现汉诺塔问题的演示

图片载入中
/**
        汉诺塔实验:
                1、三个塔 A B C 
                2、把从A 塔借助 B塔转移到C塔
                3、盘子的宽比长为3:7

        开发环境:EasyX插件+VC6.0 。新建一个.cpp文件把代码考进去就OK了
        注意事项
        目前程序只允许盘子的个数是3或者4,如需输入更多的盘子,请先调整宏定义TW的值(变大)再增加盘子的个数
*/

#include<iostream>
#include<graphics.h>
#include <stdio.h>
#include <conio.h>//kbhit()函数的头文件

using namespace std;
//宏定义
#define WIDTH 1000        //图形界面的宽度
#define HEIGHT 600  //图形界面的长度
#define TOP 150        //塔顶
#define BOTTOM 500 //塔基位置
#define ALOCATION 200 //A塔的位置
#define BLOCATION 500 //B塔的位置
#define CLOCATION 800 //C塔的位置
#define TW 100        //塔基的宽的一半,同时也是最大盘子的一半Tower Width
#define MAXD (TW*2) //最大盘子的直径
#define DEC 20        //盘子直接半径的渐变
#define LINE 5//线的宽度
//--------------------------定义数据------------------------------
typedef struct  //定义塔的数据结构
{
        int icou;        //当前塔的盘子数
        char ch;
        int tower[10];        //当前所有盘子的大小,从第二个元素开始存,第一个存塔基的位置
}T;
//-------------------------函数声明--------------------------------
void init(int in);//初始化图形界面
void showDishes(T *t);//画出盘子
void drawTower();//画出塔
void drawDish(int ix,int iy,int height,int width );//画出一个盘子
void mov(T *f,T *t,T *m);//移动一个盘子并显示移动过程
void move(T *f,T *t,T *m,int in);//移动盘子,核心算法
/*-------------------移动一个塔(关键算法)并显示移动过程--------------------------------
        移动一个塔从f到t
        参数T型的f t m
        返回:无
*/
 void mov(T *f,T *t,T *m)
{
        char *ch=(char*)malloc(sizeof(char)*60);
        
        t->tower[t->icou+1]=f->tower[f->icou];
        t->icou++;
        f->icou--;
        cleardevice();
        setfont(30, 0,"宋体");
        sprintf(ch,"从%c移动到%c,第大小为%d",f->ch,t->ch,f->tower[f->icou]);
        outtextxy(400,100,ch);
        drawTower();
        showDishes(f);
        showDishes(t);
        showDishes(m);
        Sleep(1000);
}
/*--------------------------------画出塔----------------------------------------
        参数无
        返回无
*/
void drawTower()
{
        setlinestyle(0,NULL,LINE-2); //设置线的格式,三个参数代表实线,自定义模式无效,线宽3像素
        setcolor(RED);        //设置前景色
        line(ALOCATION,TOP,ALOCATION,BOTTOM);        //A塔
        line(ALOCATION-TW,BOTTOM,ALOCATION+TW,BOTTOM);        //A塔塔基
        line(BLOCATION,TOP,BLOCATION,BOTTOM);        //B塔
        line(BLOCATION-TW,BOTTOM,BLOCATION+TW,BOTTOM);        //B塔塔基
        line(CLOCATION,TOP,CLOCATION,BOTTOM);        //C塔
        line(CLOCATION-TW,BOTTOM,CLOCATION+TW,BOTTOM);        //C塔塔基
}
/*-------------------------移动函数(核心算法)-------------------------------------
        从f移动in个盘子到t借助m
        参数:T型的f,t,m和盘子数in
        返回:无
*/
 void move(T *f,T *t,T *m,int in)
{
        if (in>0)
        {
                move(f,m,t,in-1);
                mov(f,t,m);
                move(m,t,f,in-1);
        } 
}
/*---------------------------计算并画出所有的盘子---------------------------
        显示塔中的盘子void showDish(T *t);
        参数:当前塔 t
        返回;无
*/
void showDishes(T *t)
{
        int record[3];//记录上一个盘子的左上角坐标
        for (int icou=1;icou<=t->icou;icou++)//icou为要画的第icou个盘子
        {
                //求出当前盘子的左上角坐标和长、宽
                int ix,iy,height,width;
                if (1==icou)
                {
                        height=t->tower[icou];//算出直径长度
                        width=height*3/7;//算出宽度
                        ix=t->tower[0]-height/2;
                        iy=BOTTOM-width-(LINE-2)*2;
                        //存储坐标
                        record[0]=ix;
                        record[1]=iy;
                        record[2]=height/2;
                }
                else
                {
                        height=t->tower[icou];//算出长度
                        width=height*3/7;//算出宽度
                        //计算坐标
                        ix=record[0]+record[2]-height/2;
                        iy=record[1]-width-(LINE-2)*2;
                        //存储坐标
                        record[0]=ix;
                        record[1]=iy;
                        record[2]=height/2;
                }
                
                drawDish(ix,iy,height,width);
        }
}

/*------------------------------画出一个盘子------------------------------
        画一个盘子void drawDish(int ix,int iy,int height,int width);
        参数:盘子左上角的左边(ix,iy)和盘子的长宽
        返回:无
*/
void drawDish(int ix,int iy,int height,int width)
{
        setcolor(GREEN);//设置前景色为绿色
        line(ix,iy,ix+height,iy);//上
        line(ix+height,iy,ix+height,iy+width);//右
        line(ix,iy+width,ix+height,iy+width);//下
        line(ix,iy,ix,iy+width);//左
}
/*----------------------------初始化函数----------------------------------------
        初始化函数 void init(int in)
        功能:
                1、初始化图形界面
                2、初始化A B C 三个塔,并把A塔上画出in个盘子
        参数: 三个塔的指针 f,t,m,盘子数in
        返回:无
*/
void init(T *f,T *t,T *m,int in)
{
        char ch;
        initgraph(WIDTH,HEIGHT,NULL); //初始化为800*600的图形界面
        setfont(50, 0,"宋体");        //设置字体
        setcolor(GREEN);
        outtextxy(300,200,"作者:青春天使");
        outtextxy(300,260,"扣扣:958832538");
        outtextxy(300,260,"汇编交流扣扣群:271328592");
        outtextxy(300,320,"2012-09-20");
        while(kbhit()==NULL);
        //画出A B C 三个塔
        drawTower();
        //给三个塔初始化
        f->icou=in;
        t->icou=0;
        m->icou=0;
        f->tower[0]=ALOCATION;
        t->tower[0]=CLOCATION;
        m->tower[0]=BLOCATION;
        f->ch='A';
        m->ch='B';
        t->ch='C';
        for (int icou=1;icou<=f->icou;icou++)        //初始化A塔中的盘子大小
        {
                f->tower[icou]=MAXD-DEC*2*(icou-1);        //直径
        }
        
        //显示三个塔中的盘子
        showDishes(f);
        showDishes(m);
        showDishes(t);

}

//-------------------------------主函数----------------------------------------------------
int main()
{
        //定义三个塔并分配空间
        T *a,*b,*c;
        a=(T*)calloc(1,sizeof(T));
        b=(T*)calloc(1,sizeof(T));
        c=(T*)calloc(1,sizeof(T));
        //初始化化
        init(a,b,c,5);
        move(a,b,c,5);        
        closegraph();
        return 0;
}
评论次数(1)  |  浏览次数(295)  |  类型(冥思苦想) |  收藏此文  | 

[  youthangel   发表于  2012-10-12 18:18  ]

界面虽然丑了点,但还是能说明问题的:-D

 
 请输入验证码  (提示:点击验证码输入框,以获取验证码