用 JavaScript 來做個貪吃蛇
講師:Arashi
日期:2021/03/31
Outline
- 流程圖
- 實作 - Base
- 實作 - Start & Addfood
- 實作 - draw table and snake
- 實作 - move
- 實作 - eat
- 實作 - dead
- 參考資源
流程圖
start()
addfood()
move()
drawtable()
isEat()
isDead()
初始化遊戲
添加食物
移動
更新畫布
判斷有沒有吃到食物
判斷有沒有死亡
使用函數

實作 - Base
<!DOCTYPE html>
<html>
<head>
<title>貪吃蛇</title>
<meta charset="UTF-8">
<meta name="keywords" content="貪吃蛇">
<meta name="Description" content="這是一個初學者用來學習的小遊戲">
<style type="text/css">
*{margin:0;}
.map{margin:50px auto;
height:600px;
width:900px;
background:#00D0FF;
border:10px solid #AFAEB2;
border-radius:8px;
}
</style>
</head>
<body>
<div class="map">
<canvas id="canvas" height="600" width="900">
</canvas>
</div>
</body>
</html>
網頁基本架構

展示畫面
實作 - Start & AddFood
後續內容全部加在 body 的 scrpit 內
<body>
<div class="map">
<canvas id="canvas" height="600" width="900">
</canvas>
</div>
<script type="text/javascript">
後續程式碼加在此處!!!
</script>
</body>
宣告所需的變數
var c = document.getElementById("canvas"); //取得畫布
var ctx = c.getContext("2d"); //跟畫布宣告說接下來要畫上去的圖為2D
// 初始化食物的資料
var foodx = 0;
var foody = 0;
// 初始化蛇的資料
var snake = [];
var snakeCount = 4;
// 判斷方向
var togo =0;
// 初始化
function start()
{
addfood();//在start中呼叫新增食物函式
}
function addfood()
{
foodx = Math.floor(Math.random()*60)*15;
foody = Math.floor(Math.random()*40)*15;
ctx.fillRect(foodx,foody,15,15); //繪製一個圓形,位置在(foodx, foody),長寬皆為15
}
//當載入網頁的時候,呼叫以下函式
window.onload = function()
{
start();
}
初始化與增加食物

展示畫面
Math.random() //回傳0~1之間的數字,不含1
Math.floor() //回傳整數部分
假設隨機出來的數字是0.5
Math.random() * 60
=> 0.54 * 60 = 32.4
Math.floor() * 15
=> 取32 * 15 = 480
Math 相關函式
舉例

(0,0)
x
y
程式中的座標
//繪製方形
ctx.fillRect(x軸,y軸,長,寬);
//繪製圓形
ctx.arc(圓心x軸, 圓心y軸, 半徑, 起始點弧度, 結束點弧度, anticlockwise);
anticlockwise = true //順時鐘畫圖
anticlockwise = false //逆時鐘畫圖
實作 - draw table and snake
初始化蛇的資料

(0, 0)
(15, 0)
(30, 0)
(45, 0)
//定義蛇的座標
function start()
{
for(var k = 0;k < snakeCount;k++)
{
// 定義每一節身體的位置
snake[k]={x:k * 15, y:0};
}
addfood();
}
//畫地圖的函式
function drawtable()
{
for(var k = 0;k < snakeCount;k++)//畫蛇的身體
{
ctx.fillStyle = "#000";
if (k == snakeCount-1)
{
ctx.fillStyle="red";//將蛇頭的顏色設定為紅色
}
ctx.fillRect(snake[k].x,snake[k].y,15,15);
}
//繪製食物
ctx.fillStyle ="black";
ctx.fillRect(foodx,foody,15,15);
ctx.fill(); //將顏色填滿圖形
}

將蛇畫上地圖
//當載入網頁的時候,呼叫以下函式
window.onload = function()
{
start();
drawtable(); // 增加繪製地圖
}
在載入網頁時便開始畫地圖
function addfood()
{
foodx = Math.floor(Math.random() * 60) * 15;
foody = Math.floor(Math.random() * 40) * 15;
// ctx.fillRect(foodx, foody, 15, 15);
}
刪除 addfood() 內的繪製方形

展示畫面
寫法 => {key1 : value, key2 : value......}
snake[
{x:0, y:0},
{x:15, y:0},
{x:30, y:0},
{x:45, y:0}
]
snake[1].x => 15
dict 字典

(0, 0)
(15, 0)
(30, 0)
(45, 0)
實作 - move
function keydown(e)
{
switch(e.keyCode)
{
case 37: togo=1; break;
case 38: togo=2; break;
case 39: togo=3; break;
case 40: togo=4; break;
case 65: togo=5; break;
case 68: togo=6; break;
}
}
document.onkeydown=function(e)
{
keydown(e);
}
監控按鍵操作
switch(參數)
{
case 37:
執行的事情
break;
case 38:
執行的事情
break;
case 39:
執行的事情
break;
}
switch case
當參數符合 case 的條件時,則執行該 case 要執行的內容
function move()
{
switch (togo)
{
case 1: snake.push({x:snake[snakeCount-1].x-15,y:snake[snakeCount-1].y}); break; //向左走
case 2: snake.push({x:snake[snakeCount-1].x,y:snake[snakeCount-1].y-15}); break; //向上
case 3: snake.push({x:snake[snakeCount-1].x+15,y:snake[snakeCount-1].y}); break; //向右
case 4: snake.push({x:snake[snakeCount-1].x,y:snake[snakeCount-1].y+15}); break; //向下
case 5: snake.push({x:snake[snakeCount-1].x-15,y:snake[snakeCount-1].y-15}); break; //向左上
case 6: snake.push({x:snake[snakeCount-1].x+15,y:snake[snakeCount-1].y+15}); break; //向右下
default: snake.push({x:snake[snakeCount-1].x+15,y:snake[snakeCount-1].y});
}
snake.shift();//刪除陣列第一個元素
ctx.clearRect(0,0,900,600);//清除畫布重新繪製
drawtable();
}
window.onload = function()
{
start();
setInterval(move,150); // 每0.15秒呼喚一次 move函式
drawtable();
}

(0, 0)
(15, 0)
(30, 0)
(45, 0)

(15, 0)
(30, 0)
(45, 0)
(60, 0)

(0, 0)
(15, 0)
(30, 0)
(45, 0)
(60, 0)

實作 - eat
function move()
{
......
isEat() // 增加這行
drawtable();
}
//吃到食物後長度加1
function isEat()
{
if(snake[snakeCount-1].x == foodx&&snake[snakeCount-1].y==foody)
{
addfood();
snakeCount++;
snake.unshift({x:-15,y:-15}); //增加一節身體
}
}
實作 - dead
function move()
{
......
isDead(); // 增加這行
drawtable();
}
function isDead()
{
if (snake[snakeCount-1].x > 885 || snake[snakeCount-1].y > 585 || snake[snakeCount-1].x < 0 || snake[snakeCount-1].y < 0)
{
alert("You are dead,GAME OVER!!!");
snake = []; //清空蛇的資料避免重複判斷
window.location.reload(); //重新整理頁面
}
}
參考資源
JS貪吃蛇
By arashi
JS貪吃蛇
- 131