Java學習-第一部分-第二階段-項目實戰:坦克大戰1

来源:https://www.cnblogs.com/wenjie2000/archive/2022/08/30/16641366.html
-Advertisement-
Play Games

坦克大戰【1】 筆記目錄:(https://www.cnblogs.com/wenjie2000/p/16378441.html) 坦克大戰游戲演示 為什麼寫這個項目 ✔好玩 ✔涉及到java各個方面的技術 java面向對象編程 多線程 文件i/o操作 資料庫 ✔鞏固舊知識,學習新知識 寫項目前的提 ...


坦克大戰【1】

筆記目錄:(https://www.cnblogs.com/wenjie2000/p/16378441.html)

坦克大戰游戲演示

為什麼寫這個項目
✔好玩
✔涉及到java各個方面的技術

  1. java面向對象編程
  2. 多線程
  3. 文件i/o操作
  4. 資料庫

✔鞏固舊知識,學習新知識

寫項目前的提醒

  1. 編寫坦克大戰游戲,你需要有一定的java基礎,是完全可以聽懂的,最核心的部分一起完成。

  2. 記住一點:成為一個編程高手的秘訣就是:思考------編程-----思考------編程

如何講解這個項目,授課的原則:

  1. 努力做到通俗易懂。

  2. 寧肯羅嗦一點,也不遺漏細節。

  3. 項目是從小到大的過程,每個完整的項目被分解成不同的版本,從1.0到1.1.….最後版,隨版本的增加,將新的功能和新的知識點融入到項目中,整個過程是循序漸進的。讓大家輕鬆的學習,高效的掌握java技術。

    image

java繪圖坐標體系

●坐標體系-介紹

下圖說明瞭Java坐標系。坐標原點位於左上角,以像素為單位。在Java坐標系中,第一個是x坐標,表示當前位置為水平方向,距離坐標原點x個像素;第二個是y坐標,表示當前位置為垂直方向,距離坐標原點y個像素。

image

坐標體系-像素

  1. 繪圖還必須要搞清一個非常重要的概念-像素個個像素等於多少釐米?
  2. 電腦在屏幕上顯示的內容都是由屏幕上的每一個像素組成的。例如,電腦顯示器的解析度是800×600,表示電腦屏幕上的每一行由800個點組成,共有600行,整個電腦屏幕共有480 000個像素。像素是一個密度單位,而釐米是長度單位,兩者無法比較

java繪圖技術

介紹-快速入門

先給大家寫一個小案例,在面板上畫一個小圓,然後借這個案例,來講解java繪圖技術原理。

import javax.swing.*;
import java.awt.*;

public class DrawCircle extends JFrame {//JFrame對應視窗,可以理解成是一個畫框
    //定義一個面板
    private MyPanel mp = null;
    public static void main(String[] args) {
        new Te();
        System.out.println("退出程式...");
    }
    public DrawCircle() {//構造器
        //初始化面板
        mp = new MyPanel();
        //把面板放入到視窗(畫框)
        this.add(mp);
        //設置視窗的大小
        this.setSize(400,300);
        ///當點擊視窗的小x,程式完全退出.
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);//可以顯示
    }
}

//1.先定義一個MyPanel,繼承JPanel類,畫圖形,就在面板上畫
class MyPanel extends JPanel {
    //說明:
    //1.MyPanel對象就是一個畫板
    //2.Graphics g把g理解成一支畫筆
    //3.Graphics提供了很多繪圖的方法
    //Graphics g
    @Override
    public void paint(Graphics g) {//繪圖方法
        super.paint(g);//調用父類的方法完成初始化
        System.out.println("調用了paint方法");
        //畫出一個圓形.
        g.drawOval(10, 10, 100, 100);
    }
}

繪圖原理

✔Component類提供了兩個和繪圖相關最重要的方法:

  1. paint(Graphics g)繪製組件的外觀

  2. repaint()刷新組件的外觀。

✔當組件第一次在屏幕顯示的時候,程式會自動的調用paint()方法來繪製組件。

✔在以下情況paint()將會被調用:

  1. 視窗最小化再最大化
  2. 視窗的大小發生變化
  3. repaint方法被調用

✔思考題:如何證明上面的三種情況,會調用paint()方法

Graphics類

Graphics類你可以理解就是畫筆,為我們提供了各種繪製圖形的方法:[參考jdk幫助文檔]

  1. 畫直線drawLine(int x1,int y1,int x2,int y2)

  2. 畫矩形邊框drawRect(int x, int y, int width, int height)

  3. 畫橢圓邊框drawOval(int x, int y, int width, int height)

  4. 填充矩形 fillRect(int x, int y, int width, int height)

  5. 填充橢圓fillOval(int x, int y, int width, int height)

  6. 畫圖片drawlmage(lmage img, int x, int y, ..)

  7. 畫字元串drawString(String str, int x, int y)

  8. 設置畫筆的字體setFont(Font font)

  9. 設置畫筆的顏色setColor(Color c)

import javax.swing.*;
import java.awt.*;


public class DrawCircle extends JFrame {//JFrame對應視窗,可以理解成是一個畫框
    //定義一個面板
    private MyPanel mp = null;
    public static void main(String[] args) {
        new Te();
        System.out.println("退出程式...");
    }
    public DrawCircle() {//構造器
        //初始化面板
        mp = new MyPanel();
        //把面板放入到視窗(畫框)
        this.add(mp);
        //設置視窗的大小
        this.setSize(400,300);
        ///當點擊視窗的小x,程式完全退出.
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);//可以顯示
    }
}

