首页
留言
关于
统计
友情链接
Search
1
java面试题05
241 阅读
2
java魔方矩阵
109 阅读
3
Java中的包
96 阅读
4
java中接口的作用
93 阅读
5
java中this关键字
68 阅读
随笔
笔记
计算机基础
JAVA
web前端
分享
经验
软件
其他
登录
/
注册
Search
标签搜索
JAVA
笔记
面试
五子棋
游戏
阿涛
累计撰写
23
篇文章
累计收到
9
条评论
首页
栏目
随笔
笔记
计算机基础
JAVA
web前端
分享
经验
软件
其他
页面
留言
关于
统计
友情链接
搜索到
21
篇与
JAVA
的结果
2022-04-04
javafx实现五子棋游戏
设计一个五子棋游戏,实现悔棋、保存棋谱、棋谱复盘等功能。窗口程序依赖于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); } }
2022年04月04日
58 阅读
0 评论
2 点赞
2022-03-19
java中的接口
接口的定义:interface 接口名{ ... }接口就是一个特殊的类接口中不能有字段,但可以有常量,默认被public static final修饰:interface X{ int a = 1; }等价于interface X{ public static final int a = 1; }接口的方法:1.接口中的所有方法,默认被public abstract修饰,也就是说接口中的所有方法都是抽象方法。interface X{ void f1(); }等价于interface X{ public abstract void f1(); }2.接口中也可以定义普通方法:interface X { void f1() { ... } }注意:Java中,有一个规范,当一个变量同时被static和final修饰的时候,该变量的名字中的所有字母都应该时大写的,单词和单词之间用 "_" 隔开。例:interface X{ String MY_NAME = "第一帅"; static final int HER_AGE = 20; final double HIS_SALARY = 30000; }接口无法被实例化,因为接口中的方法都是抽象的。接口的实现:class 类名 implements 接口名{ //实现接口的所有抽象方法 }接口中的抽象方法,在非抽象子类中,必须全部得以实现:interface I{ void aa(); //接口中的方法。默认被public修饰 } class A implements I{ public void aa(){ //所以子类重写方法时,访问修饰符也必须是public System.out.println("A.aa()"); } }一个类只能继承一个类,但一个类可实现多个接口:interface A{ void aa(); } interface B{ void aa(); void bb(); } class X implements A, B{ public void aa(){ //一个类实现两个接口, //两个接口的抽象方法必须全部实现 } //如果多个接口出现了相同的方法, public void bb(){ //只实现一次即可 } }一个类在继承一个类的同时,可以再去实现其他多个接口:class X extends A implements B, C{ }一个类实现一个接口,是一种比较特殊的“继承”关系,所以也能发生向上转型:interface A{ } class X implements A{ } public class Test{ public static void main(String[] args){ X x = new X(); A a = new X(); //这里发生了向上转型 } }接口的扩展接口和接口之间,时多继承的关系,也就是说,一个接口可以继承其他多个接口,等价于汇总了多个接口中的所有抽象方法到一个接口中:interface A{ void aa(); } interface B{ void bb(); } interface C extends A, B{ } class X implements C{ //接口C没有任何抽象方法, public void aa(){ //但它继承了A和B中的所有抽象方法 } public void bb(){ } }
2022年03月19日
23 阅读
0 评论
0 点赞
2022-03-15
java中类的设计技巧
1. 一定要保证数据私有这是最重要的;绝对不要破坏封装性。2. 一定要对数据进行初始化Java 不会为你初始化局部变量,但是会对对象的实例字段进行初始化。最好不要依赖于系统的默认值,而是应该显式地初始化所有的数据,可以提供默认值,也可以在所有构造器中设置默认值。3. 不要在类中使用过多的基本类型这个想法是要用其他地类替换使用多个相关的基本类型。这样会使类更易于理解,也更易于修改。例如,用一个 Address 的新类替换一个 Customer 类中的以下实例字段:class Customer { private String street; private String city; private String state; private int zip; }class Address { private String street; private String city; private String state; private int zip } class Customer { private Address address; }4. 不是所有的字段都需要单独的字段访问器和字段更改器在对象中,常常包含一些不希望别人获得或设置的实例字段。5. 分解有过多职责的类。6. 类名和方法名要能够体现它们的职责7. 优先使用不可变的类不可变类——没有方法能修改对象的状态。方法并不是更改对象,而是返回 状态已修改的新对象。更改对象的问题在于,如果多个线程试图同时更新一个对象,就会发生并发更改,其结果是不可预料的。如果类是不可变的,就可以安全地在多个线程间共享其对象。当然,并不是所有类都应当是不可变的,如果员工加薪时让 raiseSalary 方法返回一个新的 Employee 对象,这会很奇怪。
2022年03月15日
35 阅读
0 评论
0 点赞
2022-03-02
Java中的大数
java中的基本类型表示数值的有整型和浮点型,而它们都有范围,当我们的数值特别大时,就要用到大数。
2022年03月02日
39 阅读
0 评论
0 点赞
2022-02-25
Java中的运算符
运算符1. 算数运算符在 Java 中,使用算数运算符 +、-、*、/、% 表示加、减、乘、除、求余(取模)运算。当参与运算的两个操作数都是整数时,结果为正数,操作数中有浮点数时,结果为浮点数。需要注意,整数被 0 除将会产生一个异常,而浮点数被 0 除将会得到无穷大或 NaN 结果。2. 数学函数与常量在 Math 类中,包含了各种各样的数学函数。例如,要想计算一个数值的平方根,可以使用 sqrt 方法:double x = 4; double y = Math.sqrt(x); System.out.println(y); // prints 2.0注意,println 方法和 sqrt 方法存在微小差异。println 方法处理 System.out 对象。但是,Math 类中的 sqrt 方法不处理任何对象,这样的方法称为静态方法。有关静态方法的详细内容将在第 4 章学习。在 Java 中没有幂运算,因此需要借助 Math 类的 pow 方法:double y = Math.pow(x, a);将 y 的值设置为 x 的 a 次幂(x^a^)。pow 方法有两个 double 类型参数,其返回结果也为 double 类型。Math 类提供了一些常用的三角函数:Math.sinMath.cosMath.tanMath.atanMath.atan2还有指数函数以及它的反函数--自然对数以及以 10 为底的对数:Math.expMath.logMath.log10最后,Java 还提供了两个用于表示 π 和 额 е 常量的最接近的近似值:Math.PIMath.E提示:不必在数学方法名和常量名前添加前缀 "Math" ,只要在源文件的顶部加上下面这行代码就可以了。import static java.lang.Math.*;例如:System.out.println("The square root of \u03C0 is" + sqrt(PI));提示:Math 类提高了一些方法时整数有更好的运算安全性。如果一个计算溢出,数学运算符只是悄悄地返回错误结果而不做任何提醒。例如:10 亿乘以 3(1000000000 * 3)的计算结果为 -1294967296,因为最大的 int 值也只是刚刚超过 20 亿。不过,如果调用 Math.multiplyExact(1000000000, 3),就会产生一个异常。另外还有一些方法(addExact、subtractExact、incrementExact、decrementExact 和 negateExact)也可以正确地处理 int 和 long 参数。3. 数值类型之间的转换我们经常需要将一种数值类型转换为另一种类型,下图给出了数值类型之间的合法转换。其中,实线箭头表示无信息丢失的转换,虚线箭头表示可能有精度损失的转换。当用一个二元运算符连接两个值时,先要将两个操作数转换为同一类型,然后再进行计算。如果两个操作数中有一个是 double 类型,另一个操作数就会转换为 double 类型。否则,如果其中一个操作数为 float 类型,另一个操作数将会转换为 float 类型。否则,如果其中一个操作数为 long 类型,另一个操作数将会转换为 long 类型。否则,两个操作数都将被转换为 int 类型。4. 强制类型转换强制类型转换的语法格式是在圆括号中给出想要转换的目标类型,后面紧跟待转换的变量名。例如:double x = 9.97; int nx = (int)x;这样,变量 nx 的值为 9,因为强制类型转换通过截断小数部分将浮点值转换为整型。提示:如果想得到四舍五入最接近的整数,需要使用 Math.round 方法:double x = 9.97; int nx = (int)Math.round(x);现在,变量 nx 的值为 10。Math.round 方法返回的结果为 long 类型,可以通过显式的强制类型转换将 long 类型转换为 int 类型。5. 结合赋值和运算符例如:x += 4;等价于:x = x + 4;注意:如果运算符得到一个值,其类型与左侧操作数类型不同,就会发生强制类型转换。例如:int x = 0; x += 3.5;其结果为3。6. 自增与自减运算符Java 提供了自增、自减运算符:n++ 将变量 n 的当前值加 1,n-- 则将 n 的值减 1。例如:int n = 12; n++;将 n 的值改为 13。由于这些运算符改变的是变量的值,所以它们不能应用于数值本身。例如,4++ 就不是一个合法语句。实际上,这些运算符有两种形式,上面介绍的是运算符放在操作数后面的 “后缀” 形式。还有一种 “前缀” 形式:++n 。后缀和前缀形式都会是变量值加 1 或减 1。但用在表达式中时,二者就有区别了。前缀形式会先完成加 1;而后缀形式会使用变量原来的值。建议不要在表达式中使用 ++ 。
2022年02月25日
46 阅读
0 评论
0 点赞
1
2
3
...
5