node seneca_使用Node.js和Seneca編寫國際象棋微服務,第3部分

node seneca

Finishing up a three-part series on writing a rules engine with Seneca microservices.

完成有關使用Seneca微服務編寫規則引擎的三部分系列文章。

Parts 1 & 2 of this series covered:

本系列的第1部分和第2部分涉及:

  • The Seneca microservices Node.js module

    Seneca微服務Node.js模塊
  • How to write a service, how to identify it by pattern and how to call it

    如何編寫服務,如何通過模式識別服務以及如何調用服務
  • How to string service calls together

    如何將服務電話串在一起
  • How to enhance an existing service

    如何增強現有服務

Along the way, I pondered what a service should return. I came to the conclusion that returning a data object (JSON in this case) was the most flexible. It allows services to embellish the output without affecting existing clients of the service.

在此過程中,我考慮了服務應返回的內容。 我得出的結論是,返回數據對象(在這種情況下為JSON)是最靈活的。 它可以修飾服務 輸出而不會影響該服務的現有客戶。

Embellish? By that I mean intermediate results can be maintained as a means of tracking information that might be useful later, to a service not yet written. In the present case, I had a rawMoves service that returned a list of moves. That was immediately sufficient for the clients I had. The service calculated moves along movement vectors, and combined them into a 1-dimensional array.

潤? 我的意思是說,中間結果可以作為一種跟蹤信息的方式來維護,該信息以后可能對尚未編寫的服務有用。 在目前的情況下,我有一個rawMoves 服務返回了動作列表。 對于我所擁有的客戶而言,這立即就足夠了。 計算出的服務沿著運動矢量移動,并將它們組合成一維數組。

Later though, I discovered that those movement vectors would have come in handy when a legalMoves service written later needed to take into account friendly pieces that were blocking movement. Vectors would have made those calculations simpler and more efficient, but they were “tossed out” by the rawMoves service.

不過,后來我發現,當legalMoves時,這些運動向量會派上用場 稍后編寫的服務需要考慮阻礙移動的友好部分。 向量本可以使這些計算更簡單,更有效,但是rawMoves它們“拋棄”了 服務。

To go back and add the vectors (in addition to the move list) meant changing the clients of the original service to accept an object, not an array. True, I could have made the original service stateful, but that would have been overkill. I had a choice: refactor the service and its clients, or Deal with It??. In Part 2, I chose the latter.

返回并添加矢量(除了移動列表之外)意味著更改原始服務的客戶端以接受對象,而不是數組。 沒錯,我本可以使原始服務具有狀態,但是那會太過分了。 我有一個選擇:重構服務及其客戶,或者處理It?? 。 在第2部分中,我選擇了后者。

Yet in this installment, time has come to refactor. rawMoves now returns {moves, moveVectors}, and the upstream clients of the service can choose what to pay attention to. Care has to be taken, though, that moves and moveVectors are in sync at all times.

然而在本期中,時間已經到了重構的時候了。 rawMoves現在返回{moves, moveVectors} ,該服務的上游客戶端可以選擇要注意的內容。 小心,必須考慮,雖然, movesmoveVectors是同步的時刻。

Let’s see what the advantage is. In the original code, finding legalMoves was an involved process if given just a piece, move list, and friendly pieces elsewhere on the board (example). Compare that code to one that uses moveVectors:

讓我們看看有什么好處。 在原始代碼中,如果只給出一塊,移動列表和板上其他位置的友好塊,則找到legalMoves是一個涉及過程( 示例) 。 將代碼與使用moveVectors代碼進行比較:

module.exports = function (boardAndPiece, candidateMoves) {if (!boardAndPiece.board) return candidateMoves;const rangeChecks = {B: vectorChecks,R: vectorChecks,K: vectorChecks,Q: vectorChecks,P: pawnChecks,N: knightChecks};var rangeCheck = rangeChecks[boardAndPiece.piece.piece];return rangeCheck(boardAndPiece, candidateMoves)
}//...function vectorChecks(boardAndPiece, candidateMoves) {for (const [j, v] of candidateMoves.moveVectors.entries()) {for (const [i, m] of v.entries()) {const p = boardAndPiece.board.pieceAt(m);if (p) {if (p.color === boardAndPiece.piece.color) {candidateMoves.moveVectors[j] = v.slice(0, i);break;} else {candidateMoves.moveVectors[j] = v.slice(0, i + 1);Object.assign(candidateMoves.moveVectors[j].slice(-1)[0], {hasCaptured: p})break;}}}}return {moveVectors: candidateMoves.moveVectors,moves: Array.prototype.concat(...candidateMoves.moveVectors)}
}

