前言
本篇博客是明哥針對有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();
}
}