[Hero Of UnderGround 地下城] — 8F Tic-Tac-Toe 井字遊戲
成果 & 程式碼
Introduction & 前言
時間一晃又過了一個禮拜,這次晃到8樓一看嚇了一下,好像剩沒幾個人,不管了還是抱持著自己的原則,硬幹就對了。另外這次算滿大的挑戰也收穫滿滿,因為首次嘗試用 Vue 挑戰(所以有寫不好的地方請見諒…
Summary & 摘要
由於JS地下城每個BOSS的弱點都不一樣,每一層都要由弱點去進行攻略,本次BOSS的弱點有五項。
【特定技術】先手為 O,後手為 X,某方獲勝時,上方會紀錄各方的獲勝戰績
【特定技術】每回合結束後,會判定結果頁(平手、O 獲勝、X 獲勝)
【特定技術】需符合 RWD,能在低螢幕解析度也能遊玩,介面不能超出 x 軸,至少在以下解析度能夠遊玩。
iPhone SE 320px
iPhone 8 375px
iPhone PLUS 414px
4.【特定技術】請使用瀏覽器離線儲存技術,將戰績保留起來,重新打開遊戲也仍可觀看到歷史戰績。技術請任選以下幾種
Cookie
localStorage
5.【書寫能力】請寫 BLOG,描述你在開發「滿足獲勝條件」解題思維來進行加強描述
上面三個 O 符合獲勝條件
斜線三個 X 符合獲勝條件
以往的額外條件書寫BLOG這次是其中一個 BOSS 弱點了(笑
畫面製作
第一次嘗試使用 Vue 切畫面,就可以直接把 display:none 扔了(誤,這邊我用了兩個 Views,一個是遊戲開始前畫面,一個是遊戲中加上結束畫面,其實看見其他大神似乎還能把畫面在拉出去個別當 Componemt 不過還不熟的 Vue 菜雞我就先能走再說跑了。
CSS 之 before & after 之有更好得做法?
剛開始看見有框的叉叉後直覺是使用 after 跟 before 來做,在上面使用兩塊黑色的偽元素去蓋住它,但是我發現其他大神有更容易的做法。
在第二個頁面又碰到了需要白邊的字,爬了一下文後發現了救星,那就是:
1 | text-stroke: .3rem #fff; |
加上去後就不需要再用一個 before 或 after 去覆蓋他這麼麻煩了。
串起你的世界 Vue-router
想起上一層還在 display:none 來 none 去,不僅程式碼露露長也容易造成使用者直接 F12 查看你隱藏的東西,自從接觸 Vue-router 之後考試都考一百分(誤。
關於如何從零到 Vue-cli UI 介面可以看我的 Vue系列文章 — Vue-Cli #1 初次見面(後續加載中),或是直接把 Vue-cli 升級到 3x 版本後直接在終端機上輸入 vue ui。
點選添加 Vue-router 之後你的src資料夾內會多出 View 資料夾及 router.js,可以把 View 資料夾內的檔案 About.vue Home.vue 當作 Componemt 的概念。
然後新增或修改你要的頁面就好了,因為這篇主要不是要介紹 Vue-cli 之後會放到 Vue系列文章去做介紹。
開始攻略
對於資料的處理 Vue 一直很拿手,直接把需要用到的資料丟進 data 內,我們需要的有局數、玩家、九個格子的陣列、判斷贏的陣列、分數、四個畫面的變數。
其實還能再縮減,這完全看寫程式的人邏輯,菜雞如我邏輯超級爛,連出門都會迷路…
1 | <div class="play-area d-flex flex-wrap" v-if="play_area"> |
利用 v-for 造出九宮格,v-for=”(grid,id) in grids” 第一個 grid 代表用於迭代的元素,第二個 id 代表 **索引值(optional)**。後面使用 v-bind 加上 :key=”id”,目的是確保每個元素的唯一性,當元素更新,例如改變順序時,有可識別唯一性的 key 來確保重新渲染。
讓你的畫面活起來
Vue 可以在新增、更新或移除 DOM 時使用 CSS 顯示動畫,讓你的畫面更精彩,使用方式也很簡單,先來了解一下 Vue 提供的特殊 Class名稱。
v-enter:元素一開始的狀態。在元素被新增時觸發,在下一個影格立即移除。
v-enter-active:元素被新增時的狀態。在元素被新增前加入,然後在整個動畫中使用它,最後在動畫結時被移除。
v-enter-to:元素新增狀態的結束。在元素被新增後觸發,在 v-enter-active 動畫結束後被移除。這是 v2.1.8 新增的狀態,原有的 v-enter 被它取代。
v-leave:元素被刪除前的初始狀態。在刪除時立即觸發,在下一個影格立即移除。
v-leave-active:元素被刪除時的狀態。在元素被移除前加入,然後在整個動畫中使用它,最後在動畫結束時被移除。
v-leave-to:元素刪除狀態的結束。在元素被刪除後觸發,在 v-leave-active 動畫結束後移除。這是 v2.1.8 新增的狀態,原有的 v-leave 被它取代。
最前面的 v 替換成自己命名的 class 名稱,舉個例子,寫好**
1 | .test-enter-active { |
關於 Animation 的導入也會在 Vue 系列文章中提到,之後會再更新。
各種methods
1 | set(id){ |
使用 @click=”set(id)” 讓每一個格子的 id 傳回來,並且判斷這個格子有沒有被按過,以及步數是否在九步內,如果不符合就不進判斷式,如果符合的話就讓步數增加,並且利用三元運算,去判斷這次是誰下手的,我們一開始的 player 預設是叉叉先,所以除 2於 0 的都是叉叉下手,反之圈圈下手。
在我們的 template 裡我們使用 v-if 去判斷現在是誰下手,然後該出現圈圈還是叉叉,這邊剛開始有使用 1 & 2 , 但是發生悲劇,因為後面判斷輸贏是用格子的 id 加總去判斷,如果一個圈跟叉就會發生 1+2=3,但是使用 1 & -1 的話加總只有 -3 -1 1 3 這四種可能,其中前後兩個就可以拿去判斷贏或輸。
1 | v-if="grid === 1" |
最後用 $set() 去替換掉 grids 內的值,用剛剛判斷的現在是哪一個 player 去替換
關於三元運算
三元運算其實很簡單,並且有效減少你的程式碼,也是這次的收穫之一。看看下方例子就知道超簡單啦!
1 | let a = 100; |
輸或贏?
剛開始的想法是放在 computed 內,因為在學習 Vue 時查看了一下文件,這是一個專門做運算的計算屬性,但是 computed 是根據相依的資料改變時才做計算,不像 method 是不管有無相依都會計算,而且在我打在 computed 的期間,只要 run 專案,就會有警告出現,而且資料並不會即時更新,獲勝後必須去使用 Vue devtolls 才會更新資料,我想應該是渲染問題,這部分會在研究更新。
到這算是踩了一個坑,不過想了一下改了一個作法,既然 computed 不用呼叫就會進去跑,那我也可以退而求其次使用 watch 監聽我的局數,從第二步開始就去看有沒有贏家。
1 | watch:{ |
檢查的部分使用迴圈去跑,檢查八條線的贏法,在上面我們已經先把贏法存在陣列裡。
1 | checkwinner(){ |
平手怎麼辦?
因為沒有使用 computed 所以沒有 return 的值讓你去判斷,但我們可以自己寫一個 checkdraw() ,並在 watch 判斷內直接寫上,並在 methods 內加上式子,顯示平手畫面等等。
1 | watch(){ |
重新開始遊戲
1 | restart(){ |
在按鈕上加上 @click=”restart” 後,這邊很簡單的只做初始化遊戲。
打造新手遊
現在越來越多版需要符合手機大小,這邊使用 @Media 的方式,另外也可以搭上 Boostrap 的 col 去做排版,可以省的手機版還要調大小呢。
因為 BOSS 的弱點必須至少在 iPhone SE iPhone 8 iPhone PLUS 可以遊玩,這幾個此吋都介於差不多之間,就把他們一起編輯了,當然詳細的手機畫面還是要放到手機看比較清楚,因為網頁的跟手機的畫面高度差一小截呢,菜雞可是踩過幾次坑。
1 | @media screen and (min-width: 320px) and (max-width: 576px) { |
名留青史善用 LocalStorage
這是一個 HTML5 提供的 web storage,擁有 5MB 大小,但是無法跨域使用,但是你可以存一些資訊在上面,好比我們的戰績,或是購物網站常用的,短時間內你關掉網頁不用再重新登入。
localStorage 是以 key-value 儲存資料,所以我們可以給他一個 item name 還有一個 value,使用方式也很簡單,始用 setItem 給他一個 ( name , value ) 就存進去啦,之後除非你去手動清除或者程式設計者執行 clear ,否則會一直存在,甚至重開機。
1 | localStorage.setItem("Xwin", this.Xscore); |
在我們每次載入遊戲頁面的時候,使用 created 去取得 localStorage 的資料,說到 created 就會提到 Vue 的生命週期,之後也會在 Vue系列介紹,這邊先讓我們取出你的戰績吧。
1 | created() { |
關於 GitHub 的那點小事
由於以往都是單純 HTML 的檔案上傳,這次第一次使用專案方式整包上傳,所以造成網址讀不到,可以收尋 webpack baseUrl 爬文看看。
現在這情況下可以先到根目錄下創建一個 vue.config.js 檔案,並且在內打上:
1 | module.exports = { |
之後重新 Build 一次專案,然後在網址後面加上 **dist/index.html#/**,就能跑出來了。
Conclusion & 結論
這次花了幾天的時間在看 Vue 文件,最後抱著跟當初勇闖地下城的心態一樣,先做了再說,許多時候都是這樣跌跌撞撞再成長,對菜雞我這種人來說只是一昧的看文件是看不懂的,加上現在地下城有許多 Vue 大神在勇闖,我想這不失為一個學習的好機會。
一直想加強自己的邏輯概念,這次 Vue 正好是一個磨練的好時機,雖然越高樓層越來越難,不過抱著就算是成長 0.1 也要往上衝的態度,我想幾年後回頭看看自己現在,一定有所收穫,最後除了繼續努力之外還是要列出檢討的地方,然後朝下一關繼續加油,完畢。
JS
邏輯
文筆
體重
我的其他範例
Hero Of UnderGround — 1F Multiplicatio 九九乘法表
Hero Of UnderGround — 2F Clock 時鐘
Hero Of UnderGround — 3F Calculator 計算機
Hero Of UnderGround — 4F World Clock 各國時區
Hero Of UnderGround — 5F AQI 全台空氣指標儀表板
Hero Of UnderGround — 6F SECONDS CHALLENGE 倒數遊戲
Hero Of UnderGround — 7F Canvas 畫板
參考網站
- 高郁涵大神 — 新手 JS 地下城-8f 井字遊戲
- TECH A RIDE — localStorage 介紹與使用
- Summer。桑莫 — Vue.js:計算屬性 Computed
- moojing — 井字遊戲 GitHub
- 巴哈姆特 舒壓用