//1.先定義一個MyPanel,繼承JPanel類,畫圖形,就在面板上畫
class MyPanel extends JPanel {
    //說明:
    //1.MyPanel對象就是一個畫板
    //2.Graphics g把g理解成一支畫筆
    //3.Graphics提供了很多繪圖的方法
    //Graphics g
    @Override
    public void paint(Graphics g) {//繪圖方法
        super.paint(g);//調用父類的方法完成初始化
        System.out.println("調用了paint方法");

        //演示繪製不同的圖形..
        //1. 畫直線drawLine(int x1,int y1,int x2,int y2)
//        g.drawLine(10,10,100,100);
        //2. 畫矩形邊框drawRect(int x, int y, int width, int height)
//        g.drawRect(10,10,100,100);
        //3. 畫橢圓邊框drawOval(int x, int y, int width, int height)
//        g.drawOval(10, 10, 100, 100);
        //4. 填充矩形 fillRect(int x, int y, int width, int height)
//        g.setColor(Color.BLUE);
//        g.fillRect(10,10,100,100);
        //5. 填充橢圓fillOval(int x, int y, int width, int height)
//        g.setColor(Color.red);
//        g.fillOval(10,10,100,100);
        //6. 畫圖片drawlmage(lmage img, int x, int y, ..)
//        Image image = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/張文傑.jpg"));
//        g.drawImage(image,10,10,150,200,this);
        //7. 畫字元串drawString(String str, int x, int y)
//        g.setColor(Color.red);
//        g.setFont(new Font("行書",Font.BOLD,50));
//        g.drawString("你好",100,50);//x,y對應字元串左下角位置
        //8. 設置畫筆的字體setFont(Font font)
        //9. 設置畫筆的顏色setColor(Color c)
    }
}

繪出坦克

坦克大戰游戲中,我們會用到坦克,現在我們就利用java繪圖技術來畫出一個小坦克,完成我們的坦克大戰游戲1.0版本!

image

Tank//坦克位置

public class Tank {
    //坦克左上角坐標
    private int x;
    private int y;

    public Tank(int x, int y) {
        this.x = x;
        this.y = y;
    }

    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;
    }
}

Hero//玩家坦克

public class Hero extends Tank{
    public Hero(int x, int y) {
        super(x, y);
    }
}

MyPanel//面板

import javax.swing.*;
import java.awt.*;

public class MyPanel extends JPanel {
    Hero hero=null;//定義我的坦克
    public MyPanel(){
        hero=new Hero(100,100);//初始化自己的坦克位置
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0,0,1000,750);//黑色背景

