JavaSE快速複習案例

前言

      本篇博客是明哥針對有Java基礎的學員用於快速複習Javase部分基礎案例

案例一 Java計算閏年問題 - 兩種實現方式

判斷條件: 1、能被4整除,而且不能被100整除 2、能被400整除 3、&&的優先級高於||

/**
 * 實現方式一:普通方式實現
 */

public class AleapYear {
    public static void main(String[] args) {
        //鍵盤動態輸入
        Scanner input = new Scanner(System.in);
        //提示語句
        System.out.println("請輸入年份:");
        //捕捉異常
        try {
            // 循環讀取用戶輸入的值
            while (true) {
                //取得下一行輸入的年份值
                int year=input.nextInt();
                if (year < 1000 || year > 9999)
                    System.out.printf("請輸入大於1000小於9999的年份");
                else if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { // 平閏年
                    System.out.println(year+"年是閏年");
                } else {
                    System.out.println(year+"年是平年");
                }
            }
        }catch (Exception e){  // 異常處理
            System.out.println("請輸入正確年份");
            e.getStackTrace(); // 打印異常信息
        }
    }
}

/**
 * 實現方式二:面向對象方式 
 */
public class AleapYearTwo {
    //創建boolean類型的方法
    boolean tocalculate(int year) {
        //算法
        if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {//平閏年判斷
            return true;
        } else {
            return false;
        }
    }

    public static void main(String[] args) {
        // 實例化AleapYear對象
        AleapYearTwo yearTwo = new AleapYearTwo();
        //鍵盤動態輸入
        Scanner input = new Scanner(System.in);
        //提示語句
        System.out.println("請輸入年份:");
        //捕捉異常
        try {
            // 循環讀取用戶輸入的值
            while (true) {
                //取得下一行輸入的年份值
                int yea = input.nextInt();
                if (yea < 1000 || yea > 9999)
                    System.out.printf("請輸入大於1000小於9999的年份");
                else if (yearTwo.tocalculate(yea)) { //yearTwo對象tocalculate方法
                    System.out.println(yea + "年是閏年");
                } else {
                    System.out.println(yea + "年是平年");
                }
            }
        } catch (Exception e) {  // 異常處理
            System.out.println("請輸入正確年份");
            e.getStackTrace(); // 打印異常信息
        }
    }
}

案例二:輸出九九乘法表

/**
 * 實現99乘法表 外層循環控制行,內層循環控制列 注意 ln在何時使用
 */
public class PrintMultiplicationTables {
    public static void main(String[] args) {
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.print(j + "*" + i + "=" + j * i + "\t");
            }
            System.out.println();
        }
    }
}

案例三 多線程買票

package com.mg;

/**
 * 類名:com.mg.Ticket
 * 包名:com.mg
 * 創建時間:2020/6/18 2:27 上午
 * 創建人: 明哥
 * 描述:多線程買票 實現方式一 運用同步代碼塊的方式實現線程安全
 **/
public class Ticket implements Runnable {
    // 定義出售的票源
    private int tickets = 200;
    public  void run(){
        while (true) {
            payTicket();
        }
    }
    // 採用同步方法實現線程安全
    public synchronized void payTicket(){
        // 線程共享數據 保證安全 加入同步代碼塊
        // 判斷票數,大於0可以出售
        if (tickets>0) {
            try {
                //此項休眠代碼,是爲了模擬線程不安全,讓其等待
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName()+"出售票"+tickets--);
        }
    }

    public static void main(String[] args) {
        Ticket ticket = new Ticket();

        Thread threadOne = new Thread(ticket);
        Thread threadTwo = new Thread(ticket);
        Thread threadThree = new Thread(ticket);

        // 啓動線程
        threadOne.start();
        threadTwo.start();
        threadThree.start();
    }
}
package com.mg;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 類名:Ticket
 * 包名:com.mg
 * 創建時間:2020/6/18 2:41 上午
 * 創建人: 明哥
 * 描述:多線程買票 實現方式二 運用Lock類的方法實現線程安全
 **/
public class Ticket implements Runnable{
    //定義出售的票源
    private int tickets = 100;

