admin 管理员组文章数量: 887021
2024年2月26日发(作者:电脑如何下载matlab软件下载)
连连看游戏C语言源代码
#include
#include
#include
#include
#include
#define true 1
#define false 0
/* ---------------------全局变量------------------------------------ */
int BkGndColor=BLACK;
int BorderColor=LIGHTGRAY;
int LineColor=LIGHTBLUE;/* 消除一对方块时时候的连线颜色 */
/* Pb - ProgressBar */
int PbColor=LIGHTGREEN;
int PbY=4;
int PbHeight=4;
int PbValue; /* 进度条百分比,初始值为100.*/
long StartTime; /* 开始时间的秒数,只统计分钟,秒 */
long TotalTime; /* 游戏总共的最大秒数!,*/
/* BoardDatas: a small-size board */
/* Board[x][y][0] - 0:empty, 1:filled */
/* Board[x][y][1] - cell's key; */
unsigned char Board[10][10][2];
int CellSize=30;
int BoardX=20;
int BoardY=60;
int BoardWidth=10;
int BoardHeight=10;
int CellColor=WHITE;
int SelColor=BLUE; /* selCell's border rect color */
int CurColor=RED; /* curCell's border rect color */
int EraColor=CYAN; /* 用于擦除cell的颜色!*/
int PairsCount; /* how much pairs we have put on board */
/* 用于存储逻辑坐标(索引) */
typedef struct _tagCELL
{
char x;
char y;
} CELL;
CELL selCell,curCell;/*缓存前一个被选中的位置以及当前所处位置!*/
/*Scan Codes Define*/
enum KEYCODES
{
K_ESC =0x011b,
K_UP =0x4800, /* upward arrow */
K_LEFT =0x4b00,
K_DOWN =0x5000,
K_RIGHT =0x4d00,
K_SPACE =0x3920,
K_P =0x1970,
K_RETURN =0x1c0d, /* Enter */
};
/* ---------------------函数列表------------------------------------ */
void InitGame(char *bgiPath);
void PlayGame();
void QuitGame();
void InitProgressBar();
void UpdateProgressBar(int percent);
void DrawCell(int key,int x,int y,int color);
void EraseCell(int x,int y);
void DrawBorderRect(CELL *c,int color);
void DrawGameOver(char* info);
int GetKeyCode();
int FindPath(CELL *c1,CELL *c2);
/*绘制消除方块时候的连接路径!,用指定颜色!*/
void DrawPath(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int color);
/* ----------------------函数实现----------------------------------- */
/* ----------------------[ 核心算法 ]---------------------------------
* 先进行水平方向判断,找出两点所在的水平直线活动范围,
* 算出这两条线段在垂直方向的共同区域,
* 遍历该区域判断能否在两线段间架起公垂线,能则两点连接上;
* 接着进行垂直方向判断,类同。无论两点在不在一条直线上,
* 都能使用该算法,因为两点同线只是两点作为矩形对角点的特例而已。
*/
/* 找到两个CELL之间的路径,成功返回true */
int FindPath(CELL *c1,CELL *c2)
{
int i,j,path,min1,max1,min2,max2,left,right,top,bottom;
/*---------------(0)判断是否点中相同块! ------------*/
if(Board[c1->x][c1->y][1] != Board[c2->x][c2->y][1])
return false;
/*---------------(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+1
while(max2+1
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);/*插除线条!*/
return true;
}
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);/*插除线条!*/
return true;
}
for(i=left;i<=right;i++)
{
path=0;/*统计垂直的公垂线长度!*/
for(j=min(c1->y,c2->y)+1;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);/*插除线条!*/
return true;
}
}
/*---------------(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+1
while(max2+1
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);/*插除线条!*/
return true;
}
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);/*插除线条!*/
return true;
}
for(j=top;j<=bottom;j++)
{
path=0;/*统计水平的公垂线长度!*/
for(i=min(c1->x,c2->x)+1; 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);/*插除线条!*/
return true;
}
}
/* 到达这里说明没有任何通路 */
return false;
}
/*Get Key Code */
int GetKeyCode()
{
int key=0;
if(bioskey(1))
{
key=bioskey(0);
}
return key;
}
/*绘制消除方块时候的连接路径!,用指定颜色!,坐标是CELL逻辑坐标!*/
void DrawPath(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int color)
{
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);
}
/* congratulations info,the user has success finish the game ! */
void DrawGameOver(char* info)
{
/*计算棋盘的中心点*/
int cx=BoardX+CellSize*BoardWidth/2;
int cy=BoardY+CellSize*BoardHeight/2;
struct textsettingstype textInfos;
/*获取此前的文字信息*/
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);
/*restore orignal text settings */
settextjustify(, );
}
/* draw a focus rect on the cell with the color */
/* 用制定颜色绘制一个选中的外边框 */
void DrawBorderRect(CELL *c,int color)
{
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之间随机 */
void DrawCell(int key,int x,int y,int color)
{
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 */
void EraseCell(int x,int y)
{
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);
}
/* 初始化进度条 */
void InitProgressBar()
{
int width=CellSize*BoardWidth;
/* progress bar border rect */
setcolor(BorderColor);
rectangle(BoardX-2,PbY-2,BoardX+width+2,PbY+PbHeight+2);
/* draw a value = 100% progress bar */
setcolor(PbColor);
rectangle(BoardX,PbY,BoardX+width,PbY+PbHeight);
setfillstyle(SOLID_FILL,PbColor);
floodfill(BoardX+1,PbY+1,PbColor);
}
/* 更新进度条,设置为某个百分比 */
void UpdateProgressBar(int percent)
{
int p=percent;
int width;
if(percent<0) p=0;
else if(percent>100) p=100;
width=BoardWidth*percent/100*CellSize;
setfillstyle(SOLID_FILL,BkGndColor);
floodfill(BoardX+1,PbY+1,BorderColor);
if(width<2) return;/* too small value? */
setcolor(PbColor);
rectangle(BoardX,PbY,BoardX+width,PbY+PbHeight);
setfillstyle(SOLID_FILL,PbColor);
floodfill(BoardX+1,PbY+1,PbColor);
}
/* 初始化程序 */
void InitGame(char *bgiPath)
{
int gdriver=DETECT,gmode,i,x,y,key;
struct time sysTime;
/*清空棋盘数据!*/
memset(Board,0,sizeof(Board[0][0][0]*BoardWidth*BoardHeight*2));
/* set new seed! */
gettime(&sysTime);
srand(_hour*3600+_min*60+_sec);
/* enter graphics mode */
initgraph(&gdriver,&gmode,bgiPath);
PairsCount=BoardWidth*BoardHeight/4;
for(i=0; i { key=random(10)+2; /* fill first cell of pair */ 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; /* fill second cell of pair */ 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,"Press ESC to Exit!"); outtextxy(BoardX,BoardY+BoardHeight*CellSize+42,"ArrowKeys to move, Confirm."); Enter to outtextxy(BoardX,BoardY+BoardHeight*CellSize+54,"--by Hoodlum1980"); PbValue=100; TotalTime=3*60; /* Total minutes. */ gettime(&sysTime); StartTime=_min*60+_sec; } /* 游戏进行 */ void PlayGame() { int key,percent; long curTime; struct time sysTime; curCell.x = curCell.y = 0;/*当前所处位置!*/ selCell.x = selCell.y = -1;/*为-1表示当前未选中*/ DrawBorderRect(&curCell, CurColor); /*用一个循环检测按键!*/ while(key!=K_ESC) { /* wait until a key pressed */ while(!(key=GetKeyCode())) { gettime(&sysTime); curTime=_min*60+_sec; percent=(int)((1-(curTime-StartTime)*1.0/TotalTime)*100); if(percent<=1) { DrawGameOver("YOU HAVE LOSE!"); return; } else if(percent!=PbValue) { UpdateProgressBar(percent); PbValue=percent;/* update cache PbValue */ } delay(1000); } /* 这时用户按下了某个键 */ /*需要恢复的是此前选中的cell!*/ if(curCell.x==selCell.x && curCell.y==selCell.y) DrawBorderRect(&curCell, SelColor); /*恢复选中cell的focus痕迹 */ else DrawBorderRect(&curCell, BkGndColor); /*擦除此前的focus痕迹 */ switch(key) { case K_LEFT: curCell.x--; if(curCell.x < 0) curCell.x += BoardWidth; break; case K_RIGHT: curCell.x++; if(curCell.x >= BoardWidth) curCell.x -= BoardWidth; break; case K_UP: curCell.y--; if(curCell.y < 0) curCell.y += BoardHeight; break; case K_DOWN: curCell.y++; if(curCell.y >= BoardHeight) curCell.y -= BoardHeight; break; /* 对回车键 */ case K_RETURN: /* 如果此处没有任何cell,不处理! */ if(Board[curCell.x][curCell.y][0]==0) break; /* 与此前选中的位置重合,则不处理 */ if(curCell.x==selCell.x && curCell.y==selCell.y) break; /*如果此前没有任何选中,则设置改点为选中位置*/ if(selCell.x<0 || selCell.y<0) { selCell.x=curCell.x; selCell.y=curCell.y; DrawBorderRect(&selCell,SelColor); continue; } /*如果此前已有选中,则判断是否可以消除!*/ if(FindPath(&selCell,&curCell)) { /* 消除这两个cell!*/ EraseCell(selCell.x,selCell.y); EraseCell(curCell.x,curCell.y); /* 清除棋盘数据 */ Board[selCell.x][selCell.y][0]=0; Board[selCell.x][selCell.y][1]=0; Board[curCell.x][curCell.y][0]=0; Board[curCell.x][curCell.y][1]=0; /* 清除selCell */ DrawBorderRect(&selCell,BkGndColor); selCell.x=selCell.y=-1; /* decrease the pairs count */ PairsCount--; if(PairsCount==0) { DrawGameOver("CONGRATULATIONS!"); return; } } else { /* 不能消除这两个cell!*/ /* erase the selCell's focus rect!*/ DrawBorderRect(&selCell,BkGndColor); selCell.x=selCell.y=-1; } break; case K_ESC: DrawGameOver("GAME OVER!"); break; default: break; } /*绘制当前focus位置*/ DrawBorderRect(&curCell, CurColor); } } /* 退出程序 */ void QuitGame() { closegraph(); } /* Entry Point */ int main(int argc,char *argv[]) { InitGame(""); InitProgressBar(); PlayGame(); getch(); QuitGame(); return 0; getch(); }
版权声明:本文标题:连连看游戏C语言源代码 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1708939554h535010.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论