Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am creating a Minesweeper game. However, while testing the generating function, It malfunctions almost always (if not always), and I do not understand why.
Here is my code:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
struct board {
int width=9, mines=10;
char board[9][9];
/* char board[][]
* -1 = Mine
* 0 = No mines near
* 0+ = x amount of mines are near
*/
};
struct point {
int x,y;
};
board newBoard(){
board board1;
point randPoint;
for(int i=0;i<board1.width;i++){
for(int j=0;j<board1.width;j++) board1.board[i][j]=0; // Initialize array
}
for(int i=0;i<board1.mines;i++){
randPoint.x=rand()%board1.width, randPoint.y=rand()%board1.width; // Where will the mine go?
if(board1.board[randPoint.x][randPoint.y]!=-1){ // If not already a mine
board1.board[randPoint.x][randPoint.y]=-1; //make a mine
} else i--; //else don't count this
}
for(int i=0;i<board1.width;i++){
for(int j=0;j<board1.width;j++){
if(board1.board[i][j]==-1) { // If mine exists
// The if checks preceding the ++'s are to prevent out of bounds erors
if (j-1>=0) board1.board[i][j-1]++;
if (j+1<board1.width) board1.board[i][j+1]++;
if (i-1>=0) board1.board[i-1][j]++;
if (i+1<board1.width) board1.board[i+1][j]++;
if ((i-1>=0) && (j-1>=0)) board1.board[i-1][j-1]++;
if ((i-1>=0) && (j+1<board1.width))board1.board[i-1][j+1]++;
if ((i+1<board1.width) && (j-1>=0))board1.board[i+1][j-1]++;
if ((i+1<board1.width) && (j+1<board1.width))board1.board[i+1][j+1]++;
}
}
}
return board1;
}
int main() {
board boardGame=newBoard();
printf("- ");
for(int i=0;i<boardGame.width;i++) printf("%i ",i+1);
printf("\n\n");
for(int i=0;i<boardGame.width;i++){
printf("%i. ",i+1);
for(int j=0;j<boardGame.width;j++) if (boardGame.board[i][j]==-1) {
printf(" X");
} else {
printf(" %i", boardGame.board[i][j]);
}
printf("\n");
}
return 0;
}
This produces:
- 1 2 3 4 5 6 7 8 9
1. 0 0 0 0 1 X 1 0 0
2. 1 1 0 0 2 2 2 1 1
3. X 2 1 1 1 X 1 1 X
4. 1 2 X 0 1 1 0 1 1
5. 0 1 1 1 0 0 0 0 0
6. 0 0 0 0 1 1 1 0 0
7. 0 0 1 1 2 X 1 0 0
8. 1 1 2 X 2 1 1 0 0
9. 1 X 2 1 1 0 0 0 0
As you most likely already know, in the game of minesweeper, there is mines (in this case will they will be marked as X), and all nearby grid points are the number of mines near it (if you are still unfamiliar with it this page may of use). As you can see, the numbers at 4,7 and 4,4 are incorrect.
I do not know why this is this way. Could someone aid my understanding in this, and tell my how to to fix this?
Also, I just noticed that this produces the same output every time it is run. Why?
Ioums is correct, you are not checking to see if a cell is a mine before incrementing it. However, with the way that your code is currently set up, this will mean adding a check that the cell does not equal -1 in every single if statement. You should consider creating a function to safely increment a cell if it is within bounds and not a mine, like so:
void safeIncrement(int x, int y, board& b)
{
if(x >= 0 && y >= 0 && x < b.width && y < b.width && b.board[x][y] != -1)
{
b.board[x][y]++;
}
}
This means that you can replace your if statements with:
safeIncrement(i-1,j,board1);
safeIncrement(i-1,j-1,board1);
safeIncrement(i-1,j+1,board1);
safeIncrement(i,j-1,board1);
safeIncrement(i,j+1,board1);
safeIncrement(i+1,j,board1);
safeIncrement(i+1,j-1,board1);
safeIncrement(i+1,j+1,board1);
Which is much more readable in my opinion. Additionally, since the function doesn't increment the cell if it is a mine, you could also replace the if statements with the following code!
for(int a=-1; a<=1; a++)
{
for(int b=-1; b<=1; b++)
{
safeIncrement(i+a,j+b, board1);
}
}
The problem happens when 2 mines are close together: when you're adding to the mine count, you don't check if that square has a mine.
Suppose you get a mine on (0, 0) and another on (0, 1). When you're adding to the mine count around (0, 0), you accidentally also add to the mine in (0, 1), changing it from -1 to 0. It also makes the second mine being processed disappear.
I suggest using another number to signal a mine, like -999, and check if the number is negative when looking for them. It's easier than adding another condition for all if clauses you already have.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I tried writing a program that outputs "YES" whether every x value or y value is all the same. Otherwise it gives the output "NO". The logic is, if all the x values maximum value is the same as the all the x values minimum value, than this value has never changed, hence all the x values are the same. Same for the y values.
However, the output sometimes give the correct result, sometimes not (for the same input). Moreover, the outputs are not regular. (For example, 2 correct, 3 wrong, 5 correct, 1 wrong etc.)
Here is my code:
#include <iostream>
#include <climits>
using namespace std;
int main(){
int n;
int minX,minY=INT_MAX;
int maxX,maxY=INT_MIN;
cin>>n;
while(n--){ //for the next n line
int x,y;
cin>>x>>y;
maxX=max(maxX,x);
//cout<<maxX<<" "; //comments I write to find out what the heck is happening
minX=min(minX,x); // This value changes irregularly, which I suspect is the problem.
//cout<<minX<<" ";
maxY=max(maxY,y);
//cout<<maxY<<" ";
minY=min(minY,y);
//cout<<minY<<endl;
}
if(maxX==minX||maxY==minY){ //If the x values or the y values are all the same, true
cout<<"YES";
}
else{
cout<<"NO";
}
return 0;
}
Input:
5
0 1
0 2
0 3
0 4
0 5
Output when it Works (with the couts I commented):
0 0 1 1
0 0 2 1
0 0 3 1
0 0 4 1
0 0 5 1
YES
One of the output when it doesn't work(with the couts I commented)
0 -1319458864 1 1 // Not all the wrong outputs are the same, each wrong output is different than the other wrong output.
0 -1319458864 2 1
0 -1319458864 3 1
0 -1319458864 4 1
0 -1319458864 5 1
NO
In these lines
int minX,minY=INT_MAX;
int maxX,maxY=INT_MIN;
^
minX and maxX is never initialized. This is an UB as defined by the standard. Whatever you read is not predictable - it's usually what'l left on that block of memory by another process.
Do note that = has a higher priority than comma, so the expression is evaluated as
int (minX),(minY=INT_MAX);
Actually the comma has the lowest priority among all operators in C++. Change them to these should fix
int minX=INT_MAX,minY=INT_MAX;
int maxX=INT_MIN,maxY=INT_MIN;
^~~~~~~
I have been stuck with this problem for two days and I still can't get it right.
Basically, I have a 2D array with relations between certain numbers (in given range):
0 = the order doesn't matter
1 = the first number (number in left column) should be first
2 = the second number (number in upper row) should be first
So, I have some 2D array, for example this:
0 1 2 3 4 5 6
0 0 0 1 0 0 0 2
1 0 0 2 0 0 0 0
2 2 1 0 0 1 0 0
3 0 0 0 0 0 0 0
4 0 0 2 0 0 0 0
5 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0
And my goal is to create a new array of given numbers (0 - 6) in such a way that it is following the rules from the 2D array (e.g. 0 is before 2 but it is after 6). I probably also have to check if such array exists and then create the array. And get something like this:
6 0 2 1 4 5
My Code
(It doesn't really matter, but I prefer c++)
So far I tried to start with ordered array 0123456 and then swap elements according to the table (but that obviously can't work). I also tried inserting the number in front of the other number according to the table, but it doesn't seem to work either.
// My code example
// I have:
// relArr[n][n] - array of relations
// resArr = {1, 2, ... , n} - result array
for (int i = 0; i < n; i++) {
for (int x = 0; x < n; x++) {
if (relArr[i][x] == 1) {
// Finding indexes of first (i) and second (x) number
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
// Placing the (i) before (x) and shifting array
int tmp, insert = iX+1;
if (iX < iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert < iI+1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert++;
}
}
} else if (relArr[i][x] == 2) {
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
int tmp, insert = iX-1;
if (iX > iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert > iI-1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert--;
}
}
}
}
}
I probably miss correct way how to check whether or not it is possible to create the array. Feel free to use vectors if you prefer them.
Thanks in advance for your help.
You seem to be re-ordering the output at the same time as you're reading the input. I think you should parse the input into a set of rules, process the rules a bit, then re-order the output at the end.
What are the constraints of the problem? If the input says that 0 goes before 1:
| 0 1
--+----
0 | 1
1 |
does it also guarantee that it will say that 1 comes after 0?
| 0 1
--+----
0 |
1 | 2
If so you can forget about the 2s and look only at the 1s:
| 0 1 2 3 4 5 6
--+--------------
0 | 1
1 |
2 | 1 1
3 |
4 |
5 |
6 | 1
From reading the input I would store a list of rules. I'd use std::vector<std::pair<int,int>> for this. It has the nice feature that yourPair.first comes before yourPair.second :)
0 before 2
2 before 1
2 before 4
6 before 0
You can discard any rules where the second value is never the first value of a different rule.
0 before 2
6 before 0
This list would then need to be sorted so that "... before x" and "x before ..." are guaranteed to be in that order.
6 before 0
0 before 2
Then move 6, 0, and 2 to the front of the list 0123456, giving you 6021345.
Does that help?
Thanks for the suggestion.
As suggested, only ones 1 are important in 2D array. I used them to create vector of directed edges and then I implemented Topological Sort. I decide to use this Topological Sorting Algorithm. It is basically Topological Sort, but it also checks for the cycle.
This successfully solved my problem.
So, my program is supposed to receive test inputs like:
3
1 0 1
0 1 1
1 0 1
5
1 1 1 0 0
1 1 0 1 1
1 0 1 0 1
0 1 0 1 0
0 1 1 1 1
3
1 0 0
0 1 0
0 0 1
2
1 1
1 1
0
where the single-valued lines (n) are the size of a NxN matrix located in the following n entries like shown above. If n = 0, the program stops. The output must be the biggest sum amongst the columns of the matrix. So I expect outputs like this:
3
4
1
2
After a lot of effort and wasted time, I managed to get the first output correctly, but I noticed the following ones sometimes summed up and suggested some variable was not being reset. Here's my code:
#include <iostream>
using namespace std;
int pop = 0;
int main() {
int n, i, j, k;
cin >> n;
while (n!=0) {
int alunos[n]={0};
pop = 0;
for (i=0;i<n;i++) {
int array[n]={0};
for (j=0;j<n;j++) {
cin >> array[j];
if (array[j]==1) alunos[j]++;
}
}
for (k=0;k<n;k++) {
if(alunos[k]>pop) pop = alunos[k];
}
cout << pop << endl;
cin >> n;
}
return 0;
}
Noticed that I'm outputting pop(the biggest sum) and resetting it to 0 everytime a new n is given. alunos[n] is an array with the sums of each column (also resetted on every while loop) and array[n] is just an auxiliary array for reading each line of input. My outputs with this are:
3
5
6
8
Thanks in advance!
You cannot use initializers with variable length arrays. Either switch to some sort of container:
std::vector<int> alunos(n);
or fill the array with zeros manually:
int alunos[n];
std::fill(alunos, alunos+n, 0);
Also, ignoring errors is unhealthy. Don't do it.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I am trying to recreate the game 2048 in C++.
I'm working on a spawn function right now. It takes in an array of the current values of the 16 spots, randomly scans for an empty one, and puts either a 2 or a 4 in that spot.
I am starting out with a test array, b. I want to pass this array to a function that will alter one of its values, which I know I need to do by passing a pointer, but none of the changes are staying after I leave the function.
Can anyone see what is wrong here? How do I properly pass the array in so the changes will stay after the spawn function?
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
void showBoard(int board[]);
void spawn(int* board);
int main() {
srand(time(NULL));
int b[16] = {2, 2, 2, 2};
int* bp = b;
showBoard(b);
spawn(bp);
showBoard(b);
}
// print out the 16 current tiles to the console
void showBoard(int board[]) {
for(int i=0; i<=15; ++i){
if(i%4==0)
cout<<'\n';
cout<<board[i]<<" ";
}
cout<<'\n';
}
void spawn(int* board) {
int x; // index
// randomly choose an index to spawn a 2 or 4:
do x=rand()%16; while(board[x]!=0);
// when found empty place (with value 0), spawn a new tile.
/* there should be a 90% chance of spawning a 2
* and a 10% chance of spawning a 4. Generate a
* random number between 0 and 9, and if it is
* 9, make the new spawn tile a 4.
*/
if (rand()%10 == 9) {
board[x] == 4;
cout << "added 4 \n";
}
else {
board[x] == 2;
cout << "added 2 \n";
}
}
The output:
2 2 2 2
0 0 0 0
0 0 0 0
0 0 0 0
added 2
2 2 2 2
0 0 0 0
0 0 0 0
0 0 0 0
So my cout confirms that I got to the if block where I would set board[x] to 2, but when I do showBoard afterwards, there is no update to the array. Any help?
board[x] == 2;
board[x] == 4;
Need to be:
board[x] = 2;
board[x] = 4;
Also, it may make the code simpler if you make this a 2D 4x4 array. Picking a random square would then become:
int x = rand() % 16;
int board_spot = board[x%4][x/4];
When the following program is fead the following input (reading from cin):
1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1
The output is surprising:
1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1
#include<iostream>
using namespace std;
int main()
{
int arey[3][3];
int i,j;
for(j=0;j<=3;j++)
{
for(i=0;i<=3;i++)
{
cin>>arey[j][i];
}
}
arey[0][0]=1;
arey[3][3]=1;
i=0,j=0;
for(j=0;j<=3;j++)
{
for(i=0;i<=3;i++)
{
cout<<arey[j][i];
}
}
return 0;
}
Can someone explain what I should change to get the same output as the input?
Is the matrix 3x3 or 4x4?
you created 3x3 but the loops run for 4 elements and you also update [3][3]
Basically your indexes overflow and you overwrite a different cell in the matrix.
Update: cheecked your input, use: int arey[4][4];
Arrays use 0 based indices, so the valid range of indices for your
int arey[3][3];
are 0 <= i < 3 and 0 <= j < 3
So you need to change the condition in your for loops to be strictly < instead of <=
I really don't think I understand your question, but this is wrong:
int arey[3][3];
...
for(j=0;j<=3;j++) // <= invalid
...
array[3][3]=1; // out of bounds
arey is a 3*3 array. You can't access arey[3][?], that's out of bounds. The only valid indices are 0..2.
Once you've written past the bounds of your array, your program behavior becomes undefined.