You can set any size of the field and any number of bombs. I think I got a pretty flexible program again(Tic tac toe game for the console). What do you think about the code? I would like to know if I made mistakes in program design.
skeleton:
public class Minesweeper {
public static void play(){
final int HOWMANYBOMBS;
boolean isItWin;
Area[][] area;
final Scanner SCANNER = new Scanner(System.in);
final String greeting = "Hi, lets play minesweeper!";
System.out.println(greeting);
area = pickLengthsOfArea(SCANNER);
HOWMANYBOMBS = getHowManyBombs(area,SCANNER);
System.out.println("hi");
fillArea(area,HOWMANYBOMBS);
while(true) {
printPole(area);
if(playerTurnsAndIsPlayersTurnInBomb(area,SCANNER)) {
isItWin=false;
break;
}
if(weHaveNotGotAnyEmptyAreaThatNotCheckedAndWeMarkedOnlyBombs(area)) {
isItWin=true;
break;
}
}
if(isItWin) {
System.out.println("U won!");
}
else {
System.out.println("Defieat!");
}
}
private static boolean weHaveNotGotAnyEmptyAreaThatNotCheckedAndWeMarkedOnlyBombs(Area[][] area) {}
private static boolean playerTurnsAndIsPlayersTurnInBomb(Area[][] area,Scanner scanner) {}
private static void openAllAround(int x, int y, Area[][] area,ArrayList<AreaWithXandY> weOpenedThese) { // do you know another implementation?
AreaWithXandY[] areasAround = getAllAreasAroundWithTheirXandY(area,x,y);
for(AreaWithXandY a:areasAround) {
if(!weOpenedThese.contains(a)) {
a.getArea().setStatusOfArea(StatusOfArea.OPENED);
weOpenedThese.add(a);
if(a.getArea().getValueOfArea()==ValueOfArea.NOONEBOMBAROUND) {
openAllAround(a.getX(),a.getY(),area,weOpenedThese);
}
}
}
}
private static void printPole(Area[][] area) {}
private static void fillArea(Area[][] area, int howManyBombs) {
fillAreaWithBombs(area,howManyBombs);
fillAreaWithEmptyArea(area);
}
private static void fillAreaWithEmptyArea(Area[][] area) {}
private static Area[] getAllAreasAround(Area[][] area,int x,int y) {}
private static AreaWithXandY[] getAllAreasAroundWithTheirXandY(Area[][] area,int x,int y) {}
private static void fillAreaWithBombs(Area[][] area, int howManyBombs) {}
private static int getHowManyBombs(Area[][] area, Scanner scanner) {}
private static Area[][] pickLengthsOfArea(Scanner scanner) {}
private static boolean isXandYIn(int turnX,int turnY, Area[][] area) {}
public static boolean isNumeric(String strNum) {}
}
class Area{
private final ValueOfArea valueOfArea;
private StatusOfArea statusOfArea;
{
statusOfArea = StatusOfArea.CLOSED;
}
Area(ValueOfArea valueOfArea){
this.valueOfArea = valueOfArea;
}
ValueOfArea getValueOfArea() {
return valueOfArea;
}
StatusOfArea getStatusOfArea() {
return statusOfArea;
}
void setStatusOfArea(StatusOfArea statusOfArea) {
this.statusOfArea = statusOfArea;
}
}
class AreaWithXandY{
private int x,y;
Area area;
AreaWithXandY(int x,int y,Area area){
this.area = area;
this.x = x;
this.y = y;
}
int getX() {
return x;
}
int getY() {
return y;
}
Area getArea() {
return area;
}
@Override
public boolean equals(Object obj) {
if(obj==null) {
return false;
}
if(false==(obj instanceof AreaWithXandY)) {
return false;
}
AreaWithXandY object = (AreaWithXandY) obj;
if(object.getX()==x && object.getY()==y) { //its enouth
return true;
}
else {
return false;
}
}
}
enum StatusOfArea{
MARKEDASBOMB,OPENED,CLOSED
}
enum ValueOfArea{
BOMB("@"),
NOONEBOMBAROUND("0"),ONEBOMBAROUND("1"),TWOBOMBAROUND("2"),TREEBOMBAROUND("3"),FOURBOMBAROUND("4"),FIVEBOMBAROUND("5"),SIXBOMBAROUND("6"),SEVENBOMBAROUND("7"),EIGHTBOMBAROUND("8");
private String icon;
ValueOfArea(String icon){
this.icon = icon;
}
String getIcon() {
return icon;
}
static ValueOfArea getValueOfAreaByString(String value) {
ValueOfArea[] values = ValueOfArea.values();
for(int i=0;i<values.length;i++) {
if(values[i].getIcon().equals(value)) {
return values[i];
}
}
System.err.println("ERROR in getValueOfAreaByString(String value), we could not find this value");
return null;
}
}
fullcode:
public class Minesweeper {
public static void play(){
final int HOWMANYBOMBS;
boolean isItWin;
Area[][] area;
final Scanner SCANNER = new Scanner(System.in);
final String greeting = "Hi, lets play minesweeper!";
System.out.println(greeting);
area = pickLengthsOfArea(SCANNER);
HOWMANYBOMBS = getHowManyBombs(area,SCANNER);
System.out.println("hi");
fillArea(area,HOWMANYBOMBS);
while(true) {
printPole(area);
if(playerTurnsAndIsPlayersTurnInBomb(area,SCANNER)) {
isItWin=false;
break;
}
if(weHaveNotGotAnyEmptyAreaThatNotCheckedAndWeMarkedOnlyBombs(area)) {
isItWin=true;
break;
}
}
if(isItWin) {
System.out.println("U won!");
}
else {
System.out.println("Defieat!");
}
}
private static boolean weHaveNotGotAnyEmptyAreaThatNotCheckedAndWeMarkedOnlyBombs(Area[][] area) {
for(int y = 0;y<area.length;y++) {
for(int x = 0;x<area[0].length;x++) {
if(area[y][x].getValueOfArea()!=ValueOfArea.BOMB/*is not bomb*/ && (area[y][x].getStatusOfArea()==StatusOfArea.CLOSED || area[y][x].getStatusOfArea()==StatusOfArea.MARKEDASBOMB) ) {
return false;
}
}
}
return true;
}
private static boolean playerTurnsAndIsPlayersTurnInBomb(Area[][] area,Scanner scanner) {
while(true) {
System.out.println("Print \"open x y\", if u want open this area, print \"mark x y\", if u want mark this area as bomb or unmark this area");
String[] commandAndXAndY = scanner.nextLine().split(" ");
if(commandAndXAndY.length!=3) {
System.out.println("fill out the form correctly!");
}
else if(!commandAndXAndY[0].equals("open") && !commandAndXAndY[0].equals("mark")) {
System.out.println("first work should be equal \"open\" or \"mark\"!");
}
else if(!isNumeric(commandAndXAndY[1]) || !isNumeric(commandAndXAndY[2])) {
System.out.println("x and y should be numbers!");
}
else if(!isXandYIn(Integer.parseInt(commandAndXAndY[1]),Integer.parseInt(commandAndXAndY[2]),area)) {
System.out.println("x and y should be in area! P.S.: area.lengthY="+area.length+", area.lengthX="+area[0].length);
}
else {
int y = Integer.parseInt(commandAndXAndY[2]),x = Integer.parseInt(commandAndXAndY[1]);
if(commandAndXAndY[0].equals("open")) {
if(area[y][x].getValueOfArea()==ValueOfArea.BOMB) {
return true;
}
else {
area[y][x].setStatusOfArea(StatusOfArea.OPENED);
if(area[y][x].getValueOfArea()==ValueOfArea.NOONEBOMBAROUND) {
openAllAround(x,y,area, new ArrayList<>());
}
return false;
}
}
else { // mark
area[y][x].setStatusOfArea(StatusOfArea.MARKEDASBOMB);
return false;
}
}
}
}
private static void openAllAround(int x, int y, Area[][] area,ArrayList<AreaWithXandY> weOpenedThese) {
AreaWithXandY[] areasAround = getAllAreasAroundWithTheirXandY(area,x,y);
for(AreaWithXandY a:areasAround) {
if(!weOpenedThese.contains(a)) {
a.getArea().setStatusOfArea(StatusOfArea.OPENED);
weOpenedThese.add(a);
if(a.getArea().getValueOfArea()==ValueOfArea.NOONEBOMBAROUND) {
openAllAround(a.getX(),a.getY(),area,weOpenedThese);
}
}
}
}
private static void printPole(Area[][] area) {
System.out.println();
for(int y = 0;y<area.length;y++) {
for(int x=0;x<area[0].length;x++) {
if(area[y][x].getStatusOfArea()==StatusOfArea.CLOSED) {
System.out.print("?");
}
else if(area[y][x].getStatusOfArea()==StatusOfArea.OPENED) {
System.out.print(area[y][x].getValueOfArea().getIcon());
}
else if(area[y][x].getStatusOfArea()==StatusOfArea.MARKEDASBOMB) {
System.out.print("*");
}
}
System.out.println();
}
}
private static void fillArea(Area[][] area, int howManyBombs) {
fillAreaWithBombs(area,howManyBombs);
fillAreaWithEmptyArea(area);
}
private static void fillAreaWithEmptyArea(Area[][] area) {
for(int y = 0;y<area.length;y++) {
for(int x=0;x<area[0].length;x++) {
if(area[y][x] == null) {
int howManyBombsAround=0;
Area[] areasAround = getAllAreasAround(area,x,y);
for(Area a:areasAround) {
if(a!=null && a.getValueOfArea()==ValueOfArea.BOMB) {
howManyBombsAround++;
}
}
area[y][x] = new Area(ValueOfArea.getValueOfAreaByString(Integer.toString(howManyBombsAround)));
}
}
}
}
private static Area[] getAllAreasAround(Area[][] area,int x,int y) {
Area[] areasAround = new Area[8];
int i=0;
if(y!=0 && x!=0) { //left up
areasAround[i] = area[y-1][x-1];
i++;
}
if(y!=0) { // up
areasAround[i] = area[y-1][x];
i++;
}
if(x!=area[0].length-1 && y!=0) { //right up
areasAround[i] = area[y-1][x+1];
i++;
}
if(x!=0) { // left
areasAround[i] = area[y][x-1];
i++;
}
if(x!=area[0].length-1) { //right
areasAround[i] = area[y][x+1];
i++;
}
if(x!=0 && y!=area.length-1) { // left down
areasAround[i] = area[y+1][x-1];
i++;
}
if(y!= area.length-1) { //down
areasAround[i] = area[y+1][x];
i++;
}
if(x!=area[0].length-1 && y!=area.length-1) { // right down
areasAround[i] = area[y+1][x+1];
i++;
}
Area[] areasAroundWhithoutNullObjects = new Area[i];
for(int b = 0;b<i;b++) {
areasAroundWhithoutNullObjects[b] = areasAround[b];
}
return areasAroundWhithoutNullObjects;
}
private static AreaWithXandY[] getAllAreasAroundWithTheirXandY(Area[][] area,int x,int y) {
AreaWithXandY[] areasAroundWithXandY = new AreaWithXandY[8];
int i=0;
if(y!=0 && x!=0) { //left up
areasAroundWithXandY[i] = new AreaWithXandY(x-1,y-1,area[y-1][x-1]);
i++;
}
if(y!=0) { // up
areasAroundWithXandY[i] = new AreaWithXandY(x,y-1,area[y-1][x]);
i++;
}
if(x!=area[0].length-1 && y!=0) { //right up
areasAroundWithXandY[i] = new AreaWithXandY(x+1,y-1,area[y-1][x+1]);
i++;
}
if(x!=0) { // left
areasAroundWithXandY[i] = new AreaWithXandY(x-1,y,area[y][x-1]);
i++;
}
if(x!=area[0].length-1) { //right
areasAroundWithXandY[i] = new AreaWithXandY(x+1,y,area[y][x+1]);
i++;
}
if(x!=0 && y!=area.length-1) { // left down
areasAroundWithXandY[i] = new AreaWithXandY(x-1,y+1,area[y+1][x-1]);
i++;
}
if(y!= area.length-1) { //down
areasAroundWithXandY[i] = new AreaWithXandY(x,y+1,area[y+1][x]);
i++;
}
if(x!=area[0].length-1 && y!=area.length-1) { // right down
areasAroundWithXandY[i] = new AreaWithXandY(x+1,y+1,area[y+1][x+1]);
i++;
}
AreaWithXandY[] areasAroundWithXandYWhithoutNullObjects = new AreaWithXandY[i];
for(int b = 0;b<i;b++) {
areasAroundWithXandYWhithoutNullObjects[b] = areasAroundWithXandY[b];
}
return areasAroundWithXandYWhithoutNullObjects;
}
private static void fillAreaWithBombs(Area[][] area, int howManyBombs) {
ArrayList<Integer> listOfAllNumbers = new ArrayList<>(area.length*area[0].length);
for(int i=0;i<area.length*area[0].length;i++) {
listOfAllNumbers.add(i,i);
}
int tempId,y,x;
for(int i=0;i<howManyBombs;i++) {
tempId = listOfAllNumbers.get((int) (Math.random()*listOfAllNumbers.size()));
listOfAllNumbers.remove(new Integer(tempId));
y = ((int)tempId/area[0].length);
x = tempId%area[0].length;
area[y][x] = new Area(ValueOfArea.BOMB);
}
}
private static int getHowManyBombs(Area[][] area, Scanner scanner) {
while(true) {
System.out.println("print number of bombs: ");
String howManyBombsString = scanner.nextLine();
if(!isNumeric(howManyBombsString)) {
System.out.println("it should be number!");
}
else if(false==(0<Integer.parseInt(howManyBombsString) && Integer.parseInt(howManyBombsString)<area.length*area[0].length)) {
System.out.println("it should be positive and it should not exceed the field capacity!");
}
else {
return Integer.parseInt(howManyBombsString);
}
}
}
private static Area[][] pickLengthsOfArea(Scanner scanner) {
String[] turnXandY;
while(true) {
System.out.println("Pick x.length and y.length of area(print \"x y\"): ");
turnXandY = scanner.nextLine().split(" ");
if(turnXandY.length != 2) {
System.out.println("print: \"x y\"!");
}
else if(!isNumeric(turnXandY[0]) || !isNumeric(turnXandY[1])) {
System.out.println("x and y should be numbers!");
}
else if(Integer.parseInt(turnXandY[0]) <= 0 || Integer.parseInt(turnXandY[1]) <= 0) {
System.out.println("x and y should be >0!");
}
else {
return new Area[Integer.parseInt(turnXandY[0])][Integer.parseInt(turnXandY[1])];
}
}
}
private static boolean isXandYIn(int turnX,int turnY, Area[][] area) {
if(turnX<0 || area[0].length<=turnX) {
return false;
}
if(turnY<0 || area.length<=turnY) {
return false;
}
return true;
}
public static boolean isNumeric(String strNum) {
try {
Integer.parseInt(strNum);
} catch (NumberFormatException | NullPointerException nfe) {
return false;
}
return true;
}
}
class Area{
private final ValueOfArea valueOfArea;
private StatusOfArea statusOfArea;
{
statusOfArea = StatusOfArea.CLOSED;
}
Area(ValueOfArea valueOfArea){
this.valueOfArea = valueOfArea;
}
ValueOfArea getValueOfArea() {
return valueOfArea;
}
StatusOfArea getStatusOfArea() {
return statusOfArea;
}
void setStatusOfArea(StatusOfArea statusOfArea) {
this.statusOfArea = statusOfArea;
}
}
class AreaWithXandY{
private int x,y;
Area area;
AreaWithXandY(int x,int y,Area area){
this.area = area;
this.x = x;
this.y = y;
}
int getX() {
return x;
}
int getY() {
return y;
}
Area getArea() {
return area;
}
@Override
public boolean equals(Object obj) {
if(obj==null) {
return false;
}
if(false==(obj instanceof AreaWithXandY)) {
return false;
}
AreaWithXandY object = (AreaWithXandY) obj;
if(object.getX()==x && object.getY()==y) { //its enouth
return true;
}
else {
return false;
}
}
}
enum StatusOfArea{
MARKEDASBOMB,OPENED,CLOSED
}
enum ValueOfArea{
BOMB("@"),
NOONEBOMBAROUND("0"),ONEBOMBAROUND("1"),TWOBOMBAROUND("2"),TREEBOMBAROUND("3"),FOURBOMBAROUND("4"),FIVEBOMBAROUND("5"),SIXBOMBAROUND("6"),SEVENBOMBAROUND("7"),EIGHTBOMBAROUND("8");
private String icon;
ValueOfArea(String icon){
this.icon = icon;
}
String getIcon() {
return icon;
}
static ValueOfArea getValueOfAreaByString(String value) {
ValueOfArea[] values = ValueOfArea.values();
for(int i=0;i<values.length;i++) {
if(values[i].getIcon().equals(value)) {
return values[i];
}
}
System.err.println("ERROR in getValueOfAreaByString(String value), we could not find this value");
return null;
}
}
playerTurnsAndIsPlayersTurnInBomb
which could also be split in two methods - one to check if user input was valid, the other to make the actual move. Also - you passArea[][]
around a lot. If you wrapped it in a class and exposed some methods the code would become a bit cleaner. It would also be easier to name the methods then. \$\endgroup\$