Html5 小游戲 俄羅斯方塊

来源:https://www.cnblogs.com/zyyz1126/archive/2019/12/03/11976260.html
-Advertisement-
Play Games

導言 在一個風和日麗的一天,看完了瘋狂HTML 5+CSS 3+JavaScript講義,跟著做了書里最後一章的俄羅斯方塊小游戲,並做了一些改進,作為自己前端學習的第一站。 游戲效果: 製作思路 因為書里的俄羅斯方塊比較普通,太常規了,不是很好看,所以我在網上找了上面那張圖片,打算照著它來做。(請無 ...


導言

在一個風和日麗的一天,看完了瘋狂HTML 5+CSS 3+JavaScript講義,跟著做了書里最後一章的俄羅斯方塊小游戲,並做了一些改進,作為自己前端學習的第一站。

游戲效果:

 

 

 

製作思路

 

因為書里的俄羅斯方塊比較普通,太常規了,不是很好看,所以我在網上找了上面那張圖片,打算照著它來做。(請無視成品和原圖的差距)

然後便是游戲界面和常規的俄羅斯方塊游戲邏輯。

接著便是游戲結束界面了。

原本想做個彈出層,但覺得找圖片有點麻煩,所以就在網上找了文字特效,套用了一下。

代碼實現:

 

 首先是html文件和css文件,主要涉及了佈局方面。作為新手,在上面真的是翻來覆去的踩坑。o(╥﹏╥)o

index.html

<!DOCTYPE html>
<html>
<head>
    <title>俄羅斯方塊</title>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <link rel=stylesheet type="text/css" href="teris.css">
    <style type="text/css">
        /*導入外部的字體文件*/
        @font-face{
            font-family:tmb;/*為字體命名為tmb*/
            src:url("DS-DIGIB.TTF") format("TrueType");/*format為字體文件格式,TrueType為ttf*/
        }
        div>span{
            font-family:tmb;
            font-size:18pt;
            color:green;
        }
    </style>
</head>

<body>
    <div id="container" class="bg">
        <!--ui-->
        <div class="ui_bg">
            <div style="float:left;margin-right:4px;">
                速度:<span id="cur_speed">1</span>
            </div>
            <div style="float:left;">
                當前分數:<span id="cur_points">0</span>
            </div>
            <div style="float:right;">
                最高分數:<span id="max_points">0</span>
            </div>
        </div>
        <canvas id="text" width="500" height="100" style="position:absolute;"></canvas>
        <canvas id="stage" width="500" height="100" style="position:absolute;"></canvas>
    </div>
    <script src='EasePack.min.js'></script>
    <script src='TweenLite.min.js'></script>
    <script src='easeljs-0.7.1.min.js'></script>
    <script src='requestAnimationFrame.js'></script>
    <script type="text/javascript" src="jquery-3.4.1.min.js"></script>
    <script type="text/javascript" src="teris.js"></script>
</body>
</html>

teris.css

*{
    margin:0;
    padding:0;
}
html, body{
    width:100%;
    height:100%;
}

.bg{
    font-size:13pt;
    background-color:rgb(239, 239, 227);
    /*好看的漸變色*/
    background-image:radial-gradient(rgb(239, 239, 227), rgb(230, 220, 212));
    /*陰影*/
    box-shadow:#cdc8c1 -1px -1px 7px 0px;
    padding-bottom:4px;
}

.ui_bg{
    border-bottom:1px #a69e9ea3 solid;
    padding-bottom:2px;
    overflow:hidden;/*沒有這句的話因為子div都設置了float,所以是浮在網頁上的,所以父div就沒有高度,這句清除了浮動,讓父div有了子div的高度*/
}

然後是重頭戲,teris.js

游戲變數

//游戲設定
var TETRIS_ROWS = 20;
var TETRIS_COLS = 14;
var CELL_SIZE = 24;
var NO_BLOCK=0;
var HAVE_BLOCK=1;
// 定義幾種可能出現的方塊組合
var blockArr = [
    // Z
    [
        {x: TETRIS_COLS / 2 - 1 , y:0},
        {x: TETRIS_COLS / 2 , y:0},
        {x: TETRIS_COLS / 2 , y:1},
        {x: TETRIS_COLS / 2 + 1 , y:1}
    ],
    // 反Z
    [
        {x: TETRIS_COLS / 2 + 1 , y:0},
        {x: TETRIS_COLS / 2 , y:0},
        {x: TETRIS_COLS / 2 , y:1},
        {x: TETRIS_COLS / 2 - 1 , y:1}
    ],
    //
    [
        {x: TETRIS_COLS / 2 - 1 , y:0},
        {x: TETRIS_COLS / 2 , y:0},
        {x: TETRIS_COLS / 2 - 1 , y:1},
        {x: TETRIS_COLS / 2 , y:1}
    ],
    // L
    [
        {x: TETRIS_COLS / 2 - 1 , y:0},
        {x: TETRIS_COLS / 2 - 1, y:1},
        {x: TETRIS_COLS / 2 - 1 , y:2},
        {x: TETRIS_COLS / 2 , y:2}
    ],
    // J
    [
        {x: TETRIS_COLS / 2  , y:0},
        {x: TETRIS_COLS / 2 , y:1},
        {x: TETRIS_COLS / 2  , y:2},
        {x: TETRIS_COLS / 2 - 1, y:2}
    ],
    // □□□□
    [
        {x: TETRIS_COLS / 2 , y:0},
        {x: TETRIS_COLS / 2 , y:1},
        {x: TETRIS_COLS / 2 , y:2},
        {x: TETRIS_COLS / 2 , y:3}
    ],
    //
    [
        {x: TETRIS_COLS / 2 , y:0},
        {x: TETRIS_COLS / 2 - 1 , y:1},
        {x: TETRIS_COLS / 2 , y:1},
        {x: TETRIS_COLS / 2 + 1, y:1}
    ]
];

// 記錄當前積分
var curScore=0;
// 記錄曾經的最高積分
var maxScore=1;
var curSpeed=1;
//ui元素
var curSpeedEle=document.getElementById("cur_speed");
var curScoreEle=document.getElementById("cur_points");
var maxScoreEle=document.getElementById("max_points");

var timer;//方塊下落控制

var myCanvas;
var canvasCtx;
var tetris_status;//地圖數據
var currentFall;//當前下落的block

游戲界面的完善

//create canvas
function createCanvas(){
    myCanvas=document.createElement("canvas");
    myCanvas.width=TETRIS_COLS*CELL_SIZE;
    myCanvas.height=TETRIS_ROWS*CELL_SIZE;
    //繪製背景
    canvasCtx=myCanvas.getContext("2d");
    canvasCtx.beginPath();
    //TETRIS_COS
    for(let i=1; i<TETRIS_COLS; i++){
        canvasCtx.moveTo(i*CELL_SIZE, 0);
        canvasCtx.lineTo(i*CELL_SIZE, myCanvas.height);
    }
    for(let i=1; i<TETRIS_ROWS; i++){
        canvasCtx.moveTo(0, i*CELL_SIZE);
        canvasCtx.lineTo(myCanvas.width, i*CELL_SIZE);
    }
    canvasCtx.closePath();
    canvasCtx.strokeStyle="#b4a79d";
    canvasCtx.lineWidth=0.6;
    canvasCtx.stroke();
    //第一行,最後一行,第一列,最後一列粗一點。
    canvasCtx.beginPath();
    canvasCtx.moveTo(0, 0);
    canvasCtx.lineTo(myCanvas.width, 0);
    canvasCtx.moveTo(0, myCanvas.height);
    canvasCtx.lineTo(myCanvas.width, myCanvas.height);
    canvasCtx.moveTo(0, 0);
    canvasCtx.lineTo(0, myCanvas.height);
    canvasCtx.moveTo(myCanvas.width, 0);
    canvasCtx.lineTo(myCanvas.width, myCanvas.height);
    canvasCtx.closePath();
    canvasCtx.strokeStyle="#b4a79d";
    canvasCtx.lineWidth=4;
    canvasCtx.stroke();
    //設置繪製block時的style
    canvasCtx.fillStyle="#201a14";
}
draw canvas
 1 function changeWidthAndHeight(w, h){
 2     //通過jquery設置css
 3     h+=$("ui_bg").css("height")+$("ui_bg").css("margin-rop")+$("ui_bg").css("margin-bottom")+$("ui_bg").css("padding-top")+$("ui_bg").css("padding-bottom");
 4     $(".bg").css({
 5         "width":w,
 6         "height":h,
 7         "top":0, "bottom":0, "right":0, "left":0,
 8         "margin":"auto"
 9     });
10 }
change width and height
 1 //draw blocks
 2 function drawBlocks(){
 3     //清空地圖
 4     for(let i=0; i<TETRIS_ROWS;i++){
 5         for(let j=0;j<TETRIS_COLS;j++)
 6             canvasCtx.clearRect(j*CELL_SIZE+1, i*CELL_SIZE+1, CELL_SIZE-2, CELL_SIZE-2);
 7     }
 8     //繪製地圖
 9     for(let i=0; i<TETRIS_ROWS;i++){
10         for(let j=0;j<TETRIS_COLS;j++){
11             if(tetris_status[i][j]!=NO_BLOCK)
12                 canvasCtx.fillRect(j*CELL_SIZE+1, i*CELL_SIZE+1, CELL_SIZE-2, CELL_SIZE-2);//中間留點縫隙
13         }
14     }
15     //繪製currentFall
16     for(let i=0;i<currentFall.length;i++)
17         canvasCtx.fillRect(currentFall[i].x*CELL_SIZE+1, currentFall[i].y*CELL_SIZE+1, CELL_SIZE-2,CELL_SIZE-2);
18 }
draw block

游戲邏輯

 1 function rotate(){
 2     // 定義記錄能否旋轉的旗標
 3     var canRotate = true;
 4     for (var i = 0 ; i < currentFall.length ; i++)
 5     {
 6         var preX = currentFall[i].x;
 7         var preY = currentFall[i].y;
 8         // 始終以第三個方塊作為旋轉的中心,
 9         // i == 2時,說明是旋轉的中心
10         if(i != 2)
11         {
12             // 計算方塊旋轉後的x、y坐標
13             var afterRotateX = currentFall[2].x + preY - currentFall[2].y;
14             var afterRotateY = currentFall[2].y + currentFall[2].x - preX;
15             // 如果旋轉後所在位置已有方塊,表明不能旋轉
16             if(tetris_status[afterRotateY][afterRotateX + 1] != NO_BLOCK)
17             {
18                 canRotate = false;
19                 break;
20             }
21             // 如果旋轉後的坐標已經超出了最左邊邊界
22             if(afterRotateX < 0 || tetris_status[afterRotateY - 1][afterRotateX] != NO_BLOCK)
23             {
24                 moveRight();
25                 afterRotateX = currentFall[2].x + preY - currentFall[2].y;
26                 afterRotateY = currentFall[2].y + currentFall[2].x - preX;
27                 break;
28             }
29             if(afterRotateX < 0 || tetris_status[afterRotateY-1][afterRotateX] != NO_BLOCK)
30             {
31                 moveRight();
32                 break;
33             }
34             // 如果旋轉後的坐標已經超出了最右邊邊界
35             if(afterRotateX >= TETRIS_COLS - 1 || 
36                 tetris_status[afterRotateY][afterRotateX+1] != NO_BLOCK)
37             {
38                 moveLeft();
39                 afterRotateX = currentFall[2].x + preY - currentFall[2].y;
40                 afterRotateY = currentFall[2].y + currentFall[2].x - preX;
41                 break;
42             }
43             if(afterRotateX >= TETRIS_COLS - 1 || 
44                 tetris_status[afterRotateY][afterRotateX+1] != NO_BLOCK)
45             {
46                 moveLeft();
47                 break;
48             }
49         }
50     }
51     if(canRotate){
52         for (var i = 0 ; i < currentFall.length ; i++){
53             var preX = currentFall[i].x;
54             var preY = currentFall[i].y;
55             if(i != 2){
56                 currentFall[i].x = currentFall[2].x + 
57                     preY - currentFall[2].y;
58                 currentFall[i].y = currentFall[2].y + 
59                     currentFall[2].x - preX;
60             }
61         }
62         localStorage.setItem("currentFall", JSON.stringify(currentFall));
63     }
64 }
旋轉
 1 //按下 下 或 interval到了
 2 function next(){
 3     if(moveDown()){
 4         //記錄block
 5         for(let i=0;i<currentFall.length;i++)
 6             tetris_status[currentFall[i].y][currentFall[i].x]=HAVE_BLOCK;
 7         //判斷有沒有滿行的
 8         for(let j=0;j<currentFall.length;j++){
 9             for(let i=0;i<TETRIS_COLS; i++){
10                 if(tetris_status[currentFall[j].y][i]==NO_BLOCK)
11                     break;
12                 //最後一行滿了
13                 if(i==TETRIS_COLS-1){
14                     //消除最後一行
15                     for(let i=currentFall[j].y; i>0;i--){
16                         for(let j=0;j<TETRIS_COLS;j++)
17                             tetris_status[i][j]=tetris_status[i-1][j];
18                     }
19                     //分數增加
20                     curScore+=5;
21                     localStorage.setItem("curScore", curScore);
22                     if(curScore>maxScore){
23                         //超越最高分
24                         maxScore=curScore;
25                         localStorage.setItem("maxScore", maxScore);
26                     }
27                     //加速
28                     curSpeed+=0.1;
29                     localStorage.setItem("curSpeed", curSpeed);
30                     //ui輸出
31                     curScoreEle.innerHTML=""+curScore;
32                     maxScoreEle.innerHTML=""+maxScore;
33                     curSpeedEle.innerHTML=curSpeed.toFixed(1);//保留兩位小數
34                     clearInterval(timer);
35                     timer=setInterval(function(){
36                         next();
37                     }, 500/curSpeed);
38                 }
39             }
40         }
41         //判斷是否觸頂
42         for(let i=0;i<currentFall.length;i++){
43             if(currentFall[i].y==0){
44                 gameEnd();
45                 return;
46             }
47         }
48         localStorage.setItem("tetris_status", JSON.stringify(tetris_status));
49         //新的block
50         createBlock();
51         localStorage.setItem("currentFall", JSON.stringify(currentFall));
52     }
53     drawBlocks();
54 }
55 
56 //右移
57 function moveRight(){
58     for(let i=0;i<currentFall.length;i++){
59         if(currentFall[i].x+1>=TETRIS_ROWS || tetris_status[currentFall[i].y][currentFall[i].x+1]!=NO_BLOCK)
60             return;
61     }
62     for(let i=0;i<currentFall.length;i++)
63         currentFall[i].x++;
64     localStorage.setItem("currentFall", JSON.stringify(currentFall));
65     return;
66 }
67 //左移
68 function moveLeft(){
69     for(let i=0;i<currentFall.length;i++){
70         if(currentFall[i].x-1<0 || tetris_status[currentFall[i].y][currentFall[i].x-1]!=NO_BLOCK)
71             return;
72     }
73     for(let i=0;i<currentFall.length;i++)
74         currentFall[i].x--;
75     localStorage.setItem("currentFall", JSON.stringify(currentFall));
76     return;
77 }
78 //judge can move down and if arrive at end return 1, if touch other blocks return 2, else, return 0
79 function moveDown(){
80     for(let i=0;i<currentFall.length;i++){
81         if(currentFall[i].y>=TETRIS_ROWS-1 || tetris_status[currentFall[i].y+1][currentFall[i].x]!=NO_BLOCK)
82             return true;
83     }
84 
85     for(let i=0;i<currentFall.length;i++)
86         currentFall[i].y+=1;
87     return false;
88 }
上下左右移動
 1 function gameKeyEvent(evt){
 2     switch(evt.keyCode){
 3         //向下
 4         case 40://
 5         case 83://S
 6             next();
 7             drawBlocks();
 8             break;
 9         //向左
10         case 37://
11         case 65://A
12             moveLeft();
13             drawBlocks();
14             break;
15         //向右
16         case 39://
17         case 68://D
18             moveRight();
19             drawBlocks();
20             break;
21         //旋轉
22         case 38://
23         case 87://W
24             rotate();
25             drawBlocks();
26             break;
27     }
28 }
keydown事件監聽

其他的詳細情況可以看源代碼,我就不整理了。

接下來我們看游戲結束時的特效。因為我也不是很懂,所以在這裡整理的會比較詳細。當做學習。

 1 //game end
 2 function gameEnd(){
 3     clearInterval(timer);
 4     //鍵盤輸入監聽結束
 5     window.onkeydown=function(){
 6         //按任意鍵重新開始游戲
 7         window.onkeydown=gameKeyEvent;
 8         //初始化游戲數據
 9         initData();
10         createBlock();
11         localStorage.setItem("currentFall", JSON.stringify(currentFall));
12         localStorage.setItem("tetris_status", JSON.stringify(tetris_status));
13         localStorage.setItem("curScore", curScore);
14         localStorage.setItem("curSpeed", curSpeed);
15         //繪製
16         curScoreEle.innerHTML=""+curScore;
17         curSpeedEle.innerHTML=curSpeed.toFixed(1);//保留兩位小數
18         drawBlocks();
19         timer=setInterval(function(){
20             next();
21         }, 500/curSpeed);
22         //清除特效
23         this.stage.removeAllChildren();
24         this.textStage.removeAllChildren();
25     };
26     //特效,游戲結束
27     setTimeout(function(){
28         initAnim();
29         //擦除黑色方塊
30         for(let i=0; i<TETRIS_ROWS;i++){
31             for(let j=0;j<TETRIS_COLS;j++)
32                 canvasCtx.clearRect(j*CELL_SIZE+1, i*CELL_SIZE+1, CELL_SIZE-2, CELL_SIZE-2);
33         }
34     }, 200);
35     //推遲顯示Failed
36     setTimeout(function(){
37         if(textFormed) {
38             explode();
39             setTimeout(function() {
40                 createText("FAILED");
41             }, 810);
42         } else {
43             createText("FAILED");
44         }
45     }, 800);
46 }

上面代碼里的localstorage是html5的本地數據存儲。因為不是運用很難,所以具體看代碼。

整個特效是運用了createjs插件。要引入幾個文件。

easeljs-0.7.1.min.js, EasePacj.min.js, requestAnimationFrame.js和TweenLite.min.js
游戲重新開始就要清除特效。我看api里我第一眼望過去最明顯的就是removeAllChildren(),所以就選了這個。其他的改進日後再說。

        //清除特效
        this.stage.removeAllChildren();
        this.textStage.removeAllChildren();
function initAnim() {
    initStages();
    initText();
    initCircles();
    //在stage下方添加文字——按任意鍵重新開始游戲.
    tmp = new createjs.Text("t", "12px 'Source Sans Pro'", "#54555C");
    tmp.textAlign = 'center';
    tmp.x = 180;
    tmp.y=350;
    tmp.text = "按任意鍵重新開始游戲";
    stage.addChild(tmp);
    animate();
}
initAnim

上面初始化了一個stage,用於存放特效,一個textstage,用於形成“FAILED”的像素圖片。還有一個按任意鍵重新游戲的提示。同時開始每隔一段時間就刷新stage。

根據block的位置來初始化小圓點。

 1 function initCircles() {
 2     circles = [];
 3     var p=[];
 4     var count=0;
 5     for(let i=0; i<TETRIS_ROWS;i++)
 6         for(let j=0;j<TETRIS_COLS;j++)
 7             if(tetris_status[i][j]!=NO_BLOCK)
 8                 p.push({'x':j*CELL_SIZE+2, 'y':i*CELL_SIZE+2, 'w':CELL_SIZE-3, 'h':CELL_SIZE-4});
 9     for(var i=0; i<250; i++) {
10         var
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、filter() 方法創建一個新的數組,新數組中的元素是通過檢查指定數組中符合條件的所有元素。 原數組不變 不會對空數組進行檢測 2、find() 對於空數組,函數是不會執行的。 不會改變原數組 返回符合測試條件的第一個數組元素值 3、some 用於檢測數組中的元素是否滿足指定條件會依次執行數組 ...
  • 基本包裝類型 普通變數不能直接調用屬性或者方法 對象可以直接調用屬性和方法 基本包裝類型: 本身是基本類型, 但是在執行代碼的過程中, 如果這種類型的變數調用了屬性或者是方法, 那麼這種類型就不再是基本類型了, 而是基本包裝類型, 這個變數也不是普通的變數了, 而是基本包裝類型對象 string n ...
  • css 層疊樣式表,作用是為標簽加效果 基本選擇器 元素選擇器 標簽名稱{css屬性:值} id選擇器 id{} 類選擇器 .class1{屬性:值} 屬性選擇器 後代選擇器 html代碼: 組合選擇器 div,a{ color: yellow;} css樣式引入方式 head標簽中引入 外部文件引 ...
  • Array對象的方法 Array.isArray(對象) >判斷這個對象是不是數組 instanceof關鍵字 判斷對象是不是數組類型:兩種方法: //1 instanceof var obj = []; console.log(obj instanceof Array);//ture //2 使用 ...
  • 練習1: var str = "我的寶寶最可愛,聲音嗲嗲的"; var key = "可愛"; //先獲取要截取的字元串的索引位置 var index = str.indexOf(key); //從指定的桅子花開始截取,截取一定個數 str = str.substr(index, 7); conso ...
  • switch功能:簡單條件判斷,比if判斷標簽少些不等於相同功能,視個人習慣而用。 ...
  • 實例方法 >必須要通過new的方式創建的對象(實例對象)來調用的方法 靜態方法 >直接通過大寫的構造函數的名字調用的方法(直接通過大寫的對象名字調用的) 字元串的常用屬性: .length >字元串的長度 var str = "12345"; console.log(str.length); .ch ...
  • 1、是否合法IP地址 export function validateIP(rule, value,callback) { if(value==''||value==undefined||value==null){ callback(); }else { const reg = /^(\d{1,2} ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...