reading from a txt file to a 2D matrix in C++ - c++

I m trying to read from a txt file which is ;
0 1 1 1 0 0 0
1 0 0 0 1 0 0
1 0 0 0 1 1 0
1 0 0 0 0 1 0
0 1 1 0 0 1 0
0 0 1 1 1 0 0
0 0 0 0 0 0 0
and copy it into a 2D matrix. Following code tries to do it
int readFile(int indirectedAdjacencyList[][7])
{
ifstream dPathList;
dPathList.open ("input.txt");
for(int i=0; i<7; i++)
{
for (int j=0; j<7; j++)
{
dPathList >> indirectedAdjacencyList[i][j];
}
}
dPathList.close();
return 0;
}
but it seems there is a problem in my code. in 2D matrix I have only zeros but the size of matrix is ok (7x7) .is there anyone could tell me what is wrong with it ?

Related

Extract submatrix of unknown size from bigger matrix while values are equal to specified value

So let's say we have this matrix:
0 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0
0 1 1 1 0 0 0 0
0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 0
0 0 0 0 1 1 1 0
And we need those outputs:
Submatrix 1:
1 1 1
1 1 1
1 1 1
Submatrix 2:
1 1 1
1 1 1
The matrix size can vary, so can the submatrix sizes but they will have either square or rectangle shape. And is only 0 and 1.
How can i do that? Is there any algorithm to do that?
for (i=0; i<m;i++){
for (j=2; j<n; j++){
if ( A[i+1,j]==1 && A[i,j+1]==1 || A[i+1,j]==1 && A[i,j-1]==1 || A[i-1,j]==1 && A[i,j+1]==1 || A[i-1,j]==1 && A[i,j-1]==1 || A[i-1,j]==1 && A[i+1,j]==1 && A[i,j-1]==1 && A[i,j+1]==1 )
B[i,j]=A[i,j];
}
}
This is the first ideea that comes to my mind, but i don't know how to stop after i'm done with the first block of ones, and in the end the matrix B is the same as matrix A. Also i don't know how to set the submatrix size to be exactly the size that it needs to be. For now i'm only trying to break the big matrix in 2. Should i allocate the submatrix dynamically?

Inverting bits of PBM image while vs for loop