        //畫出坦克
        drawTank(hero.getX(),hero.getY(),g,0,1);
    }

    /**
     *
     * @param x 坦克左上角x坐標
     * @param y 坦克左上角y坐標
     * @param g 畫筆
     * @param direct 坦克方向(上下左右)
     * @param type 坦克類型
     */
    public void drawTank(int x,int y,Graphics g,int direct,int type){

        switch (type){
            case 0://我們的坦克
                g.setColor(Color.cyan);
                break;
            case 1://敵人的坦克
                g.setColor(Color.yellow);
                break;
        }
        //根據坦克方向,繪製坦克
        switch (direct){
            case 0://向上
                g.fill3DRect(x,y,10,60,false);//畫出坦克左邊輪子
                g.fill3DRect(x+30,y,10,60,false);//畫出坦克右邊輪子
                g.fill3DRect(x+10,y+10,20,40,false);//畫出坦克蓋子
                g.fillOval(x+10,y+20,20,20);//畫出圓形蓋子
                g.drawLine(x+20,y+30,x+20,y);//畫出炮筒
                break;
            case 1:
            case 2:
            case 3:
        }
    }
}

HspTankGame01//窗體

import javax.swing.*;

public class HspTankGame01 extends JFrame {
    MyPanel mp=null;
    public static void main(String[] args) {
        new HspTankGame01();
    }

    public HspTankGame01() {
        mp=new MyPanel();
        this.add(mp);
        this.setSize(1000,750);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
}

java事件處理機制

事件處理機制-看個問題

請大家看一個小程式。(BallMove.java)怎樣讓小球受到鍵盤的控制,上下左右移動.

image

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class BallMove extends JFrame{//視窗
    MyPanel mp=null;
    public static void main(String[] args) {
        new BallMove();
    }
    public BallMove(){
        mp=new MyPanel();
        this.add(mp);
        this.setSize(400,300);
        //視窗JFrame對象可以監聽鍵盤事,即可以監聽到面板發生的鍵盤事件
        this.addKeyListener(mp);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
}

//面板,可以畫出小球
//KeyListener是監聽器,可以監聽鍵盤事件
class MyPanel extends JPanel implements KeyListener {
    //為了讓小球可以移動,把他的左上角的坐標(x,y)設置變數
    int x = 10;
    int y =10;
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillOval(x,y,20,20);
    }

    //有字元輸出,該方法就會觸發
    @Override
    public void keyTyped(KeyEvent e) {

    }

    //當某個鍵按下,該方法觸發
    @Override
    public void keyPressed(KeyEvent e) {
        //System.out.println((char)e.getKeyCode()+"被按下");

        //根據用戶按下的不同鍵,來處理小球的移動(上下左右)
        //在java中,會給每一個鍵,分配一個值(int)
        if(e.getKeyCode()==KeyEvent.VK_DOWN){//KeyEvent.VK_DOWN就是向下的箭頭對應的code
            y++;
        }else if (e.getKeyCode()==KeyEvent.VK_UP){
            y--;
        }else if(e.getKeyCode()==KeyEvent.VK_RIGHT){
            x++;
        }else if(e.getKeyCode()==KeyEvent.VK_LEFT){
            x--;
        }
        //讓面板重繪
        this.repaint();
    }

    //當某個鍵鬆開,被觸發
    @Override
    public void keyReleased(KeyEvent e) {

    }
}

基本說明

java事件處理是採取"委派事件模型"。當事件發生時,產生事件的對象,會把此"信息”傳遞給"事件的監聽者"(例:KeyListener)處理,這裡所說的“信息"實際上就是java.awt.event事件類庫里某個類所創建的對象,把它稱為"事件的對象"(例:KeyEvent)。

請大家看一個示意圖:

image

事件處理機制深入理解

  1. 前面我們提到幾個重要的概念事件源,事件,事件監聽器我們下麵來全面的介紹它們。

  2. 事件源:事件源是一個產生事件的對象,比如按鈕,窗回等。

  3. 事件:事件就是承載事件源狀態改變時的對象,比如當鍵盤事件、滑鼠事件、視窗事件等等,會生成一個事件對象,該對象保存著當前事件很多信息,比如KeyEvent對象有含義被按下鍵的Code值。java.awt.event包和javax.swing.event包中定義了各種事件類型

  4. 事件類型:查閱jdk文檔

image

  1. 事件監聽器介面:

    (1)當事件源產生一個事件,可以傳送給事件監聽者處理

    (2)事件監聽者實際上就是一個類,該類實現了某個事件監聽器介面比如前面我們案例中的MyPanle就是一個類,它實現了KeyListener介面,它就可以作為一個事件監聽者,對接受到的事件進行處理

    (3)事件監聽器介面有多種,不同的事件監聽器介面可以監聽不同的事件,一個類可以實現多個監聽介面

    (4)這些介面在java.awt.event包和javax.swing.event包中定義。列出常用的事件監聽器介面,查看jdk文檔聚集了.

坦克大戰游戲(1.0版)

繪製己方坦克(能夠使用WASD移動)

繪製敵方坦克(顏色有差別,至少3個)//要想敵人的坦克移動,需要下一節的線程知識

Tank//坦克

package tankgame02;

public class Tank {
    //坦克左上角坐標
    private int x;
    private int y;
    private int direct;//坦克方向 0上 1右 2下 3左

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    private int speed=1;//坦克速度

    //上右下左移動方法
    public void moveUp(){
        y-=speed;
    }
    public void moveDown(){
        y+=speed;
    }
    public void moveLeft(){
        x-=speed;
    }
    public void moveRight(){
        x+=speed;
    }

    public int getDirect() {
        return direct;
    }

    public void setDirect(int direct) {
        this.direct = direct;
    }

    public Tank(int x, int y) {
        this.x = x;
        this.y = y;
    }

    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;
    }
}

Hero//己方坦克

package tankgame02;

public class Hero extends Tank {
    public Hero(int x, int y) {
        super(x, y);
    }
}

EnemyTank//敵方坦克

package tankgame02;

public class EnemyTank extends Tank{
    public EnemyTank(int x, int y) {
        super(x, y);
    }
}

MyPanel//面板

package tankgame02;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Hashtable;
import java.util.Vector;

////為了監聽鍵盤事件,實現KeyListener
public class MyPanel extends JPanel implements KeyListener {
    Hero hero = null;//定義我的坦克
    Vector<EnemyTank> enemyTanks = new Vector<>();//定義敵人坦克
    int enemyTankSize = 3;

    public MyPanel() {
        hero = new Hero(100, 100);//初始化自己的坦克位置
        for (int i = 0; i < enemyTankSize; i++) {//初始化敵人的坦克位置
            enemyTanks.add(new EnemyTank(100 * (i + 1), 0));
        }

//        hero.setSpeed(5);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0, 0, 1000, 750);//黑色背景

        //畫出坦克
        drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 0);

        //畫出敵人坦克
        for (int i = 0; i < enemyTankSize; i++) {
            //取出坦克
            EnemyTank enemyTank = enemyTanks.get(i);
            enemyTank.setDirect(2);
            drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 1);
        }
    }

    /**
     * @param x      坦克左上角x坐標
     * @param y      坦克左上角y坐標
     * @param g      畫筆
     * @param direct 坦克方向(上下左右)
     * @param type   坦克類型
     */
    public void drawTank(int x, int y, Graphics g, int direct, int type) {

        switch (type) {
            case 0://我們的坦克
                g.setColor(Color.cyan);
                break;
            case 1://敵人的坦克
                g.setColor(Color.yellow);
                break;
        }
        //根據坦克方向,繪製坦克
        switch (direct) {
            case 0://向上
                g.fill3DRect(x, y, 10, 60, false);//畫出坦克左邊輪子
                g.fill3DRect(x + 30, y, 10, 60, false);//畫出坦克右邊輪子
                g.fill3DRect(x + 10, y + 10, 20, 40, false);//畫出坦克蓋子
                g.fillOval(x + 10, y + 20, 20, 20);//畫出圓形蓋子
                g.drawLine(x + 20, y + 30, x + 20, y);//畫出炮筒
                break;
            case 1://右
                g.fill3DRect(x - 10, y + 10, 60, 10, false);//畫出坦克左邊輪子
                g.fill3DRect(x - 10, y + 40, 60, 10, false);//畫出坦克右邊輪子
                g.fill3DRect(x, y + 20, 40, 20, false);//畫出坦克蓋子
                g.fillOval(x + 10, y + 20, 20, 20);//畫出圓形蓋子
                g.drawLine(x + 20, y + 30, x + 50, y + 30);//畫出炮筒
                break;
            case 2://下
                g.fill3DRect(x, y, 10, 60, false);//畫出坦克左邊輪子
                g.fill3DRect(x + 30, y, 10, 60, false);//畫出坦克右邊輪子
                g.fill3DRect(x + 10, y + 10, 20, 40, false);//畫出坦克蓋子
                g.fillOval(x + 10, y + 20, 20, 20);//畫出圓形蓋子
                g.drawLine(x + 20, y + 30, x + 20, y + 60);//畫出炮筒
                break;
            case 3://左
                g.fill3DRect(x - 10, y + 10, 60, 10, false);//畫出坦克左邊輪子
                g.fill3DRect(x - 10, y + 40, 60, 10, false);//畫出坦克右邊輪子
                g.fill3DRect(x, y + 20, 40, 20, false);//畫出坦克蓋子
                g.fillOval(x + 10, y + 20, 20, 20);//畫出圓形蓋子
                g.drawLine(x + 20, y + 30, x + -10, y + 30);//畫出炮筒
                break;
        }

    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    //處理WDSA鍵按下情況
    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_W) {
            //改變坦克方向
            hero.setDirect(0);
            //修改坦克坐標
            hero.moveUp();
        } else if (e.getKeyCode() == KeyEvent.VK_D) {
            hero.setDirect(1);
            hero.moveRight();
        } else if (e.getKeyCode() == KeyEvent.VK_S) {
            hero.setDirect(2);
            hero.moveDown();
        } else if (e.getKeyCode() == KeyEvent.VK_A) {
            hero.setDirect(3);
            hero.moveLeft();
        }
        this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }
}

