How do I make a maze tile 3x3 - c++

Like the question says, I have a 10X11 array and I need each tile to be a 3x3 instead of 1x1 and Im not sure how to do that. I also am having trouble pulling the correct x value for my finish point. Any help would be much appreciated. here is my code so far:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
int main()
{
//establishing constant variables;
const char Walls = '#';
const char Mazes = '-';
const int row = 10;
const int col = 11;
//defining strings to pull from text file
std::string arraysize_sx;
std::string arraysize_sy;
std::string start_sx;
std::string start_sy;
std::string finish_sx;
std::string finish_sy;
std::string walls_s;
std::ifstream openfile ("input.txt");
std::ofstream outputfile ("output.txt",std::ios::app);
//gets points from text file, using , and . as delimiters
std::getline(openfile, arraysize_sx , ',');
std::getline(openfile, arraysize_sy, '.');
std::getline(openfile, start_sx, ',');
std::getline(openfile, start_sy, '.');
std::getline(openfile, finish_sx , ',');
std::getline(openfile, finish_sy , '.');
std::getline(openfile,walls_s, '.');
int startx,starty;
int finishx,finishy;
//convert string to int
std::stringstream rowconv(arraysize_sx);
std::stringstream colconv(arraysize_sy);
std::stringstream startsx(start_sx);
std::stringstream startsy(start_sy);
std::stringstream finishsx(finish_sx);
std::stringstream finishsy(finish_sy);
// rowconv >> row;
// colconv >> col;
startsx >> startx;
startsy >> starty;
finishsx >> finishx;
finishsy >> finishy;
//defining the shape of the maze
char maze [col][row] = {
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
};
maze[startx][starty] = 's';
maze[finishx+3][finishy] = 'f';
outputfile << *maze;
openfile.close();
}
Here is my .txt input for refrence, each different point is marked by a period. i.e dimentions. start. finish. walls:
10, 11.
(0, 0).
(3, 10).
(0, 6), (0, 7), (0, 9),
(1, 1), (1, 2), (1, 4), (1, 7),
(2, 1), (2, 7), (2, 8), (2, 10),
(3, 1), (3, 2), (3, 3), (3, 4), (3, 7),
(4, 0), (4, 6), (4, 9), (4, 10),
(5, 2), (5, 3), (5, 4), (5, 5), (5, 7),
(6, 1), (6, 8), (6, 9),
(7, 1), (7, 2), (7, 3), (7, 6),
(8, 1), (8, 5), (8, 6), (8, 8), (8, 10),
(9, 3), (9, 7).
Update:
I updated my code so that instead of creating the array like I did above. I used for loops to create the start and finish. Im still working on adding the walls in and creating 3X3 squares for each point. I'm trying to find out if its possible to place a 3X3 array within one point on another array.
Updated code:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
int main()
{
//establishing constant variables;
const int row = 10;
const int col = 11;
double p1x,p1y;
//defining strings to pull from text file
std::string arraysize_sx;
std::string arraysize_sy;
std::string start_sx;
std::string start_sy;
std::string finish_sx;
std::string finish_sy;
// std::string walls_sx;
// std::string walls_sy;
std::string walls_sf;
std::ifstream openfile ("input.txt");
std::ofstream outputfile ("output.txt",std::ios::app);
// int wx,wy;
int startx,starty;
int finishx,finishy;
//gets points from text file, using , and . as delimiters
std::getline(openfile, arraysize_sx , ',');
std::getline(openfile, arraysize_sy, '.');
std::getline(openfile, start_sx, ',');
std::getline(openfile, start_sy, '.');
std::getline(openfile, finish_sx , ',');
std::getline(openfile, finish_sy , '.');
// std::getline(openfile,walls_sx, ',');
// std::getline(openfile,walls_sy, ',');
std::getline(openfile,walls_sf, '.');
//convert string to int
std::stringstream rowconv(arraysize_sx);
std::stringstream colconv(arraysize_sy);
std::stringstream startsx(start_sx);
std::stringstream startsy(start_sy);
std::stringstream finishsx(finish_sx);
std::stringstream finishsy(finish_sy);
// std::stringstream wallx(walls_sx);
// std::stringstream wally(walls_sy);
startsx >> startx;
startsy >> starty;
finishsx >> finishx;
finishsy >> finishy;
// wallx >> wx;
// wally >> wy;
//defining the shape of the maze
char maze [col][row];
char s [3][3] = {
{'-','-','-'},
{'-','S','-'},
{'-','-','-'}
};
//defining the start point and endpoint using the points pulled from the text file
for (int x = 0; x < col; x++){
for (int y = 0; y < row; y++){
if (x == startx && y == starty){
maze[x][y] = 'S';
}
else if (y == finishx+3 && x == finishy){
maze[x][y] = 'F';
}
else{
maze [x][y] = '-';
}
}
}
std::cout << walls_sf << std::endl;

Related

fin >> noskipws >> ch is always false

I'm learning C++.
I'm trying to convert a text file like this one:
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
...
Into a file like this one:
int grid[20][30] =
{
{ 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },
Both piece of text file are only and example to show you what I'm trying to do. The first text file doesn't generate the second text file.
I have written down this code:
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char *argv[])
{
if ((argc == 1) || (argc != 5)) {
cout << "Usage: format rows columns input_file output_file\n";
return 0;
}
// Number of rows in the image.
int rows = atoi(argv[1]);
// Number of columns in the image.
int columns = atoi(argv[2]);
// Character read from the input file.
char ch;
// Counter to create arrays of "columns" elements.
int colCount = 0;
// Counter for the number of rows added to the grid.
int rowCount = 0;
// Output file.
ofstream fout;
fout.open(argv[4], ios::out);
// Write the header to output file.
fout << "int grid[" << rows << "][" << columns << "] = {";
// Read input file.
fstream fin(argv[3], fstream::in);
while (fin >> noskipws >> ch)
{
if (colCount == 0)
fout << "\n{";
if ((!isspace(ch)) && ((ch == '1') || (ch == '0') || (ch == ','))) {
fout << ch;
colCount++;
}
if (colCount == columns) {
colCount = 0;
rowCount++;
if (rowCount != rows)
fout << "},";
}
}
fout << "}};\n";
fout.close();
return 0;
}
But it seems that it never enters into the main loop (while (fin >> noskipws >> ch)). I get this output in the text file:
int grid[365][484] = {}};
I'm compiling with g++ on Linux (Ubuntu) with the following command line:
g++ FormatMatrix.cpp -o format
What am I doing wrong?
Check if create/open your input stream 'fin' succeeded before you enter the while loop.

