Java坦克大戰(一)

来源:https://www.cnblogs.com/1693977889zz/archive/2018/02/10/8440075.html
-Advertisement-
Play Games

接下來的幾篇博客,想記錄一下通過學習坦克大戰項目來循序漸進的學習Java基礎。主要是為了鞏固基礎知識,當然學習編程重要的還是多敲,問題通常是在敲代碼的過程中發現的,積累也是在敲代碼中尋求的經驗。這個坦克大戰項目是利用Java圖形界面來做的,比較簡陋。但是,在不斷的往裡面加功能的時候,可以學到很多知識 ...


接下來的幾篇博客,想記錄一下通過學習坦克大戰項目來循序漸進的學習Java基礎。主要是為了鞏固基礎知識,當然學習編程重要的還是多敲,問題通常是在敲代碼的過程中發現的,積累也是在敲代碼中尋求的經驗。這個坦克大戰項目是利用Java圖形界面來做的,比較簡陋。但是,在不斷的往裡面加功能的時候,可以學到很多知識,最重要的還是體會Java的面向對象編程思想。下麵介紹幾個用的上的Demo,最後是坦克大戰的1.0版本。

Demo1:回顧事件處理機制

/*
 * 功能:事件處理機制(ActionListener的應用)
 */
package com.fanghua1;
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.*;

public class Demo1_1 extends JFrame implements ActionListener {
    // 定義一個panel
    MyP mp = null;
    JButton jb1 = null;
    JButton jb2 = null;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Demo1_1 be = new Demo1_1();
    }

    public Demo1_1() {
        mp = new MyP();
        jb1 = new JButton("黑色");
        jb2 = new JButton("紅色");

        this.add(jb1, BorderLayout.NORTH);
        mp.setBackground(Color.black);
        this.add(mp);// 中間是預設的,不用加參數
        this.add(jb2, BorderLayout.SOUTH);
        

        // 註冊監聽(this 代表Demo9_4)(每創建一個對象就有一個this)
        //jb1、jb2都是事件源對象
        jb1.addActionListener(this);
        // 指定Action命令
        jb1.setActionCommand("aa");
        jb2.addActionListener(this);
        jb2.setActionCommand("bb");

        jb1.addActionListener(new Cat());
        jb2.addActionListener(new Cat());
        
        this.setSize(200, 150);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    @Override
    // 對事件處理的方法,actionPerformed函數 
    //ActionEvent e 是事件對象
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        // System.out.println("OK");//用來測試監聽有沒有實現,看控制台
        // 判斷那個按鈕被點擊
        if (e.getActionCommand().equals("aa")) {
            System.out.println("你點擊的是黑色");
            mp.setBackground(Color.black);
        } else if (e.getActionCommand().equals("bb")) {
            System.out.println("你點擊的是紅色");
            mp.setBackground(Color.red);
        } else {
            System.out.println("不知道");
        }
    }

    class MyP extends JPanel {

        public void Paint(Graphics g) {
            super.paint(g);
            g.fillRect(0, 0, 30, 30);

        }
    }
}
//一個事件源並不是只有一個事件監聽者,他可以有多個事件監聽者
class Cat implements ActionListener{

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getActionCommand().equals("aa")){
            System.out.println("我監聽到了黑色");
        }else if(e.getActionCommand().equals("bb")){
            System.out.println("我監聽到了紅色");
        }else{
            System.out.println("Nothing");
        }
        
    }
    
}

Demo2:加深對事件處理機制的理解

/*
 * 加深對事件處理機制的理解
 * 通過上下左右鍵,來控制小球的位置
 */
package com.fanghua1;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class Demo1_2 extends JFrame {

    // 定義
    PaintO jp = null;

    // 構造函數中初始化
    public Demo1_2() {
        jp = new PaintO();

        this.add(jp);

        this.addKeyListener(jp);

        this.setSize(400, 300);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Demo1_2();
    }

}

// 定義自己的面板
class PaintO extends JPanel implements java.awt.event.KeyListener {
    int x = 10;
    int y = 10;

    public void paint(Graphics g) {
        super.paint(g);
        g.fillOval(x, y, 40, 40);
    }

    @Override
    // 鍵的一個值被輸出
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    // 鍵被按下
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub
        // System.out.print("按下"+(char)e.getKeyCode());

        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            // x=x;這樣就不用寫了
            y++; // y+=5;提速

