patternjavaMinor
Text based 2D Minesweeper
Viewed 0 times
minesweepertextbased
Problem
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 map.length - 1) || (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 = 0 && c - 1 == 9)
```
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 map.length - 1) || (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 = 0 && c - 1 == 9)
Solution
- 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 mines = new ArrayList();
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.
Code Snippets
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);
}
}Context
StackExchange Code Review Q#6709, answer score: 4
Revisions (0)
No revisions yet.