📄 model.java
字号:
/*
* Created on Mar 27, 2005
*
* TODO the model of MVC structure. when model data are changed, call the view
* to show result to user
*/
package model;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import java.util.Observable;
import javax.swing.Timer;
/**
* @author mqqqvpppm
*
* TODO the model of MVC structure. when model data are changed, call the view
* to show result to user
*
*/
public class Model extends Observable {
//for debug
public void view() {
for (int y = 0; y != height; ++y) {
for (int x = 0; x != width; ++x) {
if (matrix[y][x].isMine())
System.out.print("m ");
else
System.out.print(matrix[y][x].getValue() + " ");
}
System.out.println(" ");
}
}
public Model(int width, int height, int mineNumber, int type) {
notifingObject = new NotifingObject();
cellNotifingObject = new CellNotifingObject();
timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (freezed || isNewGame || time >= 1000)
return;
++time;
notifyTimerChanged();
}
});
restart(width, height, mineNumber, type);
}
//reset the model data by parameters
public void restart(int width, int height, int mineNumber, int type) {
unclickedNumber = height * width - mineNumber;
freezed = false;
isNewGame = true;
isFirstClicking = true;
time = 0;
markedMineNumber = 0;
int x = 0;
int y = 0;
if (width == this.width && height == this.height
&& mineNumber == this.mineNumber) {
for (y = 0; y != height; ++y) {
for (x = 0; x != width; ++x) {
matrix[y][x].clear();
}
}
notifyRestartChanged();
return;
}
this.width = width;
this.height = height;
this.mineNumber = mineNumber;
this.type = type;
time = 0;
matrix = new ModelCellProperty[height][width];
for (y = 0; y != height; ++y) {
for (x = 0; x != width; ++x) {
matrix[y][x] = new ModelCellProperty();
}
}
notifyRestartChanged();
}
//release a area
public void unlockAll(Location aLocation) {
if(release == null){
release = new Release();
}
release.go(aLocation);
}
//release a square
public void unlockOne(Location location) {
if(getMarkedMineNumber == null){
getMarkedMineNumber = new GetMarkedMineNumber();
}
getMarkedMineNumber.go(location);
if (getMarkedMineNumber.getValue() == matrix[location.y][location.x].getValue()) {
if(setClicked == null){
setClicked = new SetClicked();
}
setClicked.go(location);
}
}
//set the mine and numbers randomly
private void setMineAndNumber() {
int x = 0;
int y = 0;
Random XRandom = new Random();
Random YRandom = XRandom;
for (int i = 0; i != mineNumber; i++) {
x = XRandom.nextInt(width);
y = YRandom.nextInt(height);
if (matrix[y][x].isMine() == true) {
--i;
continue;
}
matrix[y][x].setMine(true);
matrix[y][x].setNumber(false);
if(setNumber == null){
setNumber = new SetNumber();
}
setNumber.go(new Location(x, y));
}
}
protected ModelCellProperty[][] getMatrix() {
return matrix;
}
public void setFirstClicking(boolean value){
isFirstClicking = value;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getMineNumber() {
return mineNumber;
}
public int getTime() {
return time;
}
public int getValue(Location location) {
return matrix[location.y][location.x].getValue();
}
public boolean isClickedButton(Location location) {
return matrix[location.y][location.x].isClickedButton();
}
public boolean isMark(Location location) {
return matrix[location.y][location.x].isMark();
}
public boolean isMarkedMine(Location location) {
return matrix[location.y][location.x].isMarkedMine();
}
public boolean isMine(Location location) {
return matrix[location.y][location.x].isMine();
}
public boolean isNumber(Location location) {
return matrix[location.y][location.x].isNumber();
}
public void setClickedButton(Location location) {
if(isFirstClicking){
new Traverse(){
void run(int x, int y) {
matrix[y][x].setMine(true);
}
int getValue() {return 0;}
}.go(location);
setMineAndNumber();
new Traverse(){
void run(int x, int y) {
matrix[y][x].setMine(false);
}
int getValue() {return 0;}
}.go(location);
isFirstClicking = false;
}
matrix[location.y][location.x].setClickedButton(true);
if (isMine(location)) {
notifyGameoverChanged();
return;
}
notifyCellChanged(location);
--unclickedNumber;
if(unclickedNumber == 0){
notifyWinChanged();
}
}
public int getMarkedMineNumber() {
return markedMineNumber;
}
public int getType(){
return type;
}
public void setMenuMarkSelected( boolean value ){
this.isMenuMarkSelected = value;
}
public boolean isMenuMarkSelected(){
return isMenuMarkSelected;
}
public void setTime(int time) {
this.time = time;
notifyTimerChanged();
}
public void setMarkedMineNumber(int markedMineNumber) {
this.markedMineNumber = markedMineNumber;
notifyCellChanged(new Location(0, 0));
}
public void setMark(boolean val, Location location) {
matrix[location.y][location.x].setMark(val);
notifyCellChanged(location);
}
public void setMarkedMine(boolean val, Location location) {
if (val == true)
++markedMineNumber;
else
--markedMineNumber;
matrix[location.y][location.x].setMarkedMine(val);
notifyCellChanged(location);
}
public boolean isFreezed(){
return freezed;
}
public void setValue(int val, Location location) {
matrix[location.y][location.x].setValue(val);
}
private void notifyCellChanged(Location location) {
if (freezed == true)
return;
if (isNewGame) {
time = 0;
timer.restart();
isNewGame = false;
}
cellNotifingObject.setLocation(location);
cellNotifingObject.setType(NotifingObject.TYPE_CELLCHANGED);
setChanged();// Model notify view
notifyObservers(cellNotifingObject);
}
private void notifyRestartChanged() {
freezed = false;
//notifingObject.setLocation(null);
notifingObject.setType(NotifingObject.TYPE_RESTART);
setChanged();
notifyObservers(notifingObject);
}
private void notifyWinChanged() {
if (freezed == true)
return;
freezed = true;
// time = 0;
// notifyTimerChanged();
//notifingObject.setLocation(null);
notifingObject.setType(NotifingObject.TYPE_WIN);
setChanged();
notifyObservers(notifingObject);
}
private void notifyGameoverChanged() {
//notifingObject.setLocation(null);
if (freezed == true)
return;
// time = 0;
// notifyTimerChanged();
notifingObject.setType(NotifingObject.TYPE_GAMEOVER);
setChanged();
notifyObservers(notifingObject);
freezed = true;
}
private void notifyTimerChanged() {
notifingObject.setType(NotifingObject.TYPE_TIME);
setChanged();
notifyObservers(notifingObject);
}
public static final int TYPE_EASY = 0;
public static final int TYPE_HARD = 1;
public static final int TYPE_HELL = 2;
public static final int TYPE_CUSTOM = 3;
/**
* @author mqqqvpppm
*
* TODO traverse the square
*/
private abstract class Traverse {
Traverse() {
//ret.clear();
firstTimeTarget = true;
}
abstract void run(int x, int y);
abstract int getValue();
void go(Location aLocation) {
int y = 0;
int x = 0;
if (firstTimeTarget) {
x = aLocation.x;
y = aLocation.y;
run(x, y);
firstTimeTarget = false;
}
y = aLocation.y + 1;
if (isValidY(y))
run(aLocation.x, y);
y = aLocation.y - 1;
if (isValidY(y))
run(aLocation.x, y);
x = aLocation.x + 1;
if (isValidX(x))
run(x, aLocation.y);
x = aLocation.x - 1;
if (isValidX(x))
run(x, aLocation.y);
x = aLocation.x + 1;
y = aLocation.y + 1;
if (isValidX(x) && isValidY(y))
run(x, y);
x = aLocation.x - 1;
y = aLocation.y - 1;
if (isValidX(x) && isValidY(y))
run(x, y);
x = aLocation.x + 1;
y = aLocation.y - 1;
if (isValidX(x) && isValidY(y))
run(x, y);
x = aLocation.x - 1;
y = aLocation.y + 1;
if (isValidX(x) && isValidY(y))
run(x, y);
}
private boolean isValidX(int coordinate) {
if (coordinate < 0 || coordinate >= width)
return false;
return true;
}
private boolean isValidY(int coordinate) {
if (coordinate < 0 || coordinate >= height)
return false;
return true;
}
}
//recursion to release the area
private class Release extends Traverse {
private Release() {
super();
}
void run(int x, int y) {
Location tempLocation = new Location(x, y);
if (matrix[y][x].isMarkedMine() || matrix[y][x].isClickedButton()
|| matrix[y][x].isMine()) {
return;
}
if (matrix[y][x].isNumber()) {
setClickedButton(tempLocation);
} else {
setClickedButton(tempLocation);
go(tempLocation);
}
}
/* (non-Javadoc)
* @see model.Model.Traverse#getValue()
*/
int getValue() {
return 0;
}
}
private class SetClicked extends Traverse {
private SetClicked() {
super();
}
void run(int x, int y) {
if (matrix[y][x].isClickedButton())
return;
if (!matrix[y][x].isMarkedMine()) {
Location tempLocation = new Location(x, y);
if (!isNumber(tempLocation) && !isMine(tempLocation)) {
unlockAll(tempLocation);
} else {
setClickedButton(tempLocation);
}
}
}
int getValue() {return 0;}
}
//set the value of a cell whose type is number
private class SetNumber extends Traverse {
SetNumber() {
super();
}
void run(int x, int y) {
matrix[y][x].setValue(matrix[y][x].getValue() + 1);
matrix[y][x].setNumber(true);
}
int getValue() {return 0;}
}
//get the number of the cells that be marked as mine
private class GetMarkedMineNumber extends Traverse {
GetMarkedMineNumber() {
super();
number = 0;
}
void run(int x, int y) {
if (matrix[y][x].isMarkedMine())
++number;
}
private int number;
int getValue() {
int temp = number;
number = 0;//i need set number as 0,when call this method
return temp;
}
}
private Traverse release;
private Traverse setClicked;
private Traverse setNumber;
private Traverse getMarkedMineNumber;
private boolean firstTimeTarget;
private boolean isNewGame;
private int type;
private int time;
private boolean freezed;
private ModelCellProperty matrix[][];
private int width;
private int height;
private int mineNumber;
private int unclickedNumber;
private int markedMineNumber;
private NotifingObject notifingObject;
private CellNotifingObject cellNotifingObject;
private Timer timer;
private boolean isFirstClicking;
private boolean isMenuMarkSelected;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -