c语言6 10智力拼图,智力拼图问题演示算法

/*

智力拼图问题:将一个6*8的矩阵模块,划分成n个小模块,设计一个算法,用这n个小模块再重新拼接成原

6*8矩阵,要求给出所有的可行方案。

本函数是演示程序,程序最多可以将6*8大小的矩阵分成15个模块,每个小模块的大小不能超过4*4大。并允许

手动编辑。该程序计算所有的可行方案并显示出组合拼接的所有结果。本程序在初始的时候已经给了一个11模块的划分形式,要演示按回车即可。

backup函数是本程序的核心函数,该函数采用标准的递归回溯算法,算法的基本思想是:

从左到右,从上到下扫描6*8矩阵,如果发现某个位置为空(用0表示)就依次尝试每一个还没有用到的

小模块,如果该小模块可以安放在这个位置,那么就放置上去并递归调用下一个可行的位置,否则如果所有小

模块用尽,那么就产生回溯。该函数有两个主要参数x0,y0,表示在6*8矩阵中的第一个空位置。

本程序的操作方法为:

回车:演示开始。

q:在演示过程中退出演示进入模块编辑模式。

c:在编辑模式中减少一个编辑值。

v:在编辑模式中增加一个编辑值。

空格:用于在光标出设置该编辑值。

上,下,左,右:移动光标。

ESC:在编辑模式下退出程序。

如果想让本程序独立运行即其exe文件可以脱离tc根目录到其他目录下运行,要进行如下操作:

在tc根目录下键入:

c:\turboc2>bgiobj egavga //bgiobj是tc下的命令,它将egavga.bgi转换成egavga.obj的目标文件

c:\turboc2>tlib lib\graphics.lib+egavga //tlib将egavga.obj的目标模块装到graphics.lib库中

最后在本程序的opengraph函数中加入registerbgidriver(EGAVGA_driver);语句

本程序采用了很好的算法思想,有很高的阅读价值和参考价值,但并不适合c语言初学者,

特别是那些还没有学过数据结构的同学。

本程序建议在vc++6.0下打开阅读,在tc2.0下编译链接

*/

#include

#include

#include

#include

#include

/*以下定义键盘扫描码*/

#define k_enter 7181

#define k_up 18432

#define k_down 20480

#define k_left 19200

#define k_right 19712

#define k_space 14624

#define k_esc 283

#define k_c 11875

#define k_q 4209

#define k_v 12150

#define _ROW 6

#define _COL 8

#define _MDLM 25

#define _MDLN 25

#define FLASH 2 /*光标闪烁间隔时间*/

typedef struct point {

int x;

int y;

}point;

int Qmat[_ROW][_COL]; /*该数组用于存储原始数据_ROW=6,_COL=8*/

int Qmatd[_ROW][_COL]; /*该数组保存运行时结果*/

int shapep[16][17][2]; /*该数组用于保存每个小模块的形状*/

static int Initmat[_ROW][_COL]={1,1,2,2,7,7,10,11,/*该数组保存初始的设置值*/

1,1,2,2,7,7,10,10,

1,1,3,3,7,8,9,10,

3,3,3,3,6,8, 9,10,

4,4,4,5,6,8,9,9,

4,4,4,5,6,8,9,9};

int f_num[16]; /*该函数用于记录每个小模块的数组元素组成个数*/

void opengraph(void); /*打开图形模式*/

void delayx(int); /*精确延时函数*/

void Init(void); /*对相关数据结构进行初始化*/

int DispModule(void); /*显示所有的小模块形状并计算相关数据结构值*/

void OutputMessage(char* str); /*在屏幕特定位置显示一行信息str*/

void dispcnum(int num); /*在屏幕特定位置显示一个数值num*/

void backup(int x0,int y0,int* f_exit); /*完成对问题的回溯求解*/