            // 調用repaint()函數,來重繪界面
            this.repaint();

        } else if (e.getKeyCode() == KeyEvent.VK_UP) {
            y--;
            this.repaint();
        } else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            x--;
            this.repaint();
        } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            x++;
            this.repaint();
        }

    }

    @Override
    // 鍵被釋放
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub

    }

}
//功能:事件處理機制 演示1.2
package com.fanghua1;
import java.awt.*;
import javax.swing.*;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

public class Demo1_3 extends JFrame {

    Mypanl1_3 mp1 = null;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Demo1_3();
    }

    public Demo1_3() {

        // 這裡經常忘記
        mp1 = new Mypanl1_3();

        this.add(mp1);

        // 註冊監聽
        this.addKeyListener(mp1);
        this.addMouseListener(mp1);
        this.addWindowListener(mp1);
        this.addMouseMotionListener(mp1);
        // this.addActionListener(mp1);

        // 按鈕用這個,this.addActionListener(mp1);

        this.setSize(300, 400);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);

    }
}

// 這個經常用,java.awt.event.MouseMotionListener 滑鼠移動和拖拽
class Mypanl1_3 extends JPanel implements java.awt.event.MouseMotionListener,
        KeyListener, MouseListener, WindowListener {

    public void paint(Graphics g) {
        super.paint(g);
    }

    @Override
    public void windowOpened(WindowEvent e) {
        // TODO Auto-generated method stub
        System.out.print("開啟視窗被調用" + e.getClass());
    }

    @Override
    public void windowClosing(WindowEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void windowClosed(WindowEvent e) {
        // TODO Auto-generated method stub
        System.out.println("視窗關閉了");

    }

    @Override
    public void windowIconified(WindowEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void windowDeiconified(WindowEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    // 視窗激活
    public void windowActivated(WindowEvent e) {
        // TODO Auto-generated method stub
        System.out.println("視窗激活");
    }

    @Override
    // 視窗不激活
    public void windowDeactivated(WindowEvent e) {
        // TODO Auto-generated method stub
        System.out.println("視窗不激活");

    }

    @Override
    // 1.滑鼠點擊
    public void mouseClicked(MouseEvent e) {
        // TODO Auto-generated method stub
        System.out
                .println("當前滑鼠點擊的橫坐標是" + e.getX() + "當前滑鼠點擊de縱坐標是" + e.getY());
    }

    @Override
    // 2.滑鼠按壓,沒鬆開
    public void mousePressed(MouseEvent e) {
        // TODO Auto-generated method stub
        System.out.println("滑鼠按壓,沒鬆開");

    }

    @Override
    // 3.滑鼠鬆開
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub
        System.out.println("滑鼠鬆開");

    }

    @Override
    // 4.滑鼠移動到MyPanel
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub
        System.out.println("滑鼠移動到面板");

    }

    @Override
    // 5.滑鼠離開
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub
        System.out.println("滑鼠離開");

    }

    @Override
    // 1.鍵輸入 (與 keyPressed的不同是,外圍一圈的鍵都不會有反應)
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    // 2.鍵按下(我測試過了:
    // 字母和少數鍵沒反應,其他鍵盤最外一圈F1-F12,Delete等控制台之類都有反應)
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub
        // 註意:這裡切換到美式鍵盤下演示。我在搜狗輸入法下演示了,結果總出不來
        System.out.println(e.getKeyChar() + "鍵按下");
    }

    @Override
    // 鍵鬆開
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    // 重要:滑鼠拖拽
    public void mouseDragged(MouseEvent e) {
        // TODO Auto-generated method stub
        System.out.println("滑鼠拖拽了");

    }

    @Override
    // 重要:滑鼠移動
    public void mouseMoved(MouseEvent e) {
        // TODO Auto-generated method stub
        // System.out.println("滑鼠移動了");
        System.out.println("當前移動移動橫坐標是" + e.getX() + "當前移動縱坐標是" + e.getY());
    }
}

Demo3:進程與線程

/* 功能:進程與線程練習
 * Java中一個類要當作線程來使用,方法有兩種:
 * 1.繼承Thread類,並重寫run函數
 * 2.實現Runnable介面,並重寫run函數
 * 在這裡就可以看出繼承(類)和實現(類)的區別了
 */
package com.fanghua1;