    //在類的成員位置,創建Lock接口的實現類對象
    private Lock lock = new ReentrantLock();

    public void run(){
        while(true){
            //調用Lock接口方法lock獲取鎖
            lock.lock();
            //對票數判斷,大於0可以出售
            if(tickets >0){
                try {
                    //模擬線程不安全,讓其待機。
                    Thread.sleep(10);
                    System.out.println(Thread.currentThread().getName()+"出售票"+tickets--);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    lock.unlock();
                }
            }
        }
    }
}

案例四 簡單實現Socket聊天室

   Socket 又稱套接字 ,套接字使用TCP提供了兩臺計算機之間的通信機制,客戶端程序創建一個套接字,並嘗試連接服務器的套接字。當連接建立時,服務器會創建一個 Socket 對象,客戶端和服務器現在可以通過對 Socket 對象的寫入和讀取來進行通信。java.net.ServerSocket類爲服務器提供了一種監聽客戶端並與他們建立連接的機制。本案例我們使用簡單的單線程來做一個實例對Socket有個概念。

package com.mg;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/**
 * 類名:SingThreadServer
 * 包名:com.mg
 * 創建時間:2020/6/18 2:46 上午
 * 創建人: 明哥
 * 描述: 服務端
 *  操作流程:
 *       1、建立一個服務端Server
 *       2、使用Java字節流傳輸進行信息交互
 *       3、其中用InputStream來實現消息接收
 *       4、OutputStream來實現消息發送
 **/
