📄 mazefog2.java
字号:
/* doSmallerButton() method The user clicked the "Smaller" button for smaller board squares, or typed an equivalent keyboard mnemonic.*/ void doSmallerButton() { if (sizeIndex > 0) sizeIndex --; // go to a smaller size, if there is one doNewgameButton(); // and start a new game } // end of doSmallerButton() method/* drawBoardExit() method Draw the exit or goal for the maze, at the given board position. Currently, this is done with alternating blue and white boxes. Anything else is really difficult to draw at small sizes.*/ void drawBoardExit( Graphics gr, // graphics context of <boardCanvas> int row, // row number (index) int col) // column number (index) { boolean colorFlag; // flips between two colors int hz; // temporary number of horizontal pixels int size; // remaining box size int vt; // temporary number of vertical pixels int width; // width of current box line colorFlag = true; // start with first color size = boardSymbolSize + (2 * boardBorderSize); // initial box size hz = (col * boardGridSize) + boardLineWidth + canvasBorder; // x position vt = (row * boardGridSize) + boardLineWidth + canvasBorder; // y position while (size > 0) { width = colorFlag ? 2 : 3; // different width for each color gr.setColor(colorFlag ? ColorEXIT1 : ColorEXIT2); // select clor gr.fillRect(hz, vt, size, size); // draw box colorFlag = ! colorFlag; // flip color flag hz += width; // next x position vt += width; // next y position size -= (width * 2); // next box size } } // end of drawBoardExit() method/* drawBoardLeftLine() method Draw a left (vertical) line on the game board at the given board position.*/ void drawBoardLeftLine( Graphics gr, // graphics context of <boardCanvas> int row, // row number (index) int col, // column number (index) Color shade) // <BACKGROUND> or <ColorLINE> { gr.setColor(shade); // switch to caller's favorite color gr.fillRect( // draw line as filled rectangle (col * boardGridSize) + canvasBorder, (row * boardGridSize) + canvasBorder, boardLineWidth, (boardGridSize + boardLineWidth)); } // end of drawBoardLeftLine() method/* drawBoardTopLine() method Draw a top (horizontal) line on the game board at the given board position.*/ void drawBoardTopLine( Graphics gr, // graphics context of <boardCanvas> int row, // row number (index) int col, // column number (index) Color shade) // <BACKGROUND> or <ColorLINE> { gr.setColor(shade); // switch to caller's favorite color gr.fillRect( // draw line as filled rectangle (col * boardGridSize) + canvasBorder, (row * boardGridSize) + canvasBorder, (boardGridSize + boardLineWidth), boardLineWidth); } // end of drawBoardTopLine() method/* drawBoardUser() method Draw the user's position as a blue circle. The caller gives us row and column numbers, plus pixel row and column offsets. We assume that the offsets are valid, and drawing in that location won't overlap something like a wall!*/ void drawBoardUser( Graphics gr, // graphics context of <boardCanvas> int row, // row number (index) int col, // column number (index) int rowOffset, // row offset (y coordinate) in pixels int colOffset, // column offset (x coordinate) in pixels Color shade) // <BACKGROUND> or <ColorUSER> { gr.setColor(shade); // switch to caller's favorite color gr.fillOval( (col * boardGridSize) + boardBorderSize + boardLineWidth + canvasBorder + colOffset, (row * boardGridSize) + boardBorderSize + boardLineWidth + canvasBorder + rowOffset, boardSymbolSize, boardSymbolSize); } // end of drawBoardUser() method/* flashBoardUser() method Redraw the user's position several times in different colors, ending with the standard color.*/ void flashBoardUser( Graphics gr, // graphics context of <boardCanvas> int row, // row number (index) int col, // column number (index) int rowOffset, // row offset (y coordinate) in pixels int colOffset) // column offset (x coordinate) in pixels { drawBoardUser(gr, row, col, rowOffset, colOffset, Color.black); // 000 sleep(DelayFLASH); drawBoardUser(gr, row, col, rowOffset, colOffset, Color.green); // 010 sleep(DelayFLASH); drawBoardUser(gr, row, col, rowOffset, colOffset, Color.cyan); // 011 sleep(DelayFLASH); drawBoardUser(gr, row, col, rowOffset, colOffset, Color.blue); // 001 sleep(DelayFLASH); drawBoardUser(gr, row, col, rowOffset, colOffset, Color.magenta); // 101 sleep(DelayFLASH); drawBoardUser(gr, row, col, rowOffset, colOffset, Color.red); // 100 sleep(DelayFLASH); drawBoardUser(gr, row, col, rowOffset, colOffset, Color.yellow); // 110 sleep(DelayFLASH); drawBoardUser(gr, row, col, rowOffset, colOffset, Color.white); // 111 sleep(DelayFLASH); drawBoardUser(gr, row, col, rowOffset, colOffset, ColorUSER); // standard } // end of flashBoardUser() method/* keyPressed(), keyReleased(), keyTyped() methods We listen to arrow keys with the keyPressed() method, because arrow keys are not fully-formed Unicode characters. We listen to keyboard mnemonics (for the control buttons) with keyTyped() since they are Unicode characters. The keyReleased() method is just to complete the KeyListener interface. The arrow keys move in whole increments of one square (rows and columns); they don't use the pixel offsets like the mouse movement. Hence, the code in keyPressed() is easier to understand than in boardMouseMoved().*/ public void keyPressed(KeyEvent event) { Graphics gr; // graphics context for <boardCanvas> if (gameState == GameACTIVE) // ignore keys unless there is an active game { /* Allocate a graphics context for <boardCanvas> and erase the previous user position, even if we don't end up moving. */ gr = boardCanvas.getGraphics(); // get graphics context drawBoardUser(gr, userRow, userCol, userRowOffset, userColOffset, BACKGROUND); userColOffset = userRowOffset = 0; // cancel any pixel position offsets /* Sort out which key was pressed. */ switch (event.getKeyCode()) { case KeyEvent.VK_D: // "D" key for "down" case KeyEvent.VK_DOWN: // down arrow case KeyEvent.VK_KP_DOWN: // numeric keypad down arrow if (boardTop[userRow + 1][userCol] == LineEMPTY) { userRow ++; // move down } break; case KeyEvent.VK_L: // "L" key for "left" case KeyEvent.VK_LEFT: // left arrow case KeyEvent.VK_KP_LEFT: // numeric keypad left arrow if (boardLeft[userRow][userCol] == LineEMPTY) { userCol --; // move left } break; case KeyEvent.VK_R: // "R" key for "right" case KeyEvent.VK_RIGHT: // right arrow case KeyEvent.VK_KP_RIGHT: // numeric keypad right arrow if (boardLeft[userRow][userCol + 1] == LineEMPTY) { userCol ++; // move right } break; case KeyEvent.VK_U: // "U" key for "up" case KeyEvent.VK_UP: // up arrow case KeyEvent.VK_KP_UP: // numeric keypad up arrow if (boardTop[userRow][userCol] == LineEMPTY) { userRow --; // move up } break; default: // ignore all other keys break; } /* Did the user reach the exit? If so, then announce the success. If not, just draw or redraw the user's position normally. */ if (boardDistance[userRow][userCol] < 2) { gameState = GameFINISH; // no more moves allowed messageText.setText("You're there! You reached the exit! Click \"New Game\" to play again."); if (winSound != null) // if we were able to load winning sound clip winSound.play(); // play this sample sound from the Java SDK boardPaint(gr); // shows everything since state = GameFINISH flashBoardUser(gr, userRow, userCol, userRowOffset, userColOffset); } else { drawBoardUser(gr, userRow, userCol, userRowOffset, userColOffset, ColorUSER); // draw user normally makeLinesVisible(gr, userRow, userCol, true); // this may reveal hidden lines } gr.dispose(); // release graphics context } } // end of keyPressed() method public void keyReleased(KeyEvent event) { } public void keyTyped(KeyEvent event) { switch (event.getKeyChar()) // which character did user type on keyboard? { case ('+'): case ('B'): // "B" for "bigger" case ('b'): doBiggerButton(); // "Bigger" button for bigger board squares break; case ('G'): // "G" for "game" case ('g'): case ('N'): // "N" for "new" case ('n'): doNewgameButton(); // "New Game" button to start a new game break; case ('H'): // "H" for "help" case ('h'): case ('M'): // "M" for "me" case ('m'): case ('Q'): // "Q" for "quit" case ('q'): doShowmeButton(); // "Show Me" button to see the solution break; case ('-'): case ('S'): // "S" for "smaller" case ('s'): doSmallerButton(); // "Smaller" button for smaller board squares break; default: // ignore all other keys break; } } // end of keyTyped() method/* makeBoard() method Make the game board. That is, draw the maze. We do this by randomly picking a square along one of the four edges. This square becomes the exit or goal for the game. Then starting from this square, we "tunnel" into an array whose values indicate if a square is empty, or in use. Empty squares can be added to our current tunnel; occupied squares stop us and force us to backtrack. Directions and distances are chosen randomly. This method usually, but not always, completes the game board in the sense that it uses every available position. The incomplete sections just look like empty "fog" to the user, which can be more confusing than a totally complete maze! The created maze is simply connected: there are no loops. While drawing a maze requires a lot of pseudo-random activity, the algorithm should not be chosen randomly. The only argument to this method is a display flag. If true, then we draw the maze as we create it. If false, then we create the maze without drawing and without delays (calls to the sleep() method). Most web browsers don't display anything until after the init() method returns, so there is no point in having an animated introduction unless it runs in a separate thread. The user just sits there waiting and thinking that the program is really slow.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -