2
\$\begingroup\$

I got my 1 dimensional program to work just fine so I figured I just need a few tweaks to get the 2D to work as well. It's not fully completed but it would helpful to know if I am on the right track or completely off base with where I am at.

import java.util.Scanner;
import java.util.Random;

public class MS2D 
{
    public static int[][] map = new int[10][10];    // mine field is 10 cells

    public static boolean[][] played = new boolean[10][10]; // played moves

    public static int row_pick;               // row picked to play          
    public static int col_pick;               // column picked to play

    public static int threshold = 6;          // low threshold = more mines

      public static void main(String[] args) 
      {
         int r, c;                               // each 'row' & 'column' in 2-D array
         Scanner kb = new Scanner(System.in);    // keyboard input
         boolean hit, done;

         InitMap();          // get the map randomized
         ShowMap();          // show current map (all hidden)

         while( true ) // play loop starts
         {
            System.out.print("Which row and column to play? ( -1 to quit) ");
            row_pick = kb.nextInt();
            col_pick = kb.nextInt();
            if ((col_pick < 0) || (col_pick > map.length - 1) || (row_pick < 0) 
                || (row_pick > map.length - 1) )
            {
               System.out.println("Thanks for playing!");
               System.exit(0);
            }
            else 
            {
               if (played[row_pick][col_pick])
               {
                  System.out.println("That position has been played!");
                  continue;
               }    


            }   
            hit = false;
            done = false;
            if (map[row_pick][col_pick] == 9)
            {
               hit = true;
            }
            else
            {
               MarkPlayed(row_pick, col_pick);
               done = true;

               for (r = 0; r <= played.length - 1; r++) 
               {
                  for (c = 0; c <=played.length - 1; c++)
                  { 
                     if( played[r][c] == false)
                        done = false;
                  }
               }    
            }
            if (hit || done)
            {
               for(r = 0; r <= played.length - 1; r++)
               {
                  for(c = 0; c <= played.length - 1; c++)
                  {
                     played[r][c] = true;
                  }
               }
            }

            ShowMap();

            if (hit == true)
            {
               System.out.println("Boom! Bye, bye.");
               break;
            }   
            else if (done == true)
            {   
               System.out.println("Good Game!");
               break;      
            }  
         }
      }     
      public static int CountMines( int r, int c ) 
      {
         int count = 0; 
         if (c - 1 >= 0 && c - 1 == 9)
         {
            count++;
         }
         if (map[c + 1] == 9)
         {
            count++;
         }
         return count;

      } // end CountMines()

      public static void InitMap () 
      { // randomize map
         int r, c, num;
         Random rand_obj= new Random();// use Random class to create a rand_obj
         for (r = 0; r < map.length - 1; r++)
         {
            for (c = 0; c < map.length - 1; c++)
            {  
               num = rand_obj.nextInt(10);

               if (num > threshold)
               {
                  map[r][c] = 9;
               }
               else
               {
                  map[r][c] = 0;
               }
            }
         }
         for (r = 0; r < map.length - 1; r++)
         {
            for(c = 0; c < map.length - 1; c++)
            {
               if (map[r][c] == 0)
                  CountMines( r, c);   
            }
         }
      } // end InitMap()

      public static void MarkPlayed(int r, int c ) 
      {
         played[r][c] = true;

         if (r - 1 >= 0 && r - 1 != 9)  it true
         {
            if(c - 1 >= 0 && c - 1 != 9)
            {
               played[r][c] = true;
            }
            if (r + 1 >= 0 && r + 1 != 9)
            {
               if(c + 1 >= 0 && c + 1 != 9)
               {
                  played[r][c] = true;  
               }
            }
         }      
      } // end MarkPlayed()


