Should each element of a 2d array create a new Sprite object? - c++

I'm trying to create a tilemap with a 2d array and was struggling slightly with it. When I iterate through the array should I create a new Sprite object for each element in the array or is it possible to just create a sprite object for each of the different tiles then copy them to the relevant positions on screen. For example - note Rows and Columns are const ints already initialised to 5
int MazeMap[Rows][Columns] = { //Should the array type be int or Sprite*
{1, 1, 1, 1, 1},
{1, 0, 0, 0, 1},
{1, 0, 1, 1, 1},
{1, 0, 0, 0, 1},
{1, 1, 1, 1, 1}
};
for(int x = 0; x<Rows; x++)
{
for(int y = 0; y<Columns; y++)
{
if(MazeMap[x][y]==1)
{
//should I create a new Sprite object here or should I create
// a Tile1 sprite object above the array and then just pass it into
//this array to draw it to the screen?
}
}
}
To me it just seems really inefficient to have (in this case) 25 sprite objects when you can just have 2 sprite objects and copy them to a number of different locations on screen.

Related

How to create a variable alias on a array of arrays in c++

Say I have the following array of arrays of floats and a selector index:
const float array[][3] = {
{0, 1, 2,},
{0, 1, 2,},
{0, 1, 2,},
{0, 1, 2,},
{0, 1, 2,},
};
/// The one that select one of the five arrays
int selector = 0;
To streamline my code, I'd like to declare an array that points to the current array selector to further use it as a simple array of float, as follows:
/// A shortcut to the current selection
const float currentArray[] = array[selector];
for (int i = 0; i<3: i++) {
process(currentArray[iI]);
}
As this does not compile (initialization expected with {}), how could I declare my current-array alias?
If I understand you right you need type alias for your currentArray.
In this case you can do the following:
const float array[][3] = {
{0, 1, 2,},
{0, 1, 2,},
{0, 1, 2,},
{0, 1, 2,},
{0, 1, 2,},
};
/// The one that select one of the five arrays
int selector = 0;
using InnerArrayT = const float (&)[3];
InnerArrayT currentArray = array[selector];
for (int i = 0; i<3: i++) {
process(currentArray[i]);
}
Or as #tadman has pointed out you can use auto & but be careful because if you use just auto(without &) then currentArray type will be const float * instead of const float (&)[3].

How to access the values of a map<string, vector<int>> in C++?

