#include #include #include #include #include #include #define map_Longitudinal 27//地图高度 #define map_across 102//地图宽度 int integral = 0;//玩家积分 int MAX_integral = 0;//最高积分 int pick_food = 1;//判断地图上有没有食物 int map[map_Longitudinal][map_across];//储存地图状态 #define mark_NULL 0//标记空 #define mark_snake 1//标记蛇 #define mark_wall 2//标记墙 #define mark_food 3//标记为食物 void color ( int c )//颜色设置 { SetConsoleTextAttribute ( GetStdHandle ( STD_OUTPUT_HANDLE ) , c ); //颜色设置 //注:SetConsoleTextAttribute是一个API(应用程序编程接口) } typedef struct { int y;//纵坐标 int x;//横坐标 int MAX_x;//横坐标 } game_Integral;//得分 game_Integral * score;//全局声明得分 typedef struct { int y;//纵坐标 int x;//横坐标 } snake_head;//蛇头 snake_head * head;//全局声明蛇头 typedef struct { int y[99];//纵坐标 int x[99];//横坐标 int length;//蛇身体长度 } snake_body;//蛇身 snake_body * body;//全局声明蛇身 void HideCursor ()//隐藏光标 { CONSOLE_CURSOR_INFO curInfo; //定义光标信息的结构体变量 curInfo . dwSize = 1; //如果没赋值的话,光标隐藏无效 curInfo . bVisible = FALSE; //将光标设置为不可见 HANDLE handle = GetStdHandle ( STD_OUTPUT_HANDLE ); //获取控制台句柄 SetConsoleCursorInfo ( handle , & curInfo ); //设置光标信息 } void CursorJump ( int y , int x )//光标跳转 { COORD pos; //定义光标位置的结构体变量 pos . X = x; //横坐标 pos . Y = y; //纵坐标 HANDLE handle = GetStdHandle ( STD_OUTPUT_HANDLE ); //获取控制台句柄 SetConsoleCursorPosition ( handle , pos ); //设置光标位置 } void print_score ()//打印积分 { color ( 14 ); CursorJump ( score -> y , score -> x ); printf ( "\n当前积分为%d分\n" , integral ); CursorJump ( score -> y + 1 , score -> MAX_x ); printf ( "最高积分为%d分\n" , MAX_integral ); } void food_map ()//在动图上生成食物 { int i = rand ( ) % map_Longitudinal;//随机食物纵坐标 int j = rand ( ) % map_across;//随机食物横坐标 int random = rand ( ) % 14 + 1;//随机生成颜色 if ( map[ i ][ j ] == mark_NULL )//监测到有物体就重新生成 { map[ i ][ j ] = mark_food; // 正确标记食物 color ( random ); CursorJump ( i , j ); printf ( "●" ); } else { food_map ( ); } } void move ( int move_x , int move_y )//移动逻辑 { color ( 10 ); //颜色设置为绿色 if ( pick_food == 0 ) { body -> x[ body -> length ] = body -> x[ body -> length - 1 ]; body -> y[ body -> length ] = body -> y[ body -> length - 1 ]; map[ body -> y[ body -> length ] ][ body -> x[ body -> length ] ] = mark_snake;//标记蛇 body -> length += 1;//增加蛇身体长度 integral += 10;//增加积分 } //将最后一个取消 map[ body -> y[ body -> length - 1 ] ][ body -> x[ body -> length - 1 ] ] = mark_NULL;//标记为空 CursorJump ( body -> y[ body -> length - 1 ] , body -> x[ body -> length - 1 ] ); printf ( " " ); //更新蛇身坐标 for ( int i = body -> length - 1 ; i > 0 ; -- i ) { body -> x[ i ] = body -> x[ i - 1 ]; body -> y[ i ] = body -> y[ i - 1 ]; } body -> x[ 0 ] = head -> x; body -> y[ 0 ] = head -> y; //将蛇头原来的坐标替换为身体 CursorJump ( head -> y , head -> x ); printf ( "□" ); //更新蛇头坐标 head -> x += move_x; head -> y += move_y; //把蛇头的坐标在地图更新 map[ head -> y ][ head -> x ] = mark_snake;//标记蛇 CursorJump ( head -> y , head -> x ); printf ( "■" ); if ( pick_food == 0 ) { food_map ( ); print_score ( );//重新打印积分 pick_food = 1; } } void Begin ()//开始界面 { printf ( "\n\n\n\n\n\n\n\n\t\t\t\t\t——————————贪吃蛇——————————\n" ); printf ( "\t\t\t\t\t|使用WSAD进行上下左右移动|\n" ); printf ( "\t\t\t\t\t|按ESC退出游戏 |\n" ); printf ( "\t\t\t\t\t|回车进入游戏 |\n" ); printf ( "\t\t\t\t\t——————————贪吃蛇——————————\n" ); int a = _getch ( ); if ( a == 27 ) { exit ( 0 ); } } void initial_snake ()//初始蛇 { color ( 10 ); //颜色设置为绿色 //初始化蛇头 head -> x = 10; head -> y = 10; //初始化蛇身 body -> x[ 1 ] = 9; body -> y[ 1 ] = 10; body -> x[ 0 ] = 8; body -> y[ 0 ] = 10; body -> length = 2; //生成蛇的图像 //蛇头 map[ head -> y ][ head -> x ] = mark_snake;//标记蛇 CursorJump ( head -> y , head -> x ); printf ( "■" ); //蛇身 for ( int i = body -> length - 1 ; i >= 0 ; -- i ) { map[ body -> y[ i ] ][ body -> x[ i ] ] = mark_snake;//标记蛇 CursorJump ( body -> y[ i ] , body -> x[ i ] ); printf ( "□" ); } } void print_map ()//初始地图 { color ( 12 ); for ( int i = 0 ; i < map_Longitudinal ; ++ i ) { if ( i == 0 || i == map_Longitudinal - 1 ) { for ( int j = 0 ; j < map_across ; ++ j ) { //打印墙并且标记状态为墙 map[ i ][ j ] = mark_wall; printf ( "█" ); } printf ( "\n" ); } else { for ( int j = 0 ; j < map_across ; ++ j ) { if ( j == 0 || j == map_across - 1 )//打印边界 { //打印墙并且标记状态为墙 map[ i ][ j ] = mark_wall; printf ( "█" ); } else { map[ i ][ j ] = mark_NULL;//标记为空 printf ( " " );//输出地图 } } printf ( "\n" ); } } } int defeat ()//失败界面 { CursorJump ( 10 , 50 ); printf ( "\n\t\t\t—————————游戏失败—————————\n" ); printf ( "\t\t\t|按ESC退出游戏 |\n" ); printf ( "\t\t\t|其他键继续游戏 |\n" ); printf ( "\t\t\t—————————游戏失败—————————\n" ); int a = _getch ( ); if ( a == 27 ) { exit ( 0 ); } else { MAX_integral = integral;//保存最大积分 return 5; } } int main () { HideCursor ( );//隐藏光标 game_Begin: system ( "cls" ); score = ( game_Integral * ) malloc ( sizeof ( game_Integral ) );//动态分配光标内存 head = ( snake_head * ) malloc ( sizeof ( snake_head ) );// 动态分配蛇头内存 body = ( snake_body * ) malloc ( sizeof ( snake_body ) );// 动态分配蛇头内存 score -> x = 1;//积分横坐标 score -> y = map_Longitudinal;//积分纵坐标 score -> MAX_x = map_across - 13;//最大积分横坐标 srand ( time ( NULL ) );//设置随机数 char direction_test = 'd';//方向接收 char direction = 'd';//方向 int move_x = 0;//更新移动所产生的横坐标 int move_y = 0;//更新移动所产生的纵坐标 int pick = 0;//接收是否重开游戏 print_map ( );//打印当前地图 print_score ( );//打印积分 initial_snake ( );//生成蛇 food_map ( );//在动图上生成食物 while ( 1 ) { if ( _kbhit ( ) )//接收用户输入 { direction_test = _getch ( ); if ( direction_test == 'W' || direction_test == 'w' || direction_test == 'S' || direction_test == 's' || direction_test == 'A' || direction_test == 'a' || direction_test == 'D' || direction_test == 'd' )//判断方向对不对 { direction = direction_test;//更新移动方向 } } //判断移动的坐标 if ( direction == 'W' || direction == 'w' )//判断向上 { if ( move_y == 1 ) { move_x = 0;//更新移动所产生的横坐标 move_y = 1;//更新移动所产生的纵坐标 } else { if ( map[ head -> y - 1 ][ head -> x ] == mark_snake || map[ head -> y - 1 ][ head -> x ] == mark_wall )//判断有没有失败 { pick = defeat ( ); } if ( map[ head -> y - 1 ][ head -> x ] == mark_food ) { pick_food = 0;//提示食物没有了 } move_x = 0;//更新移动所产生的横坐标 move_y = - 1;//更新移动所产生的纵坐标 } } else if ( direction == 'S' || direction == 's' )//判断向下 { if ( move_y == - 1 ) { move_x = 0;//更新移动所产生的横坐标 move_y = - 1;//更新移动所产生的纵坐标 } else { if ( map[ head -> y + 1 ][ head -> x ] == mark_wall || map[ head -> y + 1 ][ head -> x ] == mark_snake )//判断有没有失败 { pick = defeat ( ); } if ( map[ head -> y + 1 ][ head -> x ] == mark_food ) { pick_food = 0;//提示食物没有了 } move_x = 0;//更新移动所产生的横坐标 move_y = 1;//更新移动所产生的纵坐标 } } else if ( direction == 'A' || direction == 'a' )//判断向左 { if ( move_x == 1 ) { move_x = 1;//更新移动所产生的横坐标 move_y = 0;//更新移动所产生的纵坐标 } else { if ( map[ head -> y ][ head -> x - 1 ] == mark_wall || map[ head -> y ][ head -> x - 1 ] == mark_snake )//判断有没有失败 { pick = defeat ( ); } if ( map[ head -> y ][ head -> x - 1 ] == mark_food ) { pick_food = 0;//提示食物没有了 } move_x = - 1;//更新移动所产生的横坐标 move_y = 0;//更新移动所产生的纵坐标 } } else if ( direction == 'D' || direction == 'd' )//判断右 { if ( move_x == - 1 ) { move_x = - 1;//更新移动所产生的横坐标 move_y = 0;//更新移动所产生的纵坐标 } else { if ( map[ head -> y ][ head -> x + 1 ] == mark_wall || map[ head -> y ][ head -> x + 1 ] == mark_snake )//判断有没有失败 { pick = defeat ( ); } if ( map[ head -> y ][ head -> x + 1 ] == mark_food ) { pick_food = 0;//提示食物没有了 } move_x = 1;//更新移动所产生的横坐标 move_y = 0;//更新移动所产生的纵坐标 } } if ( pick == 5 || direction_test == 'R' || direction_test == 'r' )//判断是否重开游戏 { system ( "cls" ); integral = 0;//重置玩家积分 free ( score ); free ( head ); free ( body ); goto game_Begin; } move ( move_x , move_y );//将坐标移动 Sleep ( 80 );//停顿一秒 } return 0; }