Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+;中为游戏地图使用2D数组+;_C++_Arrays_Oop_Visual C++ - Fatal编程技术网

C++ 在C+;中为游戏地图使用2D数组+;

C++ 在C+;中为游戏地图使用2D数组+;,c++,arrays,oop,visual-c++,C++,Arrays,Oop,Visual C++,软件:Visual Studio 2017社区 大家好, 我正在用C++制作一个简单的2D控制台游戏(如果你知道的话,它很简化的矮人要塞)。 我想在控制台中用ASCII显示地图 大概是这样的: 我在头文件中声明了一个WorldMap类(简化版)。 我在里面声明了一个2d数组 #pragma once #include <iostream> class WorldMap { public: WorldMap(); virtual ~WorldMap(); priv

软件:Visual Studio 2017社区

大家好,

我正在用C++制作一个简单的2D控制台游戏(如果你知道的话,它很简化的矮人要塞)。 我想在控制台中用ASCII显示地图

大概是这样的:

我在头文件中声明了一个WorldMap类(简化版)。 我在里面声明了一个2d数组

#pragma once
#include <iostream>

class WorldMap
{
public:
    WorldMap();
    virtual ~WorldMap();

private:
    int worldWidth;
    int worldHeight;
    char worldMap;     // Declare a variable that will hold all the characters for the map
};
  • 将2d数组声明为
    char worldMap[]worldMap[50][50]
  • 错误:

    error C2109: subscript requires array or pointer type
    
    error C2087: 'worldMap': missing subscript
    warning C4200: nonstandard extension used: zero-sized array in struct/union
    message : This member will be ignored by a defaulted constructor or copy/move assignment operator
    
    error C2327: 'WorldMap::worldWidth': is not a type name, static, or enumerator
    error C2065: 'worldWidth': undeclared identifier
    error C2327: 'WorldMap::worldHeight': is not a type name, static, or enumerator
    error C2065: 'worldHeight': undeclared identifier
    
  • 将2d数组声明为
    char worldMap[worldWidth][worldWidth],期望在创建对象时,首先定义宽度和高度变量,然后定义数组
  • 错误:

    error C2109: subscript requires array or pointer type
    
    error C2087: 'worldMap': missing subscript
    warning C4200: nonstandard extension used: zero-sized array in struct/union
    message : This member will be ignored by a defaulted constructor or copy/move assignment operator
    
    error C2327: 'WorldMap::worldWidth': is not a type name, static, or enumerator
    error C2065: 'worldWidth': undeclared identifier
    error C2327: 'WorldMap::worldHeight': is not a type name, static, or enumerator
    error C2065: 'worldHeight': undeclared identifier
    
  • 使用
    char*worldMap
    char**worldMap
    ,但到目前为止,我甚至无法理解双指针是如何工作的,然而
    char*worldMap
    实际上可以在1D数组中正常工作,直到我开始访问数组中元素的值为止
  • 我假设一种解决方法是使用字符串或1D字符数组,在显示它时,只需使用mapWidth以每50个字符结束一行,这将给出相同的结果。但我觉得这不是一个好办法,因为我需要访问这个地图的x坐标和y坐标等等

    我想我要问的是:

  • 为类声明2d数组并在对象中定义它的最佳方式是什么
  • 为这种游戏机存储地图的最佳方式是什么?(不一定使用数组)

  • 谢谢你的阅读。我真的很感激任何帮助,即使只是一些想法和建议也可能会把我推向正确的方向:)

    没有最好的方法做任何事情*。这是最适合你的

    据我所知,你想制作一个动态2D数组来保存你的世界地图字符。你有很多选择来做这件事。你可以有一个worldMap类,这没什么错。如果您想要动态2D数组,只需使用这种逻辑生成函数即可

    #包括
    #包括
    int main(){
    int H=10,W=20;
    char**map=NULL;//这将放在您的类中。H
    //创建一个函数来分配2D数组
    map=新字符*[H];
    对于(int i=0;i为类声明2d数组并在对象中定义它的最佳方式是什么
    
  • 为这样的游戏机存储地图的最佳方式是什么?(不一定使用数组)
  • 这不是“最好的方法”,但这是一种方法

    • 创建一个
      包装一个1D
      std::vector
    • 添加
      operator()
      s以访问各个元素
    • 类添加其他支持函数,如
      save()
      restore()
    我已经使用了你的
    作为基础,并试图记录它在代码中所做的工作:如果我使用的某些函数不熟悉,我建议查找它们,这是一个很好的wiki,其中经常有如何使用你读到的特定函数的示例

    #include <algorithm>   // std::copy, std::copy_n
    #include <filesystem>  // std::filesystem::path
    #include <fstream>     // std::ifstream, std::ofstream
    #include <iostream>    // std::cin, std::cout
    #include <iterator>    // std::ostreambuf_iterator, std::istreambuf_iterator
    #include <vector>      // std::vector
    
    class WorldMap {
    public:
        WorldMap(unsigned h = 5, unsigned w = 5) : // colon starts the initializer list
            worldHeight(h),      // initialize worldHeight with the value in h
            worldWidth(w),       // initialize worldWidth with the value in w
            worldMap(h * w, '.') // initialize the vector, size h*w and filled with dots.
        {}
    
        // Don't make the destructor virtual unless you use polymorphism
        // In fact, you should probably not create a user-defined destructor at all for this.
        //virtual ~WorldMap(); // removed
    
        unsigned getHeight() const { return worldHeight; }
        unsigned getWidth() const { return worldWidth; }
    
        // Define operators to give both const and non-const access to the
        // positions in the map.
        char operator()(unsigned y, unsigned x) const { return worldMap[y*worldWidth + x]; }
        char& operator()(unsigned y, unsigned x) { return worldMap[y*worldWidth + x]; }
    
        // A function to print the map on screen - or to some other ostream if that's needed
        void print(std::ostream& os = std::cout) const {
            for(unsigned y = 0; y < getHeight(); ++y) {
                for(unsigned x = 0; x < getWidth(); ++x)
                    os << (*this)(y, x); // dereference "this" to call the const operator()
                os << '\n';
            }
            os << '\n';
        }
    
        // functions to save and restore the map
        std::ostream& save(std::ostream& os) const {
            os << worldHeight << '\n' << worldWidth << '\n'; // save the dimensions
    
            // copy the map out to the stream
            std::copy(worldMap.begin(), worldMap.end(), 
                      std::ostreambuf_iterator<char>(os));
            return os;
        }
    
        std::istream& restore(std::istream& is) {
            is >> worldHeight >> worldWidth;            // read the dimensions
            is.ignore(2, '\n');                         // ignore the newline
            worldMap.clear();                           // empty the map
            worldMap.reserve(worldHeight * worldWidth); // reserve space for the new map
    
            // copy the map from the stream
            std::copy_n(std::istreambuf_iterator<char>(is),
                        worldHeight * worldWidth, std::back_inserter(worldMap));
            return is;
        }
    
        // functions to save/restore using a filename
        bool save(const std::filesystem::path& filename) const {
            if(std::ofstream ofs(filename); ofs) {
                return static_cast<bool>(save(ofs)); // true if it suceeded
            }
            return false;
        }
    
        bool restore(const std::filesystem::path& filename) {
            if(std::ifstream ifs(filename); ifs) {
                return static_cast<bool>(restore(ifs)); // true if it succeeded
            }
            return false;
        }
    
    private:
        unsigned worldHeight;
        unsigned worldWidth;
    
        // Declare a variable that will hold all the characters for the map
        std::vector<char> worldMap;
    };
    

    <代码> >包含在编译时未知大小的数组的< /p>。使用动态内存分配。在C++中,您不需要做太多的事情,因为标准库给了您<代码> STD::vector < /代码>。它已经为您做了所有的复杂工作。在了解此特性之后,您可能会认为<代码> STD::向量< /代码>可能是WH。至少,您正在搜索。这是可行的,但在性能方面并不理想。为了获得最佳性能,人们通常使用词典索引(例如,
    idx=y*width+x
    )这和你自己的建议差不多。然后可以将其包装到类或函数中。@TedLyngmo抱歉,我已经删除了该注释,因为该部分可能会被解释为具有构造函数的参数,该参数可能仍然是静态的。但我想这有点牵强……这正是PaulG所说的-我提到的性能注意事项的深度。最后,您的尝试不起作用的原因:1.
    WorldMap
    是一个
    char
    而不是一个char数组。这永远不会起作用。2.
    char数组[num\u元素]
    声明仅在编译时已知
    num_元素的情况下在标准C/C++中有效。有些编译器(gcc)允许您以不同的方式使用它(甚至可能像您尝试过的那样,我不知道),这意味着“非标准扩展”.3.从指针开始是向动态内存方向迈出的一步,但您仍然需要为其分配内存。但是使用“原始”像这样的指针是C的工作方式。哇!非常感谢!至少考虑到我是初学者,这看起来像是一个非常专业的代码。它非常复杂,但非常清楚。我花了几个小时来分析它,从中我学到了很多。我的代码中已经实现了这个修改版本。所以这是超级有用:)我唯一没有找到的信息是
    (*this)(y,x)
    。具体来说,为什么
    *this
    用括号括起来?也许这种使用括号的方法有一个独特的名字?@YamikoHikari我很高兴它能帮上忙,欢迎你!你可以编写
    (*this)(y,x)
    操作符()(y,x)而不是
    -这只是访问用户定义的
    操作符()
    (s)的一种方式。括号是因为。没有括号,它将与
    *(this(y,x))
    (尝试将
    this
    指针作为函数调用(然后取消引用结果),而不是
    world m