Much, much simpler…and more efficient. The wrapping function is exported and used by the legalMoves service.

更簡單,更高效。 包裝功能由legalMoves 服務導出并使用。

const legalMovesWithBoard = require("./helpers/legalMovesWithBoard")
//...this.add('role:movement,cmd:legalMoves', function (msg, reply) {this.prior(msg, function (err, result) {if (msg.board) {const result2 = legalMovesWithBoard(msg, result);//...

回到游戲 (Back to the Game)

服務總覽 (Service Overview)

All movement requests are handled by the legalMoves service, which relies on several other services and helper methods:

所有移動請求均由legalMoves處理 服務,它依賴于其他幾種服務和輔助方法:

  • Call the rawMoves service

    調用rawMoves 服務

    This will return all moves of a lone piece on a virtual 15x15 chessboard (referred to as the

    這將返回虛擬15x15棋盤上的單個棋子的所有移動(稱為

    movement mask). Explained in Part 1

    運動面具 )。 在第1部分中解釋

  • Call the base legalMoves service

    叫基地legalMoves 服務

    This will clip the

    這將剪輯

    movement mask at the edge of the “real” 8x8 board, with proper algebraic coordinates. Explained in Part 2

    位于“真實” 8x8電路板邊緣的運動遮罩 ,具有適當的代數坐標 。 在第2部分中解釋

  • Call the overriding legalMoves service

    呼叫最重要的legalMoves 服務

    If there is a board as part of the incoming message (the service pattern), then a series of checks is done to account for the presence of friendly and opposing pieces, because these will affect movement. Explained in this part (Part 3).

    如果傳入消息(服務模式)中有一塊板,則要進行一系列檢查以檢查是否存在友好的相對的部件,因為它們會影響運動。 在本部分(第3部分)中進行解釋。

So Part 2 took care of friendly pieces blocking other friendly pieces, but now there are those annoying enemy pieces to deal with. Like friendly pieces, enemy pieces can block movement, but they can also be captured. Under some conditions, enemy pieces may even increase our movement options.

因此, 第2部分照顧了友軍,阻止了其他友軍,但現在有那些煩人的敵軍要處理。 像友軍碎片一樣,敵方碎片可以阻止移動,但也可以將其捕獲。 在某些情況下,敵方部隊甚至可能增加我們的行動選擇。

Then there’s castling: the only move where two pieces can shift their position at once. Special considerations apply, some of which involve enemy pieces.

然后就是cast聲:唯一的動作,兩個棋子可以一次移動其位置。 需要特別考慮,其中一些涉及敵人。

女王,白嘴鴉和主教 (Queen, Rook, & Bishop)

The new rules involving enemy pieces extend or modify the original legalMoves service in Part 2 that dealt with friendly pieces only. The new microservice extension will need to know if the blocking piece is friend or foe. If friend, then movement is blocked at the square before. If foe, then movement is blocked by the square of the opposing piece (by capture). In the list of legal moves returned by a piece, we will denote captures by setting a hasCaptured flag, along with the type of enemy piece to be captured.

涉及敵方碎片的新規則擴展或修改了第2部分中僅處理友好碎片的原始legalMoves服務。 新的微服務擴展將需要知道阻塞塊是敵還是友。 如果是朋友,則運動被阻止在廣場之前。 如果是敵人,則移動被對方棋子的方塊阻止(通過捕獲)。 在棋子返回的合法動作列表中,我們將通過設置hasCaptured標志以及要捕捉的敵軍棋子的類型來表示捕捉。

The vectorChecks helper method shown in the previous gist listing handles all vector-based movement for Queen, Rook, and Bishop.

前面要點清單中顯示的vectorChecks幫助器方法可以處理Queen,Rook和Bishop的所有基于矢量的移動。

騎士 (Knight)

Knights jump around the board, so are only blocked by friendly pieces that are on one of its potential landing squares. An enemy piece does not block, but would be captured if a Knight landed on it. The method used by the legalMoves service is easy to write.

騎士在棋盤上跳來跳去,因此只被其潛在著陸廣場之一上的友軍所阻擋。 敵人的碎片不會阻擋,但如果有騎士降落,它將被捕獲。 legalMoves使用的方法 服務很容易寫。