I am working on my version of a genetic algorithm to solve the knapsack problem in C++. I have a map of string to vector like
map<string, vector<int>> objects
{
{"Object 1", {7, 20, 15}},
{"Object 2", {3, 50, 10}},
{"Object 3", {5, 80, 12}},
{"Object 4", {4, 80, 8}},
{"Object 5", {2, 40, 11}}
};
and a vector of vectors
vector<vector<int>> population;
where I will store information such as
population[0] = {0, 0, 1, 1, 0};
population[1] = {1, 0, 0, 0, 1};
population[2] = {1, 0, 1, 0, 1};
...
Each vector is called an individual, and each element of a given individual indicates the presence (1) or the absence (0) of the corresponding object. So, for example, the third individual (population[2]) has Object 1, Object 3 and Object 5.
What I want to do is write a function which will receive an index from population and return the sum of the corresponding values from objects. In the case of population[2] I'd like to have another vector containing {14, 140, 38} (7+5+2, 20+80+40, 15+12+11).
But I'm struggling to access the values of the objects map.
map<string, vector<int>> objects {/*...*/}
vector<vector<int>> population;
void initializePopulation() {/*...*/}
void getScore(vector<int> individual, vector<int>& sum)
{
for(int i = 0; i < 3; i++)
{
sum.push_back(0);
for(int j = 0; j < 5; j++)
{
if(individual[j] == 1)
{
sum[i] += ???;
}
}
}
int main()
{
/*...*/
initializePopulation();
vector<int> sum;
getScore(population[2], sum);
}
So, as you can see, I'm not sure how to proceed with sum[i]. Any suggestions? I'm not very fluent in C++, so a more detailed answer would be appreciated!
For both vector of vectors as well as a map, you can use for each loop!
When your map is filled with value
for(auto x: objects){
cout<<x.first<<" "<<x.second<<endl;
}
This will print key-value pairs in a map with space in between!
In this problem you'll have to iterate values (i.e. the second) in map too!
{"Object 1", {7, 20, 15}}
{"Object 2", {3, 50, 10}}
{"Object 3", {5, 80, 12}}
{"Object 4", {4, 80, 8}}}
{"Object 5", {2, 40, 11}}
For something like this the following code should work:
for(auto x: objects){
cout<<x.first<<" ";
for(auto y: x.second){
cout<<y<<" ";
}
cout<<endl;
}
For vector of vectors, you can use the same concept!
Try renaming Object 1, Object 2, .... to just 1,2, ....
This will allow you to access values in map by using j from your for loop!
For a more simplified version consider this prototype instead, since you are using words like population and genetic, I assume your data to be humungous, so you are better off using const reference while passing data around (const&, they won't be copied and will become read-only). global variable is a bad idea in general.
void getScore(map<string, vector<int>> const& objects, vector<int> const& individual, vector<int>& sum)
{
// iterate over each object for the individual
for(int i = 0; i < 5; i++)
{
// are you sure you want sum as {14, 140, 38} (7+5+2, 20+80+40, 15+12+11)
// not {14,0, 140,0, 38} (7+5+2, 0, 20+80+40, 0, 15+12+11)
// use else part for later
if(individual[i] == 1)
{
// compute sum for each object
// retrieve object vector
auto it = objects.find("KEY"); // KEY generation discussed later
if(it!=objects.end()){ // validate key :::: important
vector<int> ob = objects["KEY"]; //it->second
sum.push_back(std::accumulate(ob.begin(),ob.end(),0) ); // https://www.cplusplus.com/reference/numeric/accumulate/
}
} /*else {
sum.push_back(0);
}*/
}
}
KEY generation:
1). generating "Object 1" :
string key = "Object " + to_string(i+1)
auto it = objects.find(key);
2). suggested :
use integers as key
or
go with an enum like
enum ObjList{
OBJECT_1,
OBJECT_2,
OBJECT_3
}
auto it = objects.find(i); //mind your indexes
hope it helps, happy coding XD
I think that with some little linear algebra your problem has an easy solution: indeed, if you store the numerical data related to your objects into a matrix A, then for each population vector p your desired result is simply p^T A (or equivalently, A^T p) where ^T denotes the transpose of a matrix or of a vector.
If you are not planning to employ any linear algebra library, you could implement the scalar product by yourself. Down below there is the code implementing the above idea.
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <numeric>
std::vector<int> SP(std::vector<std::vector<int>> const &M, std::vector<int> const &P){
std::vector<int> sums(3,0);
// perform p^T * A operation
for (int j=0;j<3;j++)
for (int i=0;i<5;i++)
sums[j] += M[i][j] * P[i];
return sums;
}
int main(){
std::map<std::string, std::vector<int>> objects {
{"Object 1", {7, 20, 15}},
{"Object 2", {3, 50, 10}},
{"Object 3", {5, 80, 12}},
{"Object 4", {4, 80, 8}},
{"Object 5", {2, 40, 11}}
};
std::vector<std::vector<int>> population(3);
population[0] = {0, 0, 1, 1, 0};
population[1] = {1, 0, 0, 0, 1};
population[2] = {1, 0, 1, 0, 1};
std::vector<std::vector<int>> A;
// Extract the numerical data from the map
for (auto const& [key, val] : objects)
A.push_back(val);
// vector in which the desired values are stored for the 3rd element of the population
std::vector<int> s = SP(A,population[2]);
// Just for checking
for (int it=0; it<s.size(); it++)
std::cout << s[it] << std::endl;
return 0;
}

Arduino Icon Library

I'm working on an Arduino project and I want to display icons on a NeoMatrix 8x8 panel.
Initially, I went in direction that relied on inheritance, and requested some input on Arduino Stack Exchange where I was advised to go another route, and to ask my question elsewhere is it pertained more to C++ than to Arduino.
Instead of relying on inheritance, I was recommended to store my icons in PROGMEM and have the program build the icons from there.
I attempted the approach as much as I could, but I'm not at ease so I'd like some further insight!
The idea is to have a byte array that composes an 8x8 icon.
The values are 0-2, each representing a color set in an RGB struct array.
From what I believe I understand, my byte array stored in PROGMEM is read as a pointer, and needs to be accessed using ppm_read_byte.
I am unsure on how to handle the RGB struct. When I attempt to read it from PROGMEM, it causes my program to crash. So I removed it from PROGMEM, and the icon displays correctly. My byte array is in PROGMEM, but not the colors.
I am aware that I have a serious lack of knowledge about pointers which I need to work on...
Also, the idea is to have a collection of icons, so should I store all my icons (byte arrays and colors) in a header file? Will that not bloat it?
Thank you in advance for insight on this!
header.h
typedef struct {
byte r;
byte g;
byte b;
} RGB;
const byte PROGMEM WifiIcon[8][8] = {
{1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 2, 2, 2, 2, 1, 1},
{1, 2, 1, 1, 1, 1, 2, 1},
{2, 1, 2, 2, 2, 2, 1, 2},
{1, 2, 1, 1, 1, 1, 2, 1},
{1, 1, 1, 2, 2, 1, 1, 1},
{1, 1, 2, 1, 1, 2, 1, 1},
{0, 0, 0, 1, 1, 0, 0, 0}
};
const RGB WifiIconColors[3] = {
{0, 0, 0},
{0, 0, 0},
{0, 200, 61}
};
ESP8266Neomatrix.ino
#include "header.h"
void printIcon(int startPosition, const byte (&icon)[8][8], const RGB (&colors)[3]){
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
byte currentPixel = pgm_read_byte(&icon[i][j]);
const RGB currentColor = colors[currentPixel];
byte red = currentColor.r;
byte green = currentColor.g;
byte blue = currentColor.b;
matrix.setPixelColor(startPosition++, red, green, blue);
}
}
}
https://gist.github.com/Nate1661/0eea9200e9d1c86187c2acf205ba3602
If you want the RGB data to reside in PROGMEM, since it is not a native type handled by pgm_read_XXX functions, just read it with memcpy_P():
RGB currentColor;
memcpy_P(&currentColor, colors + currentPixel, sizeof(RGB));
If this crashes, then perhaps there is an issue with the value of currentPixel that you read.

Why doesn't my Sudoku program return an output?

So I have tried to implement a Sudoku via backtracking algorithm. I don't see why my code is not giving an expected output.
What I did was, I created a loop in which it checks for an empty cell (represented with 0) in the sudoku. As it finds it, the co-ordinates for it are passed to a function called possibleEntriescheck(). This function writes into a globally declared array called possibleEntries[9], the digits which can be possibly filled into the cell of which the co-ordinates are passed initially.
I learnt this algorithm from these videos:
https://www.youtube.com/watch?v=NuodN41aK3g
https://www.youtube.com/watch?v=QI0diwmx3OY
The expected output is a solved Sudoku. It doesn't perform expectedly. Rather, it freezes. A little help would mean a lot. Thank you.
#include <stdio.h>
#include <stdlib.h>
int board[9][9] = {
{3, 0, 6, 5, 0, 8, 4, 0, 0},
{5, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 7, 0, 0, 0, 0, 3, 1},
{0, 0, 3, 0, 1, 0, 0, 8, 0},
{9, 0, 0, 8, 6, 3, 0, 0, 5},
{0, 5, 0, 0, 9, 0, 6, 0, 0},
{1, 3, 0, 0, 0, 0, 2, 5, 0},
{0, 0, 0, 0, 0, 0, 0, 7, 4},
{0, 0, 5, 2, 0, 6, 3, 0, 0},
};
int possibleEntries[9];
void possibleEntriescheck(int i, int j)
{
int x,a=0,k,l,y;
for(x=0;x<9;x++)
possibleEntries[x]=0;
for(x=0;x<9;x++)
{
if(board[i][x]!=0)
possibleEntries[board[i][x]-1]=1;
}
for(x=0;x<9;x++)
{
if(board[x][j]!=0)
possibleEntries[board[x][j]-1]=1;
}
if(i==0 || i==1 || i==2)
k=0;
else if(i==3 || i==4 || i==5)
k=3;
else
k=6;
if(j==0 || j==1 || j==2)
l=0;
else if(j==3 || j==4 || j==5)
l=3;
else
l=6;
for(x=k;x<k+3;x++)
{
for(y=l;y<l+3;y++)
if(board[x][y]!=0)
possibleEntries[board[x][y]-1]=1;
}
for(x=0;x<9;x++)
{
if(possibleEntries[x]==0)
possibleEntries[x]=x+1;
else
possibleEntries[x]=0;
}
}
int isFull()
{
int i,j;
for(i=0;i<9;i++)
{
for(j=0;j<9;j++)
{
if(board[i][j]==0)
return 0;
}
}
return 1;
}
void solveSudoku()
{
int i,j,x,b=0,k;
if(isFull())
{
printf("The sudoku board is:\n");
for(i=0;i<9;i++)
{
for(j=0;j<9;j++)
printf("\t%d",board[i][j]);
printf("\n");
}
}
else
{
for(i=0;i<9;i++)
{
for(j=0;j<9;j++)
{
if(board[i][j]==0)
{
possibleEntriescheck(i,j);
for(x=0;x<9;x++)
{
if(possibleEntries[x]!=0)
{
board[i][j]=possibleEntries[x];
solveSudoku();
board[i][j]=0;
}
}
}
}
}
}
return;
}
int main()
{
solveSudoku();
}
You implemented backtracking incorrectly. As also explained in the video, the actual algorithm should look like this:
solve():
if the sudoku is solved
print field
terminate
x,y = the next vacant field
for each possible value in that field
assign value to x,y
call solve() recursively to try with the assigned value
clear vacant field
Now what your code does is
solve():
if the sudoku is solved
print field
return
for each field in the sudoku
if field is vacant
for each possible value
assign value
solve recursively
reset field to unassigned
Now this actually does solve the sudoku. But there are two problems with this approach:
A: It won't terminate once it's solved the sudoku. Actually this mistake was also in the code presented in the video. A simple return in a recursive call will terminate the method on the current call and continue with the recursion "one call above". So basically the algorithm solves the sudoku in every possible way (provided there are multiple, otherwise it simply tries any possible way of assigning the values).
B: This one's way more serious. Your algorithm doesn't only generate all possible solutions, but it also tries every order of assigning the values it can possibly find. The overhead is gigantic and the reason why your code simply doesn't terminate. Solving the sudoku once already takes quite some time, but your code does so a bazillion times.
If you solve these problems, your code should work find, provided the rest is implemented correctly. I'd also recommend optimizing both the search for vacant fields and the test whether the field is empty, as these can be done fairly simple and will provide some speedup. Generate a list of vacant fields in the beginning, iterate over it (one field for each recursion-level) and terminate once the entire list was processed. E.g.:
solve(vacant, count):
if count == 0
print the field
terminate
x, y = vacant[count]
count++
for each possible value assignable to the field
assign value to x, y
call solve(vacant, count) recursively
clear field
Another problem you will encounter, which will get rather ugly to debug is thanks to this line:
int possibleEntries[9];
Global variables that are used and overwritten in a recursion are a bad idea to say the least. Imagine a possible run of the program like this (ident indicates recursion-level, where no ident means the action is global):
solve
|
---> board empty? Nope
x,y <- next vacant field
possible values <- possible values for x, y
field[x, y] <- first value from possible values
solve
|
---> board empty? Nope
x, y <- next vacant field
possible values <- possible values for x, y (overwrites global variable!!!)
field[x, y] <- first value from possible values
solve
|
---> ...
<--- return
field[x, y] <- second value from possible values (WRONG!!!)
...
The last assignment won't use the list of possible values generated for the field you're currently working on, but of another one that you visited somewhere in the recursion before returning back. You can solve this in two ways:
Iterate from 1 to 9 and check for each number separately whether it can be assigned to the field
Keeping a separate list for each level of recursion

