# 用Vue.js写一个命令行贪吃蛇游戏

## 安装

``npm install temir-snake-game -g``

## 贪吃蛇游戏实现

### 实现拆解

#### 元素初始化

##### 竞技台

``````const basic = 28
const backgroundIcon = '⬛'
const arena = ref<string[]>([])

function initArena() {
arena.value = Array.from({ length: basic * basic }, () => backgroundIcon)
} ``````
##### 蛇

``````const snakeIcon = '🟧'
// 坐标(索引)30,29 长度为2的蛇身
const snakeBody = ref([30, 29])``````
##### 食物

``````const foodIcon = '🍗'
// 食物坐标
const foodCoord = ref(77)

// 生成食物
function generateFood() {
const food = Math.floor(Math.random() * basic * basic)
// 与蛇身冲突,重新生成
if (snakeBody.value.includes(food)) {
generateFood()
return
}
foodCoord.value = food
}``````

#### 蛇的爬行

``````const map = {
left: -1,
right: 1,
top: -28,
bottom: 28
}``````

``````
function move() {
const h = snakeBody.value[0]
// 计算下一次爬行坐标,并添加至蛇头
head.value = h + direction.value
snakeBody.value.unshift(head.value)

// 吃到食物,重新生成
if (head.value === foodCoord.value) {
generateFood()
}
// 只有在未吃到食物的时候,才需要移除蛇尾
else { snakeBody.value.pop() }
}``````

#### 越界逻辑

``````function isOutOfRange(h: number) {
// 1. 蛇头碰到蛇身
return snakeBody.value.indexOf(h, 1) > 0
// 2. 蛇头超出竞技台上方
|| h < 0
// 3. 蛇头超出竞技台下方
|| h > basic * basic - 1
// 4. 蛇头超出竞技台右方
|| (direction.value === 1 && h % basic === 0)
// 5. 蛇头超出竞技台左方
|| (direction.value === -1 && h % basic === basic - 1)
}``````

#### 方向控制

``````import { useInput } from '@temir/core'
useInput(onKeyBoard, { isActive: true })

function onKeyBoard(_, keys) {
const { upArrow, downArrow, leftArrow, rightArrow } = keys
const d = {
[+leftArrow]: -1,
[+rightArrow]: 1,
[+upArrow]: -basic,
[+downArrow]: basic,
}[1] ?? direction.value
direction.value = (snakeBody.value[1] - snakeBody.value[0] === d) ? direction.value : d
}``````

#### UI绘制

``````<script lang="ts" setup>
import { computed } from 'vue'
import { TBox, TText } from '@temir/core'
import { useGame } from './composables'
import Header from './components/Header.vue'
import Home from './components/Home.vue'
import Game from './components/Game.vue'
import GameOver from './components/GameOver.vue'
import Exit from './components/Exit.vue'
const { playStatus } = useGame()
const activeComponent = computed(() => {
return {
unplayed: Home,
playing: Game,
over: GameOver,
exit: Exit,
}[playStatus.value]
})
</script>

<template>
<TBox
:width="100"
justify-content="center"
align-items="center"
flex-direction="column"
border-style="double"
>
<Header />
<component :is="activeComponent" />
</TBox>
</template>``````

4.8k 声望
3.6k 粉丝
0 条评论