public class Demo1_4 extends Thread {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Demo1_4 de = new Demo1_4();
        // 啟動run函數
        de.start();
    } 

    int times = 0;

    @Override
    public void run() {
        // TODO Auto-generated method stub
        // 在控制台,每隔一秒輸出一句“HeLLo Word”
        while (true) {
            // 每隔一秒=休眠一秒
            try {
                Thread.sleep(1000);// 1000表示1000毫秒
                // sleep 會讓該線程進入到Blocked(阻塞)狀態,並釋放資源
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            times++;
            System.out.println("HeLLo Word" + times);
            if (times == 10) {
                // 退出程式
                break;
            }
        }
    }
}
/* 功能:加深理解多線程
 * 編寫程式,該程式可以接收一個整數n
 * 創建一個線程計算從1+......+n 並輸出結果
 * 創建另一個線程每隔一秒在控制台輸出“我是另一個線程,我輸出第n個HeLLo”
 * 兩個工作要同時進行
 * 註意:如果說沒有任何要求的情況下來開發線程,最好用介面來實現,給別人繼承的空間
 *之後會具體說繼承和實現的區別
 */

package com.fanghua1;

public class Demo1_6 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Thread(new Bird(10)).start();
        new Thread(new Pig(10)).start();

    }
}

// 計算需求
class Bird implements Runnable {

    int n = 0;
    int res = 0;
    int times = 0;
    public Bird(int n) {
        this.n = n;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        // 每隔1秒算一次
        while (true) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            res += (++times);
            System.out.print("當前結果是" + res);
            if (times == n) {
                System.out.print("最後結果是" + res);
                break;
            }
        }
    }

}

// 輸出需求
class Pig implements Runnable {
    int n = 0;
    int times = 0;

    public Pig(int n) {
        this.n = n;
    }

    public void run() {
        // TODO Auto-generated method stub
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("我是另一個線程,我輸出第" + times + "個HeLLo");
            times++;
            if (times == n) {
                break;
            }
        }
    }
}

坦克大戰(1.0版本)

/*
* 功能:畫出坦克 * 學習:圖形界面 */ package com.fanghua1; import java.awt.*; import javax.swing.*; public class MyTankGame1_1 extends JFrame { Mypanel mp=null; public static void main(String[] args) { // TODO Auto-generated method stub new MyTankGame1_1(); } // 構造函數 public MyTankGame1_1() { mp=new Mypanel(); this.add(mp); this.setSize(600,500); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } } // 我的面板,不要在JFram上面畫坦克,會很亂 class Mypanel extends JPanel{ //定義一個我的坦克 Hero hero=null; //在構造函數里給坦克意義初始位置 public Mypanel(){ hero=new Hero(10,10); } //重寫paint函數 public void paint(Graphics g){ //一定要調用 super.paint(g); //設置背景顏色 g.fillRect(0, 0, 600, 500); //調用繪畫坦克 this.drawTank(hero.getX(), hero.getY(), g, 0, 1); } //畫出坦克的函數 public void drawTank(int x,int y,Graphics g,int direct,int type){ //坦克類型 switch(type){ case 0: g.setColor(Color.green); break; case 1: g.setColor(Color.yellow); break; } //判斷方向 switch(direct){ //向上 case 0: //畫出坦克函數(已封裝) //畫出左邊的矩形 g.fill3DRect(x,y, 5, 30,false); g.fill3DRect(x+15, y, 5,30,false); //畫出中間矩形 g.fill3DRect(x+5, y+5, 10, 20,false); //畫出圓形 g.fillOval(x+5, y+10, 10, 10); //畫出線 g.drawLine(x+10,y+15, x+10, y); break; } } } // 坦克類(自己和敵人的坦克的父類) class Tank { // x表示坦克的橫坐標,y代表坦克的縱坐標 int x = 0; 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; } int y = 0; // 構造函數 public Tank(int x, int y) { this.x = x; this.y = y; } } // 我的坦克 class Hero extends Tank { // 因為坦克裡面沒有定義無參構造函數 // 會報錯:Implicit super constructor Tank() is undefined for default // constructor. Must define an explicit constructor // 解決1.在Tank類裡面定義無參構造函數。 // 2用父類的構造函數,來初始化子類的成員變數。如下: public Hero(int x, int y) { super(x, y); } } /* * public void paint(Graphics g){ *一定要調用 *super.paint(g); *g.fillRect(0, 0, 600, 500);q *畫出坦克函數(未封裝) *畫出左邊的矩形 *g.fill3DRect(hero.getX(),hero.getY(), 5, 30,false); *g.fill3DRect(hero.getX()+15, hero.getY(), 5,30,false); *畫出中間矩形 *g.fill3DRect(hero.getX()+5, hero.getY()+5, 10, 20,false); *畫出圓形 *g.fillOval(hero.getX()+5, hero.getY()+10, 10, 10); *畫出線 *g.drawLine(hero.getX()+10,hero.getY()+15, hero.getX()+10, hero.getY()); *} */

坦克大戰(1.0.1版本)

/*
 * 功能:坦克可移動
 * 學習:事件處理機制
*/
package com.fanghua1;
import java.awt.*;
import java.awt.event.KeyEvent;

import javax.swing.*;

public class MyTankGame1_2 extends JFrame {

    Mypanel1_2 mp = null;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new MyTankGame1_2();
    }

    // 構造函數
    public MyTankGame1_2() {
        mp = new Mypanel1_2();
        this.add(mp);
        // 註冊監聽
        this.addKeyListener(mp);

        this.setSize(600, 500);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);

    }
}