I am trying to flip the color of pixels of a simple pbm image which has only pure black and pure white. I am generating the image myself and then reading it and then flipping the bits and saving both the generated image and the color inverted image.
Here is my code (write_pbm.cpp) -
#include "headers/write_pbm.h"
int width_pbm, height_pbm;
void input_sample_dim(){
printf("Enter the width and height of image to create = ");
scanf("%d %d", &width_pbm, &height_pbm);
}
void create_sample_image(){
FILE *fp;
fp = fopen("sample.pbm", "wb");
fprintf(fp, "P1\n");
fprintf(fp, "# myfile.pbm\n");
fprintf(fp, "%d %d\n", width_pbm, height_pbm);
for (int i = 1; i <= height_pbm; i++)
{
for (int j = 1; j <= width_pbm; j++)
{
if (j == i || (width_pbm - j + 1 == i))
fprintf(fp, "0");
else
fprintf(fp, "1");
if (j == width_pbm)
fprintf(fp, "\n");
else
fprintf(fp, " ");
}
}
fclose(fp);
}
void invert (){
printf("\tinverting the image\nturning black pixels white and white pixels black\n");
FILE *fp = fopen("sample.pbm", "rb");
while(fgetc(fp) != '\n');
while(fgetc(fp) != '\n');
while(fgetc(fp) != '\n');
FILE *fp_inv;
fp_inv = fopen("inverted.pbm", "wb");
fprintf(fp_inv, "P1\n");
fprintf(fp_inv, "# inverted.pbm\n");
fprintf(fp_inv, "%d %d\n", width_pbm, height_pbm);
for (int i = 1; i <= height_pbm; i++){
for (int j = 1; j <= width_pbm; j++){
char ch = fgetc(fp);
if (ch == '1')
fputc('0', fp_inv);
else if (ch == '0')
fputc('1', fp_inv);
else
fputc(ch, fp_inv);
}}
fclose(fp);
fclose(fp_inv);
}
Below is the header I am including (write_pbm.h)
#ifndef Write_PBM_H
#define Write_PBM_H
#include <cstdio>
#include <iostream>
void create_sample_image(void);
void input_sample_dim(void);
void invert (void);
extern int width_pbm, height_pbm;
#endif
Below is my main -
#include "write/PBM/headers/write_pbm.h"
int main(){
input_sample_dim();
printf("writing sample image\n");
create_sample_image();
printf("sample image with dimenstions %d by %d created\n", width_pbm, height_pbm);
invert();
}
So I am making a V cross kind of pattern and then inverting the colors and saving both of the created image and the inverted image.
Lets suppose we provide input 10 10
then the file sample.pbm looks like
P1
# myfile.pbm
10 10
0 1 1 1 1 1 1 1 1 0
1 0 1 1 1 1 1 1 0 1
1 1 0 1 1 1 1 0 1 1
1 1 1 0 1 1 0 1 1 1
1 1 1 1 0 0 1 1 1 1
1 1 1 1 0 0 1 1 1 1
1 1 1 0 1 1 0 1 1 1
1 1 0 1 1 1 1 0 1 1
1 0 1 1 1 1 1 1 0 1
0 1 1 1 1 1 1 1 1 0
and inverted.pbm looks like this
P1
# inverted.pbm
10 10
1 0 0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 0 0 1 0 0 0
0 0 0 0 1 1 0 0 0 0
as you can see that only half the rows are getting printed in the inverted image.
If I replace the nested loops of invert() of write_pbm.cpp with
char ch;
while(!feof(fp))
{
char ch = fgetc(fp);
if (ch == '1')
fputc('0', fp_inv);
else if (ch == '0')
fputc('1', fp_inv);
else
fputc(ch, fp_inv);
}
then it gives the right output in the inverted.pbm file which is
P1
# inverted.pbm
10 10
1 0 0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 0 0 1 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 1 0 0 1 0 0 0
0 0 1 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0 0 1
\FF
I am doing the same thing through both the nested loops and the while loop then why is it giving the wrong output in case of nested for loops?
Thanks for reading this, Please provide your valuable response.
Looking at your input file, it appears that every meaningful char (i.e. '0' or '1') is followed by a space.
In the while loop that is working, you read as many chars as needed, until the end of file, just inverting the correct chars and copying unexpected chars. So everything is processed.
In the nested for loops, you are reading the exact number of chars corresponding to the dimensions of the picture so 10*10. Taking into account the layout of the input file, you are therefore reading only 100 chars, so 50 '1' or '0' and 50 spaces. So you process only half of the input.
Unrelated: your code uses C++ header, but all the rest is just plain C. In C++, you should consider to use fstream to read your files, and not the C legacy FILE* API.

Read first and third column of numbers in a ¿binary/text? file (.GRF) in C++

