[英]Using a 2D array for a game map in C++
Software: Visual Studio 2017 Community软件:Visual Studio 2017 社区
Hi, everybody,大家好你们好,
I am making a simple 2d console game in C++ (perhaps very simplified Dwarf Fortress if you know it).我正在 C++ 中制作一个简单的 2d 控制台游戏(如果你知道的话,也许是非常简化的矮人要塞)。
And I want a map to be displayed in console with ASCII.我希望 map 以 ASCII 显示在控制台中。
Something like this:像这样的东西:
I have a WorldMap class declared in the header file(simplified version).我在 header 文件(简化版)中声明了 WorldMap class。 And I declare a 2d array inside it.我在里面声明了一个二维数组。
#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
};
And then define it in the.cpp file:然后在.cpp文件中定义:
#include "WorldMap.h"
#include <algorithm>
WorldMap::WorldMap()
{
worldWidth = 50;
worldHeight = 50;
worldMap[50][50]; // Define the map array
// And then here I will also somehow need to be able to fill the whole map with '.' symbols, and so on
}
So that is the basic idea of what I am trying to achieve.这就是我想要实现的基本理念。 The reason why I can't define the array size immediately is because I want to be able to choose the size of the map when the map is created.我不能立即定义数组大小的原因是因为我希望能够在创建 map 时选择 map 的大小。
I have already tried:我已经尝试过:
Error:错误:
error C2109: subscript requires array or pointer type
char worldMap[][];
将二维数组声明为char worldMap[][];
and then defining it as worldMap[50][50];
然后将其定义为worldMap[50][50];
. .Error:错误:
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
char worldMap[worldWidth][worldHeight];
将二维数组声明为char worldMap[worldWidth][worldHeight];
, expecting that when the object is created, the width and height variables will be defined first, and then they will define the array. ,期望在创建object时,会先定义width和height变量,然后再定义数组。Error:错误:
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;
and char** worldMap
, but so far I can't even understand how double pointer works, yet char* worldMap
actually works with a 1D array without errors, until I start accessing values of the elements in the array.和char** worldMap
,但到目前为止我什至无法理解双指针是如何工作的,但char* worldMap
实际上可以毫无错误地使用一维数组,直到我开始访问数组中元素的值。I suppose a workaround would be to use a string or 1D char array and when displaying it just use mapWidth to end line each 50 characters for example, which will give the same result.我想一种解决方法是使用字符串或一维字符数组,并且在显示它时只需使用 mapWidth 来结束每 50 个字符的行,例如,这将给出相同的结果。 But I feel like that's not a good way to achieve this since I will need to access x and y coords of this map and so on.但我觉得这不是实现这一目标的好方法,因为我需要访问这个 map 等的 x 和 y 坐标。
I guess what I am asking is:我想我要问的是:
Thank you for reading.感谢您的阅读。 I will really appreciate any help, even just ideas and tips might push me in the right direction:)我将非常感谢任何帮助,即使只是想法和提示也可能将我推向正确的方向:)
- What's the best way of declaring a 2d array for a class and then defining it in the object?为 class 声明二维数组然后在 object 中定义它的最佳方法是什么?
- What's the best way to store a map for such a console game?为这样的主机游戏存储 map 的最佳方式是什么? (Not necessarily using arrays) (不一定使用数组)
This is not " the best way " but it's one way of doing it.这不是“最好的方式”,但它是一种方式。
class
wrapping a 1D std::vector<char>
.创建一个包装一维std::vector<char>
的class
。operator()
s to access the individual elements.添加operator()
以访问各个元素。class
, like save()
and restore()
. class
的其他支持功能,例如save()
和restore()
。 I've used your class
as a base and tried to document what it's doing in the code: If some of the functions I've used are unfamiliar, I recommend looking them up at https://en.cppreference.com/ which is an excellent wiki that often has examples of how to use the particular function you read about.我使用您的class
作为基础,并尝试记录它在代码中的作用:如果我使用的某些功能不熟悉,我建议在https://en.cppreference.com/上查找它们一个出色的 wiki,其中经常包含有关如何使用您所读到的特定 function 的示例。
#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;
};
There is no best way to do anything*.没有最好的方法来做任何事情*。 It's what works best for you.这是最适合你的。
From what I understand you want to make a dynamic 2D arrays to hold your char of world map.据我了解,您想要制作一个动态的 2D arrays 来保存您的世界 map 的字符。 You have a lot of options to do this.你有很多选择来做到这一点。 You can have a worldMap class nothing wrong with that.你可以有一个世界地图 class 没有错。 If you want dynamic 2D arrays just make functions out of this kind of logic.如果您想要动态 2D arrays 只需使用这种逻辑制作函数即可。
#include <iostream>
#include <vector>
int main() {
int H = 10, W = 20;
char** map = NULL; //This would go in your class.H
//Make a function to allocate 2D array
map = new char* [H];
for (int i = 0; i < H; i++) {
map[i] = new char[W];
}
//FILL WITH WHATEVER
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
map[i][j] = 'A';
}
}
//do what ever you want like normal 2d array
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
std::cout << map[i][j] << " ";
}
std::cout << std::endl;
}
//Should always delete when or if you want to make a new one run time
for (int i = 0; i < H; i++)
delete[] map[i];
delete[] map;
map = NULL;
//Also you can use vectors
std::cout << "\n\n With vector " << std::endl;
std::vector<std::vector<char>> mapV;
//FILL WITH WHATEVER
for (int i = 0; i < H; i++) {
std::vector<char> inner;
for (int j = 0; j < W; j++) {
inner.push_back('V');
}
mapV.push_back(inner);
}
//do what ever you want kind of like a normal array
//but you should look up how they really work
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
std::cout << mapV[i][j] << " ";
}
std::cout << std::endl;
}
mapV.clear();
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.