📄 chessboard.java
字号:
/**
* 棋盘类: ChessBoard.class
* @author obtuseSword
* @date 2008-05-29
*/
import java.util.*;
import java.awt.*;
import javax.swing.*;
public class ChessBoard extends JPanel{
/************* 公开字段:开始 ***************/
// (静态)棋子枚举类型: 白棋、黑棋、无棋
public static enum ChessType{
WHITE_CHESS, BLACK_CHESS, NONE_CHESS
};
// (静态)玩家类型: 黑方、白方
public static enum PlayerType{
BLACK_PLAYER, WHITE_PLAYER
};
// (静态)对弈局面: 进行中、黑方胜、白方胜、平局
public static enum GameState{
PLAYING, BLACK_WON, WHITE_WON, TIE
};
// 棋盘规模: 高度(行数)、宽度(列数)
public final int boardHeight = 15, boardWidth = 15;
// 棋盘左上角的坐标及相邻的两个落子点的间距
// (利用这两个信息确定棋盘上各落子点的坐标)
public final Point base = new Point(6,6);
public final double dis = 29.2;
/**----------- 公开字段:结束 -------------**/
/************* 公开方法:开始 ***************/
// 构造函数(初始化棋盘为一个黑子在中心,其余无棋子)
public ChessBoard(){
restart();
}
// 重新开始游戏
public void restart(){
// 清空棋盘
for(int i = 0; i < boardHeight; i++)
Arrays.fill( board[i], ChessType.NONE_CHESS );
// 黑方先手
board[7][7] = ChessType.BLACK_CHESS;
// 已下棋子数归一
chessCount = 1;
// 当前待落子玩家初始化为“白方”
playingPlayer = PlayerType.WHITE_PLAYER;
// 游戏局面状态为“进行中”
state = GameState.PLAYING;
}
// (GUI相关)覆盖 JComponent 的组件绘制方法
public void paintComponent(Graphics g){
//---------- 加载棋盘与棋子的图像文件 -----------//
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(chessBoardImg, 1);
tracker.addImage(blackChessImg, 2);
tracker.addImage(whiteChessImg, 3);
try{
tracker.waitForID(1);
tracker.waitForID(2);
tracker.waitForID(3);
}catch(InterruptedException exception){
// 图像文件加载异常处理
Font font = new Font("宋体", Font.PLAIN, 40);
g.setFont(font);
g.drawString("图像文件加载异常!", 20, 20);
}
//---------- 在面板中绘制棋盘及棋子 ------------//
g.drawImage(chessBoardImg, 0, 0, null);
for(int i = 0; i < boardHeight; i++){
for(int j = 0; j < boardWidth; j++){
int x = (int)(base.getX() + j * dis);
int y = (int)(base.getY() + i * dis);
switch( board[i][j] ){
case BLACK_CHESS:
g.drawImage(blackChessImg, x, y, null);
break;
case WHITE_CHESS:
g.drawImage(whiteChessImg, x, y, null);
break;
default:
break;
}
}
}
//------------- 设置面板大小 ----------------//
setSize(chessBoardImg.getWidth(null), chessBoardImg.getHeight(null) + 60);
//------------- 产生提示信息 ----------------//
String tips = ""; // 提示信息
switch( state ){
case BLACK_WON:
tips = "黑方获胜";
break;
case WHITE_WON:
tips = "白方获胜";
break;
case TIE:
tips = "平局";
break;
case PLAYING:
if( playingPlayer == PlayerType.BLACK_PLAYER )
tips = "请黑方落子";
else
tips = "请白方落子";
break;
default:
break;
}
//------------- 显示提示信息 ----------------//
int tips_base_x = 0; // 提示信息区域基点(左上角)横坐标
int tips_base_y = // 提示信息区域基点(左上角)纵坐标
getLocation().y + chessBoardImg.getHeight(null) + 1;
// 绘制提示信息区域边框
g.setColor(Color.LIGHT_GRAY);
g.fillRect(tips_base_x, tips_base_y, getWidth() - 1, 78);
// 显示提示信息
Font font = new Font("黑体", Font.BOLD, 32);
g.setFont(font);
g.setColor(Color.BLACK);
g.drawString(tips, getWidth() / 2 - 75, tips_base_y + 40);
}
// 获取棋盘上某一位置的棋子信息
public ChessType getChess(int row,int col){
return board[row][col];
}
// 获取当前待下子的玩家
public PlayerType getPlayingPlayer(){
return playingPlayer;
}
// 在棋盘的某一位置落子,并返回落子后局面状态
public GameState go(int row,int col){
// 对非法的落子请求不予理睬
if( row < 0 || row > boardHeight )
return state;
if( col <0 || col > boardWidth )
return state;
if( state != GameState.PLAYING )
return state;
if( board[row][col] != ChessType.NONE_CHESS )
return state;
// 处理合法的落子请求
if( playingPlayer == PlayerType.BLACK_PLAYER ){
board[row][col] = ChessType.BLACK_CHESS;
playingPlayer = PlayerType.WHITE_PLAYER;
}else{
board[row][col] = ChessType.WHITE_CHESS;
playingPlayer = PlayerType.BLACK_PLAYER;
}
chessCount++; // 落子数增一
// 刷新棋盘
repaint();
// 判断局面状态并返回
return judge();
}
// 判断当前局面
public GameState judge(){
// 枚举可能的五子连珠的起始点(不包括左斜的五子连珠)
for(int i = 0; i < boardHeight - 4; i++){
for(int j = 0; j < boardWidth - 4; j++){
// 如果有子,判断以其为起始点是否构成五子连珠
if( board[i][j] != ChessType.NONE_CHESS ){
// 横向成五子连珠?
int k = 1;
while( k < 5 && board[i][j+k] == board[i][j] )
k++;
// 纵向成五子连珠?
k = k < 5 ? 1 : 5;
while( k < 5 && board[i+k][j] == board[i][j] )
k++;
// 右斜成五子连珠?
k = k < 5 ? 1 : 5;
while( k < 5 && board[i+k][j+k] == board[i][j] )
k++;
// 如果发现五子连珠,直接返回结果,不必再判断下去
if( k == 5 ){
if( board[i][j] == ChessType.BLACK_CHESS )
return state = GameState.BLACK_WON;
else
return state = GameState.WHITE_WON;
}
}
}
}
// 枚举可能的五子连珠的起始点(仅包括作协的五子连珠)
for(int i = 0; i < boardHeight - 4; i++){
for(int j = 4; j < boardWidth; j++){
// 如果有子,判断以其为起始点是否构成五子连珠
if( board[i][j] != ChessType.NONE_CHESS ){
// 左斜成五子连珠?
int k = 1;
while( k < 5 && board[i+k][j-k] == board[i][j] )
k++;
// 如果发现五子连珠,直接返回结果,不必再判断下去
if( k == 5 ){
if( board[i][j] == ChessType.BLACK_CHESS )
return state = GameState.BLACK_WON;
else
return state = GameState.WHITE_WON;
}
}
}
}
// 如果未出现五子连珠,还要判断是否平局,即棋盘已满
if( chessCount == boardWidth * boardHeight )
return state = GameState.TIE;
// 以上情形皆未出现,表示游戏还在进行当中
return GameState.PLAYING;
}
/**----------- 公开方法:结束 -------------**/
/************* 私有方法:开始 ***************/
/**----------- 私有方法:结束 -------------**/
/************* 私有字段:开始 ***************/
// 棋盘数据结构: 棋子为元素的二维数组
private ChessType[][] board =
new ChessType[boardHeight][boardWidth];
// 棋盘的图像
private Image chessBoardImg =
Toolkit.getDefaultToolkit().getImage("img/chessBoard.jpg");
// 黑子与白子的图像
private Image blackChessImg =
Toolkit.getDefaultToolkit().getImage("img/blackChess.gif");
private Image whiteChessImg =
Toolkit.getDefaultToolkit().getImage("img/whiteChess.gif");
// 下棋中的玩家类型(黑方、白方)
private PlayerType playingPlayer;
// 当前局面状态
private GameState state;
// 已经落到棋盘上的棋子总数
private int chessCount;
/**----------- 私有字段:结束 ------------**/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -