# GreedySnake **Repository Path**: hide-on-bush2/greedy-snake ## Basic Information - **Project Name**: GreedySnake - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-12-30 - **Last Updated**: 2021-01-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 字符游戏 - 贪吃蛇 & 智能蛇 ## 实验目的 * 了解字符游戏的表示 * 体验自顶向下的设计方法实现问题求解 * 使用伪代码表示算法 * 使用函数抽象过程 ## 会动的蛇 首先定义程序的头部: ``` class Snake{ private: int snake[max_size][max_size]; int head_low; int head_upp; int tail_low; int tail_upp; int length; public: Snake(int low = 0, int upp = 0, int len = 3); void moveHead(string direction); bool ifEatFood(int food_low, int food_upp); void eatFood(); void addTail(); void tailMove(); bool isEnd(string nextDir); bool tailOut(); void print(int food_low, int food_upp); }; ``` 该程序头部维护一些贪吃蛇的状态变量,和定义了可以对这些状态进行操作的方法: * 状态变量 * `snake[max_size][max_size]`:贪吃蛇地图 * `head_low`:贪吃蛇头部的横坐标 * `head_upp`:贪吃蛇头部的纵坐标 * `tail_low`:贪吃蛇尾部的横坐标 * `tail_upp`:贪吃蛇尾部的纵坐标 * `length`:贪吃蛇的长度 * 方法: * `Snake` 构造函数 * `moveHead` 移动贪吃蛇的头部 * `ifEatFood` 判断是否吃到食物 * `addTail` 吃到食物后增加尾部的长度 * `tailMove` 移动尾部 * `isEnd` 判断游戏是否结束 * `tailOut` 判断贪吃蛇的尾部是否出界(发生在少数情况下) * `print` 打印地图 根据输入的方向移动蛇的头部: ``` void Snake::moveHead(string direction){ if(direction == "a"){ snake[head_low][head_upp - 1] = snake[head_low][head_upp] + 1; head_upp -= 1; }else if(direction == "s"){ snake[head_low + 1][head_upp] = snake[head_low][head_upp] + 1; head_low += 1; }else if(direction == "d"){ snake[head_low][head_upp + 1] = snake[head_low][head_upp] + 1; head_upp += 1; }else if(direction == "w"){ snake[head_low - 1][head_upp] = snake[head_low][head_upp] + 1; head_low -= 1; } } ``` 根据输入的方向移动蛇的尾部: ``` //移动尾巴 void Snake::tailMove(){ if(tail_upp < max_size && snake[tail_low][tail_upp + 1] == snake[tail_low][tail_upp] + 1){ snake[tail_low][tail_upp] = 0; tail_upp += 1; return; } if(tail_low < max_size && snake[tail_low + 1][tail_upp] == snake[tail_low][tail_upp] + 1){ snake[tail_low][tail_upp] = 0; tail_low += 1; return; } if(tail_low > 0 && snake[tail_low - 1][tail_upp] == snake[tail_low][tail_upp] + 1){ snake[tail_low][tail_upp] = 0; tail_low -= 1; return; } if(tail_upp > 0 && snake[tail_low][tail_upp - 1] == snake[tail_low][tail_upp] + 1){ snake[tail_low][tail_upp] = 0; tail_upp -= 1; return; } } ``` 然后判断游戏是否结束: ``` //判断是否结束 bool Snake::isEnd(string nextDir){ int upp = head_upp, low = head_low; if(nextDir == "a"){ upp = head_upp - 1; }else if(nextDir == "s"){ low = head_low + 1; }else if(nextDir == "d"){ upp = head_upp + 1; }else if(nextDir == "w"){ low = head_low - 1; } if(!(upp >=0 && upp < max_size)){ return true; } if(!(low >= 0 && low < max_size)){ return true; } return snake[low][upp] > 0; } ``` ## 会吃的蛇 会吃的蛇比会动的蛇也就多了一个食物的游戏成分,我们用随机数来管理食物的出现: ``` int food_low = rand() % max_size; int food_upp = rand() % max_size; ``` 然后在蛇吃到食物的时候将其长度增加: ``` //判断是否吃到食物 bool Snake::ifEatFood(int food_low, int food_upp){ return snake[food_low][food_upp] > 0; } //吃到食物后尾部增长 void Snake::eatFood(){ length ++; for(int i = 0;i < max_size;i++){ for(int j = 0;j < max_size;j++){ if(snake[i][j] > 0){ snake[i][j] ++; } } } addTail(); } ``` 如果吃到了食物增加尾部的长度: ``` void Snake::addTail(){ if(tail_upp < max_size && snake[tail_low][tail_upp + 1] == snake[tail_low][tail_upp] + 1){ snake[tail_low][tail_upp - 1] = snake[tail_low][tail_upp] - 1; tail_upp -= 1; return; } if(tail_low < max_size && snake[tail_low + 1][tail_upp] == snake[tail_low][tail_upp] + 1){ snake[tail_low - 1][tail_upp] = snake[tail_low][tail_upp] - 1; tail_low -= 1; return; } if(tail_low > 0 && snake[tail_low - 1][tail_upp] == snake[tail_low][tail_upp] + 1){ snake[tail_low + 1][tail_upp] = snake[tail_low][tail_upp] - 1; tail_low += 1; return; } if(tail_upp > 0 && snake[tail_low][tail_upp - 1] == snake[tail_low][tail_upp] + 1){ snake[tail_low][tail_upp + 1] = snake[tail_low][tail_upp] - 1; tail_upp += 1; return; } } ``` ## 智能蛇 用dfs来找下一个方向: ``` int dfs(int curr_x,int curr_y,int food_x,int food_y){ // cout << "(" << curr_x << ", " << curr_y << ")" << endl; // for(int i = 0;i < max_size;i++){ // for(int j = 0;j < max_size;j++){ // if(i == curr_x && j == curr_y){ // cout << "H"; // } // else if(i == food_x && j == food_y){ // cout << "@"; // } // else if(map[i][j] == -1){ // cout << "#"; // } // else{ // cout << " "; // } // } // cout << endl; // } if(curr_x == food_x && curr_y == food_y){ cout << "eat food" << endl; return 1; } if(known[curr_x][curr_y]){ return 999999; } else{ known[curr_x][curr_y] = 1; } if(map[curr_x][curr_y] < 0){ // cout << "return 99999" << endl; return 999999; } vector res; if((curr_x+1 == food_x && curr_y==food_y) || (map[curr_x+1][curr_y] == 0)){ int dis_down = dfs(curr_x+1,curr_y,food_x,food_y); if(dis_down == 1){ return 2; } res.push_back(dis_down); } if((curr_x-1 == food_x && curr_y==food_y) || (map[curr_x-1][curr_y] == 0)){ int dis_up = dfs(curr_x-1,curr_y,food_x,food_y); if(dis_up == 1){ return 2; } res.push_back(dis_up); } if((curr_x == food_x && curr_y-1==food_y) || (map[curr_x][curr_y-1] == 0)){ int dis_left = dfs(curr_x,curr_y-1,food_x,food_y); if(dis_left == 1){ return 2; } res.push_back(dis_left); } if((curr_x == food_x && curr_y+1==food_y) || (map[curr_x][curr_y+1] == 0)){ int dis_right = dfs(curr_x,curr_y+1,food_x,food_y); if(dis_right == 1){ return 2; } res.push_back(dis_right); } // s if(res.size() == 0){ cout << "bug" << endl; } sort(res.begin(),res.end()); // cout << "min dis:" << res[0] << endl; // for(int i = 0;i < res.size();i++){ // cout << res[i] << " "; // } // cout << endl; return res[0]+1; } ``` ## 游戏玩法 ### 普通贪吃蛇 以会吃的蛇为例,输入以下命令: ``` g++ snake_eat.cpp -o snake_eat ./snake_eat ``` 然后就可以用`w`、`s`、`a`、`d`来控制蛇的移动了 ### 智能贪吃蛇 执行以下命令: ``` g++ AI_snake.cpp -o AI_snake ./AI_snake ``` 通过随便输入一个字符来让蛇走下一步