      public static void ShowMap() 
      {
         int r, c;

         for ( r = 0; r < played.length; r++ )
         {
            for ( c = 0; c < played.length; c++ )
            {
               if ( played[r][c] ) // can show
               {
                  System.out.print( map[r][c] + " " );
               }    
               else 
               {
                  System.out.print(". "); // hidden
               }
            }
         }
         System.out.println();

         for ( c = 0; c < played.length; c++ )
         {  
            System.out.print(c + " ");
         }  
         System.out.println();

      } // end ShowMap ()
} // end class
\$\endgroup\$
1
  • 1
    \$\begingroup\$ If it isn't complete, it doesn't really belong here. However if you could maybe narrow your code to a specific section you'd like reviewed, then maybe we can help you. \$\endgroup\$ – Jeff Mercado Dec 11 '11 at 7:58
3
\$\begingroup\$
  • This solution is not very object oriented. That may be okay if you are a beginner, but if you know how to initialize objects, you should use that knowledge.
  • Method names should be lowercase
  • the Random object should be reused, make it a static member
  • don't write int r, c; at the beginning of the method, just initialize the vars in the loop: for(int c=...
  • learn to use the ternary operator, e.g. map[r][c] = (num > threshold) ? 9 : 0;

And last but not least a common trick for board games: Surround your board with an invisible border of one field (e.g. your 10x10 field would become internally 12x12), which are empty. Don't show them, don't allow the user to access them. Then, if you check the neighborhood of a field for mines, you don't have to check if you are off-limits because you have that safety border, and because these fields are always empty, your count is still correct.

As a starting point, here is how I would start (without any user interaction or game loop, but with calculation and display done):

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class MS2D {

    private static class Field {

        public boolean hidden = true;
        public final boolean mine;
        public int neigbors = 0;

        public Field(boolean mine) {
            this.mine = mine;
        }
    }
    private final int size;
    private Field[][] board;

    private MS2D(int size, int numberOfMines) {
        this.size = size;
        initBord(numberOfMines);
        calculateNeighbors();
        showBoard();
    }

    private void initBord(int numberOfMines) {
        List<Field> mines = new ArrayList<Field>();
        for (int i = 0; i < size * size; i++) {
            mines.add(new Field(i < numberOfMines));
        }
        Collections.shuffle(mines);
        board = new Field[size + 2][size + 2];
        for (int i = 0; i < size + 2; i++) {
            for (int j = 0; j < size + 2; j++) {
                board[i][j] = (i == 0 || j == 0 || i == size + 1 || j == size + 1)
                        ? new Field(false)
                        : mines.remove(0);
            }
        }
    }

    private void calculateNeighbors() {
        for (int i = 1; i <= size; i++) {
            for (int j = 1; j <= size; j++) {
                int count = 0;
                for (int di = -1; di <= 1; di++) {
                    for (int dj = -1; dj <= 1; dj++) {
                       if (board[i + di][j + dj].mine) count++;  
                    }
                }
                board[i][j].neigbors = count;
            }
        }
    }

    private void showBoard() {
        for(int i = 1; i <= size; i++) {
            System.out.printf("%2d| ",i);
           for(int j = 1; j <= size; j++) {
               Field f = board[i][j];
               if(f.hidden) {
                   System.out.print(". ");
               }  else if (f.mine) {
                   System.out.print("* ");
               } else {
                   System.out.print(f.neigbors + " ");
               }
           }          
           System.out.println();
        }
        System.out.print("    ");
        for(int i = 1; i <= size; i++) {
            System.out.print(i / 10 + " ");
        }
        System.out.print("\n    ");
        for(int i = 1; i <= size; i++) {
            System.out.print(i % 10 + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        new MS2D(15, 15);
    }
}

Note that for a real world application this approach is still not "OO" enough, as there is a tight coupling between the model and the user interface. Ideally you would factor out all user interactions in a separate class, which would simplify later refactoring (e.g. using Swing instead console). However, I felt that for that small example this would be probably overkill.

\$\endgroup\$
2
  • \$\begingroup\$ Thank you for the feedback. I am a beginner at this and any sort of tips and tricks I can learn is much appreciated. \$\endgroup\$ – user1090787 Dec 13 '11 at 3:29
  • \$\begingroup\$ Man, I don't know what it is, but I really love the look of that piece of code. You just gave Eye Candy a new meaning. <3 \$\endgroup\$ – Zolomon Dec 16 '11 at 20:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.