# snack **Repository Path**: jerkhn/snack ## Basic Information - **Project Name**: snack - **Description**: C snack - **Primary Language**: Unknown - **License**: AGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-12-23 - **Last Updated**: 2020-12-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 字符游戏-贪吃蛇 *** ## 一、实验目的: 1. 了解字符游戏的表示 2. 体验自顶向下的设计方法实现问题求解 3. 使用伪代码表示算法 4. 使用函数抽象过程 ## 二、实验要求: - 给定一个10*10的字符矩阵表示蛇的生存空间,其中有一条长度5的蛇(HXXXX), “H”表示蛇头,“X”表示蛇身体。空间中可能有食物(“$”表示)和障碍物(“*”表示) - 你可以使用“ADWS”按键分别控制蛇的前进方向“左右上下”, 当蛇头碰到自己的身体或走出边界,游戏结束,否则蛇按你指定方向前进一步 ## 三、任务一:会动的蛇 - 首先我们要定义我们的游戏地图,这里我们使用老师给出的定义格式,使用二维数组来存储地图数据: ```c char map[12][12] = {"************", "*XXXXH *", "* *", "* *", "* *", "* *", "* *", "* *", "* *", "* *", "* *", "************" }; ``` - 使用两个数组来表示蛇身的x,y坐标: ```c int snake_X[SNAKE_MAX_LENGTH] = {1 , 2 , 3 , 4 , 5}; int snake_Y[SNAKE_MAX_LENGTH] = {1 , 1 , 1 , 1 , 1}; ``` - 我们接下来分析蛇的行为模式: - wasd的上下左右移动 - 蛇撞到墙壁 - 蛇碰到自身的身体 - 游戏状态判断: - 蛇的死亡状态判断 - 游戏结束判断 - 每一轮移动后的图像刷新 - 最终的行为函数为: ```c void snake_move (int dy , int dx); void output(void); void gameover(void); int if_dead(void); int eat_itself(void); ``` ### 3.1 snack_move >首先判断移动后的位置是由为边界,之后将代表蛇身位置的数组位置移动获得移动后的位置坐标 ```c void snake_move(int dy , int dx){ if((snake_X[snake_length - 1] + dx )== snake_X[snake_length - 2] && (snake_Y[snake_length - 1] + dy) == snake_Y[snake_length - 2]) return; int i; for(i = 0 ; i < snake_length - 1 ; i ++){ snake_X[i] = snake_X[i + 1]; snake_Y[i] = snake_Y[i + 1]; } snake_X[snake_length - 1] += dx; snake_Y[snake_length - 1] += dy; return; } ``` ### 3.2 eat_itself >判断蛇是否碰到自己的身体,检测蛇的身体是否由重叠部分即可 > ```c int eat_itself(){ int i , j; for(i = 0 ; i < snake_length ; i ++){ for( j = i + 1 ; j < snake_length ; j ++) if(snake_X[i] == snake_X[j] && snake_Y[i] == snake_Y[j]) return 1; } return 0; } ``` ### 3.3 if_dead >判断蛇是否撞墙死亡或者最长 ```c int if_dead(){ if(snake_X[snake_length - 1] == 0 || snake_X[snake_length - 1] == 11 || snake_Y[snake_length - 1] == 0 || snake_Y[snake_length - 1] == 11) return 0; if(eat_itself()) return 0; return 1; } ``` ### 3.4 output >刷新游戏地图,首先清空屏幕,之后重新绘制新的地图和蛇的信息 ```c void output(){ system("cls"); int x , y , i , j; for( x = 0 ; x < 12 ; x ++ ){ for( y = 0 ; y < 12 ; y ++){ if( x == 0 || x == 11 || y == 11 || y == 0) map[x][y] = '*'; else map[x][y] = ' '; } } for( i = 0 ; i < snake_length - 1 ; i ++ ){ map[snake_Y[i]][snake_X[i]] = 'X'; map[snake_Y[snake_length - 1]][snake_X[snake_length - 1]] = 'H'; } for( i = 0 ; i < 12 ; i ++ ){ for( j = 0 ; j < 12 ; j ++ ){ printf("%c",map[i][j]); } printf("\n"); } } ``` ### 3.5 gameover >游戏结束后清空屏幕 ```c void gameover(){ system("cls"); printf("END!"); return; } ``` ## 四、任务二:会吃的蛇 - 在任务一上增加随机生成食物以及蛇迟到食物的状态更新即可 - 移动部分仍然沿用以上代码 - 新增功能如下: ```c void eat_food(int dx , int dy); void produce(void); ``` ### 4.1 eat_food >每次吃到食物后,将蛇身增长,并且生成新食物 ```c void eat_food(int dx , int dy){ snake_length ++; snake_X[snake_length - 1] = snake_X[snake_length - 2] + dx; snake_Y[snake_length - 1] = snake_Y[snake_length - 2] + dy; produce_food(); } ``` ### 4.2 produce >使用随机数在地图中随机生成 ```c void produce_food(){ srand((unsigned)time(0)); while(1){ food_X = rand()%12; food_Y = rand()%12; if(map[food_Y][food_X] == ' '){ break; } } } ```