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

📄 model.java

📁 扫雷的源代码,包结构采用经典的MVC模式,包括模型、控制、视图三部分
💻 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) {
		//matrix = new ModelCellProperty[height][width];
		//ret = new ArrayList();
		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);
			
	}

	public void restart(int width, int height, int mineNumber, int type) {
		
		unclickedNumber = height * width - mineNumber;

		freezed = false;
//		gameOver = false;
		isNewGame = true;
		isFirstClicking = true;

		time = 0;
		markedMineNumber = 0;

		//		notifyTimerChanged();
		
		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();
				}
			}
//			setMineAndNumber();
			notifyRestartChanged();
			return;
		}

		this.width = width;
		this.height = height;
		this.mineNumber = mineNumber;
		this.type = type;
		time = 0;
		//unclickedNumber = height * width - mineNumber;

		matrix = new ModelCellProperty[height][width];
		//if(matrix[y][x] == null){
		for (y = 0; y != height; ++y) {
			for (x = 0; x != width; ++x) {
				matrix[y][x] = new ModelCellProperty();
			}
		}
		//}
		//unlockedNumber = 0;
//		setMineAndNumber();
		notifyRestartChanged();
		
	}

	public void unlockAll(Location aLocation) {
		Release release = new Release();
		release.go(aLocation);
	}

	public void unlockOne(Location location) {
		GetMarkedMineNumber aGMMN = new GetMarkedMineNumber();
		aGMMN.go(location);
		if (aGMMN.getNumber() == matrix[location.y][location.x].getValue()) {
			SetClicked aSC = new SetClicked();
			aSC.go(location);
		}
	}

	//public void unlockACell(Location location){
	//++unlockedNumber;
	//--remanentMineNumber;

	//	setClickedButton( location );
	//}

	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);
			
			SetNumber aSN = new SetNumber();
			aSN.go(new Location(x, y));

		}

		//view();

	}

	//	public void setGameOver(boolean val) {
	//		gameOver = val;
	//		notifyGameoverChanged();
	//	}
	//
	//	public boolean isGameOver() {
	//		return gameOver;
	//	}

	private class Release extends Traverse {
		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()) {
				//unlockACell(tempLocation);
				setClickedButton(tempLocation);
				//setTraversed(true, tempLocation);
				//ret.add(tempLocation);
			} else { //if( !matrix[y][x].isNumber() &&
				// !matrix[y][x].isTraversed() ){
				//				unlockACell(tempLocation);
				setClickedButton(tempLocation);
				//setTraversed(true, tempLocation);
				//ret.add(tempLocation);
				go(tempLocation);
			}
		}

		private Location aLocation;
	}

	private class SetClicked extends Traverse {

		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 {
					//unlockACell( tempLocation );
					setClickedButton(tempLocation);
				}
			}
		}
	}

	private class GetMarkedMineNumber extends Traverse {

		GetMarkedMineNumber() {
			super();
			number = 0;
		}

		void run(int x, int y) {
			if (matrix[y][x].isMarkedMine())
				++number;
		}

		public int getNumber() {
			return number;
		}

		private int number;
	}

	private class SetNumber extends Traverse {
		SetNumber() {
			super();
		}

		void run(int x, int y) {
//			if (!matrix[y][x].isMine()) {
				matrix[y][x].setValue(matrix[y][x].getValue() + 1);
				matrix[y][x].setNumber(true);
//			}
		}
	}

	//public Object[] getRet(){
	//	return ret.toArray();
	//}
	protected ModelCellProperty[][] getMatrix() {
		return matrix;
	}

	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();
	}

	//private boolean isTraversed(Location location){
	//	return matrix[location.y][location.x].isTraversed();
	//}

	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);
				}				
			}.go(location);
			setMineAndNumber();
			new Traverse(){
				void run(int x, int y) {
					matrix[y][x].setMine(false);
				}				
			}.go(location);
			isFirstClicking = false;
		}
		matrix[location.y][location.x].setClickedButton(true);
		if (isMine(location)) {
			notifyGameoverChanged();
			return;
		}
		notifyCellChanged(location);
		--unclickedNumber;
		if (unclickedNumber == 0 && markedMineNumber == mineNumber)
			notifyWinChanged();
	}

	public int getMarkedMineNumber() {
		return markedMineNumber;
	}
	
	public int getType(){
		return type;
	}

	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 setType(int type){
//		this.type = type;
//	}

	public void setMarkedMine(boolean val, Location location) {
		if (val == true)
			++markedMineNumber;
		else
			--markedMineNumber;
		matrix[location.y][location.x].setMarkedMine(val);
		notifyCellChanged(location);
		if (unclickedNumber == 0 && markedMineNumber == mineNumber)
			notifyWinChanged();
	}
	
	public boolean isFreezed(){
		return freezed;		
	}

	private void setMine(boolean val, Location location) {
		matrix[location.y][location.x].setMine(val);
	}

	private void setNumber(boolean val, Location location) {
		matrix[location.y][location.x].setMine(val);
	}

	//private void setTraversed(boolean val, Location location){
	//	matrix[location.y][location.x].setTraversed(val);
	//}

	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 To change the template for this generated type comment go to Window -
	 * Preferences - Java - Code Style - Code Templates
	 */
	private abstract class Traverse {

		Traverse() {
			//ret.clear();
			firstTimeTarget = true;
		}

		abstract void run(int x, int y);

		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;
		}
	}

	private boolean firstTimeTarget;

	private boolean isNewGame;

//	private boolean gameOver;
	
	private int type;

	private int time;

	private boolean freezed;

	//private ArrayList ret;
	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 int unlockedNumber;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -