Java—— IO流的應用

帶權重的點名系統

案例要求

文件中有學生的信息,每個學生的信息獨占一行。包括學生的姓名,性別,權重
要求每次被抽中的學生,再次被抽中的概率在原先的基礎上降低一半。
本題的核心就是帶權重的隨機

分析?

權重,權重和,權重占比

如何將概率降低為原先的一半

假設總共10個人,一開始設定每個人的權重都是1,權重和是10,權重占比=權重/權重和,那么每個人的權重占比是0.1,說明每個人一開始被抽中的概率都是0.1,抽中后再次被抽中的概率在原先的基礎上降低一半,需要將其權重降低為原來的一半。修改完權重要將其寫回文件,下次再抽人時權重就是0.5了。

細節:

權重降低為原來的一半,權重和也會改變,但是改變很小(由10變為9.5),人數越多改變越小(假如一共100人時,權重和為100,抽到一人,這人權重降低為原來的一半,權重和由100變為99.5),可以視作不變,而這個人權重降低為原來的一半,權重和又視作不變,則權重占比就是原來的一半。被抽中的概率就是原先的一半

權重占比的區間范圍?

如何確定抽到哪個人

?一開始每個人的權重占比是0.1,說明可以將長度為1的數軸分為10等份,每個人占其中一份

這就是權重占比的區間范圍,例如:

????????于滄浪-男-1 (0.0~0.1]?
????????雙文楠-男-1 (0.1~0.2]
????????鞠弘杰-男-1 (0.2~0.3]
????????樂弘雪-男-1 (0.3~0.4]
????????貝澤瀚-男-1 (0.4~0.5]
????????孫秀逸-女-1 (0.5~0.6]
????????藺文思-女-1 (0.6~0.7]
????????燕芷靈-女-1 (0.7~0.8]
????????酆若環-女-1 (0.8~0.9]
????????廣飛瑤-女-1 (0.9~1.0]

隨機一個0~1之間的數,其在哪個范圍就表示抽取到了哪個同學

代碼實現

Student類用于封裝文件中的數據