public class SingThreadServer {
    public static void main(String[] args) {
        int port=4406;
        try {
            //創建服務端
            ServerSocket serverSocket = new ServerSocket(port);
            System.out.println("服務端啓動,運行在"+serverSocket.getLocalSocketAddress());
            //等待客戶端連接
            Socket clientSocket=serverSocket.accept();//此時阻塞,等待客戶端連接  直到客戶端連接服務端返回Socket
            System.out.println("有新用戶連接,客戶名爲"+clientSocket.getPort());
            //數據接收和發送
            //1.接收
            InputStream in = clientSocket.getInputStream();
            Scanner scanner = new Scanner(in);
            System.out.println("客戶端>" + scanner.nextLine());
            //2.發送
            OutputStream out = clientSocket.getOutputStream();
            PrintStream printStream = new PrintStream(out);
            printStream.println("你好,我是客戶端==");
            printStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package com.mg;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;

/**
 * 類名:SingleThreadClient
 * 包名:com.mg
 * 創建時間:2020/6/18 2:48 上午
 * 創建人: 明哥
 * 描述:  客服端
 **/
public class SingleThreadClient {

    public static void main(String[] args) {
        String ip="127.0.0.1";
        int port=4406;
        try {
            Socket socket=new Socket(ip,port);
            //發送消息
            OutputStream out = socket.getOutputStream();
            PrintStream printStream=new PrintStream(out);
            printStream.println("嗨,你好");
            printStream.flush();
            //接收消息
            InputStream in = socket.getInputStream();
            Scanner scanner = new Scanner(in);
            System.out.println("服務端>" + scanner.nextLine());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

案例五 繪製表白照片

package com.mg;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;

/**
 * 類名:Photo
 * 包名:com.mg
 * 創建時間:2020/6/18 2:55 上午
 * 創建人: 明哥
 * 描述:繪製表白女友照片
 **/
public class Photo {
    public static void createFongImg(String path) {
        // 定義一段內容在圖片中展示
        String base = "我愛你寶貝";
        try {
                /*
                  讀取需要轉換的圖片,這裏使用ImageIO中靜態方法read()接着傳入一個文件
                  read()方法返回一個BufferedImage類型圖片緩存流
                 */
            BufferedImage image = ImageIO.read(new File(path));
                /*
                接着創建BufferedImage用於存放輸出後文字圖片,參數就是推按的寬高與類型
                 */
            BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
                /*
                  創建一個2D座標轉換同時繪製相關類Graphics2D,用來設置每個像素點顏色字體大小與樣式
                 */
            Graphics2D graphics2D = (Graphics2D) newImage.getGraphics();
            // 設置字體類型、樣式、大小
            graphics2D.setFont(new Font("楷體", Font.BOLD, 12));
            int index = 0;
            // 循環遍歷每一個像素點,每隔12個像素點就替換文字
            for (int y = 0; y < image.getHeight(); y += 12) {
                for (int x = 0; x < image.getWidth(); x += 12) {
                    // 循環獲取圖片當前位置像素的顏色
                    int pxcolor = image.getRGB(x, y);
                    // 循環分離rgb三種顏色,分別進行灰度與二值化處理
                    int r = (pxcolor & 0xff0000) >> 16,
                            g = (pxcolor & 0xff00) >> 8,
                            b = pxcolor & 0xff;
                    // 循環通過graphics2D設置字體顏色
                    graphics2D.setColor(new Color(r, g, b));
                    // 循環 在當前位置繪製上一個文字
                    graphics2D.drawString(String.valueOf(base.charAt(index % base.length())), x, y);
                    // 循環 當前文字被繪製上以後繪製下一個文字
                    index++;
                }
            }
            // 通過ImageIO()方法,重新把圖片繪製並輸出。
            ImageIO.write(newImage, "JPG", new FileOutputStream("tel/temp.jpg")); // 生成後的照片存放地址
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        // 在main方法中調用createFongImg()方法,傳入需要生成的照片
        Photo.createFongImg("img/ims.jpg");
        System.out.println("over");
    }

}

 

案例六 數字消消樂

   遊戲規則,點擊選中兩個相同的數字即可消除這兩個數字,沒有過多複雜判斷。

一、MapTool.java類用於產生數字和判斷選中的兩個數字是否相同


import java.util.Random;

public class MapTool {

    public static int[][] createMap() {
        int[][] map = new int[10][10];
        Random rand = new Random();
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[i].length; j++) {
                map[i][j] = rand.nextInt(9) + 1;
            }
        }
        return map;
    }

    public static int[][] removed(int[][] map, int pi, int pj, int ci, int cj) {
        if (map[pi][pj] == map[ci][cj] && (pj != cj || pi != ci)) {
            System.out.println("消除:map[" + ci + "][" + cj + "],map[" + pi + "][" + pj + "]");
            map[pi][pj] = 0;
            map[ci][cj] = 0;
        }
        return map;
    }

}

二、GamePanel.java,遊戲佈局,遊戲核心邏輯代碼


import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.Timer;

public class GamePanel extends JPanel {
    private static final long serialVersionUID = 2L;
    private static final int sx = 50;// 左邊距
    private static final int sy = 50;// 上邊距
    private static final int w = 40; // 小方格寬高
    private static final int rw = 400; // 網格總寬高

    private int pj = 0, pi = 0; // 記錄兩個點擊選中的按鈕,第一個被點擊的按鈕座標
    private int cc = 0;// 被點擊選中的按鈕個數
    private int[][] map;// 存放遊戲數據的二維數組
    private boolean isEnd = false; // 遊戲結束標誌
    private JButton[][] btnMap; // 存放按鈕的二維數組,與map對應
    private int score; // 記錄分數
    private JButton restart; // 重新開始按鈕
    private Timer timer; // 定時器
    private int timestamp; // 時間戳

    public GamePanel() {
        // 設置佈局爲不使用預設的佈局
        setLayout(null);
    }

    /**
     * 開始遊戲
     */
    public void start() {
        // 創建遊戲數據地圖
        map = MapTool.createMap();
        btnMap = new JButton[10][10];
        score = 0;
        timestamp = 0;
        isEnd = false;

        // 創建按鈕,設置按鈕屬性,監聽事件,並添加到按鈕數組和窗體中
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[i].length; j++) {
                JButton btn = new JButton(map[i][j] + "");
                btn.setBounds(sx + (j * w) + 2, sy + (i * w) + 2, w - 2, w - 2);
                btn.setForeground(Color.RED);
                btn.setFont(new Font("Arial", 0, 30));
                btn.setBackground(Color.WHITE);
                btn.setBorder(BorderFactory.createRaisedBevelBorder());
                btn.setFocusPainted(false);
                btn.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        // 如果遊戲結束,返回,不執行後面的代碼
                        if (isEnd) {
                            return;
                        }
                        for (int i = 0; i < btnMap.length; i++) {
                            for (int j = 0; j < btnMap[i].length; j++) {
                                if (e.getSource().equals(btnMap[i][j])) {
                                    // 被選中的方格個數增加一個
                                    cc++;
                                    compare(j, i);
                                }
                            }
                        }

                    }
                });
                btnMap[i][j] = btn;
                this.add(btn);
            }
        }
        if (restart != null) {
            restart.setVisible(false);
            this.remove(restart);
            restart = null;
        }
        repaint();

        // 定時器,用來刷新時間
        timer = new Timer(1000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                timestamp++;
                repaint();
            }
        });
        timer.start();
    }

    /**
     * 判斷是否遊戲結束
     * 1、判斷二維數組map中的所有元素是否均爲0, 全部爲0返回true表示遊戲結束
     * 2、有不爲0的,判斷二維數組map中是否還有重複值,沒有重複值返回true表示遊戲結束
     * 否則返回false遊戲繼續
     *
     * @param map 二維數組,元素爲int類型
     * @return
     */
    public boolean isEnd(int[][] map) {
        int count_0 = 0;
        int count = 0;
        HashSet<Integer> hashSet = new HashSet<Integer>();
        for (int[] ms : map) {
            for (int m : ms) {
                count++;
                if (m != 0) {
                    hashSet.add(m);
                } else {
                    count_0++;
                }
            }
        }

        for (int[] ms : map) {
            for (int m : ms) {
                if (m != 0) {
                    if (hashSet.size() + count_0 == count) {
                        return true;
                    }
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * 重載JPanel父類的paintComponent方法,用來繪製網格,以及Game Over等
     */
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        try {
            // 獲取分鐘
            int min = timestamp / 60;
            // 獲取秒數
            int sec = timestamp % 60;
            // 判斷是否結束遊戲
            if (isEnd) {
                // 設置畫筆顏色爲紅色
                g.setColor(Color.RED);
                // 設置字體 微軟雅黑 加粗 62號
                g.setFont(new Font("微軟雅黑", 0, 62));
                // 繪製GAME OVER字樣
                g.drawString("GAME OVER", 60, 150);
                // 設置字體 微軟雅黑 加粗 40號
                g.setFont(new Font("微軟雅黑", 0, 40));
                // 繪製得分
                g.drawString("得分:" + score, 80, 230);
                // 繪製用時
                g.drawString("用時:" + String.format("%02d", min) + ":" + String.format("%02d", sec), 80, 280);
            } else {
                // 設置字體 微軟雅黑 加粗 20號
                g.setFont(new Font("微軟雅黑", Font.BOLD, 20));
                // 設置畫筆顏色爲黑色
                g.setColor(Color.BLACK);
                // 繪製時間顯示框
                g.fillRect(100, 8, 80, 30);
                // 繪製分數顯示框
                g.fillRect(400, 8, 50, 30);
                // 設置畫筆顏色爲紅色
                g.setColor(Color.RED);
                // 繪製時間提示標籤
                g.drawString("時間:", 50, 30);
                // 繪製時間
                g.drawString(String.format("%02d", min) + ":" + String.format("%02d", sec), 110, 30);
                // 繪製分數提示標籤
                g.drawString("分數:", 350, 30);
                // 繪製分數
                g.drawString(String.format("%03d", score) + "", 405, 30);

                // 繪製外層矩形框
                g.drawRect(sx, sy, rw, rw);
                // 繪製水平10個,垂直10個方格。 即水平方向9條線,垂直方向9條線, 外圍四周4條線已經畫過了,不需要再畫。 同時內部64個方格填寫數字。
                for (int i = 1; i < 10; i++) {
                    // 繪製第i條豎直線
                    g.drawLine(sx + (i * w), sy, sx + (i * w), sy + rw);

                    // 繪製第i條水平線
                    g.drawLine(sx, sy + (i * w), sx + rw, sy + (i * w));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 繪製按鈕顯示和隱藏
     *
     * @param i
     * @param j
     */
    private void drawButton(int i, int j) {
        if (map[i][j] != 0) {
            btnMap[i][j].setVisible(true);
        } else {
            btnMap[i][j].setVisible(false);
        }
    }

    /**
     * 比較兩次點擊的按鈕對應的數字
     *
     * @param cj
     * @param ci
     */
    private void compare(int cj, int ci) {
        /**
         * 如果cc是1,表示當前一共選中了一個方格,用pj,pi來記住這個方格的位置; 否則,表示現在選中的這個方格要與之前選中的方案比較,決定是否要刪除
         */
        if (cc == 1) {
            pj = cj;
            pi = ci;
            printMap(ci, cj);
            // 將所點擊的方格背景設置爲灰色
            btnMap[ci][cj].setBackground(Color.LIGHT_GRAY);
            drawButton(ci, cj);
        } else {// 此時,cc肯定是大於1的,表示要比較兩個方格的值是否相同
            printMap(ci, cj);
            map = MapTool.removed(map, pi, pj, ci, cj);// 讓MapTool類的remove方法去判斷上一次所選的(pj,pi)處的方格值與本次選擇的(cj,ci)處的方格值是否可以消掉
            // 處理第一個方格
            btnMap[ci][cj].setBackground(Color.WHITE);
            drawButton(ci, cj);
            // 處理第二個方格
            btnMap[pi][pj].setBackground(Color.WHITE);
            drawButton(pi, pj);
            cc = 0;// 將cc的值復位

            if (map[pi][pj] == map[ci][cj]) {
                score += 10;
            }
            isEnd = isEnd(map);
            // 遊戲結束
            if (isEnd) {
                // 關閉定時器
                timer.stop();
                // 隱藏剩餘的按鈕
                for (int i = 0; i < map.length; i++) {
                    for (int j = 0; j < map[i].length; j++) {
                        if (map[i][j] != 0) {
                            btnMap[i][j].setVisible(false);
                        }
                    }
                }
                // 創建添加重新開始按鈕
                restart = new JButton("重新開始");
                restart.setBackground(Color.WHITE);
                restart.setBounds(180, 350, 120, 40);
                restart.setBorder(BorderFactory.createRaisedBevelBorder());
                restart.setFocusPainted(false);
                restart.setForeground(Color.RED);
                restart.setFont(new Font("微軟雅黑", 0, 20));
                restart.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        start();
                    }
                });
                this.add(restart);
                repaint();
            }
        }

        repaint();
    }

    /**
     * 打印網格數據
     *
     * @param ci
     * @param cj
     */
    private void printMap(int ci, int cj) {
        if (ci == pi && cj == pj) {
            System.out.println("ci:" + ci + ", cj:" + cj);
        } else {
            System.out.println("ci:" + ci + ", cj:" + cj + ", pi:" + pi + ", pj:" + pj);
        }
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[i].length; j++) {
                if (ci == pi && cj == pj) {
                    System.out.print(((ci == i && cj == j) ? "[" + map[i][j] + "]" : " " + map[i][j] + " ") + "  ");
                } else {
                    System.out.print(
                            ((ci == i && cj == j || pi == i && pj == j) ? "[" + map[i][j] + "]" : " " + map[i][j] + " ")
                                    + "  ");
                }
            }
            System.out.println();
        }
    }
}

三、GameFrame.java,定義遊戲窗體


import javax.swing.JFrame;

public class GameFrame extends JFrame {
    private static final long serialVersionUID = 1L;
    GamePanel panel;

    /**
     * GameFrame構造方法
     */
    public GameFrame() {
        // 設置窗體標題
        setTitle("數字連連消");
        // 設置窗體位置和大小
        setBounds(100, 100, 515, 520);
        // 設置窗體不能改變大小
        setResizable(false);
        // 設置窗體居中顯示
        setLocationRelativeTo(null);
        // 設置窗體關閉即退出
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        panel = new GamePanel();
        add(panel);
        // 最後顯示窗體
        setVisible(true);
    }

    /**
     * 啓動遊戲
     */
    public void start() {
        panel.start();
    }
}

四、Main.java,遊戲程序的入口

package com.feonix;

public class Main {
	public static void main(String[] args) {
		new GameFrame().start();
	}
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章