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

📄 sokocanvas.java

📁 Sun公司的J2ME官方例程若干
💻 JAVA
字号:
/* * @(#)SokoCanvas.java	1.4 01/04/04 * Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved. * */package examples.sokoban;import java.io.*;import javax.microedition.lcdui.*;import javax.microedition.midlet.*;/** * SokoCanvas displays the game board and handles key events. * The Sokoban game logic and algorithms are separated into class * Board. * SokoCanvas does not setup or use any Commands. Commands for each * screen and listeners should be setup outside this class. * SokoCanvas generates a SELECT_COMMAND when the current level is * solved. Sequencing through screens is done in the Sokoban MIDlet. * <p> * SokoCanvas handles the reading, initialization, and sequencing * of individual puzzle screens. * <p> * SokoCanvas uses the Score class to restore and save game levels * and scores for each level. To display the scores use * getScoreScreen. It will be initialized with the current scores. * To select a new level use the getLevelScreen and gotoLevel * methods. * <p> * SokoCanvas handled key events for LEFT, RIGHT, UP, and DOWN to * move the pusher in the game board. * <p> * SokoCanvas selects color and grayscale values for the different * parts of the board. */class SokoCanvas extends Canvas {	private int level = 1;	private boolean solved;	private int cell = 1;		// number of pixels per cell 	private int width, height;	// dimensions of this canvas	private Board board;		// Board makes the moves	private Sokoban sokoban;		// Sokoban MIDlet	private Display display;		// Display showing this Canvas	private CommandListener listener; // Listener for solved notice	private Score score;		// Score object	private Form scoreForm;		// Form to show scores	private Font font;		// Font for text	private int fh;			// Font height for text lines	// 2 Bit color/grayscale defaults	private int wallColor =   0x7f7f7f;	private int groundColor = 0xffffff;	private int packetColor = 0x000000;	private int storeColor =  0x000000;	private int pusherColor = 0x000000;	/**	 * Construct a new canvas	 */	public SokoCanvas(Sokoban sokoban, Score s) {		height = getHeight();		width = getWidth();		font = Font.getDefaultFont();		fh = font.getHeight();				this.sokoban = sokoban;		display = Display.getDisplay(sokoban);		score = s;		board = new Board();		initColors();	}	/**	 * Read the previous level number from the score file.	 * Read in the level data.	 */	public void init() {		/*		 * Read the last level		 * if it can't be found, revert to level 0		 */		level = score.level;		if (!readScreen(level)) {			level = 0;			readScreen(level);		}		repaint();	}		/*	 * Read the colors to use from the descriptor.	 */	private void initColors() {		boolean isColor = display.isColor();		int numColors = display.numColors();		if (isColor) {			if (numColors > 2) {				setColors(0x006D55, 0xffffff,					  0xff6d00, 0xb60055, 0x6d6dff);			}		} else {			if (numColors > 2) {				setColors(0x999999, 0xffffff,					  0x666666, 0xbbbbbb, 0x000000);			} else {				setColors(0x6a6a6a, 0xffffff,					  0x6a6a6a, 0xbbbbbb, 0x000000);			}		}	}	/*	 * Set the colors.	 */	private void setColors(int w, int g, int pa, int s, int pu) {		wallColor = w;		groundColor = g;		packetColor = pa;		storeColor = s;		pusherColor = pu;	}	/**	 * Undo the last move if possible.	 * Here so undo can be triggered by a command.	 */	public void undoMove() {		board.undoMove();		solved = board.solved();		repaint();	}	/**	 * Restart the current level.	 */	public void restartLevel() {		readScreen(level);		repaint();		solved = false;	}	/**	 * Start the next level.	 */	public void nextLevel(int offset) {		updateScores();		// save best scores 		if (readScreen(level+offset)) {			level += offset;			score.setLevel(level);			solved = false;			repaint();		}	}	/**	 * Read and setup the next level.	 * Opens the resource file with the name "/Screen.<lev>"	 * and tells the board to read from the stream.	 * <STRONG>Must be called only with the board locked.</STRONG>	 *	 * @param lev the level number to read.	 * @return true if the reading of the level worked,	 *	  false otherwise.	 */	private boolean readScreen(int lev) {		if (lev <= 0) {			// Initialize the default zero screen			board.screen0();		} else {			InputStream is = null;			try {				String base = "/examples/sokoban/data/screen.";				is = getClass().getResourceAsStream(base + lev);				if (is != null) {					board.read(is, lev);					is.close();				} else {					Alert alert = new Alert(						"Could not find level " +						level);					display.setCurrent(alert);					return false;				}			} catch (java.io.IOException ex) {				try {					is.close();				} catch (IOException x) {				}				return false;			}		}		cell = ((height-fh) / board.height < width / board.width) ?			(height-fh) / board.height : width / board.width;		return true;	}	/**	 * Return the Screen to display scores.	 * It returns a screen with the current scores.	 * @return a screen initialized with the current score	 * information.	 */	public Screen getScoreScreen() {		Form scoreForm = null;		boolean newbest = solved &&		    (score.npushes == 0 ||		     board.npushes < score.npushes);		scoreForm = new Form(null);		scoreForm.append(newbest ?				 "New Best:\n" : "Current:\n");		scoreForm.append("  ");		scoreForm.append(Integer.toString(board.npushes));		scoreForm.append(" pushes\n");		scoreForm.append("  ");		scoreForm.append(Integer.toString(board.nmoves));		scoreForm.append(" moves\n");		scoreForm.append(newbest ? "Old Best:\n" : "Best\n");		scoreForm.append("  ");		scoreForm.append(Integer.toString(score.npushes));		scoreForm.append(" pushes\n");		scoreForm.append("  ");		scoreForm.append(Integer.toString(score.nmoves));		scoreForm.append(" moves\n ");		String title = "Scores";		if (newbest) {		    title = "Congratulations";		}		scoreForm.setTitle(title);		return scoreForm;	}	/*	 * Handle a repeated arrow keys as though it were another press.	 * @param keyCode the key pressed.	 */	protected void keyRepeated(int keyCode) {		int action = getGameAction(keyCode);		switch (action) {		case Canvas.LEFT:		case Canvas.RIGHT:		case Canvas.UP:		case Canvas.DOWN:			keyPressed(keyCode);		break;		default:			break;		}	}	/**	 * Handle a single key event.	 * The LEFT, RIGHT, UP, and DOWN keys are used to	 * move the pusher within the Board.	 * Other keys are ignored and have no effect.	 * Repaint the screen on every action key.	 */	protected void keyPressed(int keyCode) {		// Protect the data from changing during painting.		synchronized (board) {			int action = getGameAction(keyCode);			int move = 0;			switch (action) { 			case Canvas.LEFT:				move = Board.LEFT;				break;			case Canvas.RIGHT:				move = Board.RIGHT;				break;			case Canvas.DOWN:				move = Board.DOWN;				break;			case Canvas.UP:				move = Board.UP;				break;				// Ignore keycodes that don't map to actions.			default:				return;			}			// Tell the board to move the piece and queue a repaint			board.move(move);			repaint();					if (!solved && board.solved()) {				solved = true;				if (listener != null) {					listener.commandAction(						List.SELECT_COMMAND, this);				}			}		} // End of synchronization on the Board.	}		/**	 * Update the scores for the current level if it has	 * been solved and the scores are better than before.	 */	private void updateScores() {		if (!solved)			return;		/*		 * Update the scores. If the score for this level is lower		 * than the last recorded score save the lower scores.		 */		if (score.npushes == 0 || board.npushes < score.npushes) {			score.setLevelScore(board.npushes, board.nmoves);		}	}	/**	 * Add a listener to notify when the level is solved.	 * The listener is send a List.SELECT_COMMAND when the	 * level is solved.	 * @param l the object implementing interface CommandListener	 */	public void setCommandListener(CommandListener l) {		super.setCommandListener(l);		listener = l;	}	/*	 * Paint the contents of the Canvas.	 * The clip rectangle of the canvas is retrieved and used	 * to determine which cells of the board should be repainted.	 * @param g Graphics context to paint to.	 */	protected void paint(Graphics g) {		// Lock the board to keep it from changing during paint		synchronized (board) {						int x = 0, y = 0, x2 = board.width, y2 = board.height;			// Figure what part needs to be repainted.			int clipx = g.getClipX();			int clipy = g.getClipY();			int clipw = g.getClipWidth();			int cliph = g.getClipHeight();			x = clipx / cell;			y = clipy / cell;			x2 = (x + (clipx + clipw + cell-1)) / cell;			y2 = (y + (clipy + cliph + cell-1)) / cell;			if (x2 > board.width)				x2 = board.width;			if (y2 > board.height)				y2 = board.height;			// Fill entire area with ground color			g.setColor(groundColor);			g.fillRect(clipx, clipy, clipw, cliph);			for (y = 0; y < y2; y++) {				for (x = 0; x < x2; x++) {					byte v = board.get(x, y);					switch (v & ~Board.PUSHER) {					case Board.WALL:						g.setColor(wallColor);						g.fillRect(x*cell, y*cell,							   cell, cell);						break;					case Board.PACKET:					case Board.PACKET | Board.STORE:						g.setColor(packetColor);						g.fillRect(x*cell+1, y*cell+1,							   cell-2, cell-2);						break;					case Board.STORE:						g.setColor(storeColor);						g.drawRect(x*cell+1, y*cell+1,							   cell-2, cell-2);						break;					case Board.GROUND:					default:						// Noop since already filled.						break;					}					if ((v & Board.PUSHER) != 0) {						g.setColor(pusherColor);						g.fillArc(x*cell, y*cell,							  cell, cell, 0, 360);					}				}			}			g.setColor(pusherColor);			g.drawString("Sokoban Level " + level, 0, height-fh,				     Graphics.TOP|Graphics.LEFT);		}	}}

⌨️ 快捷键说明

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