HspTankGame02//窗體

package tankgame02;

import javax.swing.*;

public class HspTankGame02 extends JFrame {
    MyPanel mp=null;
    public static void main(String[] args) {
        new HspTankGame02();
    }

    public HspTankGame02() {
        mp=new MyPanel();
        this.add(mp);
        this.setSize(1000,750);
        this.addKeyListener(mp);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 類型 |類型 | 例子| 描述 | | | | | | number | 1,2,-2 | 任意數字 | | string | 'hi',"hi" | 任意字元串 | | boolean | true,false | 布爾值或者true false | | 字面量 | 其本身 | 限制變數的值就是該 ...
  • 在各種短視頻界面上,我們經常會看到類似這樣的點贊動畫: 非常的有意思,有意思的交互會讓用戶更願意進行互動。 那麼,這麼有趣的點贊動畫,有沒有可能使用純 CSS 實現呢?那當然是必須的,本文,就將巧妙的藉助 transition,僅僅使用 CSS 完成這麼一個點贊動畫。 實現不同表情的不斷上升 如果使 ...
  • 在設計稿轉網頁中運用基於self-attention機制設計的機器學習模型進行設計稿的佈局,能夠結合dom節點的上下文得出合理的方案. ...
  • 代碼的執行流程分為順序,分支和迴圈三種結構,順序結構是預設的,判斷結構主要有if-else和switch-case兩種,迴圈結構有while,do-while,for三種,其中continue和break是跳出迴圈. ...
  • 蒼穹之邊,浩瀚之摯,眰恦之美; 悟心悟性,善始善終,惟善惟道! —— 朝槿《朝槿兮年說》 寫在開頭 從接觸 Java 開發到現在,大家對 Java 最直觀的印象是什麼呢?是它宣傳的 “Write once, run anywhere”,還是目前看已經有些過於形式主義的語法呢?有沒有靜下心來仔細想過, ...
  • 創建對象可能會導致大量的重覆代碼,可能會需要複合對象訪問不到的信息,也可能提供不了足夠級別的抽象,還可能並不是複合對象概念的一部分。工廠設計模式通過定義一個單獨的創建對象的方法來解決這些問題。 ...
  • 事實上,泛型才是Go lang1.18最具特色的所在,但為什麼我們一定要拖到後面才去探討泛型?類比的話,我們可以想象一下給小學一年級的學生講王勃的千古名篇《滕王閣序》,小學生有多大的概率可以理解作者的青雲之志以及壯志難酬的憤懣心情?恐怕很難罷,是的,如果對Go lang的強類型語法沒有一段時間的體驗 ...
  • 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 特效 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> O ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...