function knightChecks(boardAndPiece, candidateMoves) {const newMoves = [];for (const m of candidateMoves.moves) {const p = boardAndPiece.board.pieceAt(m)if (!p) {newMoves.push(m)} else if (p.color !== boardAndPiece.piece.color) {m.hasCaptured = p;newMoves.push(m)}}return {moves: newMoves,moveVectors: [newMoves]};
}

典當 (Pawn)

Pawns at first seem like a pretty simple case. The pawn is blocked if any piece whether friend or enemy stands in front of it. But it can to move one square diagonally forward to capture an enemy that sits in that square.

最初的典當似乎很簡單。 如果任何棋子(無論是朋友還是敵人)站在它的前面,它都會被阻止。 但是它可以對角線向前移動一個正方形,以俘獲一個坐在那個正方形中的敵人。

There is also the en passant rule, where a pawn can capture an adjacent enemy pawn that just moved two squares on the previous turn:

也有順便規則,其中的棋子可以捕獲相鄰的敵人棋子, 只是移動上一轉兩個格:

And then there’s the issue of mandatory promotion once a pawn reaches the 8th rank. Confusingly, this refers to the eighth rank in front of the pawn, which would be the first rank of the board coordinates if playing Black.

當棋子達到第8位時,就會出現強制升級的問題。 令人困惑的是,這指的是棋子前面的第8位,如果玩Black,那將是棋盤坐標的第1位。

All these considerations make for a rather involved set of rules to determine the pawn’s movement options. These can be found in the accompanying source code at GitHub.

所有這些考慮因素都構成了一套相當復雜的規則來確定棋子的移動選項。 這些可以發現在所附的源代碼在GitHub上。

國王 (King)

The Pawn was a bit of work, but the king even more so. There are several conditions:

Pawn有點工作,但國王更是如此。 有幾個條件:

  • Is a potential move square controlled by an enemy piece?

    潛在的移動方塊是否受到敵方控制?

    Eliminate that option.

    消除該選項。

  • Is the king in check?

    國王在檢查嗎?

    If so, it

    如果是這樣

    must move this turn

    必須轉彎

    * If it is in check, and can’t move out of check, game over! Checkmate!

    *如果在檢查中,并且不能移出檢查,則游戲結束! 將死!

    * If it is not in check, but there are no other legal moves by any friendly piece on the board, stalemate!

    *如果不在檢查范圍之內,但董事會上任何友好的行動都沒有其他合法行動,就此成為僵局!

  • Can the King castle (queen side or king side)?

    國王城堡(女王側還是國王側)可以嗎?

    * King is in check: No.

    *國王在檢查:不。

    * King has previously moved: No.

    * King之前已搬家:否。

    * Rook has previously moved: No.

    * Rook之前已搬家:否。

    * Intervening squares between K and R occupied: No.

    *占據K和R之間的中間方格:否。

    * Intervening squares empty, but controlled by enemy piece: No.

    *中間方塊為空,但由敵方控制:否

    * Otherwise: Yes.

    *否則:是。

This service I will break down into detail. As you may recall, the legalMoves service is broken into two parts. One part treats a piece as if it is alone on the board. The other part deals with friendly and opposing pieces. Let’s look at the listing:

我將詳細介紹這項服務。 您可能還記得, legalMoves服務分為兩部分。 一部分將棋子視為單獨在板上。 另一部分涉及友好和對立的部分。 讓我們看一下清單:

this.add('role:movement,cmd:legalMoves', function (msg, reply) {this.prior(msg, function (err, result) {if (msg.board) {const result2 = legalMovesWithBoard(msg, result);if (msg.piece.piece === 'K') {legalMovesWithKing.call(this, msg, result2, reply)} else {reply(err, result2);}} else {reply(err, result);}});});

For every piece but the King, we simply call the base service (via the Seneca framework’s prior() method) followed by the helper method legalMovesWithBoard(), parts of which were listed in the previous gists of this post.

對于每一塊,但王,我們只需調用基本服務(通過塞內卡框架的prior()方法),其次是輔助方法legalMovesWithBoard()這部分在這篇文章的前學家上市。

If the piece is a King, the additional helper method legalMovesWithKing() is called. The calling parameters are the this reference, a msg object containing board and the piece being moved (the King), the result2 which was came from the base legalMoves service call (this contains movement info), and the reply callback.

如果作品是國王,則調用附加的輔助方法legalMovesWithKing() 。 調用參數是this引用,一個包含木板和正在移動的棋子(國王)的msg對象, result2來自基礎legalMoves 服務呼叫(其中包含移動信息)和reply回調。