Converting a char in a string array to float

I'm working on a project which takes a string input from the user of coordinates.
example of input:
"Polygons = [(1, 1), (4, 1), (4, 5), (3,5), (1, 5); (5,3), (3, 4), (6, 4), (6, 12), (3, 12)]"
One of the functions that I am making is checking the minimum/maximum X, which is clearly any number after a "(", however the problem that's bugging me is converting what's after the ( into a float to use it in calculations and number comparisons.
#include <iostream>
#include "string"
#include <stdlib.h>
#include <cstdlib>
using namespace std;
//Using a constant string for testing
string Polygon_Input = "Polygons = [(1, 1), (4, 1), (4, 5), (3,5), (1, 5); (5,3), (3, 4), (6, 4), (6, 12), (3, 12)]";
string Operation;
float Min_X = 9999;
int main()
{
getline(cin, Operation);
if (Operation == "Minimum_X")
{
for (int i; i <= Polygon_Input.length(); i++)
{
if (Polygon_Input[i] == '(')
{
float X = Polygon_Input[i + 1];
if (X < Min_X)
{
Min_X = X;
}
}
}
cout << Min_X;
}
That's not working, it always prints out 49 as Min_X
I also tried the same code with one modification, but still doesn't work.
if (Polygon_Input[i] == '(')
{
string X_As_String = Polygon_Input.substr(i + 1, i + 1);
float X = atof(X_As_String.c_str());
if (X < Min_X)
{
Min_X = X;
}
First of all, there are several problems in your code.
float Min_X = 9999;
The minimum value must be in the list. Initialize the first element as the minimum value and compare it with the rest.
if (X < Min_X)
The value X is int whereas Min_X is float. Don't compare int with float. Declare both as float and then cast if you would like an integer number.
for (int i=0; i <= Polygon_Input.length(); i++)
Pay attention to <=. It should be <.
Now the solution for your problem is
//#include <limits> // no need for this
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdlib>
using namespace std;
//Using a constant string for testing
string Polygon_Input = "Polygons = [(1, 1), (4, 1), (4, 5), (3,5), (1, 5); (5,3), (3, 4), (6, 4), (6, 12), (3, 12)]";
string Operation("Minimum_X");
//float Min_X = 9999; ?????? Why
float Min_X;
bool flag(true);
int main()
{
//getline(cin, Operation); // commented out for test
if (Operation == "Minimum_X")
{
for (int i=0; i < Polygon_Input.size(); i++)
{
if ( Polygon_Input[i] == '(' )
{
// extract X values (i.e. the first co-ordinate of a point )
std::string temp = Polygon_Input.substr(i+1, Polygon_Input.find_first_of(",",i)-i-1 );
// convert strig to float
float X = std::stof(temp);
// store first element and compare it with the rest
if(flag){
Min_X = X;
flag=false;
}
// int X = Polygon_Input[i + 1] - '0'; ????? What is this?
if (X < Min_X)
{
Min_X = X;
}
}
}
cout << Min_X << endl;
}
return 0;
}
The output is
1
which the minimum X value in the list. This code handles float values as well (i.e. (3.45, 4)). Try different values for checking.

How to initialize static member array with a result of a function?

I'm translating such fragment of this Python file to C++:
SIDE = 3
LINES = []
for y in range(SIDE):
row = tuple((x, y) for x in range(SIDE))
LINES.append(row)
for x in range(SIDE):
col = tuple((x, y) for y in range(SIDE))
LINES.append(col)
LINES.append(tuple((x, x) for x in range(SIDE)))
LINES.append(tuple((SIDE - x - 1, x) for x in range(SIDE)))
LINES holds (x, y) coordinates of possible lines in Tic Tac Toe game. So for SIDE = 3 it holds:
[((0, 0), (1, 0), (2, 0)),
((0, 1), (1, 1), (2, 1)),
((0, 2), (1, 2), (2, 2)),
((0, 0), (0, 1), (0, 2)),
((1, 0), (1, 1), (1, 2)),
((2, 0), (2, 1), (2, 2)),
((0, 0), (1, 1), (2, 2)),
((2, 0), (1, 1), (0, 2))]
SIDE value can change.
What I've tried
Performance is crucial (that's why I reached for C++), so I would like to calculate LINES only once. Thus, I've chosen to implement LINES as a static member of the class TicTacToeState.
I started with such code:
static char init_lines() {
return 'a';
}
class TicTacToeState {
static char LINES;
};
char TicTacToeState::LINES = init_lines();
It works. How to change LINES to an array? Maybe vector will be better? With pairs?
Maybe static member is not the best choice, maybe there is an easier way?
How would you translate it to C++?
We know the size of LINES, it's always 2 * SIDE + 2.
Special requirement
All C++ code must be in one .cpp file, no headers. Why? Because this is fragment of a library for bot competitions and it's typical that you can submit only one file.
In C++ you can initialize static array members using group initialization
static int a[10] = {5}; //this will initialize first position item with 5 and rest with 0s
static char b[2] = {'b', 'b'};
static int c[2][2] = { {1,1}, {1,2} };
int main()
{
cout<< a[0] << endl; //output: 5
cout<< a[1] << endl; //output: 0
cout<< b[0] << endl; //output: b
cout<< c[0][1] << endl; //output: 1
}
Although the fact is you need to know size of the array not like in Python's list that are dynamically
If you need to insert to the table values calculated dynamically the best way to do this is to create factory method
static int** fact(int width, int height)
{
int** a;
a = new int*[width]; //we can do it when it is DYNAMIC array!
a[0] = new int[height];
a[1] = new int[height];
for(int i = 0; i < width; i++)
for(int k = 0; k < height; k++)
a[i][k] = i*k;
return a;
}
static int** c = fact(2, 2); //you can call it with your SIDE var
int main()
{
cout<< c[1][1] << endl; //output: 1
}
Of course you can process it in loops
The same approach will be proper when you will decide to use std Vector class which is equvalent of Python's dynamic list
I suppose you could do this using a lambda function like this:
#include <vector>
#include <iostream>
const auto SIDE = 3U;
struct coord
{
unsigned x;
unsigned y;
coord(unsigned x, unsigned y): x(x), y(y) {}
};
static const auto lines = [] // lambda function
{
// returned data structure
std::vector<std::vector<coord>> lines;
for(auto y = 0U; y < SIDE; ++y)
{
lines.emplace_back(); // add a new line to back()
for(auto x = 0U; x < SIDE; ++x)
lines.back().emplace_back(x, y); // add a new coord to that line
}
for(auto x = 0U; x < SIDE; ++x)
{
lines.emplace_back();
for(auto y = 0U; y < SIDE; ++y)
lines.back().emplace_back(x, y);
}
lines.emplace_back();
for(auto i = 0U; i < SIDE; ++i)
lines.back().emplace_back(i, i);
lines.emplace_back();
for(auto i = 0U; i < SIDE; ++i)
lines.back().emplace_back(SIDE - i - 1, i);
return lines;
}(); // NOTE: () is important to run the lambda function
int main()
{
for(auto const& line: lines)
{
std::cout << "(";
for(auto const& coord: line)
std::cout << "(" << coord.x << ", " << coord.y << ")";
std::cout << ")\n";
}
}
Output:
((0, 0)(1, 0)(2, 0))
((0, 1)(1, 1)(2, 1))
((0, 2)(1, 2)(2, 2))
((0, 0)(0, 1)(0, 2))
((1, 0)(1, 1)(1, 2))
((2, 0)(2, 1)(2, 2))
((0, 0)(1, 1)(2, 2))
((2, 0)(1, 1)(0, 2))

Replace whole row using MatSetValuesStencil with INSERT_VALUES

I am using Petsc Ksp routines.
I construct an operator using MatSetValuesStencil, where in each call of this function I specify one row matrix values of length 5.
There is a case where I sometimes need to completely replace a row from a 5 length stencil to a 3 length one. Will INSERT_VALUES mode leave the two values on non changed positions or it will discard them to zero?
The elements of the matrix that are not specified in the arguments idxm and idxn of the function MatSetValuesStencil(...) are left unchanged, even if INSERT_VALUES is used.
Here is a little code starting from ksp_ex29 to test it :
static char help[] = "Does INSERT_VALUES changes the whole row ? No.\n\n";
#include <petscdm.h>
#include <petscdmda.h>
#include <petscksp.h>
extern PetscErrorCode ComputeMatrix42(DM da,Mat jac);
extern PetscErrorCode ComputeMatrix(DM da,Mat jac);
#undef __FUNCT__
#define __FUNCT__ "main"
int main(int argc,char **argv)
{
DM da;
PetscErrorCode ierr;
Mat matrix;
PetscInitialize(&argc,&argv,(char*)0,help);
ierr = DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_PERIODIC, DM_BOUNDARY_PERIODIC,DMDA_STENCIL_STAR,-3,-3,PETSC_DECIDE,PETSC_DECIDE,1,1,0,0,&da);CHKERRQ(ierr);
DMCreateMatrix(da,&matrix);
ComputeMatrix(da,matrix);
PetscPrintf(PETSC_COMM_WORLD,"A matrix of negative terms : \n");
MatView(matrix, PETSC_VIEWER_STDOUT_WORLD );
ComputeMatrix42(da,matrix);
PetscPrintf(PETSC_COMM_WORLD,"The diagonal, i-1 and i+1 are set to 42 : \n");
MatView(matrix, PETSC_VIEWER_STDOUT_WORLD );
ierr = DMDestroy(&da);CHKERRQ(ierr);
ierr = MatDestroy(&matrix);CHKERRQ(ierr);
ierr = PetscFinalize();
return 0;
}
#undef __FUNCT__
#define __FUNCT__ "ComputeMatrix"
PetscErrorCode ComputeMatrix(DM da,Mat jac)
{
PetscErrorCode ierr;
PetscInt i,j,mx,my,xm,ym,xs,ys;
PetscScalar v[5];
MatStencil row, col[5];
PetscFunctionBeginUser;
ierr = DMDAGetInfo(da,0,&mx,&my,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr);
for (j=ys; j<ys+ym; j++) {
for (i=xs; i<xs+xm; i++) {
row.i = i; row.j = j;
v[0] = -1; col[0].i = i; col[0].j = j-1;
v[1] = -1; col[1].i = i-1; col[1].j = j;
v[2] = -13; col[2].i = i; col[2].j = j;
v[3] = -1; col[3].i = i+1; col[3].j = j;
v[4] = -1; col[4].i = i; col[4].j = j+1;
ierr = MatSetValuesStencil(jac,1,&row,5,col,v,INSERT_VALUES);CHKERRQ(ierr);
}
}
ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
PetscFunctionReturn(0);
}
#undef __FUNCT__
#define __FUNCT__ "ComputeMatrix42"
PetscErrorCode ComputeMatrix42(DM da,Mat jac)
{
PetscErrorCode ierr;
PetscInt i,j,mx,my,xm,ym,xs,ys;
PetscScalar v[3];
MatStencil row, col[3];
PetscFunctionBeginUser;
ierr = DMDAGetInfo(da,0,&mx,&my,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr);
for (j=ys; j<ys+ym; j++) {
for (i=xs; i<xs+xm; i++) {
row.i = i; row.j = j;
v[0] = 42; col[0].i = i-1; col[0].j = j;
v[1] = 42; col[1].i = i; col[1].j = j;
v[2] = 42; col[2].i = i+1; col[2].j = j;
ierr = MatSetValuesStencil(jac,1,&row,3,col,v,INSERT_VALUES);CHKERRQ(ierr);
}
}
ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
PetscFunctionReturn(0);
}
Compile it with the following makefile :
include ${PETSC_DIR}/conf/variables
include ${PETSC_DIR}/conf/rules
main: main.o chkopts
-${CLINKER} -o main main.o ${PETSC_LIB}
${RM} main.o
Output :
A matrix of negative terms :
Mat Object: 1 MPI processes
type: seqaij
row 0: (0, -13) (1, -1) (2, -1) (3, -1) (6, -1)
row 1: (0, -1) (1, -13) (2, -1) (4, -1) (7, -1)
row 2: (0, -1) (1, -1) (2, -13) (5, -1) (8, -1)
row 3: (0, -1) (3, -13) (4, -1) (5, -1) (6, -1)
row 4: (1, -1) (3, -1) (4, -13) (5, -1) (7, -1)
row 5: (2, -1) (3, -1) (4, -1) (5, -13) (8, -1)
row 6: (0, -1) (3, -1) (6, -13) (7, -1) (8, -1)
row 7: (1, -1) (4, -1) (6, -1) (7, -13) (8, -1)
row 8: (2, -1) (5, -1) (6, -1) (7, -1) (8, -13)
The diagonal, i-1 and i+1 are set to 42 :
Mat Object: 1 MPI processes
type: seqaij
row 0: (0, 42) (1, 42) (2, 42) (3, -1) (6, -1)
row 1: (0, 42) (1, 42) (2, 42) (4, -1) (7, -1)
row 2: (0, 42) (1, 42) (2, 42) (5, -1) (8, -1)
row 3: (0, -1) (3, 42) (4, 42) (5, 42) (6, -1)
row 4: (1, -1) (3, 42) (4, 42) (5, 42) (7, -1)
row 5: (2, -1) (3, 42) (4, 42) (5, 42) (8, -1)
row 6: (0, -1) (3, -1) (6, 42) (7, 42) (8, 42)
row 7: (1, -1) (4, -1) (6, 42) (7, 42) (8, 42)
row 8: (2, -1) (5, -1) (6, 42) (7, 42) (8, 42)
I am using PETSC 3.5.2.

Struct Array Indexes not being filled after first index

I have an input file with 3 fields on each line that are type: string, double, double. There are 15 lines with data.
The format of the input file data is:
Katmandu, -34, 28
cityName, lowTemp, highTemp
....
...
..
It's obvious that it's not getting the 3rd input on the line, based on the output.
Here is the code:
for (int index = 0; index < 15; index++)
{
getline(inFile, weatherInfo[index].city, ',');
inFile >> weatherInfo[index].low >> weatherInfo[index].high;
inFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
For some reason this is my output:
Katmandu (-34, 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 know my program is able to read the other lines because when I add
inFile.ignore(20);
to the beginning of my statement it the loop it outputs
28
Perth (92, 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)
Output Code:
void ShowAll(int count) //Show entire data function
{
int x = 0; //loop through the index of city[], lowTemp[], highTemp[], and print them.
while (x < count)
{
cout << weatherInfo[x].city << " (" << weatherInfo[x].low << ", " << weatherInfo[x].high << ")" << endl;
x++;
}
cout << endl;
}
If the data in a line are separated by commas then you should use the following approach
#include <sstream>
//...
std::string line;
for ( int index = 0; index < 15 && std::getline( inFile, line ); index++)
{
std::istringstream is( line );
getline( is, weatherInfo[index].city, ',');
std::string field;
if ( getline( is, field, ',') ) weatherInfo[index].low = std::stod( field );
if ( getline( is, field, ',') ) weatherInfo[index].high = std::stod( field );
}
The problem with your code is that an error occurs when you are trying to read double values and a comma is encountered. In this case ths state of the stream will be erroneous and all other input will be ignored.
Also you should check what is the point representation for doubles in the locale you are using.