⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 model.java

📁 eclipse下面实现的java扫雷游戏
💻 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 + -