I have a 2 dimensional array filled with 0s and 1s. I have to display that array in way that:
- 0s are always shown
- 1s are shown one at the time.
It suppose to look like a maze where 0 is a wall and 1 is a current position.
How can I do that in c++?
EDIT:
I came up with a solution but maybe there is simpler one. What if I'd create copy of my _array and copy 0s and blank spaces instead of 1s to it. Then in loop I'd assign one of _array "1" to second array then display whole array and then make swap 1 back with blank space?
EDIT2:
int _tmain(int argc, _TCHAR* argv[])
{
file();
int k=0,l=0;
for(int i=0;i<num_rows;i++)
{
for(int j=0;j<num_chars;j++)
{
if(_array[i][j] == 1)
{
k=i;
l=j;
break;
}
}
}
while(1)
{
for(int i=0;i<num_rows;i++)
{
for(int j=0;j<num_chars;j++)
{
if(_array[i][j] == 0) printf("%d",_array[i][j]);
else if(_array[i][j]==1)
{
if(k==i && l==j)
{
printf("1");
}
else printf(" ");
}
l++;
if(l>num_chars) break;
}
k++;
l=0;
printf("\n");
}
k=0;
system("cls");
}
return 0;
}
I wrote something like that but still i don't know how to clear screen in right moment. Function file() reads from file to 2D array.
Assuming you want something like that
000000
0 0
0000 0
0 1 0
0 0000
000000
You could print a 0 whenever it occurs and a blank space if not. To handle the current position you could use two additional variables like posX, posY. Now everytime you find a 1 in your array you check if (j == posX && i = posY) and print 1 if so...
As you just need to visualize the maze at different possible positions I'd propose a simple display function. DisplayMaze(int x, int y) is printing the maze in the required format to the screen. If _array[y][x] == 1 there is also printed a single 1...
void DisplayMaze(int x, int y)
{
for (int row = 0; row < num_rows; row++)
{
for (int col = 0; col < num_chars; col++)
{
if (_array[row][col] == 0)
std::cout << "0 ";
else if (row == y && col == x)
std::cout << "1 ";
else
std::cout << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}
In order to display all possible positions you have to iterate over all of them and check if the current position is marked with 1 in the array (otherwise displaying would't make sense)
for (int y = 0; y < num_rows; y++)
{
for (int x = 0; x < num_chars; x++)
{
if (_array[y][x] == 1)
{
DisplayMaze(x, y);
}
}
}
The output should look like:
0 0 0 0 0 0
0 1 0
0 0 0 0 0
0 0
0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 1 0
0 0 0 0 0
0 0
0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 1 0
0 0 0 0 0
0 0
0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 1 0
0 0 0 0 0
0 0
0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0
0 0 0 0 1 0
0 0
0 0 0 0 0
0 0 0 0 0 0
...
However, i'd recommend a more C++ like approach as a maze could be implemented as a class. This class could bring it's own display-method and would encapsulate the internal data. It could basically look like:
class Maze
{
public:
// generate empty maze with given size
Maze(int width, int height);
// destructor
~Maze();
// print maze if the given position is marked with 1
void printPosition(int x, int y) const;
// takes a cstring as input to initialize the maze from
Maze& operator<<(const char* input);
// returns true if the given position is marked with 1
bool isValidPosition(int x, int y) const;
private:
// this is the actual representation of the maze
std::vector<std::vector<int> > grid_;
};
it would be used as followes:
Maze myMaze(num_chars, num_rows);
myMaze << "000000"
"011110"
"000010"
"011110"
"010000"
"000000";
for (int y = 0; y < num_rows; y++)
{
for (int x = 0; x < num_chars; x++)
{
if (myMaze.isValidPosition(x,y))
{
myMaze.printPosition(x,y);
}
}
}
hire you go*[solved]*
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
int x,y;
cin>>x>>y;
char map[x][y];
memset(map, 'a', sizeof(map));
int y_pos = 0;
for (int x_pos = 0; x_pos < x * y; x_pos++){
if (x_pos == x){
x_pos = 0;
y_pos = y_pos + 1;
cout<<endl;
}
if (y_pos == y){
system("pause");
return 0;
}
cout<<map[x_pos][y_pos];
}
Related
EDITED
What I am trying to do is (after reading from file and putting the information in 2d array defined in a struct,that part works) call a method that finds out if there is any zeroes in the array and if so change it and prints it again. I know I´m missing pointers but I don't know where. Thanks in advance.
struct matrix{
const static int N=9;
int Ar[N][N];
};
void iprint(matrix s){ //my method to print the array
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
cout << (s).Ar[i][j] << ' ';
}
cout << endl;
}
}
bool annotation(matrix s, int row, int column, int num){
if(s.Ar[row][column] == 0){
(s).Ar[row][column] = num;
return true;
}
else if(s.Ar[row][column] != 0){
cout << "NO" << endl;
return false;
} else {
cout << "No" << endl;
return false;
}
iprint(s);
}
The array in first place :
0 0 6 5 0 0 1 0 0
4 0 0 0 0 2 0 0 9
0 0 0 0 3 0 0 0 8
0 7 0 1 0 0 5 0 0
0 8 0 0 0 0 0 6 0
0 0 3 0 9 0 0 4 0
2 0 0 0 4 0 0 0 0
9 0 0 7 0 0 0 0 3
0 0 5 0 0 8 2 0 0
The output that I get after those methods (calling the method annotation(s,1,1,2); )
2686428 0 0 2686524 8989288 4733208 0 0 -17974607
1 0 4201360 4662484 0 8989288 8989340 9005760 0
.
.
.
Im reading the array from a file,and the method is
bool readMatrix(matrix s){
ifstream f;
f.open("nuMatrix.txt");
if (f.is_open()) {
while(!f.eof()){
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
f>>(s).Ar[i][j];
}
}
}
f.close();
iprint(s);
return true;
}
else {
cerr << "NO";
return false;
}
}`
The matrix you're passing to readMatrix and annotation isn't modified by the functions.
You're passing the matrix by value, so you're only modifying a copy of it.
Change your functions to take a reference to a matrix:
bool annotation(matrix& s, int row, int column, int num)
bool readMatrix(matrix& s)
I have made a 'Map' array and I am attempting to populate it from a 'map' file. On creation I assign the value '0' to each element of the array but the 'Map' file contains the following:
MAP:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
I load the map using 'loadMap()'
loadMap():
void room::loadMap()
{
int x=0;
int y=0;
string line;
ifstream mapFile(NAME + "_MAP.txt");
while(!mapFile.eof())
{
for(int i=0; i<cellsY; i++)
{
getline(mapFile,line,'\n');
for(int j=0; j<cellsX; j++)
{
getline(mapFile,line,' ');
map[(cellsX*j) + cellsY] = atoi(line.c_str());
};
};
}
y = 10;
x = 15;
for(int i=0; i<y; i++)
{
cout << endl;
for(int j=0; j<x; j++)
{
cout << map[(x*j) + y];
};
};
}
In this example the elements are still assigned to '0', but I am trying to mimic the Map files layout.
For starters, you never test that any of the input works, nor
that the open succeeded. Then, in the outer loop, you read
a line from the file, and throw it away, before reading further
in the inner loop. And your calcule of the index is wrong.
What you're probably looking for is something like:
std::ifstream mapFile(...);
if ( !mapFile.is_open() ) {
// Error handling...
}
for ( int i = 0; mapFile && i != cellsY; ++ i ) {
std::string line;
if ( std::getline( mapFile, line ) ) {
std::istringstream text( line );
for ( int j = 0; j != cellsX && text >> map[cells X * i + j]; ++ j ) {
}
if ( j != cellsX ) {
// Error: missing elements in line
}
text >> std::ws;
if ( text && text.get() != EOF ) {
// Error: garbage at end of line
}
}
}
For the error handling, the simplest is just to output an
appropriate error message and continue, noting the error so you
can return some sort of error code at the end.
I think this is what you are looking for.
void room::loadMap()
{
int x=0;
int y=0;
ifstream mapFile(NAME + "_MAP.txt");
for(int i=0; i<cellsY; i++)
{
for(int j=0; j<cellsX; j++)
{
int v;
mapFile >> v;
if ( mapFile.eof() )
{
break;
}
map[(cellsX*j) + cellsY] = v;
}
}
y = 10;
x = 15;
for(int i=0; i<y; i++)
{
cout << endl;
for(int j=0; j<x; j++)
{
cout << map[(x*j) + y];
};
};
}
I should open with the fact that I am very new to c++.
I am attempting to display a constantly updating 20x20 matrix of chars. Currently, I am displaying the the matrix using for loops as cout's (code below) but that is incredibly flickery- I'm looking for something smoother.
Is there a way to convert this char matrix into an image and display that?
This is my first question here, so I apologize if I did something wrong!
Code so far:
#include <iostream>
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
using namespace std;
int main()
{
int randInt;
//Initialize matrix and location
int matrix[20][20];
int location[2] = {0,0};
for (int i=0; i<20; i++)
{
for (int j=0; j<20; j++)
{
matrix[i][j] = 1;
}
}
//move the X around
for (int i=0; i<100; i++)
{
cout << string(50, '\n');
//Change the X's location
randInt = rand() % 4;
switch (randInt)
{
case 0:
if(location[1] > 0)
location[1] = location[1]-1;
break;
case 1:
if(location[0] < 20)
location[0] = location[0]+1;
break;
case 2:
if(location[1] < 20)
location[1] = location[1]+1;
break;
case 3:
if(location[0] > 0)
location[0] = location[0]-1;
break;
default:
cout << "Switch statement problem";
}
//Display the matrix
for (int x=0; x<20; x++)
{
for (int y=0; y<20; y++)
{
if(x==location[0] && y==location[1])
cout << "X";
else
cout << matrix[x][y];
}
cout << endl;
}
Sleep(100);
}
system ("pause");
return 0;
}
You should rename the location[2] to something like `struct { int x,y; } location for readability.
Then you can build an array of characters in RAM and put out it at once.
int _tmain(int argc, _TCHAR* argv[])
{
char matrix[20][20];
char image[21][21];
struct { int x, y; } location;
int x = 0;
int y = 0;
location.x = 7;
location.y = 3;
// fill the matrix
for (x = 0; x < 20; ++x)
{
for (y = 0; y < 20; ++y)
{
matrix[y][x] = 'a' + x + y;
}
}
// prepare the image
y = 0;
while (y < 20)
{
memcpy(image[y], matrix[y], 20);
image[y][20] = '\n';
++y;
}
// add the cross
image[location.y][location.x] = 'X';
image[20][0] = '\0';
// use the image
puts((char*)image);
}
Please add you random functionality as needed.
If you want to convert the char to a image and see the color means, write the char value as pixel in simple pgm format.
Write a file in this sample format
P2
# feep.pgm
24 7
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
check this link http://netpbm.sourceforge.net/doc/pgm.html for pgm format
I am trying to determine a next hop routing table using an adjacency matrix. Each node knows the full adjacency matrix for that topology. I have found previous posts explaining how to do it, however, I don't understand why mine is wrong. I have a couple of helper functions but their names are intuitive so you could skip to " starting routing calculations".
I use the adjacency matrix as a cost matrix, it just has only 0's and 1's. The algorithm seems not to stop for some reason. The queue gets stuck on size 1,3 or 5 depending on node.
The variable rank holds the current node index, it is run in OpenMPI so each process(rank / node) runs this chunk of code independently. Variable matrix holds the adjacency matrix.
Here is the topology I am using :
0
/ \
1 2
/ / | \ / \
3 4 5 6 7 8
/ \ |
9 10 11
Adjacency matrix :
(As seen by Node 3, one of those that does not stop );
1 1 1 0 0 0 0 0 0 0 0 0
1 0 0 1 1 1 1 0 0 0 0 0
1 0 0 0 0 0 0 1 1 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 1 1 0
0 1 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 1
0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0
My code so far:
int isFull(int *d, int size) {
int i;
for(i = 0; i < size; i++) {
if(d[i] == INF) {
return -1;
}
}
return 1;
}
int vecSize(int *d, int size) {
int counter = 0;
int i;
for(i = 0; i < size; i++) {
if(d[i] != INF) {
counter++;
}
}
return counter;
}
bool List_contains(std::list<int > l, int val) {
for (std::list<int>::const_iterator iterator = l.begin(), end = l.end(); iterator != end; ++iterator) {
if (*iterator == val) {
return true;
}
}
return false;
}
int minimum (int a, int b) {
if (a < b) {
return a;
}
return b;
}
/* matrix is the complete adjacency matrix */
/* starting routing calculations
*
*/
std::list <int > visited;
int *dist;
dist = (int*) calloc(size, sizeof(int));
visited.push_back(rank);
//debug
//printf("debug not empty %d\n", isFull(dist, size));
for(i = 0; i < size; i++) {
if(matrix[rank][i] == 1) {
dist[i] = 1;
} else {
dist[i] = INF;
}
}
dist[rank] = 0;
int min;
while(isFull(dist,size) < 0) {
if(rank == 3)
printf("node - %d -debug -- list size %d\n",rank, vecSize(dist, size));
//get the first node that isn't contained
for(i = 0; i < size; i++) {
if (!List_contains(visited, i) && min != rank) {
min = i;
break;
}
}
for(i = 0; i < size; i++) {
if((min >= dist[i]) && (!List_contains(visited, i)) && min != rank) {
min = i;
}
}
if(rank == 3)
printf("min = %d\n", min);
visited.push_back(min);
for(i = 0; i < size; i++) {
if((matrix[min][i] == 1) && (!List_contains(visited, i))) {
dist[i] = minimum (dist[i], dist[min] + matrix[min][i]);
}
}
if(rank == 3)
//printf("rank %d dist = \n", rank);
for(i = 0; i < size; i++) {
if(rank == 3)
printf("%d ", dist[i]);
}
if(rank == 3)
printf("\n");
}
/*
* finished routing calculations.
*/
This would be the output so far : http://pastebin.com/x5wjKkyn
Could someone point out what am I doing wrong? Thank you !
Later edit: Technically, the algorithm provides the correct distances, it just doesn't stop. ( The output is exclusively from node 0)
Later edit: it seems that the program is not stopping because for some nodes the algo doesn't finish.
I got an float pointer (array), which represents an image.
It's elements count and index has width*height.
The image is not like a matrix, which has it's origin at the upper left.
Instead it has the origin in the lower left, like in the carthesian coordinate system.
After reaching the max-width, it starts it's next row at the left side.
So I want to efficiently convert this array to a 2D matrix (optional: opencv).
How do I do that in a good and effective manner?
And how do I convert it back?
Thanks in advance.
I'll throw a rock in the lake and watch the ripples. Note: I have no idea what the caller expects to do with the xformed data, mostly due to my fledgling knowledge of OpenCV. However the core question of transformation seemed pretty straight forward. If I'm way off-base kindly leave a comment and I'll drop the answer. I propose two approaches, one for data inversion in-place, and one for simple accessor wrapping using a C++ class.
In-place Inversion: If the caller needs to invert the rows to accommodate usage for passing to an API, it can be done in place. Just be sure to do it again once you're done using the inverted data. An example purely byte-oriented is:
// in-place inversion of the linear matrix to re-origin.
void mat_invert(float *data, size_t height, size_t width)
{
// must be at least 2 rows high for this to mean anything.
if (height < 2)
return;
// setup a pair of pointers to walk the rows in byte-form
unsigned char* top = (unsigned char*)data;
unsigned char *bottom = (unsigned char *)(data + (height-1)*width);
size_t row_width = sizeof(data[0]) * width;
while (top < bottom)
{
for (size_t i=0; i<row_width; i++)
{
*top ^= *bottom;
*bottom ^= *top;
*top++ ^= *bottom++;
}
bottom -= 2*row_width;
}
}
A sample usage:
int main(int argc, char *argv[])
{
const size_t w = 10;
const size_t h = 5;
float ar[h*w];
memset(ar, 0, sizeof(ar));
ar[0] = 0.1;
ar[1*w + 1] = 1.1;
ar[2*w + 2] = 2.1;
ar[3*w + 3] = 3.1;
ar[4*w + 4] = 4.1;
// dump original
for (size_t i=0; i<h; i++)
{
for (size_t j=0; j<w; j++)
cout << ar[i*w+j] << ' ';
cout << endl;
}
cout << endl;
// invert original
mat_invert(ar, h, w);
for (size_t i=0; i<h; i++)
{
for (size_t j=0; j<w; j++)
cout << ar[i*w+j] << ' ';
cout << endl;
}
cout << endl;
// invert again
mat_invert(ar, h, w);
for (size_t i=0; i<h; i++)
{
for (size_t j=0; j<w; j++)
cout << ar[i*w+j] << ' ';
cout << endl;
}
cout << endl;
return EXIT_SUCCESS;
}
Results:
0.1 0 0 0 0 0 0 0 0 0
0 1.1 0 0 0 0 0 0 0 0
0 0 2.1 0 0 0 0 0 0 0
0 0 0 3.1 0 0 0 0 0 0
0 0 0 0 4.1 0 0 0 0 0
0 0 0 0 4.1 0 0 0 0 0
0 0 0 3.1 0 0 0 0 0 0
0 0 2.1 0 0 0 0 0 0 0
0 1.1 0 0 0 0 0 0 0 0
0.1 0 0 0 0 0 0 0 0 0
0.1 0 0 0 0 0 0 0 0 0
0 1.1 0 0 0 0 0 0 0 0
0 0 2.1 0 0 0 0 0 0 0
0 0 0 3.1 0 0 0 0 0 0
0 0 0 0 4.1 0 0 0 0 0
Implicit Access Class: If all you need is virtualized row/height math done for you, the following will suffice to do just that:
#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std;
class matrix_xform
{
private:
size_t width, height;
float *data;
public:
matrix_xform(float *data, size_t height, size_t width)
: data(data), width(width), height(height)
{
}
float * operator[](size_t x)
{
if (x > (height-1))
throw std::out_of_range("matrix_xform[x]");
return data + (width * (height - 1 - x));
}
const float * operator[](size_t x) const
{
if (x > (height-1))
throw std::out_of_range("matrix_xform[x]");
return data + (width * (height - 1 - x));
}
};
A sample usage:
int main(int argc, char *argv[])
{
const size_t w = 10;
const size_t h = 5;
float ar[h*w];
memset(ar, 0, sizeof(ar));
matrix_xform mat(ar, h, w);
mat[0][0] = 1.0;
mat[1][1] = 1.0;
mat[2][2] = 1.0;
mat[3][3] = 1.0;
mat[4][4] = 1.0;
// dump original
for (size_t i=0; i<h; i++)
{
for (size_t j=0; j<w; j++)
cout << ar[i*w+j] << ' ';
cout << endl;
}
cout << endl;
// dump using accessor
for (size_t i=0; i<h; i++)
{
for (size_t j=0; j<w; j++)
cout << mat[i][j] << ' ';
cout << endl;
}
return EXIT_SUCCESS;
}
Results:
0 0 0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
I hope that covers every base the OP is looking for.
Planning your image processing API as
void my_func (int *src, int *dst, int x_stride, int y_stride, int N);
makes it easy to iterate in continuous memory while flipping the scanning direction between left<->right, but also between up<->down.
If the API is designed for different input & output strides, one can also change the number of bytes per image element (change eg. color mode from RGBA to RGB or from 24-bit RGB to 16-bit R5G6B5, from int to float etc.) but also image width (and height also...).
The point is that math should be the same regardless of location of each row of the image.
One of these functions can be:
copy_row(int *src, int* dst, int N, int x_stride);
copy_2D_mem(int *src_base, int* dst_base, int N, int M, int y_stride, int x_stride);
Then again, it's quite possible that many of the existing opencv algorithms do not care about the orientation of the image. And writing one's own, the same approach could be utilized.
As I understand your problem, you want to pass your array to an OpenCV API so that it interprets it as a (top,left) indexed 2-d matrix. One simple way to do that without rearranging any of your array is illustrated by the following example :
float a[8] = {1,2,3,4,5,6,7,8}; //your array containing the image
int img_width = 2;
int img_height = 4;
float** b = new float*[img_height];
for(int i=img_height ; i>0; i--)
b[img_height-i] = a+ (i-1)*img_width;
//call your API
do_something(b,img_height,img_width);
//your OpenCV API that expects a 2-d matrix
void do_something(float** x , int r, int c){};
If you want, you can turn this into a convenience function/macro that you can call to get the 2-d matrix in the desired format before calling the OpenCV API. Also, do not forget to de-allocate the memory for the temp array that was created for this purpose, once your are done.