【实例简介】
【实例截图】
【核心代码】
package com.pan.ttt;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
* 井字棋游戏: 二人对战版,玩家轮流操作
*/
@SuppressWarnings("serial")
public class TTTGame extends JFrame {
//游戏面板为3x3九宫格
public static final int ROWS = 3;
public static final int COLUMNS = 3;
//定义画图所用常量
public static final int CELL_SIZE = 100; //cell的宽度和高度
public static final int CANVAS_WIDTH = CELL_SIZE * COLUMNS; //画布尺寸
public static final int CANVAS_HEIGHT = CELL_SIZE * ROWS;
public static final int GRID_WIDTH = 8; //栅格线宽度
public static final int GRID_WIDHT_HALF = GRID_WIDTH / 2;
public static final int CELL_PADDING = CELL_SIZE / 6;
public static final int SYMBOL_SIZE = CELL_SIZE - CELL_PADDING * 2;
public static final int SYMBOL_STROKE_WIDTH = 8; //笔划宽度
//游戏过程状态
public enum GameState {
PLAYING, DRAW, CROSS_WON, NOUGHT_WON
}
//代表seeds与cell内容
public enum Seed {
EMPTY, CROSS, NOUGHT
}
private GameState currentState; //当前游戏状态
private Seed currentPlayer; //当前玩家
private Seed[][] board ; //定义游戏面板
private DrawCanvas drawCanvas; //定义游戏面板画布
private JLabel statusBar; //显示游戏过程中状态
//用于设定游戏与GUI构件
public TTTGame() {
drawCanvas = new DrawCanvas(); //构造画布
drawCanvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
//鼠标单击事件
drawCanvas.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) { //鼠标单击事件处理
int mouseX = e.getX();
int mouseY = e.getY();
//获取单击位置
int rowSelected = mouseY / CELL_SIZE;
int colSelected = mouseX / CELL_SIZE;
if (currentState == GameState.PLAYING) {
if (rowSelected >= 0 && rowSelected < ROWS && colSelected >= 0
&& colSelected < COLUMNS && board[rowSelected][colSelected] == Seed.EMPTY) {
board[rowSelected][colSelected] = currentPlayer;
updateGame(currentPlayer, rowSelected, colSelected); //更新状态
//切换用户
currentPlayer = (currentPlayer == Seed.CROSS) ? Seed.NOUGHT : Seed.CROSS;
}
} else { //游戏结束,再来一局
initTTTGame();
}
//刷新游戏面板
repaint();
}
});
// 设置状态栏显示的信息
statusBar = new JLabel(" ");
statusBar.setFont(new Font(Font.DIALOG_INPUT, Font.BOLD, 15));
statusBar.setBorder(BorderFactory.createEmptyBorder(2, 5, 4, 5));
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
cp.add(drawCanvas, BorderLayout.CENTER);
cp.add(statusBar, BorderLayout.PAGE_END);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setTitle("井字棋游戏-双人对战版");
setResizable(false);
setVisible(true);
board = new Seed[ROWS][COLUMNS]; //分配数组
initTTTGame(); //初始化
}
//初始化
public void initTTTGame() {
for (int row = 0; row < ROWS; row) {
for (int col = 0; col < COLUMNS; col) {
board[row][col] = Seed.EMPTY; //置空
}
}
currentState = GameState.PLAYING; //就绪
currentPlayer = Seed.CROSS; //设置第一次操作玩家
}
//玩家操作后更新状态
public void updateGame(Seed theSeed, int rowSelected, int colSelected) {
if (hasWon(theSeed, rowSelected, colSelected)) { //检擦获胜状态
currentState = (theSeed == Seed.CROSS) ? GameState.CROSS_WON : GameState.NOUGHT_WON;
} else if (isDraw()) { //检查是否还有空单元格
currentState = GameState.DRAW;
}
}
//无空单元格返回true,否则返回false
public boolean isDraw() {
for (int row = 0; row < ROWS; row) {
for (int col = 0; col < COLUMNS; col) {
if (board[row][col] == Seed.EMPTY) {
return false;
}
}
}
return true;
}
//获胜返回true
public boolean hasWon(Seed theSeed, int rowSelected, int colSelected) {
return (board[rowSelected][0] == theSeed //3-in-the-row
&& board[rowSelected][1] == theSeed
&& board[rowSelected][2] == theSeed
|| board[0][colSelected] == theSeed //3-in-the-column
&& board[1][colSelected] == theSeed
&& board[2][colSelected] == theSeed
|| rowSelected == colSelected //3-in-the-diagonal
&& board[0][0] == theSeed
&& board[1][1] == theSeed
&& board[2][2] == theSeed
|| rowSelected colSelected == 2 //3-in-the-opposite-diagonal
&& board[0][2] == theSeed
&& board[1][1] == theSeed
&& board[2][0] == theSeed);
}
//定义graphics drawing
class DrawCanvas extends JPanel {
@Override
public void paintComponent(Graphics graphics) {
super.paintComponent(graphics); //填充背景
setBackground(Color.WHITE); //设置背景色
//画出栅格线
graphics.setColor(Color.GREEN);
for (int row = 1; row < ROWS; row) {
graphics.fillRoundRect(0, CELL_SIZE * row - GRID_WIDHT_HALF,
CANVAS_WIDTH-1, GRID_WIDTH, GRID_WIDTH, GRID_WIDTH);
}
for (int col = 1; col < COLUMNS; col) {
graphics.fillRoundRect(CELL_SIZE * col - GRID_WIDHT_HALF, 0,
GRID_WIDTH, CANVAS_HEIGHT-1, GRID_WIDTH, GRID_WIDTH);
}
//画出当前游戏进行状态
Graphics2D graphics2D = (Graphics2D)graphics;
graphics2D.setStroke(new BasicStroke(SYMBOL_STROKE_WIDTH, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND));
for (int row = 0; row < ROWS; row) {
for (int col = 0; col < COLUMNS; col) {
int x1 = col * CELL_SIZE CELL_PADDING;
int y1 = row * CELL_SIZE CELL_PADDING;
if (board[row][col] == Seed.CROSS) {
graphics2D.setColor(Color.RED);
int x2 = (col 1) * CELL_SIZE - CELL_PADDING;
int y2 = (row 1) * CELL_SIZE - CELL_PADDING;
graphics2D.drawLine(x1, y1, x2, y2);
graphics2D.drawLine(x2, y1, x1, y2);
} else if (board[row][col] == Seed.NOUGHT) {
graphics2D.setColor(Color.BLUE);
graphics2D.drawOval(x1, y1, SYMBOL_SIZE, SYMBOL_SIZE);
}
}
}
//打印状态栏信息
if (currentState == GameState.PLAYING) {
statusBar.setForeground(Color.BLACK);
if (currentPlayer == Seed.CROSS) {
statusBar.setText("轮到X玩家");
} else {
statusBar.setText("轮到O玩家");
}
} else if (currentState == GameState.DRAW) {
statusBar.setForeground(Color.RED);
statusBar.setText("平局!单击再来一局.");
} else if (currentState == GameState.CROSS_WON) {
statusBar.setForeground(Color.RED);
statusBar.setText("X玩家获胜!单击再来一局.");
} else if (currentState == GameState.NOUGHT_WON) {
statusBar.setForeground(Color.RED);
statusBar.setText("O玩家获胜!单击再来一局.");
}
}
}
}