There’s a bit of code to slog through, so I will refer to sections by line number:

有一些代碼可以通過,所以我將按行號引用各節:

module.exports = function (boardAndPiece, candidateMoves, reply) {const opposingColor = boardAndPiece.piece.color === 'W' ? 'black' : 'white';//temporarily remove the K to avoid cyclesboardAndPiece.board.removePiece(boardAndPiece.piece);function canCastle(king, rook, intervening, opposing) {// console.log("canCastle", arguments)const opposingControlled = [...opposing.controlled]const board = boardAndPiece.board;const canCastle = !candidateMoves.inCheck &&!king.hasMoved &&rook &&rook.color === king.color &&!rook.hasMoved;if (!canCastle) return false;const pieceInTheWay = !!intervening.find(sq => board.pieceAt(sq));if (pieceInTheWay) return false;const passThruCheck = !!intervening.find(sq =>opposingControlled.find(opp => (opp.rank === sq.rank && opp.file == sq.file)))if (passThruCheck) return false;return true;}this.use(require('../SquareControl'))this.act({role: "board",cmd: "squaresControlledBy",board: boardAndPiece.board,color: opposingColor,}, (err, opposing) => {if (err) {reply(err);return;}const king = boardAndPiece.piece;// console.log(opposing.controlled)// add the removed K back inboardAndPiece.board.addPiece(king);const filteredMoves = candidateMoves.moves.filter(m =>!!!opposing.controlled.find(o => o.rank === m.rank && o.file === m.file))const kingSq = king.position;const inCheck = !!opposing.controlled.find(o => o.rank === kingSq.rank && o.file === kingSq.file)const additional = {}additional.inCheck = inCheck;additional.checkMated = (inCheck && filteredMoves.length === 0)const rank = additional.color === 'W' ? 1 : 8;let rook = boardAndPiece.board.pieceAt(`a${rank}`);let intervening = [`b${rank}`, `c${rank}`, `d${rank}`]additional.canQSideCastle = canCastle(king, rook, intervening, opposing)rook = boardAndPiece.board.pieceAt(`h${rank}`);intervening = [`f${rank}`, `g${rank}`]additional.canKSideCastle = canCastle(king, rook, intervening, opposing)candidateMoves.moves = filteredMoves;delete candidateMoves.moveVectors; // no longer valid, and no longer neededObject.assign(candidateMoves, additional);console.log(candidateMoves)reply(null, candidateMoves)});
};

Let start from the middle, at line 30. A service called squaresControlledBy is imported into the framework from SquareControl.js. It gathers all legal moves of the opposing side and calls those the controlled squares. We need this information because the King cannot move into a square ‘controlled’ by the enemy. The King cannot move into check.

讓我們從中間的第30行開始。一個名為squaresControlledBy的服務 從SquareControl.js導入到框架中。 它收集了對方的所有合法舉動,并稱這些為受控方。 我們需要這些信息,因為國王無法進入被敵人“控制”的廣場。 國王無法阻止。

There’s a tricky bit to this, and that is because the squaresControlledBy service relies on the legalMoves service. What can happen is that:

這有一個棘手的問題,這是因為squaresControlledBy 服務依賴legalMoves 服務。 可能發生的情況是:

  • legalMoves service is called for friendly piece

    legalMoves服務被稱為友好作品

  • if the friendly piece is a King, squaresControlledBy is called for opposing side

    如果友善的棋子是國王, squaresControlledBy稱為對面

  • squaresControlledBy requests legalMoves for all opposing sides pieces

    squaresControlledBy要求為所有相對的邊塊legalMoves

  • if legalMoves is requested for the opposing King, it will call service squaresControlledBy for its opposing side (our side).

    如果legalMoves要求為反對國王,它會調用服務squaresControlledBy 相反側(我方)。

  • we’ve come full circle, and round and round we go…

    我們走了整整一個圈,然后又走了……

These cycles are one of the gotchas of microservices, and have to be carefully accounted for. I won’t go into the various strategies for dealing with this, but Seneca provides trace options for actions ( — seneca.print.tree)and service invocations ( — seneca.log.all) that can be helpful in debugging.

這些周期是微服務的陷阱之一,必須仔細考慮。 我不會討論用于解決此問題的各種策略,但是Seneca提供了對操作( — seneca.print.tree)和服務調用( — seneca.log.all)跟蹤選項,這些選項可能有助于調試。

