www.pudn.com > snake.rar > snake.C
/*---------------------------------------------------------------------------------------------------------------------- * 对snakemap矩阵元素含义的定义: * 0: 空 * -1: 障碍 * -2: 食物 * 正数: 有可能是蛇节点(程序正常就是蛇节点) * * 对于正数 * 个位=1/2/3/4 = 上/下/左/右 * 十位=1/0 = 曾经吃过食物还没加长度的/最近没在这个位置吃过食物 * * 不在定义之外的正数应该不会出现吧 * ---------------------------------------------------------------------------------------------------------------------*/ #include#include #include #include #include /* 几个键盘的ASCII码值 */ /* 上下左右键盘游戏 */ /* 可以改成其他的ASCII值来更换热键 */ #define UP 0x48 #define DOWN 0x50 #define LEFT 0x4b #define RIGHT 0x4d /*-定义游戏格子矩阵,可以配置修改游戏矩阵-*/ #define height 9 #define width 16 int snakemap[height][width]= { /*----------0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ /* 0 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 1 */ { 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 2 */ { 0, 0, 0, 0, 0, 0,-1, 0,-1, 0, 0, 0, 0, 0, 0, 0 }, /* 3 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 4 */ { 0, 0, 0, 0, 0, 0,-1, 0,-1, 0, 0, 0, 0, 0, 0, 0 }, /* 5 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 6 */ { 0, 0, 0, 0, 0, 0,-1, 0,-1, 0, 0, 0, 0, 0, 0, 0 }, /* 7 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 8 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; #define map_left 160 /*界面左边界的x像素 */ #define map_top 125 /*界面左边界的y像素 */ #define blcok_size 15 /*一个蛇身格子的边长 */ #define margin_size1 1 /*格子之间留得空隙长度*/ #define margin_size2 1 /*格子之间留得空隙长度*/ #define snakecolor LIGHTBLUE /*蛇体颜色 */ #define headcolor GREEN /*蛇头颜色 */ #define barriercolor BROWN /*障碍颜色 */ #define bgcolor WHITE /*背景颜色 */ #define foodcolor MAGENTA /*食物颜色 */ #define margin_color1 GREEN /*间隔1颜色*/ #define margin_color2 bgcolor /*间隔2颜色*/ /*定义贪吃蛇控制结构*/ struct snakecotrol { int head_i; /*蛇头*/ int head_j; int tail_i; /*蛇尾*/ int tail_j; }snakecotrol; /* 当前移动方向 : 默认最开始往右边 */ /* 移动方向信心将会记录在矩阵元素中 */ /* 1/2/3/4 = 上/下/左/右 */ int derection=4; /* 记录当前map中空白格的数量,即0的数量 */ /* 游戏结束,和随机产生食物将要用到这个 */ /* spacenum的初始值在mian函数开始设置 */ int spacenum; /* 延迟功能的设计: */ /* if(上次触发时间 - 此刻) > 基本等待 * 倍数 */ /* 触发并且记录此刻时间 */ /* else */ /* 不触发 */ #define persec 30 /*基本等待时间,单位百分之一秒 */ int mulpersec = 1; /*等待时间的倍数 */ int history_sec = 0; /*上次触发的秒值 */ int history_persec = 0; /*上次触发的百分之一秒值 */ int trigger(); /*触发函数,返回1触发,返回0不触发 */ void show(int i,int j,int color,int bargin1, int bargin2); /*打印一个格子,坐标i,坐标j,颜色,间隔色 */ int anlyse(int i,int j); /*分析元素的类型 */ void clear(int i,int j); /*清理一个格子的显示 */ void getnextpos(int *i,int *j,int d); /*根据蛇的位置,和当时移动方向,取得下一个位置 */ int mov(); /*做一次移动,mov成功返回1,继续游戏,mov失败返回-1,游戏结束 */ int genfood(); /*产生食物,如果没有空白位置来产生食物,则游戏结束 */ void main() { int gameoversign = 0; int derectionback = derection; /*不能对任意一次按键就更新全局变量derection,所以设置备份 */ int i,j; char keyboard_hit; /*初始化显示器图形模式: 640 X 480 */ int driver=VGA,mode=VGAHI; registerbgidriver(EGAVGA_driver); initgraph(&driver,&mode,"c:\\tc"); setbkcolor(bgcolor); /*初始化随机数种子用于生成随机食物 */ srand((unsigned)time(NULL)); /*游戏地图初始化,并初始化空白格数量*/ spacenum = 0; for (j = 0; j < width; j++){ for (i = 0; i < height; i++){ if (snakemap[i][j] == 0){/*空白*/ spacenum++; show(i, j, bgcolor,margin_color1,margin_color2); }else if(snakemap[i][j] == -1){/*障碍*/ show(i, j, barriercolor,margin_color1,margin_color2); }else if (snakemap[i][j] == -2){/*食物*/ show(i, j, foodcolor,margin_color1,margin_color2); }else{ show(i, j, snakecolor,margin_color1,margin_color2);/*蛇*/ } } } /*初始化贪吃蛇控制结构*/ /*蛇头(1,1),蛇尾(0,1)*/ snakecotrol.head_i = 1; snakecotrol.head_j = 1; snakecotrol.tail_i = 1; snakecotrol.tail_j = 0; /*最开始的两节蛇,位置要与上面的数组一致*/ show(snakecotrol.head_i,snakecotrol.head_j,snakecolor,margin_color1,margin_color2); show(snakecotrol.tail_i,snakecotrol.tail_j,snakecolor,margin_color1,margin_color2); /*产生食物*/ genfood(); /*游戏循环*/ while (gameoversign == 0){ /*如果有合法按键则接受键盘字符*/ if (kbhit()!=0){ keyboard_hit = getch(); switch(keyboard_hit) { /*设置derectionback,的目的是为了多次接受输入,最后再更新全局量*/ case UP: {if (derection != 2) derectionback = 1;break;} case DOWN: {if (derection != 1) derectionback = 2;break;} case LEFT: {if (derection != 4) derectionback = 3;break;} case RIGHT: {if (derection != 3) derectionback = 4;break;} }; } /*如果到了触发时间就mov()*/ if (trigger() == 1){ /*更新移动方向*/ derection = derectionback; /*移动*/ if (mov() == -1){ gameoversign = 1; } } } /*关闭图形模式*/ closegraph(); } int genfood() { int i = 0,j = 0; int v; if (spacenum == 0){ return -1;/*游戏结束*/ } v = rand() % spacenum + 1; while(v > 0){ if(snakemap[i][j] == 0){ if (--v == 0) break; } if(j < width - 1){ j++; }else{ j=0; i++; } } if (v != 0 || i < 0 || i >= height || j < 0 || j >= width){ printf("genfood() error: i = %d, j = %d, v = %d", i, j, v); getch(); } /*产生食物*/ spacenum--; snakemap[i][j] = -2; show(i, j, foodcolor, margin_color1,margin_color2); return 1; } int mov() { int i = snakecotrol.head_i, j = snakecotrol.head_j; int r; /*处理蛇尾*/ i = snakecotrol.tail_i, j = snakecotrol.tail_j; if (snakemap[i][j]/10 > 0){ /*加长*/ snakemap[i][j] -= 10; }else{ /*不用加长*/ clear(i,j); getnextpos(&i,&j,snakemap[i][j]%10); snakemap[snakecotrol.tail_i][snakecotrol.tail_j] = 0; snakecotrol.tail_i = i; snakecotrol.tail_j = j; } /*处理蛇头*/ i = snakecotrol.head_i; j = snakecotrol.head_j; show(i,j,snakecolor,margin_color1,margin_color2); getnextpos(&i,&j,derection); r = anlyse(i,j); if (r != 0 && r != -2){ return -1;/*移动到的地方非空非食物则撞了,游戏结束*/ } snakemap[snakecotrol.head_i][snakecotrol.head_j] /= 10; snakemap[snakecotrol.head_i][snakecotrol.head_j] *= 10; snakemap[snakecotrol.head_i][snakecotrol.head_j] += derection; show(i,j,headcolor,margin_color1,margin_color2); snakecotrol.head_i = i; snakecotrol.head_j = j; if (r == -2){ snakemap[snakecotrol.head_i][snakecotrol.head_j] = 0; snakemap[snakecotrol.head_i][snakecotrol.head_j] += 10; if(genfood() == -1){ return -1; } } return 1; } void getnextpos(int *i, int *j, int d) { /*根据方向移动*/ switch(d) { case 1:{(*i)--;}break; case 2:{(*i)++;}break; case 3:{(*j)--;}break; case 4:{(*j)++;}break; } /*处理越边界情况*/ if (*i<0) *i = height-1; else if(*i>= height) *i = 0; else if(*j<0) *j = width-1; else if(*j>= width) *j = 0; } int anlyse(int i, int j) { int x; x = snakemap[i][j]; if (x == 0){ return 0;/*空*/ }else if(x == -1){ return -1;/*障碍*/ }else if (x == -2){ return -2;/*食物*/ }else if(x > 0 && x < 9 && (x%10) >= 1 && (x%10) <= 4){ return 1;/*蛇身*/ }else if((x/10) > 0 && (x%10) >= 1 && (x%10) <= 4){ return 2;/*蛇身,因在此处吃过食物,待加长*/ }else{ printf("anlyse ERROR elem : %d",x); getch(); return 100; } } void clear(int i,int j) { show(i,j,bgcolor,margin_color1,margin_color2); } void show(int i,int j,int color,int bargin1, int bargin2) { int x1,x2,x3,x4; int s_left,s_top; x1 = blcok_size; x2 = margin_size1; x3 = margin_size2; x4 = x1 + x2 + x2 + x3 + x3; s_left = map_left + j * x4; s_top = map_top + i * x4; /* 打印间隔1 */ setfillstyle(SOLID_FILL,bargin1); bar(s_left, s_top, s_left+x4, s_top+x2); bar(s_left, s_top + x4 - x2, s_left + x4, s_top + x4); bar(s_left, s_top, s_left+x2, s_top+x4); bar(s_left+x4-x2,s_top,s_left+x4,s_top+x4); /* 打印间隔2 */ s_left = s_left + x2; s_top = s_top + x2; x4 -= x2*2; setfillstyle(SOLID_FILL,bargin2); bar(s_left, s_top, s_left+x4, s_top+x3); bar(s_left, s_top + x4 - x3, s_left + x4, s_top + x4); bar(s_left, s_top, s_left+x3, s_top+x4); bar(s_left+x4-x3,s_top,s_left+x4,s_top+x4); /* 打印方块 */ s_left = s_left + x3; s_top = s_top + x3; x4 -= x3*2; setfillstyle(SOLID_FILL,color); bar(s_left,s_top,s_left+x4,s_top+x4); } int trigger() { int d; struct time now; gettime(&now); d = (now.ti_sec + 60 - history_sec) % 60; d = (d * 100 + now.ti_hund - history_persec); if (d > persec * mulpersec){ history_sec = now.ti_sec; history_persec = now.ti_hund; return 1;/*触发*/ }else{ return 0;/*不触发*/ } }