How to initialize 3D array in C++

How do you initialize a 3d array in C++
int min[1][1][1] = {100, { 100, {100}}}; //this is not the way
The array in your question has only one element, so you only need one value to completely initialise it. You need three sets of braces, one for each dimension of the array.
int min[1][1][1] = {{{100}}};
A clearer example might be:
int arr[2][3][4] = { { {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4} },
{ {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4} } };
As you can see, there are two groups, each containing three groups of 4 numbers.
Instead of static multidimensional arrays you should probably use one-dimensional array and calculate the index by multiplication. E.g.
class Array3D {
size_t m_width, m_height;
std::vector<int> m_data;
public:
Array3D(size_t x, size_t y, size_t z, int init = 0):
m_width(x), m_height(y), m_data(x*y*z, init)
{}
int& operator()(size_t x, size_t y, size_t z) {
return m_data.at(x + y * m_width + z * m_width * m_height);
}
};
// Usage:
Array3D arr(10, 15, 20, 100); // 10x15x20 array initialized with value 100
arr(8, 12, 17) = 3;
std::vector allocates the storage dynamically, which is a good thing because the stack space is often very limited and 3D arrays easily use a lot of space. Wrapping it in a class like that also makes passing the array (by copy or by reference) to other functions trivial, while doing any passing of multidimensional static arrays is very problematic.
The above code is simply an example and it could be optimized and made more complete. There also certainly are existing implementations of this in various libraries, but I don't know of any.
Here's another way to dynamically allocate a 3D array in C++.
int dimX = 100; int dimY = 100; int dimZ = 100;
int*** array; // 3D array definition;
// begin memory allocation
array = new int**[dimX];
for(int x = 0; x < dimX; ++x) {
array[x] = new int*[dimY];
for(int y = 0; y < dimY; ++y) {
array[x][y] = new int[dimZ];
for(int z = 0; z < dimZ; ++z) { // initialize the values to whatever you want the default to be
array[x][y][z] = 0;
}
}
}
Everyone seems to forget std::valarray. It's the STL template for flat multidimensional arrays, and indexing and slicing them.
http://www.cplusplus.com/reference/std/valarray/
No static initialization, but is that really essential?