reversimodel.java
来自「开源项目openfire的完整源程序」· Java 代码 · 共 419 行
JAVA
419 行
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006 Jive Software. All rights reserved.
* This software is the proprietary information of Jive Software. Use is subject to license terms.
*/
package org.jivesoftware.game.reversi;
import java.util.Arrays;
/**
* Model for a Reversi game. <a href="http://en.wikipedia.org/wiki/Reversi">Reversi</a>
* is a game played by two players ({@link #WHITE White} and {@link #BLACK Black}) on
* an 8x8 board. Board positions are 0-63; starting at 0 in the upper-left corner then
* travelling horizontally row by row until position 63 in the bottom-right corner of
* the board.<p>
*
* This class maintains game state as individual turns are taken until the game is
* {@link #isGameFinished() finished}. {@link #BLACK Black} always starts the game.
* Two stones for each player are always placed in the center of the game board at
* the start of each game (following standard Reversi rules).
*
* @author Matt Tucker
*/
public class ReversiModel {
/**
* Blank.
*/
public static int BLANK = 0;
/**
* White.
*/
public static int WHITE = 1;
/**
* Black.
*/
public static int BLACK = 2;
private int[] board;
private int currentPlayer;
private boolean gameFinished = false;
private int[] flipBuffer = new int[7];
private int flipBufferSize = 0;
/**
* Constructs a new game instance and sets up initial board positions.
*/
public ReversiModel() {
board = new int[64];
// Set all positions to blank.
Arrays.fill(board, BLANK);
// Setup initial positions.
board[27] = WHITE;
board[28] = BLACK;
board[35] = BLACK;
board[36] = WHITE;
// Black always starts.
currentPlayer = BLACK;
}
/**
* Returns true if the game is finished (i.e., no more moves are possible.). The winner
* is the player with the highest score when the game is finished.
*
* @return true if the game is finished.
*/
public boolean isGameFinished() {
return gameFinished;
}
/**
* Returns true if the current player can place a stone at the specified position.
*
* @param position the position on the board (0-63).
* @return true if the position is a valid move.
*/
public boolean isValidMove(int position) {
return !gameFinished && isValidMove(position, getCurrentPlayer());
}
/**
* Returns the current value at a specific board position (between 0 and 63, inclusive). The value
* is either {@link #BLANK blank}, {@link #WHITE white}, or {@link #BLACK black}.
*
* @param position the board position.
* @return the value at the specified board position.
*/
public int getBoardValue(int position) {
if (position < 0 || position > 63) {
throw new IllegalArgumentException("Invalid position: " + position + ". Valid board " +
"positions are 0 through 63");
}
return board[position];
}
/**
* Returns the current player: {@link #WHITE white} or {@link #BLACK black}. Note that
* it's possible for a player to have several turns in a row, depending on whether
* there's a valid move available for the other player. The {@link #BLACK black} player
* always starts the game.
*
* @return the current player.
*/
public int getCurrentPlayer() {
return currentPlayer;
}
/**
* Returns the black player's current score.
*
* @return the black player's current score.
*/
public int getWhiteScore() {
int score = 0;
for (int i=0; i<board.length; i++) {
if (board[i] == WHITE) {
score++;
}
}
return score;
}
/**
* Returns the white player's current score.
*
* @return the white player's current score.
*/
public int getBlackScore() {
int score = 0;
for (int i=0; i<board.length; i++) {
if (board[i] == BLACK) {
score++;
}
}
return score;
}
/**
* Causes the {@link #getCurrentPlayer() current player} to execute a move by placing a stone at
* the specified position. Executing a move will flip one or more of the other player's stones.
*
* @param position the position to make the move at.
* @return true if the move was successful; false otherwise.
*/
public boolean makeMove(int position) {
if (!isValidMove(position)) {
return false;
}
board[position] = currentPlayer;
// Execute the move
getFlipCount(position, currentPlayer, true);
// See if other user has a valid move. If so, switch to other player.
int otherPlayer = currentPlayer==WHITE ? BLACK: WHITE;
boolean hasMove = false;
for (int i=0; i<board.length; i++) {
if (isValidMove(i, otherPlayer)) {
hasMove = true;
break;
}
}
// If the other player has at least one valid move, switch players.
if (hasMove) {
currentPlayer = otherPlayer;
}
// Otherwise, stick with the current player.
else {
// Make sure the current player has a valid move. Otherwise, the game must be over.
hasMove = false;
for (int i=0; i<board.length; i++) {
if (isValidMove(i, currentPlayer)) {
hasMove = true;
break;
}
}
if (!hasMove) {
gameFinished = true;
}
}
return true;
}
/**
* Returns a String representation of the current game board (ASCII art). A fixed
* width font is necessary to display the String properly.
*
* @return a String representation of the current game board.
*/
public String printBoard() {
StringBuffer buf = new StringBuffer();
buf.append("+----------------+\n");
for (int i=0; i<64; i++) {
if (i%8 == 0) {
buf.append("|");
}
if (board[i] == BLANK) {
buf.append(" ");
}
else if (board[i] == WHITE) {
buf.append(" w");
}
else {
buf.append(" b");
}
if (i%8 == 7) {
buf.append("|\n");
}
}
buf.append("+----------------+");
return buf.toString();
}
/**
* Returns true if the specified player has a valid move at the specified position (ignoring
* whose turn it is currently).
*
* @param position the position.
* @param player the player.
* @return return true if the player has a move at the position.
*/
private boolean isValidMove(int position, int player) {
if (position < 0 || position > 63) {
return false;
}
if (board[position] != BLANK) {
return false;
}
else {
return getFlipCount(position, player, false) > 0;
}
}
/**
* Computes the number of stones that would be flipped by executing a move at the specified position.
* If <tt>doFlip</tt> is true, the game board will be updated.
*
* @param position the position for the move.
* @param player the player.
* @param doFlips true if stones should be actually flipped; false if flips should only
* be calculated hypothetically.
* @return the number of stones that were or that would be flipped by the move.
*/
private synchronized int getFlipCount(int position, int player, boolean doFlips) {
int flipCount = 0;
// Traverse vertically, horizontally, and diagonally to flip pieces.
// Going left horizontally.
if (position%8 != 0) {
for (int i=position-1; i%8!=0; i--) {
if (board[i] == BLANK) {
break;
}
else if (board[i] == player) {
for (int j=0; j<flipBufferSize; j++) {
flipCount++;
if (doFlips) {
board[flipBuffer[j]] = player;
}
}
break;
}
flipBuffer[flipBufferSize++] = i;
}
// Reset flip buffer.
flipBufferSize = 0;
}
// Going right horizontally.
if (position%8 != 7) {
for (int i=position+1; i%8!=7; i++) {
if (board[i] == BLANK) {
break;
}
else if (board[i] == player) {
for (int j=0; j<flipBufferSize; j++) {
flipCount++;
if (doFlips) {
board[flipBuffer[j]] = player;
}
}
break;
}
flipBuffer[flipBufferSize++] = i;
}
// Reset flip buffer.
flipBufferSize = 0;
}
// Going up vertically.
if (position/8 >= 2) {
for (int i=position-8; (i/8)>=2; i-=8) {
if (board[i] == BLANK) {
break;
}
else if (board[i] == player) {
for (int j=0; j<flipBufferSize; j++) {
flipCount++;
if (doFlips) {
board[flipBuffer[j]] = player;
}
}
break;
}
flipBuffer[flipBufferSize++] = i;
}
// Reset flip buffer.
flipBufferSize = 0;
}
// Going down vertically.
if (position/8 <= 7) {
for (int i=position+8; i/8<=7; i+=8) {
if (board[i] == BLANK) {
break;
}
else if (board[i] == player) {
for (int j=0; j<flipBufferSize; j++) {
flipCount++;
if (doFlips) {
board[flipBuffer[j]] = player;
}
}
break;
}
flipBuffer[flipBufferSize++] = i;
}
// Reset flip buffer.
flipBufferSize = 0;
}
// Diagonal up-left
if (position/8 >= 2 && position%8 != 0) {
for (int i=position-9; i/8>=2 && i%8!=0; i-=9) {
if (board[i] == BLANK) {
break;
}
else if (board[i] == player) {
for (int j=0; j<flipBufferSize; j++) {
flipCount++;
if (doFlips) {
board[flipBuffer[j]] = player;
}
}
break;
}
flipBuffer[flipBufferSize++] = i;
}
// Reset flip buffer.
flipBufferSize = 0;
}
// Diagonal up-right
if (position/8 >= 2 && position%8 != 7) {
for (int i=position-7; i/8>=2 && i%8!=7; i-=7) {
if (board[i] == BLANK) {
break;
}
else if (board[i] == player) {
for (int j=0; j<flipBufferSize; j++) {
flipCount++;
if (doFlips) {
board[flipBuffer[j]] = player;
}
}
break;
}
flipBuffer[flipBufferSize++] = i;
}
// Reset flip buffer.
flipBufferSize = 0;
}
// Diagonal down-left
if (position/8 <= 7 && position%8 != 0) {
for (int i=position+7; i/8<=7 && i%8!=0; i+=7) {
if (board[i] == BLANK) {
break;
}
else if (board[i] == player) {
for (int j=0; j<flipBufferSize; j++) {
flipCount++;
if (doFlips) {
board[flipBuffer[j]] = player;
}
}
break;
}
flipBuffer[flipBufferSize++] = i;
}
// Reset flip buffer.
flipBufferSize = 0;
}
// Diagonal down-right
if (position/8 <= 7 && position%8 != 7) {
for (int i=position+9; i/8<=7 && i%8!=7; i+=9) {
if (board[i] == BLANK) {
break;
}
else if (board[i] == player) {
for (int j=0; j<flipBufferSize; j++) {
flipCount++;
if (doFlips) {
board[flipBuffer[j]] = player;
}
}
break;
}
flipBuffer[flipBufferSize++] = i;
}
// Reset flip buffer.
flipBufferSize = 0;
}
return flipCount;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?