燒腦!JS+Canvas 帶你體驗「偶消奇不消」的智商挑戰

2020-12-19 SegmentFault思否

本文原載於 SegmentFault 專欄 一個會小程序開發的iOSer

作者:huangjianke

整理編輯:SegmentFault

啟邏輯之高妙,因想像而自由

層疊拼圖Plus 是一款需要空間想像力和邏輯推理能力完美結合的微信小遊戲。

偶消奇不消,在簡單的遊戲規則下卻有著無數種可能性,需要你充分發揮想像力去探索。

看似簡單卻具有極大的挑戰性和趣味性,這就是其魅力所在!溫馨提示,體驗後再閱讀此文體驗更佳哦!

預覽:

Talk is cheap,Show me the code.

層疊拼圖Plus 微信小遊戲採用js+canvas實現,沒有使用任何遊戲引擎,對於初學者來說,也比較容易入門。

接下來,我將通過以下幾個點循序漸進的講解層疊拼圖Plus 微信小遊戲的實現。

如何解決 Canvas 繪圖模糊?如何繪製任意多邊形圖形?1 + 1 = 0,「偶消奇不消」的效果如何實現?如何判斷一個點是否在任意多邊形內部 ?如何判斷遊戲結果是否正確?排行榜的展示遊戲性能優化

如何解決 Canvas 繪圖模糊?

canvas 繪圖時,會從兩個物理像素的中間位置開始繪製並向兩邊擴散 0.5 個物理像素。當設備像素比為 1 時,一個 1px 的線條實際上佔據了兩個物理像素(每個像素實際上只佔一半),由於不存在 0.5 個像素,所以這兩個像素本來不應該被繪製的部分也被繪製了,於是 1 物理像素的線條變成了 2 物理像素,視覺上就造成了模糊。

繪圖模糊的原因知道了,在微信小遊戲裡面又該如何解決呢?

const ratio = wx.getSystemInfoSync().pixelRatiolet ctx = canvas.getContext('2d')canvas.width = screenWidth * ratiocanvas.height = screenHeight * ratioctx.fillStyle = 'black'ctx.font = `${18 * ratio}px Arial`ctx.fillText('我是清晰的文字', x * ratio, y * ratio)ctx.fillStyle = 'red'ctx.fillRect(x * ratio, y * ratio, width * ratio, height * ratio)

可以看到,我們先通過 wx.getSystemInfoSync().pixelRatio 獲取設備的像素比ratio。

然後將在屏 Canvas 的寬度和高度按照所獲取的像素比ratio進行放大,在繪製文字、圖片的時候,坐標點 x、y 和所要繪製圖形的 width、height均需要按照像素比 ratio 進行縮放。

這樣我們就可以清晰的在高清屏中繪製想要的文字、圖片。

另外,需要注意的是,這裡的canvas是由 weapp-adapter 預先調用 wx.createCanvas()創建一個上屏 Canvas,並暴露為一個全局變量 canvas。

如何繪製任意多邊形圖片?

任意一個多邊形圖形,是由多個平面坐標點所組成的圖形區域。

在遊戲畫布內,我們以左上角為坐標原點 {x: 0, y: 0} ,一個多邊形包含多個單位長度的平面坐標點。

如:[{ x: 1, y: 3 }, { x: 5, y: 3 }, { x: 3, y: 5 }] 表示為一個三角形的區域,需要注意的是,x、y 並不是真實的平面坐標值,而是通過屏幕寬度計算出來的單位長度。

在畫布內的真實坐標值則為 {x: x * itemWidth, y: y * itemWidth} 。

繪製多邊形代碼實現如下:

/** * 繪製多邊形 */export defaultclassBlock{constructor() { } init(points, itemWidth, ctx) {this.points = []this.itemWidth = itemWidth // 單位長度this.ctx = ctxfor (let i = 0; i < points.length; i++) { let point = points[i]this.points.push({ x: point.x * this.itemWidth, y: point.y * this.itemWidth }) } } draw() {this.ctx.globalCompositeOperation = 'xor'this.ctx.fillStyle = 'black'this.ctx.beginPath()this.ctx.moveTo(this.points[0].x, this.points[0].y)for (let i = 1; i < this.points.length; i++) { let point = this.points[i]this.ctx.lineTo(point.x, point.y) }this.ctx.closePath()this.ctx.fill() }}

使用:

let points = [ [{ x: 4, y: 5 }, { x: 8, y: 9 }, { x: 4, y: 9 }], [{ x: 10, y: 8 }, { x: 10, y: 12 }, { x: 6, y: 12 }], [{ x: 7, y: 4 }, { x: 11, y: 4 }, { x: 11, y: 8 }]]points.map((sub_points) => {let block = new Block() block.init(sub_points, this.itemWidth, this.ctx) block.draw()})

效果如下圖:

1+1=0,「偶消奇不消」的效果如何實現?

1 + 1 = 0,是層疊拼圖Plus小遊戲玩法的精髓所在。

有經驗的同學,也許一眼就發現了,1 + 1 = 0 剛好符合通過 異或運算 得出的結果。

當然,細心的同學也可能已經發現,在 如何繪製任意多邊形圖形 這一章節內,有一句特殊的代碼:this.ctx.globalCompositeOperation = 'xor',也正是通過設置 CanvasContext 的 globalCompositeOperation 屬性值為 xor 便實現了「偶消奇不消」的神奇效果。

globalCompositeOperation 是指 在繪製新形狀時應用的合成操作的類型

如何判斷一個點是否在任意多邊形內部?

當迴轉數為 0 時,點在閉合曲線外部。

講到這裡,我們已經知道如何在Canvas畫布內繪製出偶消奇不消效果的層疊圖形了,接下來我們來看下玩家如何移動選中的圖形。

我們發現繪製出的圖形對象並沒有提供點擊事件綁定之類的操作,那又如何判斷玩家選中了哪個圖形呢?

這裡我們就需要去實現如何判斷玩家觸摸事件的x,y坐標在哪個多邊形圖形內部區域,從而判斷出玩家選中的是哪一個多邊形圖形。

判斷一個點是否在任意多邊形內部有多種方法,比如:

射線法面積判別法叉乘判別法迴轉數法...層疊拼圖Plus 小遊戲內,採用的是 迴轉數 法來判斷玩家觸摸點是否在多邊形內部。迴轉數 是拓撲學中的一個基本概念,具有很重要的性質和用途。

當然,展開討論 迴轉數 的概念並不在該文的討論範圍內,我們僅需了解一個概念:當迴轉數為 0 時,點在閉合曲線外部。

上面面這張圖動態演示了迴轉數的概念:圖中紅色曲線關於點(人所在位置)的迴轉數為 2。

對於給定的點和多邊形,迴轉數應該怎麼計算呢?

用線段分別連接點和多邊形的全部頂點

計算所有點與相鄰頂點連線的夾角

計算所有夾角和。注意每個夾角都是有方向的,所以有可能是負值

最後根據角度累加值計算迴轉數。360°(2π)相當於一次迴轉。

在使用 JavaScript 實現時,需要注意以下問題:

JavaScript 的數只有 64 位雙精度浮點這一種。對於三角函數產生的無理數,浮點數計算不可避免會造成一些誤差,因此在最後計算迴轉數需要做取整操作。通常情況下,平面直角坐標系內一個角的取值範圍是 -π 到 π 這個區間,這也是 JavaScript 三角函數 Math.atan2() 返回值的範圍。但 JavaScript 並不能直接計算任意兩條線的夾角,我們只能先計算兩條線與 x 正軸夾角,再取兩者差值。這個差值的結果就有可能超出 -π 到 π 這個區間,因此我們還需要處理差值超出取值區間的情況。代碼實現:

/** * 判斷點是否在多邊形內/邊上 */isPointInPolygon(p, poly) {let px = p.x, py = p.y, sum = 0for (let i = 0, l = poly.length, j = l - 1; i < l; j = i, i++) {let sx = poly[i].x, sy = poly[i].y, tx = poly[j].x, ty = poly[j].y// 點與多邊形頂點重合或在多邊形的邊上if ((sx - px) * (px - tx) >= 0 && (sy - py) * (py - ty) >= 0 && (px - sx) * (ty - sy) === (py - sy) * (tx - sx)) {returntrue }// 點與相鄰頂點連線的夾角let angle = Math.atan2(sy - py, sx - px) - Math.atan2(ty - py, tx - px)// 確保夾角不超出取值範圍(-π 到 π)if (angle >= Math.PI) { angle = angle - Math.PI * 2 } elseif (angle <= -Math.PI) { angle = angle + Math.PI * 2 } sum += angle }// 計算迴轉數並判斷點和多邊形的幾何關係returnMath.round(sum / Math.PI) === 0 ? false : true}

註:該章節內容圖片均來自網絡,如有侵權,請告知刪除。另外有興趣的同學可以使用其他方法來實現判斷一個點是否在任意多邊形內部。

如何判斷遊戲結果是否正確?

探索的過程固然精彩,而結果卻更令我們期待

通過前面的介紹我們可以知道,判斷遊戲結果是否正確其實就是比對玩家組合圖形的 xor 結果與目標圖形的 xor 結果。

那麼如何求多個多邊形 xor 的結果呢? polygon-clipping 正是為此而生的。

它不僅支持 xor 操作,還有其他的比如:union, intersection, difference 等操作。

層疊拼圖Plus 遊戲內通過 polygon-clipping 又是怎樣實現遊戲結果判斷的呢?

目標圖形

多邊形平面坐標點集合:

points = [ [{ x: 6, y: 6 }, { x: 10, y: 6 }, { x: 10, y: 10 }, { x: 6, y: 10 }], [{ x: 8, y: 6 }, { x: 10, y: 8 }, { x: 8, y: 10 }, { x: 6, y: 8 }]]

let results = polygonClipping.xor(...poly)// 找出左上角的點 let min_x = 100, min_y = 100 results.forEach(function(sub_results){ sub_results.forEach(function(temps){ temps.forEach(function(point){if (point[0] < min_x) min_x = point[0]if (point[1] < min_y) min_y = point[1] }) }) })// 以左上角為參考點 多邊形平移至 原點 {x: 0, y: 0} results.forEach(function(sub_results){ sub_results.forEach(function(temps){ temps.forEach(function(point){ point[0] -= min_x point[1] -= min_y }) }) })}

let result = this.polygonXor(points)

xor結果:

[ [[[0, 0], [2, 0], [0, 2], [0, 0]]], [[[0, 2], [2, 4], [0, 4], [0, 2]]], [[[2, 0], [4, 0], [4, 2], [2, 0]]], [[[2, 4], [4, 2], [4, 4], [2, 4]]]]

同理計算出玩家操作圖形的xor結果進行比對即可得出答案正確與否。

需要注意的是,獲取玩家的 xor 結果並不能直接拿來與目標圖形xor 結果進行比較。

我們需要將xor 的結果以左上角為參考點將圖形平移至原點內,然後再進行比較,如果結果一致,則代表玩家答案正確。

排行榜的展示

有人的地方就有江湖,有江湖的地方就有排行

在看本章節內容之前,建議先瀏覽一遍排行榜相關的官方文檔:好友排行榜、關係鏈數據,以便對相關內容有個大概的了解。

開放數據域開放數據域是一個封閉、獨立的 JavaScript 作用域。

要讓代碼運行在開放數據域,需要在 game.json 中添加配置項 openDataContext 指定開放數據域的代碼目錄。

添加該配置項表示小遊戲啟用了開放數據域,這將會導致一些限制。

// game.json{"openDataContext": "src/myOpenDataContext"}

在遊戲內使用 wx.setUserCloudStorage(obj) 對玩家遊戲數據進行託管。在開放數據域內使用 wx.getFriendCloudStorage(obj)拉取當前用戶所有同玩好友的託管數據展示關係鏈數據如果想要展示通過關係鏈 API 獲取到的用戶數據,如繪製排行榜等業務場景,需要將排行榜繪製到 sharedCanvas 上,再在主域將 sharedCanvas 渲染上屏。

// src/myOpenDataContext/index.jslet sharedCanvas = wx.getSharedCanvas()functiondrawRankList (data) { data.forEach((item, index) => {// ... })}wx.getFriendCloudStorage({success: res => {let data = res.data drawRankList(data) }})

sharedCanvas 是主域和開放數據域都可以訪問的一個離屏畫布。在開放數據域調用 wx.getSharedCanvas() 將返回 sharedCanvas。

// src/myOpenDataContext/index.jslet sharedCanvas = wx.getSharedCanvas()let context = sharedCanvas.getContext('2d')context.fillStyle = 'red'context.fillRect(0, 0, 100, 100)

在主域中可以通過開放數據域實例訪問 sharedCanvas,通過 drawImage() 方法可以將 sharedCanvas 繪製到上屏畫布。

// src/myOpenDataContext/index.jslet sharedCanvas = wx.getSharedCanvas()let context = sharedCanvas.getContext('2d')context.fillStyle = 'red'context.fillRect(0, 0, 100, 100)

sharedCanvas 本質上也是一個離屏 Canvas,而重設 Canvas 的寬高會清空 Canvas 上的內容。所以要通知開放數據域去重繪 sharedCanvas。

// game.jsopenDataContext.postMessage({command: 'render'})// src/myOpenDataContext/index.jsopenDataContext.onMessage(data => {if (data.command === 'render') {// 重繪 sharedCanvas }})

需要注意的是:sharedCanvas 的寬高只能在主域設置,不能在開放數據域中設置。

遊戲性能優化

性能優化,簡而言之,就是在不影響系統運行正確性的前提下,使之運行地更快,完成特定功能所需的時間更短。

一款能讓人心情愉悅的遊戲,性能問題必然不能成為絆腳石。那麼可以從哪些方面對遊戲進行性能優化呢?

離屏 Canvas

層疊拼圖Plus 小遊戲內,針對需要大量使用且繪圖繁複的靜態場景,都是使用離屏 Canvas進行繪製的,如首頁網格背景、關卡列表、排名列表等。

在微信內 wx.createCanvas() 首次調用創建的是顯示在屏幕上的畫布,之後調用創建的都是離屏畫布。

初始化時將靜態場景繪製完備,需要時直接拷貝離屏Canvas的圖像即可。

Canvas 繪製本身就是不斷的更新幀從而達到動畫的效果,通過使用離屏 Canvas,就大大減少了一些靜態內容在上屏Canvas的繪製,從而提升了繪製性能。

this.offScreenCanvas = wx.createCanvas()this.offScreenCanvas.width = this.width * ratiothis.offScreenCanvas.height = this.height * ratiothis.ctx.drawImage(this.offScreenCanvas, x * ratio, y * ratio, this.offScreenCanvas.width, this.offScreenCanvas.height)

內存優化

玩家在遊戲過程中拖動方塊的移動其實就是不斷更新多邊形圖形的坐標信息,然後不斷的清空畫布再重新繪製。

可以想像,這個繪製是非常頻繁的,按照普通的做法就需要不斷去創建多個新的 Block 對象。

針對遊戲中需要頻繁更新的對象,我們可以通過使用對象池的方法進行優化,對象池維護一個裝著空閒對象的池子。

如果需要對象的時候,不是直接new,而是從對象池中取出,如果對象池中沒有空閒對象,則新建一個空閒對象。

層疊拼圖Plus 小遊戲內使用的是官方demo內已經實現的對象池類,實現如下:

this.offScreenCanvas = wx.createCanvas()this.offScreenCanvas.width = this.width * ratiothis.offScreenCanvas.height = this.height * ratiothis.ctx.drawImage(this.offScreenCanvas, x * ratio, y * ratio, this.offScreenCanvas.width, this.offScreenCanvas.height)

垃圾回收

小遊戲中,JavaScript 中的每一個 Canvas 或 Image 對象都會有一個客戶端層的實際紋理儲存,實際紋理儲存中存放著 Canvas、Image 的真實紋理,通常會佔用相當一部分內存。

每個客戶端實際紋理儲存的回收時機依賴於 JavaScript 中的 Canvas、Image 對象回收。

在 JavaScript 的 Canvas、Image 對象被回收之前,客戶端對應的實際紋理儲存不會被回收。

通過調用 wx.triggerGC() 方法,可以加快觸發 JavaScriptCore Garbage Collection(垃圾回收),從而觸發 JavaScript 中沒有引用的 Canvas、Image 回收,釋放對應的實際紋理儲存。

但 GC 具體觸發時機還要取決於 JavaScriptCore 自身機制,並不能保證調用 wx.triggerGC() 能馬上觸發回收。

層疊拼圖Plus 小遊戲在每局遊戲開始或結束都會觸發一下,及時回收內存垃圾,以保證最良好的遊戲體驗。

多線程 Worker

對於遊戲來說,每幀 16ms 是極其寶貴的,如果有一些可以異步處理的任務,可以放置於 Worker 中運行,待運行結束後,再把結果返回到主線程。

Worker 運行於一個單獨的全局上下文與線程中,不能直接調用主線程的方法,Worker 也不具備渲染的能力。

Worker與主線程之間的數據傳輸,雙方使用 Worker.postMessage() 來發送數據,Worker.onMessage() 來接收數據,傳輸的數據並不是直接共享,而是被複製的。

this.offScreenCanvas = wx.createCanvas()this.offScreenCanvas.width = this.width * ratiothis.offScreenCanvas.height = this.height * ratiothis.ctx.drawImage(this.offScreenCanvas, x * ratio, y * ratio, this.offScreenCanvas.width, this.offScreenCanvas.height)

需要注意的是:Worker 最大並發數量限制為 1 個,創建下一個前請用 Worker.terminate() 結束當前 Worker

結語

短短的一篇文章,定不能將層疊拼圖Plus 小遊戲的前前後後講明白講透徹,加上文筆有限,有描述不當的地方還望多多海涵。

其實最讓人心累的還是軟著的申請過程,由於各種原因前前後後花了將近三個月的時間。

本來也想寫一下軟著申請相關的內容,最後發現篇幅有點長,無奈作罷,爭取後面花點時間整理一下我這邊的經驗,希望可以幫助到需要的童鞋。

由於項目結構以及代碼還比較混亂,個人覺得,目前暫時還不適合開源。

好在,小遊戲內的所有核心代碼以及遊戲實現思想均已呈上,有興趣的同學如果有相關方面的疑問也可以與我多多交流,大家互相學習,共同進步。

江湖不遠,我們遊戲裡見!

相關焦點

  • 如何用 JavaScript+Canvas 開發一款超級燒腦小遊戲?
    那麼初學者如何開發一款好玩又燒腦的微信小遊戲呢?本文作者將詳細為大家講解。「啟邏輯之高妙,因想像而自由。」層疊拼圖Plus是一款需要空間想像力和邏輯推理能力完美結合的微信小遊戲,偶消奇不消,在簡單的遊戲規則下卻有著無數種可能性,需要你充分發揮想像力去探索,看似簡單卻具有極大的挑戰性和趣味性,Talk is cheap. Show me the code!
  • 用一天入門 canvas 和 JavaScript
    然後我們定義一個寬800和高800的 canvas 。最後,我們在 script 標籤裡引用了 app.js ,所有魔法都在這裡。我們開始使用 app.js 做一些事情。讓我們解決這個問題,以獲得更好的實時體驗。如果考慮一下,答案非常簡單:每次執行draw函數時,我們都希望初始點始終是 MouseEvent 對象的 offsetX 和 offsetY 屬性。
  • 「強烈建議收藏」小程序canvas繪製帶二維碼海報全流程(枚舉踩坑,詳解解決方案)
    一 寫在前面1 canvas繪製帶二維碼的海報,這些坑總有一個你可能會踩到,我會帶你一步步解決這些坑技術選型背景:taro3.0-vue先來十一個問題壓壓驚,相信你做繪製海報過程中,一定會遇到taro框架遇到的坑① taro-vue createCanvasContext 獲取canvas實例無效問題,繪製不出來效果?
  • html2canvas - 動態生成海報的優質js庫
    今天分享的html2canvas就可以。介紹在微信項目中經常會遇到動態生成海報的需求,Web前端合成圖片往往會使用canvas。canvas雖然強大,但用來合成海報非常繁瑣,一不小心就幾百行代碼了。而html2canvas.js是一款輕鬆地將HTML+CSS寫成的布局直接轉換成canvas,生成可保存分享的圖片。
  • 「想見你」團隊新作曝光!鄭元暢柯佳嬿加盟演繹燒腦時間軸!
    「想見你」製作團隊、編劇再推新作,「無神之地不下雨」8日舉辦卡司發布會,曾之喬、傅孟柏、顏毓麟主演之外,更找來因「想」劇再奪金鐘視後的柯佳嬿及6年未在臺拍戲的鄭元暢友情演出。「無」劇跟「想」劇一樣劇情走燒腦、懸疑、愛情故事路線,柯佳嬿透露,「無」劇邏輯性、時間軸及牽扯層面將比「想」劇更複雜。《無神之地不下雨》是一部人神愛情故事,靈感來自阿美族泛靈神話。故事描述以因為環境問題,眾神不再祝福這片土地作為開端,在下最後一場雨之後,眾神將紛紛離開祂們所眷戀的人間。
  • 【口袋單詞卡】10個最燒腦英文謎語,挑戰你的智商
    然而,當一道英文謎語擺在了面前,呃……卻感覺英語思維的腦迴路遭到了碾壓~今天跟小夥伴們分享10道號稱史上最燒腦(無釐頭)的英文謎語,夠膽就來挑戰下自己的智商吧!Q: What will you break once you say it?Q: Will liars be honest after they die?A: No, they won't.
  • 燒腦「劇本殺」一觸即發,戲精迅速集合!寧波這幾家店超過癮!
    2020-12-28 14:25:45 來源: 帶你玩遍寧波 舉報
  • GitHub 上有什麼好玩又有挑戰的前端項目?
    今天推薦一些免費好玩又有挑戰的前端項目,難度層層遞進,內容也很有趣,以遊戲和小工具為主。如果你還沒有前端基礎,推薦從這 3 門課開始:基礎階段1. HTML5 簡明教程 HTML5 簡明教程從網站的基礎概念開始,帶你了解其運行機制。然後學習 HTML 基礎知識,了解各種常用標籤的意義以及基本用法。此外,課程還會涉及 HTML5 的內容。
  • html2canvas 將代碼轉為圖片
    只是,不管是系統默認截屏還是截屏工具,都不是特別好用,尤其當代碼超過一屏的時候,還得分屏截取,而當你決定修改代碼的一部分的時候,有可能又要調整和重新截屏,這對於一大段一大段代碼的文章編輯來說是個噩夢一樣的體驗,而且截成一段段的代碼,對讀者也不友好。
  • 2019年上映的10部懸疑驚悚電影,無限燒腦、挑戰智商!
    今天 ,我給大家分享推薦2019年上映的無限燒腦、挑戰智商的10部懸疑驚悚電影,目前這些電影都有資源。 2、《海市蜃樓》(西班牙) 上映日期:2019年3月28日(中國大陸)、2018年11月30日(西班牙) 片長:128分鐘 頂級燒腦,頂級好看,最後半小時每分鐘爆口一句「臥槽」。
  • Canvas框架-FabricJS簡介
    簡單來說我們可以通過使用Fabric從而以較為簡單的方式實現較為複雜的Canvas功能官網文檔地址:http://fabricjs.com/docs/github地址:https://github.com/fabricjs/fabric.jsDemo地址:http://fabricjs.com/demos/起步
  • 考驗智商的時候到了,一份燒腦影單敬上
    除了生與死更是智商博弈!大溼奉上一份燒腦影單,考驗智商的時候到了!! 彗星來的那一夜 燒腦迷影:小格局中細節的編排夠認真,還是很難得的。讓我想起那篇關於複製人的科幻小說。只是平行空間的多個自我為何不能友好相處呢,真是個問題。
  • 《想見你》編劇燒腦新作!曾之喬、柯佳嬿新劇《無神之地不下雨...
    三鳳製作全新臺劇《無神之地不下雨》,是一部「人神愛情題材」的燒腦劇,故事背景由編劇團隊部分取材阿美族泛靈神話,所構造的原創架空世界觀。劇情講述因環境問題而使眾神選擇不再祝福這片土地為開端,隨著最後一場雨的到來,眾神紛紛離開祂們所眷戀的人間,然而一段在末日倒數前的人神愛情故事即將展開。
  • 這4道燒腦的數學題,研究生解到「智商欠費」,你能行嗎?
    隨著知識水平的提高,各類題目也是呈現出了燒腦的特性。這一些抽象的題目經常會以語文題目或者數學規律題的形勢展現出來。有時候看似一道題非常簡單,但是其中包含的學問可就大了。一次機緣巧合的機會,小編遇到過4道非常燒腦的智力題,剛一開始接觸就我這不認輸的牛性格肯定是信心滿滿,但是做過之後又是不得不服,想了一個通宵,但是還是感覺沒有一題會的。最終小編得出了一個結論,人比人比死人,作為研究生的我還好小學畢業早不然怎麼可能可以競爭過現在的年輕人!1、簡簡單單的說,說愛不愛!
  • 到日本九州陶瓷小鎮體驗「有田燒」技術、潛入倉庫尋寶
    喜歡日本瓷器的人想必都聽過九州佐賀縣所生產的「有田燒」,來到有田除了觀光、購買陶瓷品之外,深入陶瓷窯廠內參觀工廠內部,了解生產過程是很知性的旅行新選擇,還能在工廠內體驗日本高超的工藝技術,製作屬於自己的瓷器呢!
  • 最全微信最燒腦大挑戰答案匯總 最燒腦大挑戰答案一覽
    微信最燒腦大挑戰最全微信最燒腦大挑戰答案匯總 最燒腦大挑戰答案一覽。微信最燒腦大挑戰是一款非常火也很有意思的小遊戲,難度對於普通人來說還是有點高的,需要懂得各方面的知識,下面就來為各位玩家詳細的分享一下微信最燒腦大挑戰的全部答案匯總。
  • 如何利用TensorFlow.js部署簡單的AI版「你畫我猜」圖像識別應用
    作者使用谷歌 Colab 來訓練模型,並使用 TensorFlow.js 將它部署到瀏覽器上。你可以閱讀下面的教程(https://medium.com/deep-learning-turkey/google-colab-free-gpu-tutorial-e113627b9f5d)了解如何創建 notebook 和開始進行 GPU 編程。
  • 腦科學專家力薦!手把手教你如何讓孩子成為「優等生」
    」、「了解身體」、「疏導能量」、「集中注意力」、「提升專注力」這 5 個方面設置活動,幫助小讀者提升專注力,效果非常顯著!」、「傾聽身體,使用身體」、「知道自己有能力,要讓自己有能力」、「戰勝對失敗的恐懼」、「尋求外部資源」這 5 個方面設置活動,幫助小讀者提升自信心。
  • Swift 燒腦體操(五)- Monad
    Swift 相關的學習資料已經很多,我想從另外一個角度來介紹它的一些特性,我把這個角度叫做「燒腦體操」。什麼意思呢?就是我們專門挑一些比較費腦子的語言細節來學習。通過「燒腦」地思考,來達到對 Swift 語言的更加深入的理解。這是本體操的第五節,練習前請做好準備運動,保持頭腦清醒。Why Monad?
  • 「Web全棧教程」手把手教你用 Vue.js + Django 搭建在線教育平臺
    比如,「實驗樓」就在年初接到了國內部分高校的計算機開課請求,讓學校們可以使用實驗樓的在線環境進行教學工作。那麼, 實驗樓」這樣的在線編程教育網站是如何搭建的呢?今天給大家分享一個 Web 全棧項目: 以「實驗樓」為例,用 Vue.js 和 Django 搭建一個在線教育網站!