首页 > 解决方案 > 我达到 18 分后,蛇游戏停止。为什么?

问题描述

好的,这是我编写的经典蛇游戏的一些非常基本的代码。我需要它作为我正在处理的一个更大项目的一部分,但是在测试时我遇到了这个非常烦人的错误。如果有人可以执行它并告诉我我缺少什么,那就太好了。也欢迎任何额外的建议。我附上了下面的代码并写了一些非常基本的注释,希望它们足以理解它。

错误:我的代码在玩家获得 18 分后停止。具体来说,在 score = 18 时控制台上不再出现水果。

#include<iostream>
#include<conio.h>
#include<vector>
#include<queue>
#include<utility>
#include<windows.h>

using namespace std;

bool play = true;
int score = 0;

class Arena
{
    private: 

    int length, w, h, size, fx, fy;
    char snakerep, fruitrep, dir;
    queue<pair<int,int>> snakey, marker;
    vector<vector<char>> arena;

    public:

    Arena()
    {
        //snake stuff
        length = 1;
        snakerep = 'O';
        for(int i = 0 ; i < length ; i++)
            snakey.push({1, i+1});
        dir = 'R';
        
        //arena stuff
        size = 25;
        h = size, w = 2*size;
        arena.resize(h, vector<char>(w, ' '));
        
        //fruit stuff
        fruitrep = 'F';
        fx = 1 + (rand() % h);
        fy = 1 + (rand() % w);
        arena[fx][fy] = fruitrep;
    }

    void setFruit()
    {
        fx = 1 + (rand() % h);
        fy = 1 + (rand() % w);
        
        arena[fx][fy] = fruitrep;
    }
    
    void setArena()
    {
        
        for(int i = 0 ; i < w ; i++)
        {
            arena[0][i] = '*';
            arena[h-1][i] = '*';
        }

        for(int i = 1 ; i < h-1 ; i++)
        {
            arena[i][0] = '*';
            arena[i][w-1] = '*';
        }

        for(int i = 1 ; i < h-1; i++)
        {
            for(int j = 1; j < w-1 ; j++)
            {
                arena[i][j] = ' ';
            }
        }

        arena[fx][fy] = fruitrep;
    }

    void setSnake()
    {
        queue<pair<int,int>> temp_snakey = snakey;
        
        while(!temp_snakey.empty())
        {

            pair<int, int> xy = temp_snakey.front();
            temp_snakey.pop();

            int x = xy.first, y = xy.second;

            //condition for hitting any of the boundaries
            if (x <= 0 || y <= 0 || x >= size-1 || y >= 2*size-1)
                play = false;

            //condition for hitting itself
            if (arena[x][y] == snakerep)
                play = false;

            //condition for if a fruit is eaten
            if (arena[x][y] == fruitrep)
            {
                setFruit();
                //increase length of the snake 
                length++, score++;
                marker.push({x,y});
            }

            arena[x][y] = snakerep;
        }
    }

    void moveSnake(char dir)
    {
        //calculate the new location of the head or whatever according to the direction given within the brackets
        pair<int,int> prevHead = snakey.back(), newHead;

        if (dir == 'R')
            newHead = {prevHead.first, prevHead.second+1};
        else if (dir == 'L')
            newHead = {prevHead.first, prevHead.second-1};
        else if (dir == 'U')
            newHead = {prevHead.first-1, prevHead.second}; 
        else if (dir == 'D')
            newHead = {prevHead.first+1, prevHead.second};

        //pop the tail from the queue and add the new head
        pair<int, int> tail = snakey.front();
        if (!marker.empty() && tail == marker.front())
            marker.pop();
        else
            snakey.pop();
        
        snakey.push(newHead);
    }

    void printAll()
    {
        //prints the matrix
        for(int i = 0 ; i < h ; i++)
        {
            for(int j = 0 ; j < w ; j++)
            {
                cout<<arena[i][j];
            }
            cout<<endl;
        }
    }

    void getDirection()
    {
        if(_kbhit())
        {
            char ch = _getch();
            if (dir == 'R' || dir == 'L')
            {
                if (ch == 'w')
                    dir = 'U'; 
                else if (ch == 's')
                    dir = 'D';
                else if (ch == 'x')
                    play = false;
            }   
            else if (dir == 'U' || dir == 'D')
            {
                if (ch == 'd')
                    dir = 'R'; 
                else if (ch == 'a')
                    dir = 'L';
                else if (ch == 'x')
                    play = false;
            }
        }
    }

    void playGame()
    {
        getDirection();
        setArena();
        moveSnake(dir);
        setSnake();
        printAll();
    }
};

int main()
{
    Arena A;

    while(play)
    {
        A.playGame();
        cout<<" SCORE = "<<score<<endl;
        //better than using system("cls"), because it moves cursor to beginning of console, flickering stops
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), {0, 0});
    }
    return 0;
}

标签: c++

解决方案


第 18 个水果越界生成。您的随机定位功能不正确。你有

void setFruit()
{
    fx = 1 + (rand() % h);
    fy = 1 + (rand() % w);
    
    arena[fx][fy] = fruitrep;
}

好的,考虑一下fxrand() % h会给你一个包含 [0 .. h-1] 的数字,但你要给它加一,因为第零个位置是一堵墙。所以现在你有 [1..h] 但h超出了界限。右边也有一堵墙。所以把所有这些放在一起,我想你想要的是

void setFruit()
{
    fx = 1 + (rand() % (h-2));
    fy = 1 + (rand() % (w-2));
    
    arena[fx][fy] = fruitrep;
}

此外,您应该更改 Arena 构造函数以使用此函数。最好不要重复这样的代码。


推荐阅读