353. 贪吃蛇
题目:
请你设计一个 贪吃蛇游戏,该游戏将会在一个 屏幕尺寸 = 宽度 x 高度 的屏幕上运行。如果你不熟悉这个游戏,可以 点击这里 在线试玩。
起初时,蛇在左上角的 (0, 0) 位置,身体长度为 1 个单位。
你将会被给出一个 (行, 列) 形式的食物位置序列。当蛇吃到食物时,身子的长度会增加 1 个单位,得分也会 +1。
食物不会同时出现,会按列表的顺序逐一显示在屏幕上。比方讲,第一个食物被蛇吃掉后,第二个食物才会出现。
当一个食物在屏幕上出现时,它被保证不能出现在被蛇身体占据的格子里。
对于每个 move() 操作,你需要返回当前得分或 -1(表示蛇与自己身体或墙相撞,意味游戏结束)。
示例:
给定 width = 3, height = 2, 食物序列为 food = [[1,2],[0,1]]。
Snake snake = new Snake(width, height, food);
初始时,蛇的位置在 (0,0) 且第一个食物在 (1,2)。
|S| | |
| | |F|
snake.move("R"); -> 函数返回 0
| |S| |
| | |F|
snake.move("D"); -> 函数返回 0
| | | |
| |S|F|
snake.move("R"); -> 函数返回 1 (蛇吃掉了第一个食物,同时第二个食物出现在位置 (0,1))
| |F| |
| |S|S|
snake.move("U"); -> 函数返回 1
| |F|S|
| | |S|
snake.move("L"); -> 函数返回 2 (蛇吃掉了第二个食物)
| |S|S|
| | |S|
snake.move("U"); -> 函数返回 -1 (蛇与边界相撞,游戏结束)
解答:
条件巨多,写的我要吐了。不能撞墙,不能撞之前的身体。
然后我用的方法是矩阵用来查找新坐标是否是之前的身体,双向链表用来保存身体。
1 class SnakeGame { 2 public: 3 int cur_x=0,cur_y=0; 4 vector<vector<int>> food; 5 vector<vector<bool>> matrix; 6 int next_food=0,width,height; 7 bool gameover=false; 8 list<vector<int>> body; 9 unordered_map<string,vector<int>> mp={{"U",{-1,0}},{"D",{1,0}},{"L",{0,-1}},{"R",{0,1}}}; 10 11 SnakeGame(int width, int height, vector<vector<int>>& food) { 12 this->width=width,this->height=height,this->food=food; 13 matrix.resize(height,vector<bool>(width,false)); 14 matrix[0][0]=true; 15 body.push_back({0,0}); 16 } 17 18 int move(string direction) { 19 if(gameover){return -1;} 20 cur_x+=mp[direction][0],cur_y+=mp[direction][1]; 21 if(next_food<food.size() and food[next_food][0]==cur_x and food[next_food][1]==cur_y){//吃了 22 next_food++; 23 } 24 else{//没吃 25 auto tail=body.front(); 26 matrix[tail[0]][tail[1]]=false; 27 body.pop_front(); 28 } 29 if(cur_x<0 or cur_x>=height or cur_y<0 or cur_y>=width or matrix[cur_x][cur_y]==true){ 30 gameover=true; 31 return -1; 32 } 33 matrix[cur_x][cur_y]=true; 34 body.push_back({cur_x,cur_y}); 35 // cout<<direction<<" "<<cur_x<<" "<<cur_y<<endl; 36 return next_food; 37 } 38 };
我看见评论区还有用双端队列保存身体,哈希表用来查找之前的身体的。这样效率应该会高一点,毕竟建立矩阵比较费时。