main() {

int flag_f=1,f_flash=0,f_putok=1,f_b=1;

int i=0,j=0,keyid;

int ix,jx;

int fnum=1;

char strn[5];

opengraph();

Init();

setcolor(WHITE);

settextstyle(0,0,1);

dispcnum(fnum);

while(flag_f) { /*flag_f状态循环*/

if(bioskey(1)) { /*如果有键按下*/

keyid=bioskey(0); /*读取键值*/

if(keyid==k_up||keyid==k_down||keyid==k_left||keyid==k_right) {

setfillstyle(SOLID_FILL,BLACK); /*重显示光标下隐藏数字*/

setcolor(WHITE);

bar(_MDLN*(j+1)+4,_MDLM*(i+1)+4,_MDLN*(j+2)-4,_MDLM*(i+2)-4);

itoa(Qmat[i][j],strn,10);

outtextxy(_MDLN*(j+1)+6,_MDLM*(i+1)+_MDLM/2,strn);

}

switch(keyid) {

case k_up:

i=i==0?i:i-1;

break;

case k_down:

i=i+1==_ROW?i:i+1;

break;

case k_left:

j=j==0?j:j-1;

break;

case k_right:

j=j+1==_COL?j:j+1;

break;

case k_esc:

flag_f=0;

break;

case k_v:

if(fnum<15) ++fnum;

dispcnum(fnum);

break;

case k_c:

if(fnum>1) --fnum;

dispcnum(fnum);

break;

case k_space:

Qmat[i][j]=fnum;

itoa(fnum,strn,10);

setcolor(WHITE);

outtextxy(_MDLN*(j+1)+6,_MDLM*(i+1)+_MDLM/2,strn);

if((f_putok=DispModule())<=0) OutputMessage("Module Error!");

else OutputMessage("Module must less than 4x4!");

break;

case k_enter:

if(f_putok>0) {/*f_putok>0表示模块拆分的合理(小于4*4)*/

f_b=1;

backup(0,0,&f_b); /*计算所有可行方案*/

OutputMessage("That's all! Anykey to return!");

getch();

setcolor(WHITE);

settextstyle(0,0,1);

setfillstyle(SOLID_FILL,BLACK);

for(ix=0;ix<_row>

for(jx=0;jx<_col>

bar(_MDLN*(jx+1)+4,_MDLM*(ix+1)+4,_MDLN*(jx+2)-4,_MDLM*(ix+2)-4);

itoa(Qmat[ix][jx],strn,10);

outtextxy(_MDLN*(jx+1)+6,_MDLM*(ix+1)+_MDLM/2,strn);

}

}

OutputMessage("Module must less than 4x4!");

}

break;

}

}

delayx(FLASH);

if(f_flash) { /*用于在编辑模式下完成光标的闪烁*/

f_flash=0;

setcolor(WHITE);

setfillstyle(SOLID_FILL,BLACK);

bar(_MDLN*(j+1)+4,_MDLM*(i+1)+4,_MDLN*(j+2)-4,_MDLM*(i+2)-4);

itoa(Qmat[i][j],strn,10);

outtextxy(_MDLN*(j+1)+6,_MDLM*(i+1)+_MDLM/2,strn);

}

else {

f_flash=1;

setfillstyle(SOLID_FILL,WHITE);

bar(_MDLN*(j+1)+4,_MDLM*(i+1)+4,_MDLN*(j+2)-4,_MDLM*(i+2)-4);

}

}

closegraph();

}

void dispcnum(int num) {

char strn[5];

setcolor(WHITE);

settextstyle(0,0,1);

setfillstyle(SOLID_FILL,BLACK);

bar(30,180,100,198);

itoa(num,strn,10);

outtextxy(30,185,strn);

}

