Java大作业五子棋实验报告
实验目的
通过此次实验,对这一学期学习的内容尤其是界面开发部分做了一个很好的回顾,看似简单的五子棋程序,设计好也确实费了我一点功夫
功能模块简介和系统结构图
ChessGame类
作为布局的基类,设置一些基本的按钮,用于启动程序,接收一些基本参数的传入(如谁先行)
ChessPane类
本类主要保存一些关于界面的基本信息,起到绘制界面,绘制棋子的功能
UserPlay类
本类存储一些关于用户动作的基本信息,接受并处理PlayAction传回的动作信息
PlayAction类
本类用于接收用户传入的关于棋局的动作信息
系统结构图
系统主界面设计及运行说明
主界面设计
如下图所示
运行说明
启动程序后,先选择先行方,如果不选择,默认黑棋先行,此后,双方轮流下子,直到一方先连成五子,游戏结束。
主要的源程序代码
使用到的包
import javafx
.application
.*
;
import javafx
.geometry
.Insets
;
import javafx
.geometry
.Pos
;
import javafx
.scene
.*
;
import javafx
.scene
.control
.Alert
;
import javafx
.scene
.control
.Button
;
import javafx
.scene
.control
.Dialog
;
import javafx
.scene
.input
.MouseEvent
;
import javafx
.scene
.paint
.Color
;
import javafx
.stage
.*
;
import javafx
.scene
.layout
.*
;
import javafx
.scene
.text
.*
;
import javafx
.scene
.canvas
.*
;
import javafx
.event
.*
;
ChessGame类
public class ChessGame extends Application {
public static void main(String
[] args
) {
Application
.launch(args
);
}
@Override
public void start(Stage primaryStage
) throws Exception
{
ChessPane chessPane
= new ChessPane();
BorderPane borderPane
= new BorderPane();
UserPlay userPlay
= new UserPlay();
PlayAction playAction
= new PlayAction(chessPane
, userPlay
);
chessPane
.setOnMouseClicked(playAction
);
borderPane
.setCenter(chessPane
);
VBox vBoxButton
= new VBox();
vBoxButton
.getChildren().addAll();
borderPane
.setRight(vBoxButton
);
vBoxButton
.setSpacing(100);
vBoxButton
.setAlignment(Pos
.CENTER
);
vBoxButton
.setPadding(new Insets(0, 30, 0, 0));
Button buttonReplay
= new Button("Try again");
buttonReplay
.setPrefHeight(50);
buttonReplay
.setPrefWidth(100);
buttonReplay
.setStyle("-fx-background-color:linear-gradient(to right,#00fffc,#fff600);-fx-background-radius:25 ;-fx-border-radius:25;-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.7), 10, 0, 0, 1);");
buttonReplay
.setOnMouseClicked(event
-> {
primaryStage
.close();
});
Button buttonExit
= new Button("Exit");
vBoxButton
.getChildren().add(buttonExit
);
buttonExit
.setPrefHeight(50);
buttonExit
.setPrefWidth(100);
buttonExit
.setStyle("-fx-background-color:linear-gradient(to right,#d580ff,#80d5ff);-fx-background-radius:25 ;-fx-border-radius:25;-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.7), 10, 0, 0, 1);");
buttonExit
.setOnMouseClicked(event
-> {
primaryStage
.close();
});
Scene scene
= new Scene(borderPane
, 800, 800);
primaryStage
.setScene(scene
);
primaryStage
.setTitle("五子棋");
primaryStage
.show();
BorderPane borderPaneFirst
= new BorderPane();
Scene sceneFirst
= new Scene(borderPaneFirst
, 300, 300);
HBox hBoxFirst
= new HBox();
borderPaneFirst
.setCenter(hBoxFirst
);
hBoxFirst
.setAlignment(Pos
.CENTER
);
hBoxFirst
.setSpacing(50);
Button buttonFirstBlack
= new Button("black first");
buttonFirstBlack
.setPrefWidth(100);
buttonFirstBlack
.setPrefHeight(50);
buttonFirstBlack
.setStyle("-fx-background-color:linear-gradient(to right,#00fffc,#fff600);-fx-background-radius:25 ;-fx-border-radius:25;-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.7), 10, 0, 0, 1);");
hBoxFirst
.getChildren().add(buttonFirstBlack
);
Button buttonFirstWhite
= new Button("white first");
buttonFirstWhite
.setPrefHeight(50);
buttonFirstWhite
.setPrefWidth(100);
buttonFirstWhite
.setStyle("-fx-background-color:linear-gradient(to right,#FFFFCC,#FFCCFF);-fx-background-radius:25 ;-fx-border-radius:25;-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.7), 10, 0, 0, 1);");
hBoxFirst
.getChildren().add(buttonFirstWhite
);
Stage stageWhoFirst
= new Stage();
stageWhoFirst
.setScene(sceneFirst
);
stageWhoFirst
.setTitle("Who first?");
stageWhoFirst
.show();
buttonFirstBlack
.setOnMouseClicked(event
-> {
userPlay
.setCurrentSide(1);
stageWhoFirst
.close();
});
buttonFirstWhite
.setOnMouseClicked(event
-> {
userPlay
.setCurrentSide(2);
stageWhoFirst
.close();
});
}
}
UserPlay类
class UserPlay extends ChessPane {
private int sideLength
= getSideLength();
private double width
= getWidth();
private double height
= getPaneHeight();
private double cellLen
= getCellLen();
private int currentSide
= 1;
public int getCurrentSide() {
return currentSide
;
}
public void setCurrentSide(int currentSide
) {
this.currentSide
= currentSide
;
}
private int[][] chess
= new int[sideLength
+ 10][sideLength
+ 10];
void initChess() {
for (int i
= 0; i
<= sideLength
; i
++) {
for (int j
= 0; j
<= sideLength
; j
++) {
chess
[i
][j
] = 0;
}
}
}
public int realX
, realY
;
public int getRealX(int x
) {
boolean isRealX
= false;
int RangeX
= (int) getAlign();
System
.out
.println(RangeX
+ getCellLen() * getSideLength());
for (int i
= RangeX
, j
= 0; i
< RangeX
+ getCellLen() * getSideLength(); i
+= getCellLen(), j
++) {
if ((x
>= i
- 10) && (x
<= i
+ 10)) {
realX
= j
;
isRealX
= true;
break;
}
}
System
.out
.println("xinf: " + x
);
System
.out
.println("realX: " + realX
);
if (isRealX
) return realX
;
else return -1;
}
public int getRealY(int y
) {
boolean isRealY
= false;
int RangeY
= (int) getAlign();
for (int i
= RangeY
, j
= 0; i
< RangeY
+ getCellLen() * getSideLength(); i
+= getCellLen(), j
++) {
if ((y
>= i
- 10) && (y
<= i
+ 10)) {
realY
= j
;
isRealY
= true;
break;
}
}
System
.out
.println("yinf: " + y
);
System
.out
.println("realY: " + realY
);
if (isRealY
) return realY
;
else return -1;
}
public boolean isOverArea(int findX
, int findY
) {
return findX
== -1 || findY
== -1;
}
public boolean dropDownTheChess(int x
, int y
) {
if (!isOverArea(x
, y
) && chess
[x
][y
] == 0) {
chess
[x
][y
] = currentSide
;
System
.out
.println("chessxy " + chess
[x
][y
]);
return true;
} else {
Alert alert
= new Alert(Alert
.AlertType
.ERROR
);
alert
.setTitle("错误");
alert
.setContentText("棋子不可以下在这里");
alert
.showAndWait();
return false;
}
}
public void changeSide() {
if (currentSide
== 1) currentSide
= 2;
else currentSide
= 1;
}
public boolean judgeGame(int row
, int col
, int chessColor
) {
int plane
= plane(row
, col
, chessColor
);
int vertical
= vertical(row
, col
, chessColor
);
int left
= leftOblique(row
, col
, chessColor
);
int right
= rightOblique(row
, col
, chessColor
);
changeSide();
System
.out
.println("currentsideinjudge" + currentSide
);
System
.out
.println("plane" + plane
);
System
.out
.println("vertical" + vertical
);
System
.out
.println("left" + left
);
System
.out
.println("right" + right
);
if (plane
>= 5 || vertical
>= 5 || left
>= 5 || right
>= 5) {
return true;
} else return false;
}
public boolean judgementOverArea(int x
, int y
) {
if (x
>= 0 && x
<= getSideLength() && y
>= 0 && y
<= getSideLength()) {
return false;
} else return true;
}
public int plane(int row
, int col
, int chessColor
) {
int line
= 1;
int i
= row
- 1;
for (; !judgementOverArea(i
, col
) && chess
[i
][col
] == chessColor
; i
--)
line
++;
for (i
= row
+ 1; !judgementOverArea(i
, col
) && chess
[i
][col
] == chessColor
; i
++)
line
++;
return line
;
}
public int vertical(int row
, int col
, int chessColor
) {
int line
= 1;
int j
= col
- 1;
for (; !judgementOverArea(row
, j
) && chess
[row
][j
] == chessColor
; j
--)
line
++;
for (j
= col
+ 1; !judgementOverArea(row
, j
) && chess
[row
][j
] == chessColor
; j
++)
line
++;
return line
;
}
public int leftOblique(int row
, int col
, int chessColor
) {
int line
= 1;
int i
= row
- 1, j
= col
- 1;
for (; !judgementOverArea(i
, j
) && chess
[i
][j
] == chessColor
; i
--, j
--)
line
++;
for (i
= row
+ 1, j
= col
+ 1; !judgementOverArea(i
, j
) && chess
[i
][j
] == chessColor
; i
++, j
++)
line
++;
return line
;
}
public int rightOblique(int row
, int col
, int chessColor
) {
int line
= 1;
int i
= row
- 1, j
= col
+ 1;
for (; !judgementOverArea(i
, j
) && chess
[i
][j
] == chessColor
; i
--, j
++)
line
++;
for (i
= row
+ 1, j
= col
- 1; !judgementOverArea(i
, j
) && chess
[i
][j
] == chessColor
; i
++, j
--)
line
++;
return line
;
}
}
ChessPane类
class ChessPane extends Pane {
public Canvas canvas
;
public GraphicsContext graphicsContext
;
private double cellLen
= 40;
private double align
= 70;
private double paneWidth
= 560;
private double paneHeight
= 560;
private int sideLength
= 15;
public void setAlign(double align
) {
this.align
= align
;
}
public void setCanvas(Canvas canvas
) {
this.canvas
= canvas
;
}
public void setCellLen(double cellLen
) {
this.cellLen
= cellLen
;
}
public void setGraphicsContext(GraphicsContext graphicsContext
) {
this.graphicsContext
= graphicsContext
;
}
public void setPaneHeight(double paneHeight
) {
this.paneHeight
= paneHeight
;
}
public void setPaneWidth(double paneWidth
) {
this.paneWidth
= paneWidth
;
}
public void setSideLength(int sideLength
) {
this.sideLength
= sideLength
;
}
public Canvas
getCanvas() {
return canvas
;
}
public double getCellLen() {
return cellLen
;
}
public double getPaneHeight() {
return paneHeight
;
}
public double getPaneWidth() {
return paneWidth
;
}
public int getSideLength() {
return sideLength
;
}
public double getAlign() {
return align
;
}
public ChessPane() {
draw();
getChildren().add(canvas
);
}
public void draw() {
canvas
= new Canvas(700, 700);
this.graphicsContext
= canvas
.getGraphicsContext2D();
graphicsContext
.setFill(Color
.BURLYWOOD
);
graphicsContext
.fillRect(align
- 15, align
- 15, 560 + 30, 560 + 30);
for (int i
= 0; i
< 15; i
++) {
graphicsContext
.strokeLine(align
, i
* cellLen
+ align
, 560 + align
, i
* cellLen
+ align
);
}
for (int i
= 0; i
< 15; i
++) {
graphicsContext
.strokeLine(i
* cellLen
+ align
, align
, i
* cellLen
+ align
, 560 + align
);
}
for (int i
= 3; i
<= 14; i
+= 4)
for (int j
= 3; j
<= 14; ) {
graphicsContext
.setFill(Color
.BLACK
);
if (i
== 7) {
j
= 7;
graphicsContext
.strokeOval(i
* cellLen
+ align
- 4, j
* cellLen
+ align
- 4, 8, 8);
graphicsContext
.fillOval(i
* cellLen
+ align
- 4, j
* cellLen
+ align
- 4, 8, 8);
break;
}
else {
graphicsContext
.strokeOval(i
* cellLen
+ align
- 4, j
* cellLen
+ align
- 4, 8, 8);
graphicsContext
.fillOval(i
* cellLen
+ align
- 4, j
* cellLen
+ align
- 4, 8, 8);
j
+= 8;
}
}
graphicsContext
.setLineWidth(3.0f);
graphicsContext
.strokeRect(align
, align
, 560, 560);
}
public void paintChess(int x
, int y
, int currentSide
) {
System
.out
.println("xinPaintChess" + x
);
System
.out
.println("yinPaintChess" + y
);
if (currentSide
== 1) {
graphicsContext
.setFill(Color
.BLACK
);
} else {
graphicsContext
.setFill(Color
.WHITE
);
}
System
.out
.println(getAlign() + x
* cellLen
);
System
.out
.println(getAlign() + y
* cellLen
);
System
.out
.println("currentsideinPaintChess" + currentSide
);
graphicsContext
.strokeOval(getAlign() + x
* cellLen
- cellLen
/ 3, getAlign() + y
* cellLen
- cellLen
/ 3, cellLen
- 10, cellLen
- 10);
graphicsContext
.fillOval(getAlign() + x
* cellLen
- cellLen
/ 3, getAlign() + y
* cellLen
- cellLen
/ 3, cellLen
- 10, cellLen
- 10);
}
}
PlayAction类
class PlayAction extends UserPlay implements EventHandler<MouseEvent> {
private ChessPane chessPane
;
private UserPlay userPlay
;
public PlayAction(ChessPane chessPane
, UserPlay userPlay
) {
this.chessPane
= chessPane
;
this.userPlay
= userPlay
;
}
@Override
public void handle(MouseEvent event
) {
double cellLen
= getCellLen();
int x
= (int) (event
.getX());
int y
= (int) (event
.getY());
System
.out
.println("x: " + x
);
System
.out
.println("y: " + y
);
int realX
, realY
;
realX
= getRealX(x
);
realY
= getRealY(y
);
if (userPlay
.dropDownTheChess(realX
, realY
)) {
chessPane
.paintChess(realX
, realY
, userPlay
.getCurrentSide());
if (userPlay
.judgeGame(realX
, realY
, userPlay
.getCurrentSide())) {
Alert alert1
= new Alert(Alert
.AlertType
.INFORMATION
);
alert1
.setTitle("Author's smile");
String winner
;
if (userPlay
.getCurrentSide() == 1) {
winner
= "white side";
} else winner
= "black side";
alert1
.setContentText("Game over " + winner
+ " is winner!");
alert1
.showAndWait();
}
}
}
实验总结
收获
通过此次实验,我在写代码的过程中体会到了动手实践对于Java编程学习的重要性,学到了以下知识
Canava在JavaFx界面开发中绘制图形的应用
https://blog.csdn.net/u010164507/article/details/89106632
使用this显式激活构造方法Alert的基本使用(show!)Button的简单美化
创新
精确的将鼠标位置和数组值相联系
存在的不足
没有实现重玩的按钮,在前期设计中对于初始化不便没有实现AI和人的对战
需要改进的地方
整体的系统架构不尽合理,有需要改善的空间,在写代码时,函数与变量的调用多有不便,参数回传较为凌乱