// 我的面板,不要在JFram上面畫坦克,會很亂
class Mypanel1_2 extends JPanel implements java.awt.event.KeyListener {

    // 定義一個我的坦克
    Hero1_2 hero = null;

    // 在構造函數里給坦克意義初始位置
    public Mypanel1_2() {
        hero = new Hero1_2(10, 10);
    }

    // 重寫paint函數
    public void paint(Graphics g) {
        // 一定要調用
        super.paint(g);
        // 設置背景顏色
        g.fillRect(0, 0, 600, 500);
        // 調用繪畫坦克
        this.drawTank(hero.getX(), hero.getY(), g, 0, 1);

    }

    // 畫出坦克的函數
    public void drawTank(int x, int y, Graphics g, int direct, int type) {
        // 坦克類型
        switch (type) {
        case 0:
            g.setColor(Color.green);
            break;
        case 1:
            g.setColor(Color.yellow);
            break;
        }
        // 判斷方向
        switch (direct) {
        // 向上
        case 0:
            // 畫出坦克函數(已封裝)
            // 畫出左邊的矩形
            g.fill3DRect(x, y, 5, 30, false);
            g.fill3DRect(x + 15, y, 5, 30, false);
            // 畫出中間矩形
            g.fill3DRect(x + 5, y + 5, 10, 20, false);
            // 畫出圓形
            g.fillOval(x + 5, y + 10, 10, 10);
            // 畫出線
            g.drawLine(x + 10, y + 15, x + 10, y);
            break;
        }

    }

    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub
        // e.getKeyCode() ==KeyEvent.VK_W 這句話我試了好久,都不能實現
        // 原因:我在測試的時候,輸入法是搜狗輸入法,應該切換到美式鍵盤或者英文狀態下!!!!!
        if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_W) {
            // 這裡有三處不好的地方:
            // 1.方向(比如this.hero.y--;)寫死了,以後想改變移動速度,這裡實現起來麻煩。更正(將“速度”在坦克類里封裝成函數)
            // 2.重繪(this.repaint();)不用每個都寫一遍,在for迴圈之外,一個就可以了
            // 3.方向設置最好按照順時針或者逆時針,依次。我這個上下左右,容易亂
            this.hero.moveUp();// 之前版本:this.hero.y--;
            // this.repaint();
            // 設置我的坦克的方向
            this.hero.setDirect(0);
        } else if (e.getKeyCode() == KeyEvent.VK_DOWN
                || e.getKeyCode() == KeyEvent.VK_S) {
            this.hero.moveDown();// 之前版本: this.hero.y++;
            // this.repaint();
            this.hero.setDirect(2);
        } else if (e.getKeyCode() == KeyEvent.VK_LEFT
                || e.getKeyCode() == KeyEvent.VK_A) {
            this.hero.moveLeft();// 之前版本:this.hero.x--;
            // this.repaint();
            this.hero.setDirect(3);
        } else if (e.getKeyCode() == KeyEvent.VK_RIGHT
                || e.getKeyCode() == KeyEvent.VK_D) {
            // this.repaint();
            this.hero.setDirect(1);
            this.hero.moveRight();// 之前版本:this.hero.x++;
        }
        this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub

    }
}

// 坦克類 (自己和敵人坦克的父類)
class Tank1_2 {
    // 坦克的坐標:x橫坐標,y縱坐標
    int x = 0;
    int y = 0;

    // 坦克方向:0表示上,1表示右,2表示下,3表示左
    int direct = 0;

    // 坦克的速度(預設為1,如果將來想給自己和敵人的坦克設置速度,set一下就可以了)
    int speed = 1;

    public int getSpeed() {
        return speed;
    }

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

    public int getDirect() {
        return direct;
    }

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

    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 Tank1_2(int x, int y) {
        this.x = x;
        this.y = y;

    }

}

// 我的坦克
class Hero1_2 extends Tank1_2 {
    // 因為坦克裡面沒有定義無參構造函數
    // 會報錯:Implicit super constructor Tank() is undefined for default
    // constructor. Must define an explicit constructor
    // 解決:
    // 1.在Tank類裡面定義無參構造函數。
    // 2.用父類的構造函數,來初始化子類的成員變數。如下:
    public Hero1_2(int x, int y) {
        super(x, y);
    }

    // 坦克向上移動
    public void moveUp() {
        y -= speed;
    }

    // 坦克向右移動
    public void moveRight() {
        x += speed;
    }

    // 坦克向下移動
    public void moveDown() {
        y += speed;
    }

    // 坦克向左移動
    public void moveLeft() {
        x -= speed;
    }
}

接下來幾天我會連續更新幾篇博客,介紹該坦克大戰的漸進完善過程,和中間需要初學者掌握的基礎知識,有很多代碼實例,也會漸進的增加坦克大戰裡面的元素和功能。

PS:這個好久之前的了,現在看著有些想看小時候的日記,自我感覺很好玩。


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

-Advertisement-
Play Games
更多相關文章
  • 自己最近研發了一套新的htmlcss教程,併進行了授課實施,視頻教程百度雲下載鏈接如下: "視頻及案例源碼下載地址" 本套教程視頻需要安裝屏幕錄像專家軟體才能觀看,屏幕錄像專家下載地址如下: "屏幕錄像專家" 本套教程的目標為讓具備初中以上學歷的任何人都可以在短時間內(20個小時)入門網頁製作。 本 ...
  • 背景:最近做了一個網站,傳單伺服器之後,每次打開都是亂碼,不對啊,我在本地測得明明是排版很整齊啊,然後發現,360用的是“相容模式”打開的,這就尷尬了,用戶一打開就是亂碼,這用戶體驗得有多差!用戶可不管你是什麼模式。我研究了一番,終於找到解決辦法。 國內的主流瀏覽器基本都是雙核瀏覽器:基於Webki ...
  • 承接上篇文章: "小白學Docker之Compose" ,自學網站來源於 "https://docs.docker.com/get started" 系列文章: "小白學Docker之基礎篇" "小白學Docker之Compose" "小白學Docker之Swarm" 概念 Docker Swarm ...
  • 進入到第六章了,我們要開始聊聊分散式系統之中的核心問題: 數據分區 。分散式系統通常是通過大規模的數據節點來處理單機沒有辦法處理的海量數據集,因此,可以將一個大型數據集可以分佈在多個磁碟上,查詢負載可以分佈在多個處理器上。在這一章中,我們首先討論劃分大型數據集的不同方法,並觀察數據索引如何與分區交互 ...
  • Chip Factory Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 4414 Accepted Submission(s): 1954 ...
  • 繼承使用繼承優化設計使用:將重覆的代碼抽取到父類中繼承的優點和實現優點:方便修改代碼減少代碼量 子類和父類關係是is-a的關係(可以有多個子類,但只能有一個父類) 如何使用繼承?class Pet {/公共的屬性和方法}class Dog extends Pet {/子類特有的屬性和方法}class ...
  • 一、巴什博弈(Bash Game) 有n個物品,兩個人輪流從這堆物品中取物,規定每次至少取一個,最多取m個,最後取光者得勝。 顯然,如果n=m+1,那麼由於一次最多只能取m個,所以,無論先取者拿走多少個,後取者都能夠一次拿走剩餘的物品,後取者取勝。因此我們發現瞭如何取勝的法則: 如果n=(m+1)* ...
  • 明明一天都想著一會兒就更新,可是總是忘了,今天公司的項目上線倒是有點忙 這個月不是很順啊, 狗被金毛把腿咬了兩個洞,花錢不說,還不能洗澡,看著也怪心疼的, 摩托車忘了開U鎖就起步,導致鏈條蓋碎了, 公司加班太多缺少睡眠又莫名其妙的撞了頭,起了一個大包,裡外頭疼了好幾天, 沒有14薪了,只有13薪 看 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...