tags:

views:

103

answers:

3

Hi everyone,

I'v been bored so I created a small console minesweeper game and while writting it I had to find the neighbor positions of an element in a size*size matrix which is represented as an vector of elements and one variable which holds the size value. I didn't want to return the actual values of the neighbor elements but their positions so that I could use that as a public function (otherwise the client could see where the mines are at :P).

For example for field eq 0 and size eq 3 the function should return {1, 3, 4}:

1 0 0    0 1 0
0 0 0 => 1 1 0
0 0 0    0 0 0

Well, basicaly it looks like this:

vector<int> adjecantPositions(int field, int size)
{   
    int row = field / size;
    int col = field % size;
    vector<int> result;

    /*
        1 0 0
        1 0 0
        1 0 0
    */    
    if (col > 0)
    {
        result.push_back(calcField(row, col-1, size));

        if (row > 0)    
            result.push_back(calcField(row-1, col-1, size));
        if (row < size - 1)
            result.push_back(calcField(row+1, col-1, size));
    }

    /* 
       0 0 1
       0 0 1
       0 0 1
    */
    if (col < size - 1)
    {
        result.push_back(calcField(row, col+1, size));

        if (row > 0)    
            result.push_back(calcField(row-1, col+1, size));
        if (row < size - 1)
            result.push_back(calcField(row+1, col+1, size));

    }

    /*
        0 1 0
        0 0 0
        0 1 0
    */
    if (row > 0)
        result.push_back(calcField(row-1, col, size));
    if (row < size - 1)
        result.push_back(calcField(row+1, col, size));

    return result;
}

calcField(int, int, int) is just converting coordinates into field number (row*size + col).

This is a fast solution but it's not elegant and I bet there's some better way to do this. Any ideas?

+1  A: 

Yeah, your code is awful. Here's a better attempt (fixed, sorry):

for (int dx=-1; dx<=1; dx++)
  for (int dy=-1; dy<=1; dy++) 
    if (dx || dy){
      int x = row+dx, y=col+dy;
      if (x=>0 && x<size && y>=0 && y<size)
         result.push_back(calcField(x, y, size));
    }
Pavel Shved
This code returns incorrect results but I see that you are traversing the 3x3 matrix formed around the field... I can't understand that I didn't think of this.
schmrz
A: 

Here's the fixed code for Pavel's solution:

for (int drow = -1; drow <= 1; drow++)
{
    int rrow = row + drow;

    for (int dcol = -1; dcol <= 1; dcol++)
    {
        int rcol = col + dcol;

        if (rrow >= 0 && rrow < size && rcol >= 0 && rcol < size 
            && !(rrow == row && rcol == col))
            result.push_back(calcField(rrow, rcol, size));
    }
}
schmrz
+1  A: 

Why don't using an object for your coordinates ? I think this will be more readable:

struct Coords
{
  int row;
  int col;

  Case(row, col) : row(row), col(col) {}
  bool isValid(int size)
  {
    return row >= 0 && col >= 0 && row < size && col < size;
  }
}

vector<Coords> adjecantPositions(const Coords & field, int size)
{
  vector<Coords> result;
  for( int drow = -1; drow <= 1; ++drow )
  {
    for( int dcol = -1; dcol <= 1; ++dcol )
    {
      Coords current(field.row + drow, field.col + dcol);
      if( current.isValid(size) )
      {
        result.push_back(current);
      }
    }
  }
  return result;
}
Jyhess