我有以下代码,只占整个代码的一半:
// Declare map elements using an enumeration
enum entity_labels {
EMPTY = 0,
WALL
};
typedef entity_labels ENTITY;
// Define an array of ASCII codes to use for visualising the map
const int TOKEN[2] = {
32, // EMPTY
178 // WALL
};
// create type aliases for console and map array buffers
using GUI_BUFFER = CHAR_INFO[MAP_HEIGHT][MAP_WIDTH];
using MAP_BUFFER = ENTITY[MAP_HEIGHT][MAP_WIDTH];
//Declare application subroutines
void InitConsole(unsigned int, unsigned int);
void ClearConsole(HANDLE hStdOut);
WORD GetKey();
void DrawMap(MAP_BUFFER & rMap);
/**************************************************************************
* Initialise the standard output console
*/
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut != INVALID_HANDLE_VALUE)
{
ClearConsole(hStdOut);
// Set window title
SetConsoleTitle(TEXT("Tile Map Demo"));
// Set window size
SMALL_RECT srWindowRect;
srWindowRect.Left = 0;
srWindowRect.Top = 0;
srWindowRect.Bottom = srWindowRect.Top + MAP_HEIGHT;
srWindowRect.Right = srWindowRect.Left + MAP_WIDTH;
SetConsoleWindowInfo(hStdOut, true, &srWindowRect);
// Set screen buffer size
COORD cWindowSize = { MAP_WIDTH, MAP_HEIGHT };
SetConsoleScreenBufferSize(hStdOut, cWindowSize);
}
/*************************************************************************/
/*************************************************************************
* Initialise the tile map with appropriate ENTITY values
*/
MAP_BUFFER tileMap;
for (unsigned int row = 0; row < MAP_HEIGHT; row++)
{
for (unsigned int col = 0; col < MAP_WIDTH; col++)
{
tileMap [row][col] = WALL;
}
}
基本上整个代码用于创建一个tile map并将其输出到screen,但我试图在运行时使tileMap成为一个动态数组。 我尝试在创建tileMap的地方创建一个。 我已经尝试在“entity_lables”被赋予typedef“ENTITY”之后创建一个。 我尝试在“MAP_BUFFER”和“GUI_BUFFER”成为别名后创建一个。 但是我仍然感到茫然,我不知道如何成功地将一个动态数组实现到tileMap,我当然不知道最好的位置。
非常感谢任何帮助。
答案 0 :(得分:0)
用于定义数组的语法是用于恒定大小的C数组。通常,除非在编译时确定数据的大小(并且永远不需要更改),否则应该回避C数组,并且数组永远不会离开作用域(因为C数组不保留有关其自身大小的信息。)< / p>
我建议使用Vector容器来代替常量或动态大小的C数组。 Vector是一个动态大小的容器,从后面填充,是你添加到
的最后一个元素std::vector<std::vector<ENTITY>>
要将矢量容器添加到项目中,请添加
行#include <vector>
要填充容器,您的循环可能如下所示:
MAP_BUFFER tileMap;
for (unsigned int row = 0; row < MAP_HEIGHT; row++)
{
std::vector<ENTITY> column; // A column of the tile map
for (unsigned int col = 0; col < MAP_WIDTH; col++)
{
column.push_back(WALL); // Add one element to the column
}
tileMap.push_back(column); // Add the column to the tile map
}
或者您可以将Vector初始化为您想要的大小,并使用当前循环来指定切片值:
using TILE_MAP = vector<vector<ENTITY>>;
// MAP_WIDTH x MAP_HEIGHT multidimensional vector
TILE_MAP tileMap(MAP_WIDTH, vector<ENTITY>(MAP_HEIGHT));
for (unsigned int row = 0; row < MAP_HEIGHT; row++)
{
for (unsigned int col = 0; col < MAP_WIDTH; col++)
{
tileMap [row][col] = WALL;
}
}
在填充向量之后调用向量的元素具有与数组相同的语法。
tileMap[2][4]
您还可以检查矢量的长度:
int rows = tileMap.size();
if( rows > 0 )
int columnsInRow0 = tileMap[0].size()
当你在这里时,你应该研究其他容器,比如地图和套装,因为它们可以让你的生活更轻松。
编辑:
由于你想知道如何制作一个不使用矢量的动态数组,我会给你一个答案:std :: vector是C ++定义的动态大小的数组。 C数组在定义后不会改变大小,矢量将会。
但是我认为你问的是定义运行时常量大小的数组的能力。所以我会解释它们是什么以及为什么你不应该使用它们。
当您定义C数组时,您可能会收到一条警告,指出表达式需要保持不变。
C数组是指向堆栈的指针。而且编译时C数组的实现是它在编译时需要是一个常量。
int compiletimeArray[] = { 1, 2, 3 };
// turns out c arrays are pointers
int* ptr = compiletimeArray;
// prints 2
std::cout << compiletimeArray[1];
// prints 2
std::cout << ptr[1];
// prints 2
std::cout << *(compiletimeArray + 1);
// also prints 2
std::cout << *(ptr + 1); //move pointer 1 element and de-reference
指针就像一块白板,上面写着电话号码。出现与电话号码相同的问题;白板上的号码已被删除,白板上的号码已更改,收件人不存在,收件人更改了号码,服务提供商用尽了可用的号码给新用户...请记住这一点。
要创建运行时常量大小的数组,您需要在堆上分配数组并将其分配给指针。
int size = 4;
int* runtimeArray = new int[size]; // this will work
delete[] runtimeArray; // de-allocate
size = 8; // change size
runtimeArray = new int[size]; // allocate a new array
堆栈和堆栈之间的主要区别在于,当程序退出变量声明的作用域时,堆栈将取消分配变量使用的内存,另一方面,堆上声明的任何内容仍将保留在内存并且必须明确地取消分配,否则会出现内存泄漏。
// You must call this when you are never going to use the data at the memory address again
// release the memory from the heap
delete[] runtimeArray; // akin to releasing a phone number to be used by someone else
如果你没有从堆中释放内存,那么你将耗尽。
// Try running this
void crashingFunction() {
while(true)
{
// every time new[] is called ptr is assigned a new address, the memory at the old address is not freed
// 90001 ints worth of space(generally 32 or 64 bytes each int) is reserved on the heap
int* ptr = new int[90001]; // new[] eventually crashes because your system runs out of memory space to give
}
}
void okFunction() {
// Try running this
while(true)
{
// every time new[] is called ptr is assigned a new address, the old is not freed
// 90001 ints worth of space is reserved on the heap
int* ptr = new int[90001]; // never crashes
delete[] ptr; // reserved space above is de-allocated
}
}
为什么要使用std :: vector?因为std :: vector在内部管理运行时数组。
// allocates for you
vector(int size) {
// ...
runtimeArray = new runtimeArray[size];
}
// When the vector exits scope the deconstructor is called and it deletes allocated memory
// So you do not have to remember to do it yourself
~vector() {
// ...
delete[] runtimeArray;
}
所以,如果你有与上次相同的情景
void vectorTestFunction() {
// Try running this
while(true)
{
std::vector<int> vec(9001); // internally allocates memory
} // <-- deallocates memory here because ~vector is called
}
如果你想使用运行时常量数组,我建议使用std:array容器。它就像矢量一样,它管理着它的内部存储器,但如果你永远不需要添加新的元素就会进行优化。它被声明为vector,但在构造函数之后不包含resizing函数。