I want to read first and third column of numbers from a file .GRF. If I open the file with openoffice I can see correct values:
0,9415818 0 0 0 5,927979 0 -2,397739 0 -5,052835
0,9792913 0 -1,915871E-03 0 0,032 0 -2,397739 0 -5,052835
1,149846 0 -1,220657E-03 0 1,229596 0 -2,397739 0 -5,052835
1,445044 0 4,183967E-07 0 0,2993191 0 -2,397739 0 -5,052835
1,825022 0 2,269486E-03 0 0,362183 0 -2,397739 0 -5,052835
2,320204 0 4,960121E-03 0 0,1981004 0 -2,397739 0 -5,052835
2,719088 0 7,585314E-03 0 0,1872567 0 -2,397739 0 -5,052835
3,125158 0 0,0103124 0 0,1614714 0 -0,4537098 0 -4,165784
3,494056 0 1,281744E-02 0 0,1635456 0 -0,4537098 0 -4,165784
[... more rows]
507,287 0 0,6060305 0 4,375222 0 219,7832 0 7,147406
453,6478 0 0,585957 0 4,592038 0 219,7832 0 7,147406
357,4476 0 0,5346767 0 5,044852 0 219,7832 0 7,147406
226,6828 0 0,4426026 0 5,784178 0 -211,0841 0 -4,519847
135,4868 0 0,3230323 0 6,631006 0 -163,2869 0 -7,731806
75,26476 0 0,1839096 0 7,556637 0 -78,28072 0 -8,599443
1,750205 0 4,814587E-02 0 8,456 0 -11,77379 0 -10,12357
0,1572775 0 -0,1142587 0 9,47 0 -2,074077 0 -9,702723
0,2199499 0 -0,2657275 0 10,343 0 3,000968E-02 0 -10,00545
The code with I'm trying to read the file is this (previously I calculate file's size and number of rows)
//Matrix ROWSx2 where I save the values
double **mat = new double * [numRows];
for (int i = 0; i < numRows; i++)
mat[i] = new double [numCol];
double dataNumber = 00.00;
std::ifstream fileStream(nombreFich, std::ios::in | std::ios::binary);
fileStream.seekg (0, ios::beg);
if (fileStream.is_open()) {
for(int i=0; i<numRows; i++) {
for(int j=0; j<numCol; j++) {
fileStream.read((char*)&dataNumber, sizeof(double)); //read and move the pointer 8bytes
mat[i][j] = dataNumber;
fileStream.seekg (sizeof(double), ios::cur); //move 8bytes more (read third column)
}
//put the pointer at the beginning of the next row
// 5 columns + 2bytes (\n=CR+LF)
fileStream.seekg ((sizeof(double)*5)+2, ios::cur);
}
fileStream.close();
} else
cout << "Error opening the file";
I have tried to do it using floats, but It doesn't works. I'm using windows64bits and I think that the size of doubles is correct, 8 bytes.
Main problem is that I don't write the file, it's the output of other program and I have to take the values of first and third column with c++. I only know the file has 273 rows, with CR+LF between these, and 9 columns.
As you can see in the output, values that I save in mat are much more smaller than the file values :
size of the file (20266)
position value position value
Row:0 0 num 6.22783e-038 16 num 1.00408e-264
Row:1 74 num 1.20267e-153 90 num 1.00482e-264
Row:2 148 num 1.20267e-153 164 num 1.00482e-264
Row:3 222 num 1.00506e-264 238 num 1.26392e-076
Row:4 296 num 1.83054e-076 312 num 5.94315e-038
Row:5 370 num 3.42701e-062 386 num 1.72238e-047
Row:6 444 num 2.9507e-260 460 num 2.34245e-154
Row:7 518 num 2.00661e-052 534 num 2.34247e-154
Row:8 592 num 9.51165e-043 608 num 1.65633e-153
Row:9 666 num 2.31282e-057 682 num 5.87605e-062
Row:10 740 num 2.34247e-154 756 num 2.9507e-260
Row:11 814 num 2.00359e-076 830 num 6.82018e-038
Row:12 888 num 5.15436e-062 904 num 2.31696e-052
Row:13 962 num 9.6363e-092 978 num 9.6363e-092
Row:14 1036 num 1.00482e-264 1052 num 1.00604e-264
Row:15 1110 num 1.83087e-076 1126 num 6.52861e-038
Row:16 1184 num 7.54927e-096 1200 num 2.71478e-033
Row:17 1258 num 1.00408e-264 1274 num 1.00408e-264
Row:18 1332 num 1.00458e-264 1348 num 2.34246e-154
[...]
but... if I read the file complete, saving all the information in a char *, the result is this:
20266buffer
0,9415818 0 0 0 5,927979 0 -2,397739 0 -5,052835
0,9792913 0 -1,915871E-03 0 0,032 0 -2,397739 0 -5,052835
1,149846 0 -1,220657E-03 0 1,229596 0 -2,397739 0 -5,052835
1,445044 0 4,183967E-07 0 0,2993191 0 -2,397739 0 -5,052835
1,825022 0 2,269486E-03 0 0,362183 0 -2,397739 0 -5,052835
2,320204 0 4,960121E-03 0 0,1981004 0 -2,397739 0 -5,052835
2,719088 0 7,585314E-03 0 0,1872567 0 -2,397739 0 -5,052835
3,125158 0 0,0103124 0 0,1614714 0 -0,4537098 0 -4,165784
3,494056 0 1,281744E-02 0 0,1635456 0 -0,4537098 0 -4,165784
[...more rows]
0,2199499 0 -0,2657275 0 10,343 0 3,000968E-02 0 -10,00545
²²²²½½½½½½½½¯■
File complete in memory
So, how can I read it correctly? Only numbers of first and third column
Edit: At the moment I'm trying to read the file as a text file.
It seems that this file is not binary file, but is text file.
So do not read it like binary file.
You can read it say line by line
while (std::getline(f, line)) {
...
}
and the parse it.

