设计一个五子棋游戏,实现悔棋、保存棋谱、棋谱复盘等功能。
窗口程序依赖于javafx,编译运行请使用jdk1.8。
完成结果如下图:
完整代码:
- 棋子类
import javafx.scene.paint.Color;
/**
* 棋子描述类
*/
public class Chess {
/**
* 棋子横坐标
*/
private final int x;
/**
* 棋子纵坐标
*/
private final int y;
/**
* 棋子颜色
*/
private final Color color;
public Chess(int x, int y, Color color) {
this.x = x;
this.y = y;
this.color = color;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Color getColor() {
return color;
}
@Override
public String toString() {
return "Chess [x=" + x + ", y=" + y + ", color=" + color + "]";
}
}
- 主框架类
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;
import java.io.*;
import java.util.ArrayList;
import java.util.Optional;
import java.util.function.Predicate;
/**
* 主框架类
*/
public class MyChessApp extends Application {
/**
* 棋盘宽度
*/
private static final int WIDTH = 600;
/**
* 棋盘高度
*/
private static final int HEIGHT = 600;
/**
* 棋盘中线与线之间的距离
*/
private static final int PADDING = 40;
/**
* 棋盘与边框之间的距离
*/
private static final int MARGIN = 20;
/**
* 棋盘中水平线与垂直线的个数
*/
private static final int LINE_COUNT = 14;
/**
* 棋盘对象
*/
private Pane pane;
/**
* 当前落子是否为黑子
*/
private boolean isBlack = true;
/**
* 记录棋盘
*/
private Chess[][] chesses = new Chess[LINE_COUNT][LINE_COUNT];
/**
* 记录棋子顺序
*/
private Chess[] cs = new Chess[LINE_COUNT * LINE_COUNT];
/**
* 棋盘上棋子个数
*/
private int count = 0;
/**
* 是否胜利
*/
private boolean isWin = false;
/**
* 舞台对象
*/
private Stage stage;
@Override
public void start(Stage stage) {
this.stage = stage;
// 获取画板对象
this.pane = getPane();
// 落子
moveInChess();
// 创建场景对象
Scene scene = new Scene(pane, WIDTH, HEIGHT);
stage.setScene(scene);
stage.setTitle("五子棋");
stage.setOnCloseRequest(event -> {
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("退出");
alert.setHeaderText("确认提出吗?");
Optional<ButtonType> optional = alert.showAndWait();
if (optional.isPresent() && optional.get() == ButtonType.CANCEL) {
event.consume();
}
});
stage.show();
}
/**
* 落子功能
*/
private void moveInChess() {
// 给画板对象绑定鼠标点击事件
pane.setOnMouseClicked(event -> {
if (isWin) {
return;
}
// 获取鼠标点击的坐标
double x = event.getX();
double y = event.getY();
// System.out.println(x + " " + y);
if (!(x >= MARGIN && x <= MARGIN + (LINE_COUNT - 1) * PADDING && y >= MARGIN
&& y <= MARGIN + (LINE_COUNT - 1) * PADDING)) {
return;
}
// 根据鼠标点击位置计算棋子坐标
int chessX = ((int) x - MARGIN + PADDING / 2) / PADDING;
int chessY = ((int) y - MARGIN + PADDING / 2) / PADDING;
// System.out.println(_x + " " + _y);
if (chesses[chessX][chessY] != null) {
// System.out.println("已经有棋子了");
return;
}
// 绘制棋子
Chess chess = drawChess(chessX, chessY);
if (isWin(chess)) {
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("游戏结束");
String name;
if (chess.getColor() == Color.BLACK) {
name = "黑子";
} else {
name = "白子";
}
alert.setHeaderText(name + "胜利了");
alert.showAndWait();
isWin = true;
}
});
}
/**
* 绘制棋子
*/
private Chess drawChess(int chessX, int chessY) {
Circle circle;
Chess chess;
if (isBlack) {
circle = new Circle(chessX * PADDING + MARGIN, chessY * PADDING + MARGIN, 15, Color.BLACK);
chess = new Chess(chessX, chessY, Color.BLACK);
isBlack = false;
} else {
circle = new Circle(chessX * PADDING + MARGIN, chessY * PADDING + MARGIN, 15, Color.WHITE);
chess = new Chess(chessX, chessY, Color.WHITE);
isBlack = true;
}
chesses[chessX][chessY] = chess;
cs[count++] = chess;
pane.getChildren().add(circle);
return chess;
}
/**
* 创建画板对象
*/
private Pane getPane() {
// 创建画板对象
Pane pane = new Pane();
// 设置画板背景颜色
pane.setBackground(new Background(new BackgroundFill(Color.BEIGE, null, null)));
// 绘制棋盘
int increment = 0;
for (int i = 0; i < LINE_COUNT; i++) {
Line rowLine = new Line(MARGIN, MARGIN + increment, MARGIN + (LINE_COUNT - 1) * PADDING,
MARGIN + increment);
Line colLine = new Line(MARGIN + increment, MARGIN, MARGIN + increment,
MARGIN + (LINE_COUNT - 1) * PADDING);
pane.getChildren().add(rowLine);
pane.getChildren().add(colLine);
increment += PADDING;
}
// 再来一局按钮
Button startButton = getStartButton();
// 悔棋按钮
Button retractButton = getRetractButton();
// 退出按钮
Button quitButton = getQuitButton();
// 保存棋谱按钮
Button saveButton = getSaveButton();
// 保存打谱按钮
Button scoreButton = getScoreButton();
pane.getChildren().add(startButton);
pane.getChildren().add(retractButton);
pane.getChildren().add(quitButton);
pane.getChildren().add(saveButton);
pane.getChildren().add(scoreButton);
return pane;
}
/**
* 获取打谱按钮
*/
private Button getScoreButton() {
Button scoreButton = new Button("棋谱复盘");
scoreButton.setPrefSize(80, 30);
scoreButton.setLayoutX(WIDTH / 15.0 + 100 * 3);
scoreButton.setLayoutY(HEIGHT - 40);
scoreButton.setOnAction(event -> {
FileChooser fileChooser = new FileChooser();
fileChooser.getExtensionFilters().addAll(new ExtensionFilter("棋谱文件", "*.qipu"),
new ExtensionFilter("所有文件", "*.*"));
File file = fileChooser.showOpenDialog(stage);
if (file == null) {
return;
}
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
ArrayList<String> cheesiness = new ArrayList<>();
while ((line = br.readLine()) != null) {
cheesiness.add(line);
}
br.close();
resetChessBoard();
Button next = new Button(">");
next.setPrefSize(40, 40);
next.setLayoutX(WIDTH - 40);
next.setLayoutY(100);
next.setOnAction(event13 -> {
if (count >= cheesiness.size()) {
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("提示");
alert.setHeaderText("没有下一步了");
alert.showAndWait();
return;
}
String[] info = cheesiness.get(count).split(",");
drawChess(Integer.parseInt(info[0]), Integer.parseInt(info[1]));
});
pane.getChildren().add(next);
Button pre = new Button("<");
pre.setPrefSize(40, 40);
pre.setLayoutX(WIDTH - 40);
pre.setLayoutY(150);
pre.setOnAction(event12 -> retract());
pane.getChildren().add(pre);
Button exit = new Button("x");
exit.setPrefSize(40, 40);
exit.setLayoutX(WIDTH - 40);
exit.setLayoutY(200);
exit.setOnAction(event1 -> {
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("提示");
alert.setHeaderText("确定退出打谱?");
Optional<ButtonType> optional = alert.showAndWait();
if (optional.isPresent() && optional.get() == ButtonType.OK) {
resetChessBoard();
pane.getChildren().remove(pane.getChildren().size() - 3, pane.getChildren().size());
}
});
pane.getChildren().add(exit);
} catch (IOException e) {
e.printStackTrace();
}
});
return scoreButton;
}
/**
* 获取保存棋谱按钮
*/
private Button getSaveButton() {
Button saveButton = new Button("保存棋谱");
saveButton.setPrefSize(80, 30);
saveButton.setLayoutX(WIDTH / 15.0 + 100 * 2);
saveButton.setLayoutY(HEIGHT - 40);
saveButton.setOnAction(event -> {
FileChooser fileChooser = new FileChooser();
fileChooser.getExtensionFilters().addAll(new ExtensionFilter("棋谱文件", "*.qipu"),
new ExtensionFilter("所有文件", "*.*"));
File file = fileChooser.showSaveDialog(stage);
if (file == null) {
return;
}
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
for (int i = 0; i < count; i++) {
bw.write(cs[i].getX() + "," + cs[i].getY() + "," + cs[i].getColor());
bw.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
});
return saveButton;
}
/**
* 获取退出按钮
*/
private Button getQuitButton() {
Button quitButton = new Button("退出");
quitButton.setPrefSize(80, 30);
quitButton.setLayoutX(WIDTH / 15.0 + 100 * 4);
quitButton.setLayoutY(HEIGHT - 40);
quitButton.setOnAction(event -> {
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("退出");
alert.setHeaderText("确认提出吗?");
Optional<ButtonType> optional = alert.showAndWait();
if (optional.isPresent() && optional.get() == ButtonType.OK) {
System.exit(0);
}
});
return quitButton;
}
/**
* 获取悔棋按钮
*/
private Button getRetractButton() {
Button retractButton = new Button("悔棋");
retractButton.setPrefSize(80, 30);
retractButton.setLayoutX(WIDTH / 15.0 + 100);
retractButton.setLayoutY(HEIGHT - 40);
retractButton.setOnAction(event -> retract());
return retractButton;
}
/**
* 获取再来一局按钮
*/
private Button getStartButton() {
// 添加按钮对象
Button startButton = new Button("再来一局");
startButton.setPrefSize(80, 30);
startButton.setLayoutX(WIDTH / 15.0);
startButton.setLayoutY(HEIGHT - 40);
// 给按钮对象绑定鼠标点击事件
startButton.setOnAction(event -> resetChessBoard());
return startButton;
}
/**
* 悔棋
*/
private void retract() {
if (isWin) {
return;
}
if (count > 0) {
pane.getChildren().remove(pane.getChildren().size() - 1);
isBlack = !isBlack;
Chess chess = cs[--count];
chesses[chess.getX()][chess.getY()] = null;
cs[count] = null;
}
}
/**
* 重置棋盘
*/
private void resetChessBoard() {
pane.getChildren().removeIf((Predicate<Object>) t -> t instanceof Circle);
count = 0;
chesses = new Chess[LINE_COUNT][LINE_COUNT];
cs = new Chess[LINE_COUNT * LINE_COUNT];
isBlack = true;
isWin = false;
}
/**
* 判断胜负
*/
private boolean isWin(Chess chess) {
int x = chess.getX();
int y = chess.getY();
Color color = chess.getColor();
// 向右横向判断
for (int i = x + 1; i <= x + 4 && i < LINE_COUNT; i++) {
Chess c = chesses[i][y];
if (c == null || !color.equals(c.getColor())) {
break;
}
if (i == x + 4) {
return true;
}
}
// 向左横向判断
for (int i = x - 1; i >= x - 4 && i >= 0; i--) {
Chess c = chesses[i][y];
if (c == null || !color.equals(c.getColor())) {
break;
}
if (i == x - 4) {
return true;
}
}
// 向上纵向判断
for (int i = y - 1; i >= y - 4 && i >= 0; i--) {
Chess c = chesses[x][i];
if (c == null || !color.equals(c.getColor())) {
break;
}
if (i == y - 4) {
return true;
}
}
// 向下纵向判断
for (int i = y + 1; i <= y + 4 && i < LINE_COUNT; i++) {
Chess c = chesses[x][i];
if (c == null || !color.equals(c.getColor())) {
break;
}
if (i == y + 4) {
return true;
}
}
// 向右上斜向判断
for (int i = x + 1, j = y - 1; i <= x + 4 && j >= y - 4 && i < LINE_COUNT && j >= 0; i++, j--) {
Chess c = chesses[i][j];
if (c == null || !color.equals(c.getColor())) {
break;
}
if (i == x + 4 && j == y - 4) {
return true;
}
}
// 向左上斜向判断
for (int i = x - 1, j = y - 1; i >= x - 4 && j >= y - 4 && i >= 0 && j >= 0; i--, j--) {
Chess c = chesses[i][j];
if (c == null || !color.equals(c.getColor())) {
break;
}
if (i == x - 4 && j == y - 4) {
return true;
}
}
// 向左下斜向判断
for (int i = x - 1, j = y + 1; i >= x - 4 && j <= y + 4 && i >= 0 && j < LINE_COUNT; i--, j++) {
Chess c = chesses[i][j];
if (c == null || !color.equals(c.getColor())) {
break;
}
if (i == x - 4 && j == y + 4) {
return true;
}
}
// 向右下斜向判断
for (int i = x + 1, j = y + 1; i <= x + 4 && j <= y + 4 && i < LINE_COUNT && j < LINE_COUNT; i++, j++) {
Chess c = chesses[i][j];
if (c == null || !color.equals(c.getColor())) {
break;
}
if (i == x + 4 && j == y + 4) {
return true;
}
}
return false;
}
public static void main(String[] args) {
launch(args);
}
}
评论 (0)