The trick I used to avoid endless cycling was to temporarily remove the friendly king from the board (line 5) and later add it back in (line 46). I would say that best practice would be to not modify incoming service action data. There are potential hard-to-track side-effects. For purposes of finishing this series in a reasonable time frame, though, I will overlook a bit of fudging.

我用來避免無休止循環的訣竅是從板上暫時刪除友好的國王(第5行),然后將其重新添加到第46行。 我會說,最佳實踐是不修改傳入的服務操作數據。 存在潛在的難以追蹤的副作用。 但是,為了在合理的時間范圍內完成本系列文章,我會忽略一些麻煩。

We push additional information (inCheck, castle options [lines 7–28], checkmate) to the reply by storing it in a local data structure and then using Object.assign() to merge it into the candidateMoves structure. The candidateMoves object will now have moves long with new properties provided by the additional object (lines 54–73).

通過將其他信息存儲在本地數據結構中,然后使用Object.assign()將其合并到candidateMoves結構中,我們將其他信息( inCheck ,城堡選項[7–28行, checkmate )推送到reply 。 現在,帶有附加對象提供的新屬性的candidateMoves移動對象將移動很長時間(第54-73行)。

That wraps it up! Remember, if you found this series useful and engaging, please don’t forget to recommend it (click that little heart icon). Feedback always welcome.

結束了! 請記住,如果您發現本系列有用且引人入勝,請不要忘記推薦它(單擊該小心臟圖標)。 反饋隨時歡迎。

Full source (including tests) for this Part 3 of the series can be found here.

該系列第3部分的完整資源(包括測試)可以在這里找到。

翻譯自: https://www.freecodecamp.org/news/writing-a-chess-microservice-using-node-js-and-seneca-part-3-ab38b8ef9b0a/

node seneca

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/395439.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/395439.shtml
英文地址,請注明出處:http://en.pswp.cn/news/395439.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android開發畫布銷毀,Android DialogFragment 在頁面銷毀下的使用方式

今天看到了一篇文章,講了DialogFragment的封裝方式(Android:我為何要封裝DialogFragment?),想到當初也為頁面銷毀后DialogFragment的回調方式頭疼了好久,看到了po主的思路,與當初自己想的不太一樣,就整理一下.如何在開發中遇到頁面銷毀的情況在android開…

視覺智能產品發布 阿里云這項世界第一的技術現在人人可用

用手機拍下朋友的相片,軟件會自動識別進行分類并將照片發送給朋友。這不是空想,利用視覺智能對手機相冊進行管理、分類和分享正逐步成為現實。在6月10日舉行的云棲大會上海峰會上,阿里云正式發布了“圖像識別”和“人臉識別”兩款視覺智能服務…

ViewPager中Fragment的重復創建、復用問題

在ViewPager中的Fragment的生命周期 隨著頁面的切換 當前的展示頁相鄰的頁面生命周期一直在變化 一開始 剛進入Activity時候,ViewPager默認初始化好前兩個Fragment(消息和任務) 消息 ->任務 05-09 14:47:39.593 31509-31509/tyh.com.tabl…

使用VB.net建立excel文件

Add the following code snippet on top of Form1.vb Imports Excel Microsoft.Office.Interop.Excel Public Class Form1Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.ClickDim appXL As Excel.Application 聲明一個application對象Dim wbX…

沙盤演練工作坊-產品開發_Google認證的Android助理開發人員:考試演練

沙盤演練工作坊-產品開發by Rohan Taneja由Rohan Taneja Google認證的Android助理開發人員:考試演練 (Google Certified Associate Android Developer: Exam Walkthrough) UPDATE (24th July, 2018)更新(2018年7月24日) The certification exam is available agai…

linux hlist,linux內核V2.6.11學習筆記(2)--list和hlist

這兩個數據結構在內核中隨處可見,不得不拿出來單獨講講.這兩個數據結構都是為了方便內核開發者在使用到類似數據結構的時候不必自行開發(雖然不難),因此它們需要做到足夠的"通用性",也就是說,今天可以用它們做一個存放進程的鏈表,明天同樣可以做一個封裝定時器的鏈表…

14-angular.isDefined

判斷括號內的值是否存在。 格式: angular.isDefined(value); value: 被判斷是否存在的值。 返回值: true/false轉載于:https://www.cnblogs.com/ms-grf/p/6978886.html

實施工程師1分鐘即時演講_我是如何在1年內從時裝模特轉變為軟件工程師的

實施工程師1分鐘即時演講In 2015 I knew almost nothing about coding. Today, I’m a software engineer and a teacher at a code school for kids.在2015年,我對編碼幾乎一無所知。 今天,我是一名軟件工程師,還是一所代碼學校的兒童老師。…

MSSQL分組取后每一組的最新一條記錄

數據庫中二張表,用戶表和獎金記錄表,獎金記錄表中一個用戶有多條信息,有一個生效時間,現在要查詢: 獎金生效時間在三天前,每個用戶取最新一條獎金記錄,且用戶末鎖定 以前用的方法是直接寫在C#代…

android模擬器插件,Android模擬器插件找不到android SDK

首先,克隆項目詹金斯一直輸出后:[android] No Android SDK found; lets install it automatically...[android] Going to install required Android SDK components...[android] Installing the platform-tool,tool SDK component(s)...$ /var/lib/jenki…

讀書筆記--模板與泛型編程

了解隱式接口和編譯期多態 編譯期多態和運行期多態 運行期多態就好比是virtual函數再運行的時候才確定該virtual函數該被綁定為哪個函數,運行的時候才確定函數類型。  編譯期多態就好比是泛型編程和模板編程中,在編譯的時候才確定哪個函數該被調用&…

棧和遞歸的關系 144:Binary Tree Preorder Traversal

前序遍歷:根左右 //用棧來實現非遞歸解法/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/ class Solution { public:vec…

運行級別

ls -l /usr/lib/system/runlevel*target (查看運行級別)Linux系統有7個運行級別(runlevel)運行級別0:系統停機狀態,系統默認運行級別不能設為0,否則不能正常啟動運行級別1:單用戶工作狀態,roo…

微信sdk swift版_使用Swift 4的iOS版Google Maps SDK終極指南

微信sdk swift版by Dejan Atanasov通過Dejan Atanasov 使用Swift 4的iOS版Google Maps SDK終極指南 (Your ultimate guide to the Google Maps SDK on iOS, using Swift 4) Many iOS apps use Google Maps. This is a very common feature, so I have decided to prepare an u…

精確覆蓋DLX算法模板

代碼 struct DLX {int n,id;int L[maxn],R[maxn],U[maxn],D[maxn];int C[maxn],S[maxn],loc[maxn][2];void init(int nn0) //傳列長{nnn;for(int i0;i<n;i) U[i]D[i]i,L[i]i-1,R[i]i1;L[0]n; R[n]0;idn;memset(S,0,sizeof(S));}void AddRow(int x,int col,int A[]) //傳入參…

android 代碼布局設置wrap_content,android ScrollView布局(wrap_content,最大大小)

我最后編寫了自己的類,擴展了ScrollView既然你問……這是代碼.可能不是最干凈但它做我想要的.請注意,它期望在創建視圖時設置layout_weight,并且不應在父LinearLayout中設置weigthSum,否則你會得到有趣的東西(因為這個的權重從原始值變為0,具體取決于大小ScrollView的內容)首先…

ABAP數據類型

數據類型表&#xff1a; 類型縮寫 類型 默認長度 允許長度 初始值 描述 C 文本型 1 Space 字符串數據,如Program D 日期型 8 8 00000000 日期數據,格式為YYYYMMDD F 浮點型 8 8 0 浮點數 I 整型 4 10 0 帶正負符號的整數 N 數值型 1 31 00……

cocos2d-x C++ 原始工程引擎運行機制解析

新建一個工程&#xff0c;相信感興趣的同學都想知道cocos引擎都是如何運行的 想知道是如何運行的&#xff0c;看懂四個文件即可 話不多說&#xff0c;上代碼&#xff1a; 1、首先解釋 AppDelegate.h 1 #ifndef _APP_DELEGATE_H_2 #define _APP_DELEGATE_H_3 4 #include "…

web高德maker動畫_Web Maker —我如何構建一個快速的離線前端游樂場

web高德maker動畫by kushagra gour由kushagra gour Web Maker —我如何構建一個快速的離線前端游樂場 (Web Maker — How I built a fast, offline front-end playground) Web Maker is a Chrome extension that gives you a blazing fast and offline front-end playground —…

時間小知識對于時間轉換可能有幫助

那么UTC與世界各地的時間應如何換算呢?它是將全世界分為24個時區&#xff0c;地球的東、西經各180(共360)被24個時區平分&#xff0c;每個時區各占15。以經度0(即本初子午線)為基準&#xff0c;東經730′與西經730′之間的區域為零時區&#xff1b;東經和西經的730′與2230′之…