扫雷小游戏
主要步骤
1.初始化
- 用一个二维数组区装节点的值
- -1表示地雷
- 统计相近节点地雷个数作为非雷区的值
- 地雷离散化,设置一个阈值,使相近区域雷数不要过高
2.事件驱动
- 事件
- 单击事件,翻开区域
- 如果是区域值是0,则域翻开它的邻区,对邻区操作亦如此
- 双击事件,可化作对相邻区域非标记区域进行单击
- 右击事件,标记区域,再次右击则取消标记
- 单击事件,翻开区域
3.成功与失败
- 翻开地雷则失败
- 未翻开数等于地雷数则胜利
不足之处:
计时,计数未实现
代码实现
package mine;
import java.util.ArrayList;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Font;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.Window;
public class Mine extends Application{
public static void main(String[] args) {
launch();
}
public void start(Stage primaryStage) throws Exception {
this.primaryStage=primaryStage;
//GridPane gridPane=createPane(16,30,99);
GridPane gridPane=createPane(9,9,9);
Scene scene=new Scene(gridPane);
primaryStage.setScene(scene);
// primaryStage.setWidth(1600);
// primaryStage.setHeight(900);
primaryStage.setWidth(600);
primaryStage.setHeight(600);
primaryStage.show();
}
ButtonCell[][] tableCell;
private int row;
private int col;
private int sum;
private Window primaryStage;
public GridPane createPane(int row,int col,int sum) {
this.row=row;
this.col=col;
this.sum=sum;
int[][] table=rand(row,col,sum);
tableCell=new ButtonCell[row][col];
GridPane pane=new GridPane();
pane.setVgap(3);
pane.setHgap(4);
pane.setStyle("-fx-background-color:green");
for(int r=0;r<row;r++) {
for(int c=0;c<col;c++) {
ButtonCell cell=new ButtonCell(r,c,getValue(r,c, table,row,col));
cell.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
if(event.getClickCount()==1&&event.getButton().name().equals(MouseButton.PRIMARY.name())) {
singleClick(cell);
}
}
});
cell.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
if(event.getClickCount()==2&&event.getButton().name().equals(MouseButton.PRIMARY.name())) {
doubleClick(cell);
}
}
});
cell.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
if(event.getClickCount()==1&&event.getButton().name().equals(MouseButton.SECONDARY.name())) {
signClick(cell);
}
}
});
pane.add(cell, c, r);
tableCell[r][c]=cell;
}
}
return pane;
}
protected void signClick(ButtonCell cell) {
if(cell.open==false) {
if(cell.sign) {
cell.sign=false;
cell.setText("");
cell.setStyle("-fx-background-color:#FAFAD2");
}else {
cell.sign=true;
cell.setText("P");
cell.setStyle("-fx-background-color:#FF83FA");
}
}
}
private void singleClick(ButtonCell cell) {
if(cell.value==-1) {
blast();
}else if(cell.value==0) {
turnOver(cell);
findFamily(cell, tableCell, this.row, this.col);
}else {
turnOver(cell);
}
victory();
}
private void turnOver(ButtonCell cell) {
cell.open=true;
if(cell.value==0) {
cell.setText("");
cell.setStyle("-fx-background-color:E0EEE0;-fx-border-Stroke: #C6E2FF");
}else {
cell.setText(""+cell.value);
cell.setStyle("-fx-background-color:#87CEFF;-fx-border-Stroke: #8A2BE2");
}
}
private void doubleClick(ButtonCell cell) { if(cell.open==true) {
openBrothers(cell, tableCell, this.row, this.col);
}
}
private void blast() {
for(int r=0;r<row;r++) {
for(int c=0;c<col;c++) {
ButtonCell tmp = tableCell[r][c];
if(tmp.value==-1) {
tmp.setText("M");
tmp.setStyle("-fx-background-color:red");
}
}
}
achievement("Loser");
}
public int[][] rand(int x,int y,int count) {
int[][] table = new int[x][y];
while( count>0) {
int tmpx = (int)(Math.random()*x);
int tmpy = (int)(Math.random()*y);
if(dispersed(tmpx,tmpy,5,table,x,y)) {
count-=1;
table[tmpx][tmpy]=-1;
}
}
return table;
}
public boolean dispersed(int x,int y,int dis,int[][] table,int X,int Y) {
if(table[x][y]==-1) {
return false;
}
int i=x>0?(x-1):0;
int e=y>0?(y-1):0;
int count=1;
for(;i<=x+1&&i<X;i++) {
for(int j=e;j<=y+1&&j<Y;j++) {
if(table[i][j]==-1) {
count++;
}
}
}
if(count>dis)
return false;
return true;
}
public int getValue(int x,int y,int[][] table,int X,int Y) {
if(table[x][y]==-1) {
return -1;
}
int i=x>0?(x-1):0;
int e=y>0?(y-1):0;
int count=0;
for(;i<=x+1&&i<X;i++) {
for(int j=e;j<=y+1&&j<Y;j++) {
if(table[i][j]==-1) {
count++;
}
}
}
return count;
}
public void findFamily(ButtonCell cell,ButtonCell[][] tableCell,int R,int C) {
int r=cell.row>0?(cell.row-1):0;
int e=cell.col>0?(cell.col-1):0;
for(;r<=cell.row+1&&r<R;r++) {
for(int j=e;j<=cell.col+1&&j<C;j++) {
ButtonCell tmp = tableCell[r][j];
if(tmp.open==false) {
turnOver(tmp);
if(tmp.value==0) {
findFamily(tmp,tableCell, R, C);
}
}
}
}
}
public void openBrothers(ButtonCell cell,ButtonCell[][] tableCell,int R,int C) {
int r=cell.row>0?(cell.row-1):0;
int e=cell.col>0?(cell.col-1):0;
for(;r<=cell.row+1&&r<R;r++) {
for(int j=e;j<=cell.col+1&&j<C;j++) {
ButtonCell tmp = tableCell[r][j];
if(tmp.open==false) {
if(!(tmp.sign==true&&tmp.value==-1)){
singleClick(tmp);
}
}
}
}
}
public void victory() {
int count=0;
for(int r=0;r<row;r++) {
for(int c=0;c<col;c++) {
ButtonCell tmp = tableCell[r][c];
if(tmp.open==false) {
count++;
}
}
}
if(count==sum) {
achievement("Winner");
}
}
public void achievement(String str) {
StackPane sp=new StackPane();
Label lab=new Label(str);
sp.getChildren().add(lab);
sp.setStyle("-fx-background-color: linear-gradient(to right,#00eeff,#ffee00);");
Stage s=new Stage();
s.initOwner(this.primaryStage);//设置拥有者
s.setScene(new Scene(sp,100,100));
s.show();
}
}
//随手写的,封装干什么,拿来就用
class ButtonCell extends Button{
int value;
boolean sign=false;
boolean open=false;
private boolean state=false;
public int col;
public int row;
public ButtonCell(int row,int col,int value){
super("");
super.setStyle("-fx-background-color: #FAFAD2");
this.col=col;
this.row=row;
super.setPrefSize(40, 40);
this.value=value;
}
}
测试
将区域值显示出来方便测试观察
//super("");
super(""+value);
点击值大于0的一个区域
点击值等于0的一个区域
它将翻开相邻区域直至翻到值大于0的区域
点到地雷
来一个巨大的挑战
GridPane gridPane=createPane(16,30,99);
primaryStage.setWidth(1600);
primaryStage.setHeight(900);