Writing a 2D vector to a file? c++

I'm wondering how I can output a 2D vector to a file with spaces in between the values. It's to write a map to a file at a specified size that the user chooses. I am already dynamically loading the map from there. I have a basis for the function but I'm kind of lost on the next bit.
void Map::SetMapSize(int sizeX, int sizeY, const char *filename)
{
std::ofstream out(filename);
out << "[Map]" << std::endl;
MapSizeVector[sizeX][sizeY];
for(int i = 0; i <= sizeX; i++)
{
for(int j = 0; j <= sizeY; j++)
{
std::ostream_iterator<std::string> output_iterator(out, " ");
}
}
}
The Map.txt looks like this:
[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 1 1 0 0 0 1 1 0 0 1 1 1 1 1 1 0 0
0 0 1 1 0 0 0 1 1 0 0 1 1 1 1 1 1 0 0
0 0 1 1 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0
0 0 1 1 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0
0 0 1 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0
0 0 1 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0
0 0 1 1 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0
0 0 1 1 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0
0 0 1 1 0 0 0 1 1 0 0 1 1 1 1 1 1 0 0
0 0 1 1 0 0 0 1 1 0 0 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
It also has a details bit underneath it. Basically, I want to rewrite that [Map] part to whatever size x and y the user requests above the [Details] and replacing the existing [Map] part. The numbers are fine with being 0. Thanks!
Declaration of vector in Map.h
std::vector <std::vector <int> > MapSizeVector;
Your function should look like this:
void Map::SetMapSize(int sizeX, int sizeY, const char *filename)
{
std::ofstream out(filename);
out << "[Map]" << std::endl;
MapSizeVector.resize(sizeX);
for(int i = 0; i < sizeX; i++)
{
MapSizeVector[i].resize(sizeY);
for(int j = 0; j < sizeY; j++)
{
char str[20];
sprintf(str, "%d ", MapSizeVector[i][j]);
out << str;
}
out << '\n';
}
}

How do I add a number to an array if it is less than a corresponding number in a "Max" array?

So here is my issue. In the program I have below, towards the bottom of the function "SetBoardStartingConfig" I attempt to fill in the first 4 rows of an array by randomly generating numbers, checking if the square I'm attempting to place them onto is empty (0), and if the addition of the piece would make it go over the specified max values in array "MaxPieces". If it wouldn't, it should theoretically be added - but its not working as I intended, and throwing me interesting values. In main, I go on to repeat this function 10 times, but it always seems to produce a different error - below I've also pasted some of my results.
Note: I've commented out both algorithms to try this, they're separated by a bit of white space.
Sidenote: I seem to always get FlagSide = 1 (right side) the first time I run the program - any ideas on how to fix this?
Thank you all very much for your help :).
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
int board[10][10];
int AIPieces[11];
int PlayerPieces[11];
int MaxPieces[11];
string PieceNames[11];
//insert stuff for maximum number of things
#define NullSpace -1 // Spaces that pieces can not move to
#define Flag -5
#define Bomb 1
#define EmptySpace 0 //Empty board spaces
void SetMaxPieces()
{
MaxPieces[0] = 1;
MaxPieces[Bomb] = 6;
MaxPieces[2] = 8;
MaxPieces[3] = 5;
MaxPieces[4] = 4;
MaxPieces[5] = 4;
MaxPieces[6] = 4;
MaxPieces[7] = 3;
MaxPieces[8] = 2;
MaxPieces[9] = 1;
MaxPieces[10] = 1;
MaxPieces[11] = 1; //Spy
}
void ResetAIPieces()
{
for (int i = 0; i < 11; i++)
AIPieces[i] = 0;
}
void SetPieceNames()
{
PieceNames[0] = "Flags:";
PieceNames[1] = "Bombs:";
PieceNames[2] = "Twos:";
PieceNames[3] = "Threes:";
PieceNames[4] = "Fours:";
PieceNames[5] = "Fives:";
PieceNames[6] = "Sixes:";
PieceNames[7] = "Sevens:";
PieceNames[8] = "Eights:";
PieceNames[9] = "Nines:";
PieceNames[10] = "Tens:";
PieceNames[11] = "Spies:";
}
void PrintBoard()
{
for (int i=0; i<10; i++)
{
for (int j=0; j<10; j++)
{
cout << board[i][j] << " ";
if (board[i][j] >= 0)
{
cout << " ";
}
}
cout << endl;
}
}
void SetBoardStartingConfig()
{
for (int i=0; i<10; i++)
{
for (int j=0; j<10; j++)
{
board[i][j] = EmptySpace;
}
}
//arrays work in [row] and [column].
//below defines areas that the pieces can not move to.
board[4][2] = NullSpace;
board[4][3] = NullSpace;
board[5][2] = NullSpace;
board[5][3] = NullSpace;
board[4][6] = NullSpace;
board[4][7] = NullSpace;
board[5][6] = NullSpace;
board[5][7] = NullSpace;
int FlagSide = rand() % 2;
if (FlagSide == 0)
{
board[0][0] = Flag;
AIPieces[0]++;
AIPieces[board[2][0] = Bomb]++;
AIPieces[board[1][1] = Bomb]++;
AIPieces[board[0][2] = Bomb]++;
AIPieces[board[1][0] = rand() % 3 + 4]++;
AIPieces[board[0][1] = rand() % 3 + 4]++;
}
else if (FlagSide == 1)
{
board[0][9-0] = Flag;
AIPieces[0]++;
AIPieces[board[2][9-0] = Bomb]++;
AIPieces[board[1][9-1] = Bomb]++;
AIPieces[board[0][9-2] = Bomb]++;
AIPieces[board[1][9-0] = rand() % 3 + 4]++;
AIPieces[board[0][9-1] = rand() % 3 + 4]++;
}
//for (int i =0; i < 4; i++)
// for (int j = 0; j < 10; j++)
// {
// if (board[i][j] == 0)
// {
// int Chosen = rand() % 10+1;
// if (AIPieces[Chosen] < MaxPieces[Chosen])
// {
// board[i][j] = Chosen;
// AIPieces[Chosen]++;
// }
// else
// break;
// }
// else
// break;
// // if (AIPieces[0] < MaxPieces[0] || AIPieces[1] < MaxPieces[1] || AIPieces[2] < MaxPieces[2] || AIPieces[3] < MaxPieces[3] || AIPieces[4] < MaxPieces[4] || AIPieces[5] < MaxPieces[5] || AIPieces[5] < MaxPieces[5] || AIPieces[6] < MaxPieces[6] || AIPieces[7] < MaxPieces[7] || AIPieces[8] < MaxPieces[8] || AIPieces[9] < MaxPieces[9] || AIPieces[10] < MaxPieces[10] || AIPieces[11] < MaxPieces[11])
// //{
// // AIPieces[board[i][j] = rand() % 10+1]++;
// //}
// }
}
int main()
{
SetMaxPieces();
SetPieceNames();
int loop = 0;
do
{
SetBoardStartingConfig();
PrintBoard();
cout << endl;
for (int i = 0; i < 11; i++)
{
cout << PieceNames[i] << AIPieces[i] << endl;
}
cout << endl;
ResetAIPieces();
loop++;
} while (loop <= 10);
system("PAUSE");
}
My Results (They seem to be the same every time I run it using the first algorithm)
1 10 5 9 0 0 0 1 5 -5
3 5 6 6 2 8 2 2 1 6
6 3 8 7 2 5 3 4 3 1
3 2 7 0 0 0 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -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
Flags:1
Bombs:4
Twos:5
Threes:5
Fours:1
Fives:4
Sixes:4
Sevens:2
Eights:2
Nines:1
Tens:1
2 9 10 3 8 0 0 1 4 -5
6 5 4 2 3 4 4 5 1 6
2 2 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -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
Flags:1
Bombs:3
Twos:4
Threes:2
Fours:4
Fives:2
Sixes:2
Sevens:0
Eights:1
Nines:1
Tens:1
8 8 10 4 2 0 0 1 5 -5
9 7 6 1 3 0 0 0 1 6
7 1 3 5 0 0 0 0 0 1
7 6 1 0 0 0 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -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
Flags:1
Bombs:6
Twos:1
Threes:2
Fours:1
Fives:2
Sixes:3
Sevens:3
Eights:2
Nines:1
Tens:1
-5 4 1 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
2 4 9 10 4 5 5 7 1 7
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -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
Flags:1
Bombs:4
Twos:1
Threes:0
Fours:3
Fives:2
Sixes:1
Sevens:2
Eights:0
Nines:1
Tens:1
-5 5 1 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
5 10 7 4 8 9 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -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
Flags:1
Bombs:3
Twos:0
Threes:0
Fours:1
Fives:2
Sixes:1
Sevens:1
Eights:1
Nines:1
Tens:1
-5 6 1 0 0 0 0 0 0 0
4 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
4 6 10 9 5 1 8 7 4 7
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -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
Flags:1
Bombs:4
Twos:0
Threes:0
Fours:3
Fives:1
Sixes:2
Sevens:2
Eights:1
Nines:1
Tens:1
3 1 10 8 4 8 3 1 6 -5
7 1 2 7 6 0 0 0 1 6
6 5 2 3 1 0 0 0 0 1
2 5 7 0 0 0 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -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
Flags:1
Bombs:6
Twos:3
Threes:3
Fours:1
Fives:2
Sixes:4
Sevens:3
Eights:2
Nines:0
Tens:1
8 8 0 0 0 0 0 1 5 -5
4 4 6 10 0 0 0 0 1 6
9 2 0 0 0 0 0 0 0 1
3 7 7 1 4 0 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -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
Flags:1
Bombs:4
Twos:1
Threes:1
Fours:3
Fives:1
Sixes:2
Sevens:2
Eights:2
Nines:1
Tens:1
-5 4 1 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
6 1 10 5 8 9 4 6 2 3
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -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
Flags:1
Bombs:4
Twos:1
Threes:1
Fours:2
Fives:1
Sixes:3
Sevens:0
Eights:1
Nines:1
Tens:1
-5 6 1 0 0 0 0 0 0 0
5 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
5 1 7 2 9 10 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -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
Flags:1
Bombs:4
Twos:1
Threes:0
Fours:0
Fives:2
Sixes:1
Sevens:1
Eights:0
Nines:1
Tens:1
-5 4 1 0 0 0 0 0 0 0
5 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
4 10 9 0 0 0 0 0 0 0
0 0 -1 -1 0 0 -1 -1 0 0
0 0 -1 -1 0 0 -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
Flags:1
Bombs:3
Twos:0
Threes:0
Fours:2
Fives:1
Sixes:0
Sevens:0
Eights:0
Nines:1
Tens:1
Press any key to continue . . .
I'm not really clear what you expect to happen or what is happening, you should try explaining why what you get is wrong, so people don't have to spend ages analysing the code and results. Is the first algorithm working and the second not? Or are both wrong? The changes below will make the program easier to reason about anyway.
Your variable and function naming is a bit unconventional. It's more usual to see variables and functions start with a lowercase letter, and classes start with an uppercase letter. Your program looks as though Everything Is Very Important.
Why are you using macros here?
#define NullSpace -1 // Spaces that pieces can not move to
#define Flag -5
#define Bomb 1
#define EmptySpace 0 //Empty board spaces
In general, macros suck, especially if you don't name them to avoid clashing with other names. The inventor of C++ recommends using ALL_CAPS for macros. Better still, don't use them:
const int NullSpace = -1; // Spaces that pieces can not move to
const int Flag -5;
const int Bomb 1;
const int EmptySpace 0; //Empty board spaces
This is a very tedious way to set arrays:
void SetMaxPieces()
{
MaxPieces[0] = 1;
MaxPieces[Bomb] = 6;
MaxPieces[2] = 8;
...
MaxPieces[10] = 1;
MaxPieces[11] = 1; //Spy
}
Just initialize the array when you define it:
int MaxPieces[11] = {
1, 6, 8, 5, 4, 4, 4, 3, 2, 1, 1, 1
};
string PieceNames[11] = {
"Flags:", "Bombs:", "Twos:", "Threes:", "Fours:", "Fives:", "Sixes:",
"Sevens:", "Eights:", "Nines:", "Tens:", "Spies:"
};
But wait! Now the compiler refuses to compile the program:
game.cc:13:1: error: too many initializers for ‘int [11]’
game.cc:17:1: error: too many initializers for ‘std::string [11] {aka std::basic_string [11]}’
You are setting twelve values in an array of eleven! The compiler didn't complain when you did MaxPieces[11] (but maybe should have done) but it definitely won't let you initialize an array with too many values. Are your arrays supposed have twelve elements? Or are you just filling them wrong?
As a commenter pointed out, you must seed rand() or the pseudo-random number generator always starts in the same initial state and produces the exact same sequence of "random" numbers.
Why are you using do-while in main? do-while is only useful in a few situations, when the condition can't be tested initially (or for some clever hacks to make its block scope act as a single statement in evil macros). In your case the condition is initially true (loop is less than 10) so just use a for or while loop. I would prefer a for because your loop variable doesn't need to exist after the for so you can initialize it there:
for (int loop = 0; loop <= 10; ++loop)
{
SetBoardStartingConfig();
PrintBoard();
cout << '\n';
for (int i = 0; i < 11; i++)
{
cout << PieceNames[i] << AIPieces[i] << '\n';
}
cout << '\n';
ResetAIPieces();
}
cout << flush;
Using endl every time you want a newline is unnecessary, endl adds a newline and flushes the stream, which doesn't need to be done on every line. The code above does it just once after the loop.
Now for the first algorithm:
for (int i =0; i < 4; i++)
for (int j = 0; j < 10; j++)
{
if (board[i][j] == 0)
{
int Chosen = rand() % 10+1;
if (AIPieces[Chosen] < MaxPieces[Chosen])
{
board[i][j] = Chosen;
AIPieces[Chosen]++;
}
else
break;
}
else
break;
Surrounding the first for in braces could help readability too. It would also help to write rand()%10 + 1 rather than the spacing you have above, so that the operator precedence is more obvious, currently it looks like you mean it to be rand() % 11 because you've grouped the addition operands.
Shouldn't the check board[i][j] == 0 be board[i][j] == EmptySpace ? Otherwise what's the point of having that constant?
Do you really want to break there? Doesn't that mean you stop filling a row as soon as you find a non-empty square or run out of a particular kind of piece? If the break should be there, where do they go for the second algo? Your code is impossible to reason about, partly because all the important logic is commented out (that's not a helpful way to read code!) and because of the inconsistent indentation.
Your second algorithm is completely unreadable, do you have a screen wide enough to see that line without wrapping? Even if you do it would be easier to read broken up.
Does the second algo check board[i][j] == EmptySpace? It doesn't seem to, but maybe that's just your formatting.
Also, all those comments make it awkward to switch between implementations to compare the results. If you do this:
for (int i =0; i < 4; i++)
{
for (int j = 0; j < 10; j++)
{
if (board[i][j] == EmptySpace)
{
#if 0
int Chosen = rand()%10 +1;
if (AIPieces[Chosen] < MaxPieces[Chosen])
{
board[i][j] = Chosen;
AIPieces[Chosen]++;
}
else
break;
#else
if (AIPieces[0] < MaxPieces[0]
|| AIPieces[1] < MaxPieces[1]
|| AIPieces[2] < MaxPieces[2]
|| AIPieces[3] < MaxPieces[3]
|| AIPieces[4] < MaxPieces[4]
|| AIPieces[5] < MaxPieces[5]
|| AIPieces[5] < MaxPieces[5]
|| AIPieces[6] < MaxPieces[6]
|| AIPieces[7] < MaxPieces[7]
|| AIPieces[8] < MaxPieces[8]
|| AIPieces[9] < MaxPieces[9]
|| AIPieces[10] < MaxPieces[10]
|| AIPieces[11] < MaxPieces[11])
{
AIPieces[board[i][j] = rand() % 10+1]++;
}
#endif
}
else
break;
}
}
Then you only need to change one character (change #if 0 to #if 1) to switch between them.
Now I can see the second algorithm properly it's obvious that if any pieces remain you will place a piece, but that could place a piece which you've run out of. e.g. if AIPieces[1] < MaxPieces[1] but AIPieces[2] == MaxPieces[2] the condition is true, but then if rand()%10 + 1 returns 2 you put a piece you aren't allowed to place. That means you place too many of some types of piece.
I think Scott has a much better idea, separate the placing of pieces into a function, which will make that loop much easier to read:
for (int i =0; i < 4; i++)
for (int j = 0; j < 10; j++)
AddPiece(rand() % 3 + 4, 1, 0);
Now you could write AddPiece2 and change the call to that to experiment with different implementations. Comparing the two algorithms could help find where it goes wrong.
I'm not sure I'm understanding the question well. But, trying to answer it. Something like this seems to be what you're asking for:
Instead of incrementing AIPieces, you need to first check that the board doesn't already have something on it and that MaxPieces haven't already been used.
AIPieces[board[1][0] = rand() % 3 + 4]++;
So try a function to do this:
void AddPiece(int pieceType, int locationX, int locationY)
{
if( board[locationX][locationY] != 0 )
return; // board already has something here, so don't add.
if( AIPieces[pieceType] >= MaxPieces[pieceType] )
return; // Can't add as all of these pieces have already been used.
board[locationX][locationY] = pieceType;
AIPieces[pieceType]++;
}
And in place of the original line, call the function like this:
AddPiece(rand() % 3 + 4, 1, 0);
Your second algorithm won't work because when you try and add a piece, the if statement checks if any type of piece has been used, instead of just checking the type of piece you're trying to add.