一:前言
(折磨加摸鱼)后,本人在上一篇博文的基础上制作了这一次的作品,说实话,fxml的使用就我目前感觉来,其实更加偏向实际操作,理论知识可能用到的较少(也有可能是我太菜了),废话不多说,进入本次的主题吧!由于本人技术有限,期待各位读者在阅读后给出指正,谢谢!
二:总览
主要还是有三个部分,登录注册,游戏画面,以及其他操作具体的简介已经放在代码注释中了,诸位读者请慢慢食用!
另外,也先奉上fxml页面:
//由于本人写下这份博客匆忙,所以当前游戏时间暂时没有及时跟上
三:具体代码
1.gameView包
(1)GameAction类
package myRPSGame.gameView;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import myRPSGame.MainApp;
import myRPSGame.otherConduct2.DisPlayDialog;
import myRPSGame.otherConduct2.DisplayAlert;
import myRPSGame.otherConduct2.GetCurrentTime;
import myRPSGame.registerAndLogin.register.AccountList;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class GameAction implements Initializable {
@FXML
private Label username;
@FXML
private Label winningRate;
@FXML
private ListView<String> listView;
@FXML
private Label currentTime;
@FXML
private Label user;
@FXML
private Label computer;
private UserPlay userPlay;
private ObservableList<String> observableList= FXCollections.observableArrayList();
private static int theAccount;
@FXML
private RPSView View1;
@FXML
private RPSView View2;
public static void setTheAccount(int theAccount) {
GameAction.theAccount=theAccount;
}
//查询游戏记录
@FXML
public void inquireRecord()
{
observableList.clear();
for(int i=0;i<AccountList.getAccounts(theAccount).getRecord().getCurrentRecord();i++){
observableList.add(AccountList.getAccounts(theAccount).getRecord().getTheRecord(i));
}
listView.setItems(observableList);
}
//退出
@FXML
public void exit() throws IOException {
MainApp.setRoot("registerAndLogin/log/LoginView.fxml");
}
//删除游戏记录
@FXML
public void deleteRecord()
{
AccountList.getAccounts(theAccount).getRecord().deleteRecord();
inquireRecord();
}
//开始游戏
@FXML
public void start()
{
View1.loadRandomImage(100,145);
View2.loadRandomImage(100,145);
AccountList.getAccounts(theAccount).setPlayNumber(AccountList.getAccounts(theAccount).getPlayNumber()+1);
userPlay=new UserPlay(DisPlayDialog.inputChoice());
View1.stopPicture();
View2.stopPicture();
userPlay.computerChoice();
user.setText(userPlay.getUser());
loadTheView(userPlay.getUser());
computer.setText(userPlay.getComputer());
loadTheView2(userPlay.getComputer());
switch (userPlay.getResult())
{
case 0->DisplayAlert.display("游戏结束!","平局","不是哥们,这都能打平??!");
case -1->{DisplayAlert.display("游戏结束","你赢了","赢个狗吧人机看把你能的。。。"); AccountList.getAccounts(theAccount).setWinningNUmber(AccountList.getAccounts(theAccount).getWinningNUmber()+1);}
default -> DisplayAlert.display("游戏结束","你输了","人机都能输?哥们回去玩泥巴吧!");
}
AccountList.getAccounts(theAccount).setWinningRate();
winningRate.setText(STR."\{AccountList.getAccounts(theAccount).getWinningRate()}%");
AccountList.getAccounts(theAccount).getRecord().addRecord(STR."进行游戏 时间:\{GetCurrentTime.getCurrentTime()}");
}
//加载玩家和电脑选择的图片
public void loadTheView(String choice)
{
System.out.println(choice);
switch (choice)
{
case "石头"-> View1.loadStoneImage(100,145);
case "剪刀"-> View1.loadScissorImage(100,145);
default -> View1.loadClothImage(100,145);
}
}
public void loadTheView2(String choice)
{
System.out.println(choice);
switch (choice)
{
case "石头"->View2.loadStoneImage(100,145);
case "剪刀"-> View2.loadScissorImage(100,145);
default->View2.loadClothImage(100,145);
}
}
//修改用户名
@FXML
public void changeUsername() {
username.setText(DisPlayDialog.inputUsername());
}
//重置胜率
@FXML
public void overWinningRate()
{
winningRate.setText("100%");
AccountList.getAccounts(theAccount).setWinningRate(100);
AccountList.getAccounts(theAccount).setPlayNumber(0);
AccountList.getAccounts(theAccount).setPlayNumber(0);
}
//初始化
@Override
public void initialize(URL location, ResourceBundle resources)
{
username.setText(AccountList.getAccounts(theAccount).getUserName());
winningRate.setText(STR."\{AccountList.getAccounts(theAccount).getWinningRate()}%");
}
}
(2)RPSView类
package myRPSGame.gameView;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.util.Duration;
import java.util.Arrays;
import java.util.List;
public class RPSView extends AnchorPane
{
private Image image;
private ImageView imageView;
private Timeline timeline;
//加载图片并设置格式
public void loadStoneImage(double height,double width)
{
image=new Image("/myRPSGame/gameView/resouce/微信图片_20240513135843.jpg");
imageView=new ImageView();
imageView.setImage(image);
imageView.setFitHeight(height);
imageView.setFitWidth(width);
getChildren().add(imageView);
}
public void loadScissorImage(double height,double width)
{
image=new Image("/myRPSGame/gameView/resouce/微信图片_20240513135848.jpg");
imageView=new ImageView();
imageView.setImage(image);
imageView.setFitHeight(height);
imageView.setFitWidth(width);
getChildren().add(imageView);
}
public void loadClothImage(double height,double width)
{
image=new Image("/myRPSGame/gameView/resouce/微信图片_20240513135820.jpg");
imageView=new ImageView();
imageView.setImage(image);
imageView.setFitHeight(height);
imageView.setFitWidth(width);
System.out.println(1);
getChildren().add(imageView);
}
//在作出选项前循环随机播放图片
public void loadRandomImage(double height,double width)
{
List<Image> images;
final int[] currentIndex = {0};
// 加载图片
images = Arrays.asList(
new Image("/myRPSGame/gameView/resouce/微信图片_20240513135820.jpg"),
new Image("/myRPSGame/gameView/resouce/微信图片_20240513135843.jpg"),
new Image("/myRPSGame/gameView/resouce/微信图片_20240513135848.jpg")
);
imageView=new ImageView();
imageView.setFitHeight(height);
imageView.setFitWidth(width);
imageView.setImage(images.getFirst());
timeline = new Timeline(
new KeyFrame(Duration.seconds(0.2), event -> {
Platform.runLater(() -> {
imageView.setImage(images.get(currentIndex[0]));
currentIndex[0] = (currentIndex[0] + 1) % images.size();
});
})
);
timeline.setCycleCount(Timeline.INDEFINITE); // 无限循环
timeline.play();
getChildren().add(imageView);
}
//消除展示的图片
public void stopPicture() {
timeline.stop();
}
}
(3)UserPlay.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.text.*?>
<?import myRPSGame.gameView.RPSView?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="myRPSGame.gameView.GameAction">
<children>
<Label layoutX="14.0" layoutY="14.0" prefHeight="26.0" prefWidth="45.0" text="用户:">
<font>
<Font name="System Bold" size="15.0" />
</font>
</Label>
<Label layoutX="14.0" layoutY="61.0" text="胜率:">
<font>
<Font name="System Bold Italic" size="16.0" />
</font>
</Label>
<Button layoutX="152.0" layoutY="16.0" mnemonicParsing="false" onAction="#changeUsername" prefHeight="23.0" prefWidth="45.0" text="修改">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Button>
<Button layoutX="152.0" layoutY="61.0" mnemonicParsing="false" onAction="#overWinningRate" prefHeight="23.0" prefWidth="45.0" text="重置" />
<Button layoutX="19.0" layoutY="103.0" mnemonicParsing="false" onAction="#inquireRecord" prefHeight="32.0" prefWidth="90.0" text="查询游戏记录" />
<Button layoutX="165.0" layoutY="103.0" mnemonicParsing="false" onAction="#start" prefHeight="31.0" prefWidth="60.0" text="PLAY">
<font>
<Font name="System Bold Italic" size="15.0" />
</font>
</Button>
<ListView fx:id="listView" layoutX="17.0" layoutY="149.0" prefHeight="200.0" prefWidth="228.0" />
<Button layoutX="17.0" layoutY="365.0" mnemonicParsing="false" onAction="#deleteRecord" text="删除">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Button>
<Label layoutX="415.0" layoutY="8.0" text="当前时间:" />
<Label fx:id="currentTime" layoutX="475.0" layoutY="8.0" prefHeight="15.0" prefWidth="117.0" text="CurrentTime" />
<Button layoutX="175.0" layoutY="360.0" mnemonicParsing="false" onAction="#exit" text="退出">
<font>
<Font size="13.0" />
</font>
</Button>
<Label fx:id="username" layoutX="64.0" layoutY="12.0" prefHeight="30.0" prefWidth="70.0">
<font>
<Font name="System Bold Italic" size="16.0" />
</font></Label>
<Label fx:id="winningRate" layoutX="64.0" layoutY="57.0" prefHeight="30.0" prefWidth="70.0">
<font>
<Font name="System Bold Italic" size="16.0" />
</font></Label>
<Label layoutX="291.0" layoutY="45.0" prefHeight="23.0" prefWidth="43.0" text="玩家:">
<font>
<Font name="Agency FB Bold" size="14.0" />
</font>
</Label>
<Label layoutX="291.0" layoutY="337.0" prefHeight="23.0" prefWidth="43.0" text="电脑:">
<font>
<Font name="Agency FB Bold" size="14.0" />
</font>
</Label>
<Line endX="-99.99996948242188" endY="326.9999694824219" layoutX="365.0" layoutY="73.0" startX="-99.99996948242188" startY="-83.66666412353516" />
<Label fx:id="user" layoutX="335.0" layoutY="45.0" prefHeight="23.0" prefWidth="43.0" text="Label" />
<Label fx:id="computer" layoutX="335.0" layoutY="337.0" prefHeight="23.0" prefWidth="43.0" text="Label" />
<RPSView fx:id="View1" layoutX="400.0" layoutY="50.0" prefHeight="100.0" prefWidth="145.0" />
<RPSView fx:id="View2" layoutX="400.0" layoutY="250.0" prefHeight="100.0" prefWidth="145.0" />
<AnchorPane layoutX="370.0" layoutY="220.0" prefHeight="100.0" prefWidth="145.0" />
</children>
</AnchorPane>
2.otherConduct包
由于这个包内部类的功能其实和上一篇博客类似,所以这里不再过多赘述!
3. registerAndLogin包
(1)log包
LoginAction类:
package myRPSGame.registerAndLogin.log;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import myATM.otherConduct.DisplayAlert;
import myATM.otherConduct.DisplayDialog;
import myRPSGame.MainApp;
import myRPSGame.gameView.GameAction;
import myRPSGame.otherConduct2.DisPlayDialog;
import myRPSGame.otherConduct2.GetCurrentTime;
import myRPSGame.registerAndLogin.register.AccountList;
import java.io.IOException;
public class LoginAction
{
@FXML
private TextField account;
@FXML
private TextField passport;
//登录
@FXML
public void log() throws IOException
{
int n=AccountList.getTheAccount(account.getText());
if(n!=-1)
{
if(AccountList.ifMatch(n,passport.getText()))
{
System.out.println("111");
GameAction.setTheAccount(n);
AccountList.getAccounts(n).getRecord().addRecord(STR."登录 时间:\{GetCurrentTime.getCurrentTime()}");
MainApp.setRoot("gameView/View.fxml");
}
else DisplayAlert.display("输入的密码有误!");
}
}
//忘记密码
@FXML
public void forgetPassport()
{
String s= DisPlayDialog.inputAccount();
DisplayAlert.display("找回成功!",STR."账号:\{s}的密码为:",AccountList.getAccounts(AccountList.getTheAccount(s)).getPassport());
}
//注册
@FXML
public void register() throws IOException {
MainApp.setRoot("registerAndLogin/register/RegisterView.fxml");
}
}
LoginView.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="myRPSGame.registerAndLogin.log.LoginAction">
<children>
<Label layoutX="140.0" layoutY="80.0" prefHeight="35.0" prefWidth="60.0" text="账号:" textFill="#0c67ef">
<font>
<Font name="System Bold Italic" size="19.0" />
</font></Label>
<Label layoutX="140.0" layoutY="160.0" prefHeight="35.0" prefWidth="60.0" text="密码:" textFill="#08f6c7">
<font>
<Font name="System Bold Italic" size="20.0" />
</font></Label>
<TextField fx:id="account" layoutX="208.0" layoutY="86.0" />
<TextField fx:id="passport" layoutX="208.0" layoutY="166.0" />
<Button layoutX="401.0" layoutY="166.0" mnemonicParsing="false" onAction="#forgetPassport" text="忘记密码?">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Button>
<Button layoutX="266.0" layoutY="249.0" mnemonicParsing="false" onAction="#log" prefHeight="23.0" prefWidth="45.0" text="登录">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Button>
<Button layoutX="401.0" layoutY="86.0" mnemonicParsing="false" onAction="#register" prefHeight="23.0" prefWidth="70.0" text="注册账号">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Button>
<Label layoutY="2.0" prefHeight="23.0" prefWidth="180.0" text="Welcome to RPS game!" textFill="#e5bc07">
<font>
<Font name="System Bold Italic" size="14.0" />
</font>
</Label>
<Label layoutX="200.0" layoutY="304.0" prefHeight="25.0" prefWidth="100.0" text="沉迷游戏伤身," textFill="#f41111">
<font>
<Font name="System Bold Italic" size="14.0" />
</font></Label>
<Label layoutX="300.0" layoutY="304.0" prefHeight="25.0" prefWidth="100.0" text="健康游戏益脑。" textFill="#f41111">
<font>
<Font name="System Bold Italic" size="14.0" />
</font></Label>
<Label layoutX="200.0" layoutY="333.0" prefHeight="25.0" prefWidth="100.0" text="珍惜现实世界," textFill="#5edb0a">
<font>
<Font name="System Bold Italic" size="14.0" />
</font></Label>
<Label layoutX="300.0" layoutY="333.0" prefHeight="25.0" prefWidth="100.0" text="多出门去走走。" textFill="#5edb0a">
<font>
<Font name="System Bold Italic" size="14.0" />
</font></Label>
</children>
</AnchorPane>
(2)register包
Account类:
package myRPSGame.registerAndLogin.register;
import myATM.otherConduct.Record;
public class Account
{
private String Accounts;
private String Passport;
private double winningRate=100;
private String userName;
private double playNumber=0;
private double winningNUmber=0;
private Record record=new Record();
public String getAccounts() {
return Accounts;
}
public void setAccounts(String accounts) {
Accounts = accounts;
}
public String getPassport() {
return Passport;
}
public void setPassport(String passport) {
Passport = passport;
}
public double getWinningRate() {
return winningRate;
}
//更新胜率
public void setWinningRate() {
this.winningRate=winningNUmber/playNumber*100;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Record getRecord() {
return record;
}
public void setRecord(Record record) {
this.record = record;
}
public double getPlayNumber() {
return playNumber;
}
public void setPlayNumber(double playNumber) {
this.playNumber = playNumber;
}
public double getWinningNUmber() {
return winningNUmber;
}
public void setWinningNUmber(double winningNUmber) {
this.winningNUmber = winningNUmber;
}
public void setWinningRate(double winningRate) {
this.winningRate = winningRate;
}
}
AccountList类:
package myRPSGame.registerAndLogin.register;
import myATM.otherConduct.DisplayAlert;
import myRPSGame.otherConduct2.GetCurrentTime;
public class AccountList {
private static final int maxAccountNumber=1000;
private static Account[] accounts=new Account[maxAccountNumber];
private static int currentAccountNUmber=0;
//添加账号
public static void addAccount(String account,String passport,String username)
{
if(currentAccountNUmber<10)
{
accounts[currentAccountNUmber] = new Account();
accounts[currentAccountNUmber].setAccounts(account);
accounts[currentAccountNUmber].setPassport(passport);
accounts[currentAccountNUmber].setUserName(username);
accounts[currentAccountNUmber].getRecord().addRecord(STR."注册账号 注册时间:\{GetCurrentTime.getCurrentTime()}");
currentAccountNUmber++;
}
else{
DisplayAlert.display("当前的账号数已经有10个了!");
}
}
//通过账号知道当前是第几个账号(已经减一)
public static int getTheAccount(String account)
{
int i;
for(i=0;i<currentAccountNUmber;i++)
{
if(accounts[i].getAccounts().equals(account))
return i;
}
DisplayAlert.display("输入的账号不存在或者输入账号有误!");
return -1;
}
//判断账号是否与密码匹配
public static boolean ifMatch(int n,String passport) {
return accounts[n].getPassport().equals(passport);
}
public static Account getAccounts(int n) {
return accounts[n];
}
}
RegisterAction类:
package myRPSGame.registerAndLogin.register;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import myRPSGame.MainApp;
import myRPSGame.otherConduct2.DisplayAlert;
import myRPSGame.otherConduct2.GenerateRandomName;
import java.io.IOException;
public class RegisterAction
{
@FXML
private TextField account;
@FXML
private TextField passport;
@FXML
private TextField username;
//产生一个随机名
@FXML
public void RandomName()
{
username.setText(GenerateRandomName.randName());
}
//注册
@FXML
public void Register()
{
AccountList.addAccount(account.getText(),passport.getText(),username.getText());
DisplayAlert.display("注册成功","欢迎新用户",username.getText());
}
//返回
@FXML
public void Return() throws IOException {
MainApp.setRoot("registerAndLogin/log/LoginView.fxml");
}
}
RegisterView.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="myRPSGame.registerAndLogin.register.RegisterAction">
<children>
<Label layoutX="130.0" layoutY="70.0" prefHeight="30.0" prefWidth="50.0" text="账号:">
<font>
<Font name="System Bold Italic" size="16.0" />
</font></Label>
<Label layoutX="130.0" layoutY="140.0" prefHeight="30.0" prefWidth="64.0" text="用户名:">
<font>
<Font name="System Bold Italic" size="16.0" />
</font></Label>
<Label layoutX="130.0" layoutY="210.0" prefHeight="30.0" prefWidth="50.0" text="密码:">
<font>
<Font name="System Bold Italic" size="16.0" />
</font></Label>
<TextField fx:id="account" layoutX="194.0" layoutY="73.0" />
<TextField fx:id="username" layoutX="194.0" layoutY="144.0" />
<TextField fx:id="passport" layoutX="194.0" layoutY="214.0" />
<Button layoutX="368.0" layoutY="144.0" mnemonicParsing="false" onAction="#RandomName" text="随机" />
<Label layoutX="325.0" layoutY="253.0" prefHeight="23.0" prefWidth="136.0" text="tips:不要忘记密码噢!" textFill="#eb0d0d">
<font>
<Font name="System Bold Italic" size="13.0" />
</font>
</Label>
<Button layoutX="247.0" layoutY="290.0" mnemonicParsing="false" onAction="#Register" prefHeight="23.0" prefWidth="50.0" text="注册">
<font>
<Font name="System Bold Italic" size="13.0" />
</font></Button>
<Button layoutX="461.0" layoutY="313.0" mnemonicParsing="false" onAction="#Return" prefHeight="30.0" prefWidth="55.0" text="返回">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Button>
</children>
</AnchorPane>
4.MainApp类
package myRPSGame;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.Objects;
public class MainApp extends Application
{
private static Stage primaryStage;
private static AnchorPane root;
@Override
public void start(Stage primaryStage) throws Exception
{
MainApp.primaryStage=primaryStage;
MainApp.primaryStage.setTitle("剪刀石头布游戏 作者:cz Huang");
initialize();
primaryStage.show();
}
//设置根
public static void setRoot(String rooter) throws IOException
{
root= FXMLLoader.load(Objects.requireNonNull(MainApp.class.getResource(rooter)));
Scene scene=new Scene(root);
primaryStage.setScene(scene);
}
//初始化
public void initialize() throws IOException
{
root=FXMLLoader.load(Objects.requireNonNull(MainApp.class.getResource("registerAndLogin/log/LoginView.fxml")));
Scene scene=new Scene(root);
primaryStage.setScene(scene);
}
public static void main(String[] args){
launch(args);
}
}
四:后话
最近我在看红楼梦,我很喜欢那句“满纸荒唐言,谁解其中味”,正如我写的这些代码,其实在真正的高手眼中不过是一个刚学到新东西的毛头小子耍的三脚猫功夫,但我想,总会有读者能身有体会,在漫长的学习道路上,其中的酸甜苦辣,你知,我知。
最后,感谢每一位读者!