public class Student {private String name;private String sex;private double weight;public Student() {}public Student(String name, String sex, double weight) {this.name = name;this.sex = sex;this.weight = weight;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public double getWeight() {return weight;}public void setWeight(double weight) {this.weight = weight;}//toString方法數據格式與文件中相同//這樣直接傳遞學生對象的toString方法就能寫出相同格式的數據,public String toString() {return name + "-" + sex + "-" + weight;}
}

測試類?

import java.io.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;public class Test2 {public static void main(String[] args) throws IOException {//定義集合存儲學生對象ArrayList<Student> list = new ArrayList<>();//將文件中的數據讀出,交給Student對象進行封裝BufferedReader br = new BufferedReader(new FileReader("day05\\names.txt"));String line;while ((line = br.readLine()) != null) {String[] arr = line.split("-");Student stu = new Student(arr[0], arr[1], Double.parseDouble(arr[2]));//將該Student添加到集合中list.add(stu);}br.close();//獲取總權重double weightSum = 0;for (Student stu : list) {weightSum = weightSum + stu.getWeight();}//計算每個人的權重占比,保存到一個數組中double[] arr = new double[list.size()];int index = 0;for (Student stu : list) {arr[index] = stu.getWeight() / weightSum;index++;}System.out.println(Arrays.toString(arr));//計算每個人權重占比的區間范圍//例如第一個人權重占比是0.1,那么就規定0~0.1是他的權重占比的區間范圍,記為0.1//0~0.1是第一個人的,那么第二個人的權重占比的區間范圍就從0.1開始//所以第二個人的權重占比的區間范圍是 第一個人權重占比~第一個人權重占比+自己的權重占比//依次往后//隨機一個0~1之間的數,若該數處于0~0.1,就表示隨機到了第一個人for (int i = 1; i < arr.length; i++) {//利用BigDecimal精確運算BigDecimal bd1 = BigDecimal.valueOf(arr[i - 1]);BigDecimal bd2 = BigDecimal.valueOf(arr[i]);arr[i] = bd1.add(bd2).doubleValue();}System.out.println(Arrays.toString(arr));//隨機0~1之間的數double random = Math.random();System.out.println(random);//判斷random在數組中的位置//數組中元素是有序的利用二分查找法//如果要查找的元素在數組中,返回該元素的索引//如果要查找的元素不在數組中,返回值 = -索引 -1//通過加法交換率得           索引= -(返回值 +1)int i = Arrays.binarySearch(arr, random);if (i >= 0) {System.out.println(i);} else {i = -i - 1;System.out.println(i);}//索引i表示抽到的人Student stu = list.get(i);System.out.println(stu);//修改這個人的權重為原來的一半stu.setWeight(stu.getWeight() / 2);//將修改后的數據寫回文件BufferedWriter bw = new BufferedWriter(new FileWriter("day05\\names.txt"));for (Student s : list) {bw.write(s.toString());bw.newLine();}bw.close();}
}

一開始文件中的數據? ? ? ? ?第一次抽取? ? ? ? ? ? ? ? ?第二次抽取? ? ? ? ? ? ? ? ?第三次抽取 ??

游戲注冊功能以及存檔功能

可以將用戶信息和游戲進度寫到一個文件中永久保存,這樣結束程序重新啟動時,數據不會丟失,借助IO將前面介紹的拼圖游戲完善

程序啟動類?

import java.io.IOException;public class App {public static void main(String[] args) throws IOException {//創建登錄界面,在登錄界面中成功登錄后創建游戲界面new LoginJFrame();}
}

登錄界面?

import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;public class LoginJFrame extends JFrame implements MouseListener {//不止一個方法使用的變量定義在成員變量位置JButton login;JButton register;JTextField username;JTextField password;JTextField code;String codeStr;JLabel showCode;JDialog jDialog;//記錄所有用戶ArrayList<User> list = new ArrayList();//空參構造初始化登錄public LoginJFrame() throws IOException {//調用方法獲取文件中記錄的用戶信息,存儲在集合中UserInfo();//調用方法初始化登錄界面initFrame();//調用方法加載登錄界面圖式loadImages();//添加事件監聽,鼠標監聽事件MouseListenerlogin.addMouseListener(this);register.addMouseListener(this);showCode.addMouseListener(this);//設置界面可視,建議放在最后this.setVisible(true);}//定義方法獲取文件中記錄的用戶信息,存儲在集合中private void UserInfo() throws IOException {BufferedReader br = new BufferedReader(new FileReader("PuzzleGame\\UserInfo.txt"));String line;while ((line = br.readLine()) != null) {String[] arr = line.split("&");String username = arr[0].split("=")[1];String password = arr[1].split("=")[1];User u = new User(username, password);list.add(u);}br.close();}//定義方法加載登錄界面圖式private void loadImages() {//1. 添加用戶名文字JLabel usernameText = new JLabel(new ImageIcon("puzzlegame\\image\\login\\用戶名.png"));usernameText.setBounds(116, 135, 47, 17);this.getContentPane().add(usernameText);//2.添加用戶名輸入框username = new JTextField();username.setBounds(195, 134, 200, 30);this.getContentPane().add(username);//3.添加密碼文字JLabel passwordText = new JLabel(new ImageIcon("puzzlegame\\image\\login\\密碼.png"));passwordText.setBounds(130, 195, 32, 16);this.getContentPane().add(passwordText);//4.密碼輸入框password = new JTextField();password.setBounds(195, 195, 200, 30);this.getContentPane().add(password);//驗證碼提示JLabel codeText = new JLabel(new ImageIcon("puzzlegame\\image\\login\\驗證碼.png"));codeText.setBounds(133, 256, 50, 30);this.getContentPane().add(codeText);//驗證碼的輸入框code = new JTextField();code.setBounds(195, 256, 100, 30);this.getContentPane().add(code);//調用工具類生成驗證碼codeStr = CodeUtil.getCode();//顯示生成的驗證碼showCode = new JLabel();//設置內容showCode.setText(codeStr);//位置和寬高showCode.setBounds(300, 256, 50, 30);//添加到界面this.getContentPane().add(showCode);//5.添加登錄按鈕login = new JButton();login.setBounds(123, 310, 128, 47);//設置按鈕背景圖login.setIcon(new ImageIcon("puzzlegame\\image\\login\\登錄按鈕.png"));//去除按鈕的默認邊框login.setBorderPainted(false);//去除按鈕的默認背景login.setContentAreaFilled(false);this.getContentPane().add(login);//6.添加注冊按鈕register = new JButton();register.setBounds(256, 310, 128, 47);//設置按鈕背景圖register.setIcon(new ImageIcon("puzzlegame\\image\\login\\注冊按鈕.png"));//去除按鈕的默認邊框register.setBorderPainted(false);//去除按鈕的默認背景register.setContentAreaFilled(false);this.getContentPane().add(register);//7.添加界面背景圖片JLabel background = new JLabel(new ImageIcon("puzzlegame\\image\\login\\background.png"));background.setBounds(0, 0, 470, 390);this.getContentPane().add(background);}//定義方法初始化登錄界面private void initFrame() {this.setSize(488, 430);this.setTitle("拼圖游戲登錄");this.setAlwaysOnTop(true);this.setLocationRelativeTo(null);this.setDefaultCloseOperation(3);this.setLayout(null);}//定義方法判斷用戶名密碼是否正確private boolean checkUser(ArrayList<User> list, User u) {//查詢用戶名是否在集合中存在int index = checkUserName(list, u);if (index == -1) {//System.out.println("用戶名和密碼錯誤");return false;}//到這步,證明用戶名存在,判斷對應的密碼是否相同if (list.get(index).getPassWord().equals(u.getPassWord())) {//相同返回truereturn true;}//不同返回falsereturn false;}//定義方法查詢用戶名是否在集合中存在,存在返回索引,不存在返回-1private int checkUserName(ArrayList<User> list, User u) {for (int i = 0; i < list.size(); i++) {if (list.get(i).getUserName().equals(u.getUserName())) {return i;}}return -1;}//定義方法展示彈窗private void showDialog(String s) {jDialog = new JDialog();//設置彈框的寬和高:100,100jDialog.setSize(100, 100);//設置彈框居中jDialog.setLocationRelativeTo(null);//設置彈框置頂jDialog.setAlwaysOnTop(true);//設置關閉后進行其他操作jDialog.setModal(true);//創建一個JLabel去編寫文本內容JLabel textJlabel = new JLabel(s);textJlabel.setBounds(20, 50, 120, 60);//把文本JLabel添加到彈框當中jDialog.getContentPane().add(textJlabel);//把彈框展示出來jDialog.setVisible(true);}//鼠標監聽事件MouseListener//鼠標單擊調用該方法@Overridepublic void mouseClicked(MouseEvent e) {Object source = e.getSource();if (source == login) {//如果是登錄按鈕,獲取輸入框中的用戶名,密碼,驗證碼String myUserName = username.getText();String myPassWord = password.getText();String myCode = code.getText();//判斷是否為空,如果為空,提示:用戶名或密碼為空if (myUserName.equals("") || myPassWord.equals("")) {//展示彈框:用戶名或密碼為空//調用方法展示彈框,參數為需要展示的文字showDialog("用戶名或密碼為空");//換一個驗證碼codeStr = CodeUtil.getCode();showCode.setText(codeStr);return;}//判斷驗證碼是否正確if (!(myCode.equalsIgnoreCase(codeStr))) {//展示彈框:驗證碼錯誤showDialog("驗證碼錯誤");System.out.println("驗證碼錯誤");//換一個驗證碼codeStr = CodeUtil.getCode();showCode.setText(codeStr);return;}//判斷用戶名和密碼是否為正確,如果正確隱藏登錄界面,進入游戲界面。//調用方法判斷User myUser = new User(myUserName, myPassWord);boolean flag = checkUser(list, myUser);if (!flag) {//展示彈框:用戶名或密碼錯誤showDialog("用戶名或密碼錯誤");System.out.println("用戶名或密碼錯誤");//換一個驗證碼codeStr = CodeUtil.getCode();showCode.setText(codeStr);return;}//到這步,證明用戶名和密碼正確//隱藏登錄界面,進入游戲界面this.setVisible(false);new GameJFrame();} else if (source == showCode) {//重新生成驗證碼codeStr = CodeUtil.getCode();showCode.setText(codeStr);} else if (source == register) {//進行注冊//關閉登錄界面this.setVisible(false);//創建注冊界面//把存儲用戶信息的集合傳遞過去,注冊時用戶名不能與集合中的重復new RegisterJFrame(list);}}//鼠標按下調用該方法@Overridepublic void mousePressed(MouseEvent e) {Object source = e.getSource();if (source == login) {//登錄按鈕//按下不松的時候利用setIcon方法,修改登錄按鈕的背景色login.setIcon(new ImageIcon("PuzzleGame\\image\\login\\登錄按下.png"));} else if (source == register) {//注冊按鈕//按下不松的時候利用setIcon方法,修改注冊按鈕的背景色register.setIcon(new ImageIcon("PuzzleGame\\image\\login\\注冊按下.png"));}}//鼠標釋放調用該方法@Overridepublic void mouseReleased(MouseEvent e) {Object source = e.getSource();//登錄按鈕//釋放的時候利用setIcon方法,恢復登錄按鈕的背景色if (source == login) {login.setIcon(new ImageIcon("PuzzleGame\\image\\login\\登錄按鈕.png"));} else if (source == register) {//注冊按鈕//釋放的時候利用setIcon方法,恢復注冊按鈕的背景色register.setIcon(new ImageIcon("PuzzleGame\\image\\login\\注冊按鈕.png"));}}//鼠標劃入調用該方法@Overridepublic void mouseEntered(MouseEvent e) {}//鼠標劃出調用該方法@Overridepublic void mouseExited(MouseEvent e) {}}

注冊界面

import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;public class RegisterJFrame extends JFrame implements MouseListener {//存儲用戶集合ArrayList<User> list;//提升三個輸入框的變量的作用范圍,讓這三個變量可以在本類中所有方法里面可以使用。JTextField username = new JTextField();JTextField password = new JTextField();JTextField rePassword = new JTextField();//提升兩個按鈕變量的作用范圍,讓這兩個變量可以在本類中所有方法里面可以使用。JButton submit = new JButton();JButton reset = new JButton();//彈窗JDialog jDialog;public RegisterJFrame(ArrayList<User> list) {//接收傳遞過來的用戶集合this.list = list;//初始化界面initFrame();//調用方法加載登錄界面圖式initView();//添加事件監聽,鼠標監聽事件MouseListenersubmit.addMouseListener(this);reset.addMouseListener(this);//設置界面可視,建議放在最后this.setVisible(true);}//初始化界面private void initFrame() {//對自己的界面做一些設置。//設置寬高this.setSize(488, 430);//設置標題this.setTitle("拼圖游戲 V1.0注冊");//取消內部默認布局this.setLayout(null);//設置關閉模式this.setDefaultCloseOperation(3);//設置居中this.setLocationRelativeTo(null);//設置置頂this.setAlwaysOnTop(true);}//加載登錄界面圖式private void initView() {//添加注冊用戶名的文本JLabel usernameText = new JLabel(new ImageIcon("puzzlegame\\image\\register\\注冊用戶名.png"));usernameText.setBounds(85, 135, 80, 20);//添加注冊用戶名的輸入框username.setBounds(195, 134, 200, 30);//添加注冊密碼的文本JLabel passwordText = new JLabel(new ImageIcon("puzzlegame\\image\\register\\注冊密碼.png"));passwordText.setBounds(97, 193, 70, 20);//添加密碼輸入框password.setBounds(195, 195, 200, 30);//添加再次輸入密碼的文本JLabel rePasswordText = new JLabel(new ImageIcon("puzzlegame\\image\\register\\再次輸入密碼.png"));rePasswordText.setBounds(64, 255, 95, 20);//添加再次輸入密碼的輸入框rePassword.setBounds(195, 255, 200, 30);//注冊的按鈕submit.setIcon(new ImageIcon("puzzlegame\\image\\register\\注冊按鈕.png"));submit.setBounds(123, 310, 128, 47);submit.setBorderPainted(false);submit.setContentAreaFilled(false);//重置的按鈕reset.setIcon(new ImageIcon("puzzlegame\\image\\register\\重置按鈕.png"));reset.setBounds(256, 310, 128, 47);reset.setBorderPainted(false);reset.setContentAreaFilled(false);//背景圖片JLabel background = new JLabel(new ImageIcon("puzzlegame\\image\\register\\background.png"));background.setBounds(0, 0, 470, 390);this.getContentPane().add(usernameText);this.getContentPane().add(passwordText);this.getContentPane().add(rePasswordText);this.getContentPane().add(username);this.getContentPane().add(password);this.getContentPane().add(rePassword);this.getContentPane().add(submit);this.getContentPane().add(reset);this.getContentPane().add(background);}//定義方法展示彈窗private void showDialog(String s) {jDialog = new JDialog();//設置彈框的寬和高:100,100jDialog.setSize(100, 100);//設置彈框居中jDialog.setLocationRelativeTo(null);//設置彈框置頂jDialog.setAlwaysOnTop(true);//設置關閉后進行其他操作jDialog.setModal(true);//創建一個JLabel去編寫文本內容JLabel textJlabel = new JLabel(s);textJlabel.setBounds(20, 50, 120, 60);//把文本JLabel添加到彈框當中jDialog.getContentPane().add(textJlabel);//把彈框展示出來jDialog.setVisible(true);}//鼠標單擊事件@Overridepublic void mouseClicked(MouseEvent e) {Object source = e.getSource();if (source == submit) {//注冊按鈕//得到三個輸入框中的數據String myUsername = username.getText();String myPassword = password.getText();String myRePassword = rePassword.getText();//三個輸入框中的數據不能為空if (myUsername.length() == 0 || myPassword.length() == 0 || myRePassword.length() == 0) {//彈窗提醒showDialog("輸入框不能為空");//結束方法return;}//密碼和再次輸入的密碼要相同if (!myPassword.equals(myRePassword)) {//彈窗提醒showDialog("兩次輸入的密碼不同");//結束方法return;}//用戶名要符合規定,4-16位大小寫字母和數字if (!myUsername.matches("[a-zA-Z0-9]{4,16}")) {//彈窗提醒showDialog("用戶名要4-16位大小寫字母和數字");//結束方法return;}//密碼要符合規定,至少6位大小寫字母和數字if (!myPassword.matches("[a-zA-Z0-9]{6,}")) {//彈窗提醒showDialog("密碼要至少6位大小寫字母和數字");//結束方法return;}//用戶名不能與集合中的重復//調用方法判斷if (containsUsername(myUsername)) {//彈窗提醒showDialog("用戶名已存在");//結束方法return;}//到這一步,說明用戶名和密碼符合條件//將其添加到用戶集合中,并寫到文件中永久存儲User u = new User(myUsername, myPassword);list.add(u);try {BufferedWriter bw = new BufferedWriter(new FileWriter("PuzzleGame\\UserInfo.txt"));for (User user : list) {bw.write(user.toString());bw.newLine();}bw.close();//開啟登錄界面this.setVisible(false);new LoginJFrame();} catch (IOException ex) {throw new RuntimeException(ex);}} else if (source == reset) {//重置按鈕//清空三個輸入框中的內容username.setText("");password.setText("");rePassword.setText("");}}//判斷自定義用戶名是否與集合中的用戶名重復private boolean containsUsername(String myUsername) {for (User u : list) {if (u.getUserName().equals(myUsername)) {return true;}}return false;}//鼠標按下事件@Overridepublic void mousePressed(MouseEvent e) {Object source = e.getSource();//切換按鈕深色背景if (source == submit) {submit.setIcon(new ImageIcon("PuzzleGame\\image\\register\\注冊按下.png"));} else if (source == reset) {reset.setIcon(new ImageIcon("PuzzleGame\\image\\register\\重置按下.png"));}}//鼠標釋放事件@Overridepublic void mouseReleased(MouseEvent e) {Object source = e.getSource();//切換按鈕正常背景if (source == submit) {submit.setIcon(new ImageIcon("PuzzleGame\\image\\register\\注冊按鈕.png"));} else if (source == reset) {reset.setIcon(new ImageIcon("PuzzleGame\\image\\register\\重置按鈕.png"));}}@Overridepublic void mouseEntered(MouseEvent e) {}@Overridepublic void mouseExited(MouseEvent e) {}
}

游戲界面

import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.*;
import java.util.Random;//游戲界面類繼承界面類,實現鍵盤監聽和動作監聽
public class GameJFrame extends JFrame implements KeyListener, ActionListener {//多個方法需要用到的變量,記錄在成員變量的位置//定義二維數組記錄打亂后的0~15,每一個數字對應一張拼圖int[][] data = new int[4][4];//定義勝利時的數據數組int[][] winArr = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12},{13, 14, 15, 0}};//定義坐標記錄0的位置int x = 0;int y = 0;//定義計數器記錄移動步數int stepCount = 0;//創建菜單選項里下面的條目JMenuItem restartItem = new JMenuItem("重新開始");JMenuItem reLoginItem = new JMenuItem("重新登錄");JMenuItem exitItem = new JMenuItem("退出游戲");JMenuItem animalItem = new JMenuItem("動物");JMenuItem girllItem = new JMenuItem("美女");JMenuItem sportItem = new JMenuItem("運動");JMenuItem AccountItem = new JMenuItem("公眾號");JMenu saveJmenu = new JMenu("存檔");JMenuItem saveItem0 = new JMenuItem("存檔0(空)");JMenuItem saveItem1 = new JMenuItem("存檔1(空)");JMenuItem saveItem2 = new JMenuItem("存檔2(空)");JMenu loadJmenu = new JMenu("讀檔");JMenuItem loadItem0 = new JMenuItem("讀檔0(空)");JMenuItem loadItem1 = new JMenuItem("讀檔1(空)");JMenuItem loadItem2 = new JMenuItem("讀檔2(空)");//定義圖片路徑,方便后面修改String path = "PuzzleGame\\image\\animal\\animal1\\";Random r = new Random();//空參構造初始化游戲public GameJFrame() {//調用方法初始化界面initFrame();//給界面添加事件監聽,鍵盤監聽KeyListenerthis.addKeyListener(this);//調用方法添加菜單initMenu();//給菜單里的條目添加事件監聽,動作監聽ActionListenerrestartItem.addActionListener(this);reLoginItem.addActionListener(this);exitItem.addActionListener(this);AccountItem.addActionListener(this);animalItem.addActionListener(this);girllItem.addActionListener(this);sportItem.addActionListener(this);saveItem0.addActionListener(this);saveItem1.addActionListener(this);saveItem2.addActionListener(this);loadItem0.addActionListener(this);loadItem1.addActionListener(this);loadItem2.addActionListener(this);//調用方法初始化數據initData();//調用方法根據初始化后的數據加載圖片loadImages();//設置界面可視,建議放在最后this.setVisible(true);}//定義方法判斷游戲是否勝利private boolean victoty() {for (int i = 0; i < data.length; i++) {for (int j = 0; j < data[i].length; j++) {if (data[i][j] != winArr[i][j]) {//data中的數據有一個與勝利數組中的數據不同,就說明沒有勝利return false;}}}return true;}//定義方法根據初始化后的數據加載圖片private void loadImages() {//清空所有圖片this.getContentPane().removeAll();//如果勝利,加載勝利圖標if (victoty()) {JLabel vicJLabel = new JLabel(new ImageIcon("PuzzleGame\\image\\win.png"));vicJLabel.setBounds(203, 283, 197, 73);this.getContentPane().add(vicJLabel);}//加載計數器JLabel countJLabel = new JLabel("步數:" + stepCount);countJLabel.setBounds(50, 30, 100, 20);this.getContentPane().add(countJLabel);//利用循環加載拼圖圖片for (int i = 0; i < data.length; i++) {for (int j = 0; j < data[i].length; j++) {//獲得data數組里的數據int number = data[i][j];//根據數據創建圖片對象ImageIcon icon = new ImageIcon(path + number + ".jpg");//創建管理容器,將圖片交給管理容器JLabel jLabel = new JLabel(icon);//設置管理容器位置,大小jLabel.setBounds(105 * j + 83, 105 * i + 134, 105, 105);//設置邊框jLabel.setBorder(new BevelBorder(0));//將管理容器添加到界面中this.getContentPane().add(jLabel);}}//添加背景圖片JLabel bgJLabel = new JLabel(new ImageIcon("PuzzleGame\\image\\background.png"));bgJLabel.setBounds(40, 40, 508, 560);this.getContentPane().add(bgJLabel);//刷新一下this.getContentPane().repaint();}//定義方法初始化數據private void initData() {int[] tempArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};//打亂數據,根據打亂后的數據就能實現打亂拼圖for (int i = 0; i < tempArr.length; i++) {int index = r.nextInt(tempArr.length);int temp = tempArr[i];tempArr[i] = tempArr[index];tempArr[index] = temp;}//將打亂后的數據記錄在二維數組data中for (int i = 0; i < tempArr.length; i++) {//如果是0,記錄0的位置if (tempArr[i] == 0) {x = i / 4;y = i % 4;}data[i / 4][i % 4] = tempArr[i];}}//定義方法添加菜單private void initMenu() {//創建菜單JMenuBar jMenuBar = new JMenuBar();//創建菜單的選項JMenu functionJmenu = new JMenu("功能");JMenu aboutJmenu = new JMenu("關于我們");//嵌套二級菜單,JMenu里面是可以再次添加其他的JMenuJMenu updateJmenu = new JMenu("更換圖片");updateJmenu.add(animalItem);updateJmenu.add(girllItem);updateJmenu.add(sportItem);//存檔saveJmenu.add(saveItem0);saveJmenu.add(saveItem1);saveJmenu.add(saveItem2);//讀檔loadJmenu.add(loadItem0);loadJmenu.add(loadItem1);loadJmenu.add(loadItem2);//將條目添加到選項中functionJmenu.add(updateJmenu);functionJmenu.add(restartItem);functionJmenu.add(reLoginItem);functionJmenu.add(exitItem);functionJmenu.add(saveJmenu);functionJmenu.add(loadJmenu);aboutJmenu.add(AccountItem);//將選項添加到菜單中jMenuBar.add(functionJmenu);jMenuBar.add(aboutJmenu);//將菜單添加到界面中this.setJMenuBar(jMenuBar);//游戲開始時獲取游戲數據信息修改菜單提示getGameInfo();}//游戲開始時獲取游戲數據信息修改菜單提示private void getGameInfo() {//遍歷存檔文件夾File f = new File("PuzzleGame\\save");File[] files = f.listFiles();if (files == null) {return;}for (File file : files) {//讀取每一個文件信息GameInfo gi = null;try {ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));gi = (GameInfo) ois.readObject();ois.close();} catch (IOException e) {throw new RuntimeException(e);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}//獲取要體現在菜單上的步數信息int step = gi.getStepCount();//獲取要修改的條目索引String name = file.getName();//save0/1/2.dataint index = name.charAt(4) - '0';//進行修改JMenuItem item1 = saveJmenu.getItem(index);item1.setText("存檔" + index + "(" + step + "步)");JMenuItem item2 = loadJmenu.getItem(index);item2.setText("讀檔" + index + "(" + step + "步)");}}//定義方法初始化界面private void initFrame() {//設置大小this.setSize(603, 680);//設置標題this.setTitle("拼圖游戲");//設置居中this.setLocationRelativeTo(null);//設置置頂this.setAlwaysOnTop(true);//設置關閉模式this.setDefaultCloseOperation(3);//設置解除默認居中放置,只有解除了,才能根據xy軸的方式添加主件this.setLayout(null);}//動作監聽ActionListener,鼠標單擊或按空格調用該方法@Overridepublic void actionPerformed(ActionEvent e) {Object source = e.getSource();if (source == restartItem) {//重新開始//重新初始化數據initData();//計數器歸0stepCount = 0;//重新根據初始化后的數據加載圖片loadImages();} else if (source == reLoginItem) {//重新登錄//關閉本類(游戲類)this.setVisible(false);//創建登錄界面try {new LoginJFrame();} catch (IOException ex) {throw new RuntimeException(ex);}} else if (source == exitItem) {//退出游戲System.exit(0);} else if (source == AccountItem) {//顯示公眾號//創建彈窗JDialog accJDialog = new JDialog();//加載彈窗中的圖片JLabel aboutJLabel = new JLabel(new ImageIcon("PuzzleGame\\image\\about.png"));aboutJLabel.setBounds(0, 0, 258, 258);//將圖片添加到彈窗中accJDialog.getContentPane().add(aboutJLabel);//設置彈窗的大小accJDialog.setSize(344, 344);//設置彈窗置頂accJDialog.setAlwaysOnTop(true);//設置彈窗居中放置accJDialog.setLocationRelativeTo(null);//設置關閉后進行其他操作accJDialog.setModal(true);//設置彈窗可視accJDialog.setVisible(true);} else if (source == animalItem) {//隨機更換動物圖片int rAnimalNum = r.nextInt(8) + 1;path = "PuzzleGame\\image\\animal\\animal" + rAnimalNum + "\\";//重新初始化數據initData();//計數器歸0stepCount = 0;//重新根據初始化后的數據加載圖片loadImages();} else if (source == girllItem) {//隨機更換美女圖片int rGirlNum = r.nextInt(13) + 1;path = "PuzzleGame\\image\\girl\\girl" + rGirlNum + "\\";//重新初始化數據initData();//計數器歸0stepCount = 0;//重新根據初始化后的數據加載圖片loadImages();} else if (source == sportItem) {//隨機更換運動圖片int rSportlNum = r.nextInt(10) + 1;path = "PuzzleGame\\image\\sport\\sport" + rSportlNum + "\\";//重新初始化數據initData();//計數器歸0stepCount = 0;//重新根據初始化后的數據加載圖片loadImages();} else if (source == saveItem0 || source == saveItem1 || source == saveItem2) {//進行存檔//得到點擊的存檔序號JMenuItem item = (JMenuItem) source;String text = item.getText();//存檔0/1/2(空)int index = text.charAt(2) - '0';//封裝要保存的游戲數據//包括:對應拼圖的data數組,記錄0位置的坐標x,y,圖片路徑path,步數stepCountGameInfo gi = new GameInfo(data, x, y, stepCount, path);//將游戲信息對象以序列化流寫入對應文件中,防止篡改數據try {ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("PuzzleGame\\save\\save" + index + ".data"));oos.writeObject(gi);oos.close();} catch (IOException ex) {throw new RuntimeException(ex);}//修改菜單上的提示信息item.setText("存檔" + index + "(" + stepCount + "步)");//獲取與存檔對應的讀檔菜單JMenuItem item1 = loadJmenu.getItem(index);item1.setText("讀檔" + index + "(" + stepCount + "步)");} else if (source == loadItem0 || source == loadItem1 || source == loadItem2) {//進行讀檔//得到點擊的讀檔序號JMenuItem item = (JMenuItem) source;String text = item.getText();//讀檔0/1/2(空)int index = text.charAt(2) - '0';//利用反序列化流讀取文件中的游戲數據GameInfo gi = null;try {ObjectInputStream ois = new ObjectInputStream(new FileInputStream("PuzzleGame\\save\\save" + index + ".data"));gi = (GameInfo) ois.readObject();ois.close();} catch (IOException ex) {throw new RuntimeException(ex);} catch (ClassNotFoundException ex) {throw new RuntimeException(ex);}//將游戲數據更新為存檔的游戲數據data = gi.getData();x = gi.getX();y = gi.getY();path = gi.getPath();stepCount = gi.getStepCount();//重新加載游戲loadImages();}}//鍵盤監聽KeyListener//該方法基本不使用@Overridepublic void keyTyped(KeyEvent e) {}//長按鍵盤時調用該方法@Overridepublic void keyPressed(KeyEvent e) {//判斷是否勝利if (victoty()) {//如果勝利,禁止進行顯示全圖操作,直接結束方法return;}//長按w顯示全圖int keyCode = e.getKeyCode();if (keyCode == 87) {//清空所有圖片this.getContentPane().removeAll();//加載計數器JLabel countJLabel = new JLabel("步數:" + stepCount);countJLabel.setBounds(50, 30, 100, 20);this.getContentPane().add(countJLabel);//加載全圖JLabel picJLabel = new JLabel(new ImageIcon(path + "all.jpg"));picJLabel.setBounds(83, 134, 420, 420);this.getContentPane().add(picJLabel);//添加背景圖片JLabel bgJLabel = new JLabel(new ImageIcon("PuzzleGame\\image\\background.png"));bgJLabel.setBounds(40, 40, 508, 560);this.getContentPane().add(bgJLabel);//刷新一下this.getContentPane().repaint();}}//按下并松開鍵盤時調用該方法@Overridepublic void keyReleased(KeyEvent e) {//判斷是否勝利if (victoty()) {//如果勝利,禁止進行移動操作,直接結束方法return;}int keyCode = e.getKeyCode();if (keyCode == 37) {//判斷是否到了最左邊if (y == 0) {//如果到了最左邊,不能進行向左,直接結束方法return;}//沒到最左邊,進行下面的操作System.out.println("向左");//更改data數組里的數據data[x][y] = data[x][y - 1];data[x][y - 1] = 0;//更改0的坐標y--;//步數加1stepCount++;//按照此數據重新加載圖片loadImages();} else if (keyCode == 38) {//判斷是否到了最上邊if (x == 0) {//如果到了最上邊,不能進行向上,直接結束方法return;}//沒到最上邊,進行下面的操作System.out.println("向上");//更改data數組里的數據data[x][y] = data[x - 1][y];data[x - 1][y] = 0;//更改0的坐標x--;//步數加1stepCount++;//按照此數據重新加載圖片loadImages();} else if (keyCode == 39) {//判斷是否到了最右邊if (y == 3) {//如果到了最右邊,不能進行向右,直接結束方法return;}//沒到最右邊,進行下面的操作System.out.println("向右");//更改data數組里的數據data[x][y] = data[x][y + 1];data[x][y + 1] = 0;//更改0的坐標y++;//步數加1stepCount++;//按照此數據重新加載圖片loadImages();} else if (keyCode == 40) {//判斷是否到了最下邊if (x == 3) {//如果到了最下邊,不能進行向下,直接結束方法return;}//沒到最下邊,進行下面的操作System.out.println("向下");//更改data數組里的數據data[x][y] = data[x + 1][y];data[x + 1][y] = 0;//更改0的坐標x++;//步數加1stepCount++;//按照此數據重新加載圖片loadImages();} else if (keyCode == 87) {//松開w恢復原狀loadImages();} else if (keyCode == 65) {//一鍵通過for (int i = 0; i < data.length; i++) {for (int j = 0; j < data[i].length; j++) {data[i][j] = winArr[i][j];}}loadImages();}}}

?封裝用戶信息

public class User {private String userName;private String passWord;public User() {}public User(String userName, String passWord) {this.userName = userName;this.passWord = passWord;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPassWord() {return passWord;}public void setPassWord(String passWord) {this.passWord = passWord;}@Overridepublic String toString() {return "uesrname="+userName+"&password="+passWord;}
}

封裝游戲信息

import java.io.Serial;
import java.io.Serializable;public class GameInfo implements Serializable {@Serialprivate static final long serialVersionUID = 3545018877843048289L;private int[][] data;private int x;private int y;private int stepCount;private String path;public GameInfo() {}public GameInfo(int[][] data, int x, int y, int stepCount, String path) {this.data = data;this.x = x;this.y = y;this.stepCount = stepCount;this.path = path;}public int[][] getData() {return data;}public void setData(int[][] data) {this.data = data;}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}public int getStepCount() {return stepCount;}public void setStepCount(int stepCount) {this.stepCount = stepCount;}public String getPath() {return path;}public void setPath(String path) {this.path = path;}public String toString() {return "GameInfo{data = " + data + ", x = " + x + ", y = " + y + ", stepCount = " + stepCount + ", path = " + path + "}";}
}

生成驗證碼工具類

import java.util.Random;public class CodeUtil {private CodeUtil(){}public static String getCode(){//定義StringBuilder方便拼接字符串StringBuilder sb = new StringBuilder();//記錄a~z,A~Zchar[] ch = new char[52];for (int i = 0; i < ch.length; i++) {if (i < 26) {ch[i] = (char) ('a' + i);} else {ch[i] = (char) ('A' + i - 26);}}Random r = new Random();//隨機抽取4個字母for (int i = 0; i < 4; i++) {int index = r.nextInt(ch.length);char randomCh = ch[index];//拼接sb.append(randomCh);}//隨機抽取1個字母int randomNum = r.nextInt(10);//拼接sb.append(randomNum);//數字可以位于隨機位置,因此最后一位需要與隨機位置交換char[] chars = sb.toString().toCharArray();int index = r.nextInt(chars.length);char temp = chars[chars.length-1];chars[chars.length-1] = chars[index];chars[index] = temp;return new String(chars);}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/82051.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/82051.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/82051.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Docker中部署Alertmanager

在 Docker 中部署 Alertmanager&#xff08;通常與 Prometheus 告警系統配合使用&#xff09;的步驟如下&#xff1a; 一、拉取鏡像prom/alertmanager docker pull prom/alertmanager二、 創建 Alertmanager 配置文件 首先準備Alertmanager的配置文件 alertmanager.yml(如存…

【大模型面試每日一題】Day 27:自注意力機制中Q/K/V矩陣的作用與縮放因子原理

【大模型面試每日一題】Day 27&#xff1a;自注意力機制中Q/K/V矩陣的作用與縮放因子原理 &#x1f4cc; 題目重現 &#x1f31f;&#x1f31f; 面試官&#xff1a;請解釋Transformer自注意力機制中Query、Key、Value矩陣的核心作用&#xff0c;并分析為何在計算注意力分數時…

AI+能碳管理系統:全生命周期碳管理

在"雙碳"目標的時代背景下&#xff0c;AI賦能的能碳管理系統正在重新定義企業碳管理的邊界與深度。這套系統猶如一位不知疲倦的碳管家&#xff0c;從原材料采購到產品報廢&#xff0c;在每一個價值環節編織起精密的碳管理網絡&#xff0c;實現從微觀設備到宏觀戰略的…

k8s1.27版本集群部署minio分布式

需求&#xff1a; 1.創建4個pv&#xff0c;一個pv一個minio-pod。使用sts動態分配pvc(根據存儲類找到pv)。----持久化 2.暴露minio的9001端口。&#xff08;nodeport&#xff09;----管理界面 鏡像&#xff1a;minio/minio:RELEASE.2023-03-20T20-16-18Z--->換國內源 說明…

使用 OpenCV 實現 ArUco 碼識別與坐標軸繪制

&#x1f3af; 使用 OpenCV 實現 ArUco 碼識別與坐標軸繪制&#xff08;含Python源碼&#xff09; Aruco 是一種廣泛用于機器人、增強現實&#xff08;AR&#xff09;和相機標定的方形標記系統。本文將帶你一步一步使用 Python OpenCV 實現圖像中多個 ArUco 碼的檢測與坐標軸…

Qt 控件發展歷程 + 目標(1)

文章目錄 聲明簡述控件的發展歷程學習目標QWidget屬性 簡介&#xff1a;這篇文章只是一個引子&#xff0c;介紹一點與控件相關的但不重要的內容&#xff08;瀏覽瀏覽即可&#xff09;&#xff0c;這一章節最為重要的還是要把之后常用且重要的控件屬性和作用給學透&#xff0c;學…

socc 19 echash論文部分解讀

前言&#xff1a;論文還是得吃透才行&#xff0c;不然很多細節有問題 q1 object和data chunck哪一個大 根據論文&#xff0c;一個 data chunk 通常比一個 object 大&#xff0c;因為它是由多個 object 組合而成的 。 論文中提到&#xff0c;cross-coding 會將多個 object 組合…

w~自動駕駛~合集1

我自己的原文哦~ https://blog.51cto.com/whaosoft/12371169 #世界模型和DriveGPT這類大模型到底能給自動駕駛帶來什么ne 以下分享大模型與自動駕駛結合的相關工作9篇論 1、ADAPT ADAPT: Action-aware Driving Caption Transformer&#xff08;ICRA2023&#xff09; A…

【paddle】常見的數學運算

根據提供的 PaddlePaddle 函數列表&#xff0c;我們可以將它們按照數學運算、邏輯運算、三角函數、特殊函數、統計函數、張量操作和其他操作等類型進行分類。以下是根據函數功能進行的分類&#xff1a; 取整運算 Rounding functions 代碼描述round(x)距離 x 最近的整數floor(…

繪制音頻信號的各種頻譜圖,包括Mel頻譜圖、STFT頻譜圖等。它不僅能夠繪制頻譜圖librosa.display.specshow

librosa.display.specshow 是一個非常方便的函數&#xff0c;用于繪制音頻信號的各種頻譜圖&#xff0c;包括Mel頻譜圖、STFT頻譜圖等。它不僅能夠繪制頻譜圖&#xff0c;還能自動設置軸標簽和刻度&#xff0c;使得生成的圖像更加直觀和易于理解。 ### 函數簽名 python libros…

DDR DFI 5.2 協議接口學習梳理筆記01

備注:本文新增對各種時鐘含義做了明確定義區分,避免大家產生誤解,這也是5.2版本新引入的。 1. 前言 截止2025年5月,DFI協議最新版本為 5.2,我們首先看一下過去幾代的演進: DFI全稱DDR PHY Interface,是一種接口協議,定義了 Controller 和 PHY 之間接口的信號、時序以…

windows篡改腳本提醒

? 功能簡介 該監控系統具備如下主要功能&#xff1a; &#x1f4c1; 目錄監控 實時監聽指定主目錄及其所有子目錄內文件的變動情況。 &#x1f512; 文件哈希校驗 對文件內容生成 SHA256 哈希&#xff0c;確保變更檢測基于內容而非時間戳。 &#x1f6ab; 排除機制 支…

文章記單詞 | 第102篇(六級)

一&#xff0c;單詞釋義 apologize /??p?l?d?a?z/ v. 道歉&#xff1b;認錯discharge /d?s?t?ɑ?rd?/ v./n. 排出&#xff1b;釋放&#xff1b;解雇&#xff1b; dischargequiver /?kw?v?r/ v./n. 顫抖&#xff1b;抖動&#xff1b;箭筒plantation /pln?te??…

【DCGMI專題1】---DCGMI 在 Ubuntu 22.04 上的深度安裝指南與原理分析(含架構圖解)

目錄 一、DCGMI 概述與應用場景 二、Ubuntu 22.04 系統準備 2.1 系統要求 2.2 環境清理(可選) 三、DCGMI 安裝步驟(詳細圖解) 3.1 安裝流程總覽 3.2 分步操作指南 3.2.1 系統更新與依賴安裝 3.2.2 添加 NVIDIA 官方倉庫 3.2.3 安裝數據中心驅動與 DCGM 3.2.4 服務…

主成分分析(PCA)法例題——給定協方差矩陣

已知樣本集合的協方差矩陣為 C x 1 10 [ 3 1 1 1 3 ? 1 1 ? 1 3 ] {\bm C}_x \frac{1}{10} \begin{bmatrix} 3 & 1 & 1 \\ 1 & 3 & -1 \\ 1 & -1 & 3 \end{bmatrix} Cx?101? ?311?13?1?1?13? ? 使用PCA方法將樣本向量降到二維 。 求解 計…

uni-app(4):js語法、css語法

1 js語法 uni-app的js API由標準ECMAScript的js API 和 uni 擴展 API 這兩部分組成。標準ECMAScript的js僅是最基礎的js。瀏覽器基于它擴展了window、document、navigator等對象。小程序也基于標準js擴展了各種wx.xx、my.xx、swan.xx的API。node也擴展了fs等模塊。uni-app基于E…

Idea 配合 devtools 依賴 實現熱部署

核心依賴 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency> yaml配置 spring: #…

leetcode513.找樹左下角的值:遞歸深度優先搜索中的最左節點追蹤之道

一、題目本質與核心訴求解析 在二叉樹算法問題中&#xff0c;"找樹左下角的值"是一個典型的結合深度與位置判斷的問題。題目要求我們找到二叉樹中最深層最左邊的節點值&#xff0c;這里的"左下角"有兩個關鍵限定&#xff1a; 深度優先&#xff1a;必須是…

Python入門手冊:Python基礎語法

Python是一種簡潔、易讀且功能強大的編程語言&#xff0c;非常適合初學者入門。無論你是編程新手&#xff0c;還是有一定編程基礎但想學習Python的開發者&#xff0c;掌握Python的基礎語法都是邁向高效編程的第一步。本文將詳細介紹Python的基本語法&#xff0c;包括變量和數據…

postgresql 常用參數配置

#01 - Connection-Authentication 優化點&#xff1a; listen_addresses 0.0.0.0 建議&#xff1a;生產環境應限制為具體IP&#xff08;如 192.168.1.0/24,127.0.0.1&#xff09;&#xff0c;避免暴露到公網。 ssl off 建議&#xff1a;啟用SSL&#xff08;ssl on&#xf…