介紹
今天寫了一個漢諾塔遊戲,我想大家應該都玩過,先給大家看看具體是什麼樣吧。
源碼已上傳github:github鏈接
很遺憾,也就只有3個圓盤我可以順利通過,哈哈~~~,如果誰可以玩更高的級別,還請不吝賜教啦。話不多說,先看怎麼實現吧。
遊戲規則
整個小遊戲是可以自己調整難度的,演示裏我是使用的3個圓盤,大家可以自行調整。當然,也可以改成闖關模式,這就靠大家發揮啦。
漢諾塔遊戲規則:只有寬度小的圓盤可以放在寬度大的圓盤上,否則不能放置,把所有圓盤從第一個柱子移動到第三個柱子算遊戲完成。
HTML佈局
html佈局比較簡單,大家一看就明白了,直接上代碼
<div class="container">
<div class="cloumns" id="c1">
</div>
<div class="cloumns" id="c2"></div>
<div class="cloumns" id="c3"></div>
<div class="bot"></div>
<!-- 勝利時的彈出框 -->
<div class="success">
<div>恭喜你,智商超人哦!!</div>
</div>
</div>
//按鍵控制區
<div class="btns">
<div>
<button data-from="c1" data-to="c3">左</button>
<button data-from="c1" data-to="c2">右</button>
</div>
<div>
<button data-from="c2" data-to="c1">左</button>
<button data-from="c2" data-to="c3">右</button>
</div>
<div>
<button data-from="c3" data-to="c2">左</button>
<button data-from="c3" data-to="c1">右</button>
</div>
</div>
CSS代碼
css代碼更簡單啦,配合上面的html代碼大家自行看啦,當然我的審美實在不怎麼樣,所有大家可以自己美化界面
*{
margin: 0;
padding: 0;
}
/* 外面父級的樣式 */
.container{
width: 900px;
height: 600px;
background-color: #ccc;
margin: 50px auto 0;
display: flex;
justify-content: space-around;
padding-top: 60px;
padding-bottom: 30px;
position: relative;
}
/* 中間三個柱子的樣式 */
.container .cloumns{
width: 30px;
border-radius: 15px 15px 0 0;
background-color: #8c8c8c;
display: flex;
flex-direction: column-reverse;
}
.container .bot{
position: absolute;
left: 0;
bottom: 0;
height: 30px;
width: 100%;
background-color: #000;
}
/* 每個漢諾塔中的圓盤的樣式 */
.container .cloumns > div{
width: 150px;
height: 30px;
border: 1px solid black;
border-radius: 15px;
background-color: lightblue;
margin-left: 50%;
transform: translateX(-50%);
}
/* 按鈕樣式 */
.btns{
display: flex;
width: 900px;
margin: 20px auto 0;
justify-content: space-around;
}
.btns > div > button{
width: 30px;
height: 30px;
margin: 0 1em;
cursor: pointer;
}
/* 勝利模塊的樣式 */
.container .success{
opacity: 0;
position: absolute;
width: 100%;
height: 100%;
top: 0px;
display: flex;
justify-content: center;
align-items: center;
background-color:rgba(0, 0, 0, 0.5);
}
.container .success > div{
width: 200px;
height: 100px;
text-align: center;
line-height: 100px;
font-size: 16px;
font-weight: bold;
background-color: aqua;
color: #f00;
}
JS代碼
好啦,重頭戲到了,現在開始講js代碼啦
首先獲取頁面上的元素,併爲每一個柱子創建一個數組,代表每個圓盤上的數量,後面每次移動柱子上的圓盤就比較簡單了,只需要操作數組即可。
//獲取每個柱子
let c1 = document.getElementById('c1');
let c2 = document.getElementById('c2');
let c3 = document.getElementById('c3');
// 獲取所有的按鈕
let btns = document.querySelectorAll('button');
//獲取勝利的彈出框
let success = document.getElementsByClassName('success')[0];
//創建一個數組,每個柱子的圓盤的數量
//想要增加難度,只需要在數組中添加數字即可
//例如:c1:[4, 3, 2, 1]就會生成四個圓盤了
const cloumns = {
c1: [3, 2, 1],
c2: [],
c3: []
}
到目前爲止,界面已經創建完成,每個柱子也已經獲取,每個柱子上的圓盤也已經創建,所以接下來就是將這些元素渲染到頁面上。
createDom函數負責通過傳入的柱子和負責這個柱子的數組中的元素來創建相應的圓盤個數。
//創建每個柱子裏的圓盤並渲染頁面
function render() {
//每次加載,清空頁面
createDom(cloumns.c1, c1);
createDom(cloumns.c2, c2);
createDom(cloumns.c3, c3);
function createDom(arr, dom) {
dom.innerHTML = '';
for (let i = 0; i < arr.length; i++) {
const n = arr[i];
const div = document.createElement('div');
div.style.width = minWidth + (n - 1) * stepWidth + 'px';
dom.appendChild(div);
}
}
}
render();
給每一個按鈕添加點擊事件,在這裏要注意的是,會形成閉包,因此我在for循環裏用的ES6中的let定義
for (let i = 0; i < btns.length; i++) {
btns[i].onclick = () => {
var from = cloumns[btns[i].dataset.from];
var to = cloumns[btns[i].dataset.to];
move(from, to);
}
}
爲了方便我們獲取按鈕式向左還是向右,在html中已經給每一個按鈕添加了data-from和data-to。通過獲取按鈕上屬性的值可以準確判斷出該移動到哪一個柱子上
<div class="btns">
<div>
<button data-from="c1" data-to="c3">左</button>
<button data-from="c1" data-to="c2">右</button>
</div>
<div>
<button data-from="c2" data-to="c1">左</button>
<button data-from="c2" data-to="c3">右</button>
</div>
<div>
<button data-from="c3" data-to="c2">左</button>
<button data-from="c3" data-to="c1">右</button>
</div>
</div>
移動規則
遊戲規則是隻能小圓盤放在大圓盤上,因此在每次移動之前都需要判斷下一個要移動的柱子的最頂層圓盤是否比正在移動的這個大,如果比正在移動的這個圓盤大,則可以進行移動,反之,則不行。
當第一個柱子和第二個柱子上的圓盤都爲0的時候,遊戲結束。在這裏大家可以動腦思考怎麼樣改造成闖關類型遊戲哦
//判斷兩個柱子的最頂層的圓盤大小,並且進行勝負判斷
function check(from, to){
const fromLast = from[from.length - 1];
const toLast = to[to.length - 1];
if(fromLast < toLast){
to.push(from.pop());
//每次改變需要重新渲染
render();
}else{
return;
}
if(cloumns.c1.length === 0 && cloumns.c2.length === 0){
success.style.opacity = 1;
for(let i = 0; i < btns.length; i++){
btns[i].style.opacity = 0;
}
}
}
結語
整個小遊戲就完成了,這個遊戲不難,但是可以很好的鍛鍊邏輯思維能力,我比較喜歡。寫出來之後還能自己檢驗自己能玩多少個圓盤,哈哈。反正我玩3個圓盤是得心應手,再多了就有點困難咯。