1

I was doing one problem(Minesweeper) from Steven Skiena(Programming Challenges). Where you have to output the number of mines adjacent to that square.

#include<iostream>
using namespace std;
int main()
{
int n,m;
cin>>m>>n;
char a[m][n];
for(int i=0;i<m;i++)
{
    for (int j = 0; j < n; j++)
    {
        cin>>a[i][j];
    }
}

for (int i = 0; i < m; i++)
{
    for (int j = 0; j < n; j++)
    {
        if(a[i][j]!='*')
        {
            int no=0;
            if(a[i-1][j-1]=='*')
            no++;
            else if(a[i][j-1]=='*')
            no++;
            else if(a[i+1][j-1]=='*')
            no++;
            else if(a[i+1][j]=='*')
            no++;
            else if(a[i+1][j+1]=='*')
            no++;
            else if(a[i][j+1]=='*')
            no++;
            else if(a[i-1][j+1]=='*')
            no++;
            else if(a[i-1][j]=='*')
            no++;
            a[i][j]=(char)no;
        }
    }

}


for(int i=0;i<m;i++)
{
    for (int j=0; j<n; j++)
    {
        cout<<a[i][j];
    }
    cout<<endl;
}


return 0;
}

When I try to run this program, the array where the mines isn't placed are blank. Is it something related to the casting of integer to character?

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
  • Instead of describing the output, please put it in the post – ForceBru May 15 '20 at 19:36
  • Can you provide as text your exact actual output and your exact expected output? Including input you fed to your program. Better yet, consider replacing input operations with hard coded values for your [example] so that the kind people who try to help you don't have to do any more work than is necessary. – JohnFilleau May 15 '20 at 19:36
  • 1
    `a[i][j]=(char)no;` -- That is not how you convert a one-digit `int` into the equivalent `char` representation. Yet again, this is why learning C++ from "competitive programming" sites is a waste of time. – PaulMcKenzie May 15 '20 at 19:37
  • That is a perfectly fine char representation, just not one that reads as a decimal arabic numeral. Hint: look into strings, character binary representations, why '0' != 0, or simply try the magic of adding '0'. – Abel May 15 '20 at 19:52
  • Please be aware that variable-length arrays (`char a[m][n];`) are **not** valid C++. Some compilers allow them because they're part of C99, but not all of them do. https://stackoverflow.com/questions/15013077/arrayn-vs-array10-initializing-array-with-variable-vs-real-number – Spencer May 17 '20 at 16:24

4 Answers4

1

One mistake is this:

a[i][j]=(char)no;

This is not the way you convert a one-digit integer into the char representation.

The correct way is to add '0' to the integer:

a[i][j] = no + '0';

The reason why this works is that the character representation of the number is different than the actual digit value. For example, the ASCII collating sequence uses 48 as the character '0', 49 for '1', 50 for '2', etc.

Thus adding '0', i.e. 48, will give you the character representation of the number.

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
1

You could change your program for example like this:

I changed your array to an int-array and all mines are a -1. So you don't have to mix int-values and char-values in one array. With this you have to handle this in the output with an if-condition.

#include<iostream>
using namespace std;

int main()
{
    int n,m;
    cin>>m>>n;
    char a[m][n];

    for(int i=0;i<m;i++)
    {
        for (int j = 0; j < n; j++)
        {
            char in;
            cin>>in;
            if(in == '*') {
                a[i][j] = -1;
            } else {
                a[i][j] = 0;
            }
        }
    }

    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if(a[i][j]!=-1)
            {
                int no=0;
                if(a[i-1][j-1]==-1)
                no++;
                else if(a[i][j-1]==-1)
                no++;
                else if(a[i+1][j-1]==-1)
                no++;
                else if(a[i+1][j]==-1)
                no++;
                else if(a[i+1][j+1]==-1)
                no++;
                else if(a[i][j+1]==-1)
                no++;
                else if(a[i-1][j+1]==-1)
                no++;
                else if(a[i-1][j]==-1)
                no++;
                a[i][j]=no;
            }
        }

    }


    for(int i=0;i<m;i++)
    {
        for (int j=0; j<n; j++)
        {
            if(a[i][j] == -1) {
                cout<<" * ";
            } else {
                cout<<" "<<a[i][j]<<" ";
            }
        }
        cout<<endl;
    }

    return 0;
}
Tobias
  • 543
  • 1
  • 3
  • 15
1

Since it looks like people are giving men fish, i don't see a reason not to. Change the line of how no starts for a nice solution computationally.

    char no='0';
Abel
  • 111
  • 4
1

I see a few separate issues here that, collectively, are leading to the issue you're running into.

First, as pointed out above, once you've counted the number of mines adjacent to each mine, you're currently storing the result in a way that won't print the way you expect it to. The other answers here have suggested several different ways that you can do this.

Second, your way of counting adjacent mines is (slightly) incorrect. Let's look at this code:

if(a[i-1][j-1]==-1)
   no++;
else if(a[i][j-1]==-1)
   no++;
else if(a[i+1][j-1]==-1)
   no++;
else if(a[i+1][j]==-1)
   no++;
else if(a[i+1][j+1]==-1)
   no++;
else if(a[i][j+1]==-1)
   no++;
else if(a[i-1][j+1]==-1)
   no++;
else if(a[i-1][j]==-1)
   no++;

The pattern here you're using of if / else if / else if / ... means that at most one of these branches will execute. That is, as soon as this code finds a mine, it stops looking at the other locations around the cell for other mines. One way to fix this is to make this not a chain of if / else if, but just a regular chain of ifs:

if(a[i-1][j-1]==-1)
   no++;
if(a[i][j-1]==-1)
   no++;
if(a[i+1][j-1]==-1)
   no++;
if(a[i+1][j]==-1)
   no++;
if(a[i+1][j+1]==-1)
   no++;
if(a[i][j+1]==-1)
   no++;
if(a[i-1][j+1]==-1)
   no++;
if(a[i-1][j]==-1)
   no++;

You may even want to consider changing how you've structured this so that, instead of having a long list of if statements, you use a doubly-nested for loop to enumerate all positions one step away from you. that will condense the code and make it more clearly match the pattern of "for each adjacent location, if it's a mine, count it as such."

Hope this helps!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • It worked, I placed else if instead of using if statements, Thank you. There is one thing, how can I compare all of these adjacent elements of a matrix, without using these multiple if statements? – Himanshu Joshi May 18 '20 at 18:32
  • Try using a double-for loop to enumerate each pair (dx, dy) where dx is one of -1, 0, or +1 and dy is one of -1, 0, or +1. You can then list all those deltas off, skipping delta (0, 0). – templatetypedef May 18 '20 at 18:56
  • Thanks, I'll try implementing this way. – Himanshu Joshi May 19 '20 at 09:16