连连看C语言源代码.docx
《连连看C语言源代码.docx》由会员分享,可在线阅读,更多相关《连连看C语言源代码.docx(15页珍藏版)》请在冰豆网上搜索。
连连看C语言源代码
/*
*连连看游戏C语言源代码
*/
#include
#include
#include
#include
#include
#definetrue1
#definefalse0
/*---------------------全局变量------------------------------------*/
intBkGndColor=BLACK;
intBorderColor=LIGHTGRAY;
intLineColor=LIGHTBLUE;/*消除一对方块时时候的连线颜色*/
/*Pb-ProgressBar*/
intPbColor=LIGHTGREEN;
intPbY=4;
intPbHeight=4;
intPbValue;/*进度条百分比,初始值为100.*/
longStartTime;/*开始时间的秒数,只统计分钟,秒*/
longTotalTime;/*游戏总共的最大秒数!
,*/
/*BoardDatas:
asmall-sizeboard*/
/*Board[x][y][0]-0:
empty,1:
filled*/
/*Board[x][y][1]-cell'skey;*/
unsignedcharBoard[10][10][2];
intCellSize=30;
intBoardX=20;
intBoardY=60;
intBoardWidth=10;
intBoardHeight=10;
intCellColor=WHITE;
intSelColor=BLUE;/*selCell'sborderrectcolor*/
intCurColor=RED;/*curCell'sborderrectcolor*/
intEraColor=CYAN;/*用于擦除cell的颜色!
*/
intPairsCount;/*howmuchpairswehaveputonboard*/
/*用于存储逻辑坐标(索引)*/
typedefstruct_tagCELL
{
charx;
chary;
}CELL;
CELLselCell,curCell;/*缓存前一个被选中的位置以及当前所处位置!
*/
/*ScanCodesDefine*/
enumKEYCODES
{
K_ESC=0x011b,
K_UP=0x4800,/*upwardarrow*/
K_LEFT=0x4b00,
K_DOWN=0x5000,
K_RIGHT=0x4d00,
K_SPACE=0x3920,
K_P=0x1970,
K_RETURN=0x1c0d,/*Enter*/
};
/*---------------------函数列表------------------------------------*/
voidInitGame(char*bgiPath);
voidPlayGame();
voidQuitGame();
voidInitProgressBar();
voidUpdateProgressBar(intpercent);
voidDrawCell(intkey,intx,inty,intcolor);
voidEraseCell(intx,inty);
voidDrawBorderRect(CELL*c,intcolor);
voidDrawGameOver(char*info);
intGetKeyCode();
intFindPath(CELL*c1,CELL*c2);
/*绘制消除方块时候的连接路径!
,用指定颜色!
*/
voidDrawPath(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4,intcolor);
/*----------------------函数实现-----------------------------------*/
/*----------------------[核心算法]---------------------------------
*先进行水平方向判断,找出两点所在的水平直线活动范围,
*算出这两条线段在垂直方向的共同区域,
*遍历该区域判断能否在两线段间架起公垂线,能则两点连接上;
*接着进行垂直方向判断,类同。
无论两点在不在一条直线上,
*都能使用该算法,因为两点同线只是两点作为矩形对角点的特例而已。
*/
/*找到两个CELL之间的路径,成功返回true*/
intFindPath(CELL*c1,CELL*c2)
{
inti,j,path,min1,max1,min2,max2,left,right,top,bottom;
/*---------------(0)判断是否点中相同块!
------------*/
if(Board[c1->x][c1->y][1]!
=Board[c2->x][c2->y][1])
returnfalse;
/*---------------
(1)查找水平方向公共区域!
-----------*/
min1=max1=c1->x;
min2=max2=c2->x;
while(min1-1>=0&&Board[min1-1][c1->y][0]==0)min1--;
while(min2-1>=0&&Board[min2-1][c2->y][0]==0)min2--;
left=max(min1,min2);/*左边界*/
while(max1+1y][0]==0)max1++;
while(max2+1y][0]==0)max2++;
right=min(max1,max2);/*右边界*/
/*检查两条水平线之间是否有公垂线连通!
*/
/*可以在边缘连通*/
if(left==0)
{
/*左边缘连通*/
DrawPath(c1->x,c1->y,-1,c1->y,-1,c2->y,c2->x,c2->y,LineColor);
delay(6000);
DrawPath(c1->x,c1->y,-1,c1->y,-1,c2->y,c2->x,c2->y,BkGndColor);/*插除线条!
*/
returntrue;
}
if(right==(BoardWidth-1))
{
DrawPath(c1->x,c1->y,BoardWidth,c1->y,BoardWidth,c2->y,c2->x,c2->y,LineColor);
delay(6000);
DrawPath(c1->x,c1->y,BoardWidth,c1->y,BoardWidth,c2->y,c2->x,c2->y,BkGndColor);/*插除线条!
*/
returntrue;
}
for(i=left;i<=right;i++)
{
path=0;/*统计垂直的公垂线长度!
*/
for(j=min(c1->y,c2->y)+1;jy,c2->y);j++)
{
path+=Board[i][j][0];
if(path>0)break;
}
if(path==0)
{
DrawPath(c1->x,c1->y,i,c1->y,i,c2->y,c2->x,c2->y,LineColor);
delay(6000);
DrawPath(c1->x,c1->y,i,c1->y,i,c2->y,c2->x,c2->y,BkGndColor);/*插除线条!
*/
returntrue;
}
}
/*---------------
(2)查找垂直方向公共区域!
-----------*/
min1=max1=c1->y;
min2=max2=c2->y;
while(min1-1>=0&&Board[c1->x][min1-1][0]==0)min1--;
while(min2-1>=0&&Board[c2->x][min2-1][0]==0)min2--;
top=max(min1,min2);
while(max1+1x][max1+1][0]==0)max1++;
while(max2+1x][max2+1][0]==0)max2++;
bottom=min(max1,max2);
/*检查两条垂直线之间是否有公垂线连通!
*/
/*可以在边缘连通*/
if(top==0)
{
/*同在顶端消除*/
DrawPath(c1->x,c1->y,c1->x,-1,c2->x,-1,c2->x,c2->y,LineColor);
delay(6000);
DrawPath(c1->x,c1->y,c1->x,-1,c2->x,-1,c2->x,c2->y,BkGndColor);/*插除线条!
*/
returntrue;
}
if(bottom==(BoardHeight-1))
{
DrawPath(c1->x,c1->y,c1->x,BoardHeight,c2->x,BoardHeight,c2->x,c2->y,LineColor);
delay(6000);
DrawPath(c1->x,c1->y,c1->x,BoardHeight,c2->x,BoardHeight,c2->x,c2->y,BkGndColor);/*插除线条!
*/
returntrue;
}
for(j=top;j<=bottom;j++)
{
path=0;/*统计水平的公垂线长度!
*/
for(i=min(c1->x,c2->x)+1;ix,c2->x);i++)
{
path+=Board[i][j][0];
if(path>0)break;
}
if(path==0)
{
/*水平公垂线*/
DrawPath(c1->x,c1->y,c1->x,j,c2->x,j,c2->x,c2->y,LineColor);
delay(6000);
DrawPath(c1->x,c1->y,c1->x,j,c2->x,j,c2->x,c2->y,BkGndColor);/*插除线条!
*/
returntrue;
}
}
/*到达这里说明没有任何通路*/
returnfalse;
}
/*GetKeyCode*/
intGetKeyCode()
{
intkey=0;
if(bioskey
(1))
{
key=bioskey(0);
}
returnkey;
}
/*绘制消除方块时候的连接路径!
,用指定颜色!
,坐标是CELL逻辑坐标!
*/
voidDrawPath(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4,intcolor)
{
setcolor(color);
moveto(BoardX+CellSize/2+CellSize*x1,BoardY+CellSize/2+CellSize*y1);
lineto(BoardX+CellSize/2+CellSize*x2,BoardY+CellSize/2+CellSize*y2);
lineto(BoardX+CellSize/2+CellSize*x3,BoardY+CellSize/2+CellSize*y3);
lineto(BoardX+CellSize/2+CellSize*x4,BoardY+CellSize/2+CellSize*y4);
}
/*congratulationsinfo,theuserhassuccessfinishthegame!
*/
voidDrawGameOver(char*info)
{
/*计算棋盘的中心点*/
intcx=BoardX+CellSize*BoardWidth/2;
intcy=BoardY+CellSize*BoardHeight/2;
structtextsettingstypetextInfos;
/*获取此前的文字信息*/
gettextsettings(&textInfos);
setcolor(DARKGRAY);
setfillstyle(SOLID_FILL,BLUE);
/*文字居中*/
rectangle(cx-102,cy-22,cx+102,cy+22);
floodfill(cx,cy,DARKGRAY);
rectangle(cx-100,cy-20,cx+100,cy+20);
settextjustify(CENTER_TEXT,CENTER_TEXT);
setcolor(LIGHTBLUE);
outtextxy(cx,cy,info);
/*restoreorignaltextsettings*/
settextjustify(textInfos.horiz,textInfos.vert);
}
/*drawafocusrectonthecellwiththecolor*/
/*用制定颜色绘制一个选中的外边框*/
voidDrawBorderRect(CELL*c,intcolor)
{
setcolor(color);
rectangle(BoardX+(c->x)*CellSize+1,BoardY+(c->y)*CellSize+1,BoardX+(c->x+1)*CellSize-2,BoardY+(c->y+1)*CellSize-2);
rectangle(BoardX+(c->x)*CellSize,BoardY+(c->y)*CellSize,BoardX+(c->x+1)*CellSize-1,BoardY+(c->y+1)*CellSize-1);
}
/*在x,y处用指定颜色绘制键为key的CELL,key在2,3,4,5,6,7,8,9,10,11之间随机*/
voidDrawCell(intkey,intx,inty,intcolor)
{
setcolor(color);
rectangle(BoardX+x*CellSize+2,BoardY+y*CellSize+2,BoardX+(x+1)*CellSize-3,BoardY+(y+1)*CellSize-3);
setfillstyle(key,color);
floodfill(BoardX+x*CellSize+3,BoardY+y*CellSize+3,color);
}
/*擦除CELL*/
voidEraseCell(intx,inty)
{
setcolor(EraColor);
rectangle(BoardX+x*CellSize+2,BoardY+y*CellSize+2,BoardX+(x+1)*CellSize-3,BoardY+(y+1)*CellSize-3);
setfillstyle(SOLID_FILL,BkGndColor);
floodfill(BoardX+x*CellSize+3,BoardY+y*CellSize+3,EraColor);
setcolor(BkGndColor);
rectangle(BoardX+x*CellSize+2,BoardY+y*CellSize+2,BoardX+(x+1)*CellSize-3,BoardY+(y+1)*CellSize-3);
}
/*初始化进度条*/
voidInitProgressBar()
{
intwidth=CellSize*BoardWidth;
/*progressbarborderrect*/
setcolor(BorderColor);
rectangle(BoardX-2,PbY-2,BoardX+width+2,PbY+PbHeight+2);
/*drawavalue=100%progressbar*/
setcolor(PbColor);
rectangle(BoardX,PbY,BoardX+width,PbY+PbHeight);
setfillstyle(SOLID_FILL,PbColor);
floodfill(BoardX+1,PbY+1,PbColor);
}
/*更新进度条,设置为某个百分比*/
voidUpdateProgressBar(intpercent)
{
intp=percent;
intwidth;
if(percent<0)p=0;
elseif(percent>100)p=100;
width=BoardWidth*percent/100*CellSize;
setfillstyle(SOLID_FILL,BkGndColor);
floodfill(BoardX+1,PbY+1,BorderColor);
if(width<2)return;/*toosmallvalue?
*/
setcolor(PbColor);
rectangle(BoardX,PbY,BoardX+width,PbY+PbHeight);
setfillstyle(SOLID_FILL,PbColor);
floodfill(BoardX+1,PbY+1,PbColor);
}
/*初始化程序*/
voidInitGame(char*bgiPath)
{
intgdriver=DETECT,gmode,i,x,y,key;
structtimesysTime;
/*清空棋盘数据!
*/
memset(Board,0,sizeof(Board[0][0][0]*BoardWidth*BoardHeight*2));
/*setnewseed!
*/
gettime(&sysTime);
srand(sysTime.ti_hour*3600+sysTime.ti_min*60+sysTime.ti_sec);
/*entergraphicsmode*/
initgraph(&gdriver,&gmode,bgiPath);
PairsCount=BoardWidth*BoardHeight/4;
for(i=0;i{
key=random(10)+2;
/*fillfirstcellofpair*/
do
{
x=random(BoardWidth);
y=random(BoardHeight);
}
while(Board[x][y][0]!
=0);
DrawCell(key,x,y,CellColor);
Board[x][y][0]=1;
Board[x][y][1]=key;
/*fillsecondcellofpair*/
do
{
x=random(BoardWidth);
y=random(BoardHeight);
}
while(Board[x][y][0]!
=0);
DrawCell(key,x,y,CellColor);
Board[x][y][0]=1;
Board[x][y][1]=key;
}
setcolor(YELLOW);
outtextxy(BoardX,BoardY+BoardHeight*CellSize+30,"PressESCtoExit!
");
outtextxy(BoardX,BoardY+BoardHeight*CellSize+42,"ArrowKeystomove,EntertoConfirm.");
outtextxy(BoardX,BoardY+BoardHeight*CellSize+54,"--byHoodlum1980");
PbValue=100;
TotalTime=3*60;/*Totalminutes.*/
gettime(&sysTime);
StartTime=sysTime.ti_min*60+sysTime.ti_sec;
}
/*游戏进行*/
voidPlayGame()
{
intkey,percent;
longcurTime;
structtimesysTime;
curCell.x=curCell.y=0;/*当前所处位置!
*/
selCell.x=selCell.y=-1;/*为-1表示当前未选中*/
DrawBorderRect(&curCell,CurColor);
/*用一个循环检测按键!
*/
while(key!
=K_ESC)
{
/*waituntilakeypressed*/
while(!
(key=GetKeyCode()))
{
gettime(&sysTime);
curTime=sysTime.ti_min*60+sysTime.ti_sec;
percent=(int)((1-(curTime-StartTime)*1.0/TotalTime)*100);
if(percent<=1)
{
DrawGameOver("YOUHAVELOSE!
");
return;
}
elseif(percent!
=PbValue)
{
UpdateProgressBar(percent);
PbValue=percent;/*updatecachePbValue*/
}
delay(1000);
}
/*这时用户按下了某个键*/
/*需要恢复的是此前选中的cell!
*/
if(curCell.