void backup(int x0,int y0,int* f_exit) {/*递归函数*/

int i,j,f_ok,x,y;

char strn[5];

for(i=1;i<16;i++) if(f_num[i]>0) break;

if(x0>=_ROW||y0>=_COL||i==16) { /*i==16表示所有模块都以用完,这样就得到了一个可行方案*/

setcolor(BLACK);

settextstyle(0,0,1);

for(i=0;i<_row>

for(j=0;j<_col>

setfillstyle(SOLID_FILL,Qmatd[i][j]);

bar(_MDLN*(j+1)+4,_MDLM*(i+1)+4,_MDLN*(j+2)-4,_MDLM*(i+2)-4);

itoa(Qmatd[i][j],strn,10);

outtextxy(_MDLN*(j+1)+6,_MDLM*(i+1)+_MDLM/2,strn);

}

}

OutputMessage("Anykey to continue,q to Quit!");

if(getch()=='q') *f_exit=0; /*如果按下'q'则强行退出递归*/

return;

}

for(i=1;i<16&&*f_exit;i++) {/*计算每一个可用的模块*/

if(f_num[i]>0) { /*如果未用*/

f_ok=1;

x=x0; y=y0;

for(j=1;j<=f_num[i]&&f_ok;j++) { /*完成对该模块的放置并检查可行性*/

if(x>=0&&y>=0&&x<_row qmatd>

else {

f_ok=0;

for(x=0;x<_row>

for(y=0;y<_col>

if(Qmatd[x][y]==i) Qmatd[x][y]=0;

}

x=x0+shapep[i][j][0]; /*又偏移得到组成模块的下一个位置*/

y=y0+shapep[i][j][1];

}

if(f_ok) { /*如果放置成功则继续递归,否则回溯*/

f_num[i]=0-f_num[i]; /*求负表示该模块以用*/

for(x=0;x<_row>

for(y=0;y<_col>

if(Qmatd[x][y]==0) f_ok=0;

backup(x-1,y-1,f_exit); /*对该空位置产生递归调用*/

for(x=0;x<_row>

for(y=0;y<_col>

if(Qmatd[x][y]==i) Qmatd[x][y]=0;

f_num[i]=0-f_num[i]; /*恢复*/

}

}

}

}

void Init(void) {

int i,j;

char strn[5];

setcolor(WHITE);

settextstyle(0,0,1);

outtextxy(_MDLN,_MDLN/2,"QiQiaoBan question by STN_LCD!I love doudou!");

for(i=0;i<_row>

for(j=0;j<_col>

setcolor(YELLOW);

rectangle(_MDLN*(j+1),_MDLM*(i+1),_MDLN*(j+2),_MDLM*(i+2));

Qmat[i][j]=Initmat[i][j];

Qmatd[i][j]=0;

itoa(Qmat[i][j],strn,10);

setcolor(WHITE);

outtextxy(_MDLN*(j+1)+6,_MDLM*(i+1)+_MDLM/2,strn);

}

}

OutputMessage("Module must less than 4x4 !");

DispModule();

}

void OutputMessage(char* str) {

setfillstyle(SOLID_FILL,BLACK);

bar(250,50,630,80);

setcolor(WHITE);

settextstyle(0,0,1);

outtextxy(252,60,str);

}

int DispModule(void) {

int dispnum=0,flag,ip_sharp;

int Qmatnum;

int i,j,ik,jk,x,y,in,jn;

char strn[5];

memset(f_num,0,16*sizeof(int));

for(i=0;i<_row>

for(j=0;j<_col>

++f_num[Qmat[i][j]];

setfillstyle(SOLID_FILL,BLACK);

bar(20,200,600,450);

for(dispnum=1;dispnum<=15;dispnum++) {

if(f_num[dispnum]) {

flag=1;

for(i=0;i<=2&&flag;i++) {

for(j=0;j<=4&&flag;j++) {

Qmatnum=0;

for(ik=i;ik

for(jk=j;jk

if(Qmat[ik][jk]==dispnum) ++Qmatnum;

if(Qmatnum==f_num[dispnum]) {

flag=0;

x=(dispnum-1)%5; y=(dispnum-1)/5;

x=20+80*x; y=200+80*y;

setcolor(WHITE);

rectangle(x,y,x+80,y+80);

ip_sharp=0;

for(in=0,ik=i;ik

for(jn=0,jk=j;jk

if(Qmat[ik][jk]==dispnum) {

if(ip_sharp==0) {

shapep[dispnum][ip_sharp][0]=ik;

shapep[dispnum][ip_sharp++][1]=jk;

}

else {

shapep[dispnum][ip_sharp][0]=ik-shapep[dispnum][0][0];

shapep[dispnum][ip_sharp++][1]=jk-shapep[dispnum][0][1];

}

setcolor(BLACK);

setfillstyle(SOLID_FILL,Qmat[ik][jk]);

bar(x+20*jn+2,y+20*in+2,x+20*(jn+1)-2,y+20*(in+1)-2);

itoa(Qmat[ik][jk],strn,10);

outtextxy(x+20*jn+3,y+20*in+5,strn);

}

}

}

}

}

}

if(flag) return 0;

}

}

return 1;

}

void opengraph(void) {

int gdriver=VGA,gmode=VGAHI;

/*registerbgidriver(EGAVGA_driver);*/

initgraph(&gdriver,&gmode,"");

}

void delayx(int clicks) {

unsigned int far *clock=(unsigned int far*)0x0000046cL;

unsigned int now;

now=*clock;

while(abs(*clock-now)

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个采用C语言开发的项目是一个多功能的软件应用程序。它旨在提供一个高效、可靠的解决方案,用于处理各种计算机科学和软件开发任务。该项目的目标是为开发人员和计算机科学专业人员提供一个功能强大且易于使用的工具集。 该项目具有许多令人印象深刻的特性。首先,它提供了一组丰富的库和工具,以支持C语言的开发和调试。这些库包括用于字符串处理、内存管理、文件操作和网络编程等常见任务的函数。此外,该项目还提供了一套强大的调试工具,帮助开发人员快速定位和修复代码中的错误。 另一个令人赞赏的特点是该项目的跨平台性。它可以在多个操作系统上运行,包括Windows、Linux和Mac OS等。这使得开发人员可以在不同的环境中使用同一套工具和库,从而提高了开发的灵活性和效率。 该项目还具有高度可定制性。开发人员可以根据自己的需求和偏好,灵活地配置和扩展项目的功能。这包括选择所需的库、启用或禁用特定的功能模块以及修改项目的行为。 此外,该项目还注重性能和效率。通过优化算法和数据结构,以及利用硬件资源的最佳方式,该项目能够在处理大规模数据和复杂计算时提供出色的性能。 总之,这个采用C语言开发的项目是一个强大而灵活的工具,为开发人员和计算机科学专业人员提供了丰富的功能和可靠的解决方案。它的跨平台性、可定制性和高性能使其成为一个理想的选择,无论是进行系统编程、嵌入式开发还是进行科学计算和数据处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值