我再也不要当舔狗了,我要当"King"!

1,188 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

落霞与孤鹜齐飞,秋水共长天一色

——唐·王勃《滕王阁序》

身为一名合格的CRUD Boy(前端摆子) & 孤寡,注定这个周末是要在Timi中度过,却没想摆子的快乐周末被断网打断了。闭目养神,神游天际一刹,想到自己是个程序猿,不能被断网困扰,于是乎,决定祭出自己的"屎山"功底,写一个简单、能运行、耗时的小游戏。自己写的游戏,肯定要自己当"King",最好还有一个"后宫"。"八皇后"这不就来了。

虽然"八皇后"应该有很多看官大佬都知道,但是我觉得还是有必要简单说下规则:
打个比方就是你有八个女朋友,那么怎么让她们能和谐相处,最好的办法莫过于在她们的必经之路上都不会遇到(老死不相往来最好),现在给你一个8×8的棋盘,请各位"空间管理大师"给每一个"女朋友"都安排一个约会场地,并且在她们可以"出行"的八个方向都不会相互遇见

(PS:红色区域都是不可以放置棋子的)

不知道有没有给各位看官大佬说明白,反正我自己是明白了,O(∩_∩)O哈哈~,下面进入正题了

这里孤寡 & 摆子用的是Vue3、Vite、Less、ts,项目搭建以及各个技术就不一一介绍了,毕竟我一个摆子(骄傲),重点是为了当"King"

先说一下大概思路,通过一个8*8的二维数组来控制,每个棋格上都有一个"女朋友"(咳咳,棋子棋子),在初始化的时候全部隐藏掉,在点击对应的棋格后,让棋子显示(给你其中的一个女朋友安排在这里),在之后安排的"女朋友"都要对这个位置进行一个检测,不可放置就给提示,可以就不提示,直至八个"女朋友"全部安排到位,发现空间没有管理好,再放会被发现,就点"重置"一键重开

骨架——Html

Html就不过多介绍了,周末我就要摆烂

<div v-for="(row, rIndex) in boardList" :key="rIndex" class="board">
  <div v-for="(cell, cIndex) in row" :key="cIndex" class="board-box" @click="getResult(rIndex, cIndex)">
    <div style="color: #fff;" v-if="cell.visible">Queen</div>
  </div>
</div>
<button class="resetBtn" @click="resetBoard">重置</button>

样式

这里的话,由于是自己周末随便写写,主要是用来玩的,样式问题忽略就好,简单写一个看个大概就好。大概的思路就是实现一个8*8的棋盘,外加一个重置按钮(用于发现空间管理失败后)

.board {
  width: 480px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  .board-box {
    width: 60px;
    height: 60px;
    text-align: center;
    line-height: 60px;
    background-color: #c0c0c0;
    &:nth-child(2n) {
      background-color: gray;
    }
  }
  &:nth-child(2n) .board-box:nth-child(2n){
    background-color: #c0c0c0;
  }
  &:nth-child(2n) .board-box:nth-child(2n-1){
    background-color: gray;
  }
}
.resetBtn {
  background-color: #f5483b;
  color: #fff;
  border-radius: 5px;
  margin-top: 20px;
  width: 80px;
  height: 40px;
  border: none;
  cursor: pointer;
  &:active {
    background-color: #d82e25;
  }
}

逻辑——js(ts)


<script setup lang="ts">
import { ref, watch, Ref } from 'vue'

type Queen = {
  id: string,
  visible: boolean
}
const boardList: Ref<Queen[][]> = ref(initBoardList())

// 初始化boardList(这么写一切为了重开,毕竟刚开始做空间管理大师,可能会被当场抓奸)
function initBoardList(): Queen[][]{
  return new Array(8).fill(1).map((_, I) => new Array(8).fill(1).map((_,i) => ({ id: `${I}-${i}`, visible: false })))
}

// 重置棋盘
function resetBoard() {
  boardList.value = initBoardList()
}

// 检验位置是否正确(级别高的大师应该不需要)
function checkSeat(rIndex: number, cIndex: number): boolean {
  // 横
  for (let i: number = 0; i < boardList.value[rIndex].length; i++) {
    if (boardList.value[rIndex][i].visible) return false
  }

  // 竖
  for (let i: number = 0; i < boardList.value.length; i++) {
    if (boardList.value[i][cIndex].visible) return false
  }

  // 撇
  for (let i: number = 0; i < boardList.value[0].length; i++) {
    const index: number = rIndex + cIndex - i
    if (index >= 0 && index < boardList.value.length && boardList.value[index][i].visible) return false
  }

  // 捺
  for (let i: number = 0; i < boardList.value[rIndex].length; i++) {
    const index: number = rIndex - cIndex + i
    if (index >= 0 && index < boardList.value.length && boardList.value[index][i].visible) return false
  }

  return true
}

// 获取结果(刚开始当"渣男"没关系,有老师带你避坑)
function getResult(rIndex: number, cIndex: number) {
  const res: boolean = checkSeat(rIndex, cIndex)
  if (res) {
    boardList.value[rIndex][cIndex].visible = true
  } else {
    alert('当前位置不允许放置!')
  }
}

//watch这里写的很糙,大概就是想做一个八个棋子放置好后,提示一下成功后直接开始下一局,懒得去琢磨好的想法了
watch(boardList, newValue => {
  let count: number = 0
  newValue.forEach(E => {
    E.forEach(e => {
      if (e.visible) count++
    })
  })
  if (count === 8) {
    setTimeout(() => {
      alert('游戏已完成,确认后将自动刷新!')
      resetBoard()
    }, 0);
  }
}, {deep: true})
</script>

效果

不能放置效果:

成功效果:

完整代码

<script setup lang="ts">
import { ref, watch, Ref } from 'vue'

type Queen = {
  id: string,
  visible: boolean
}
const boardList: Ref<Queen[][]> = ref(initBoardList())

// 初始化boardList
function initBoardList(): Queen[][]{
  return new Array(8).fill(1).map((_, I) => new Array(8).fill(1).map((_,i) => ({ id: `${I}-${i}`, visible: false })))
}

// 重置棋盘
function resetBoard() {
  boardList.value = initBoardList()
}

// 检验位置是否正确
function checkSeat(rIndex: number, cIndex: number): boolean {
  // 横
  for (let i: number = 0; i < boardList.value[rIndex].length; i++) {
    if (boardList.value[rIndex][i].visible) return false
  }

  // 竖
  for (let i: number = 0; i < boardList.value.length; i++) {
    if (boardList.value[i][cIndex].visible) return false
  }

  // 撇
  for (let i: number = 0; i < boardList.value[0].length; i++) {
    const index: number = rIndex + cIndex - i
    if (index >= 0 && index < boardList.value.length && boardList.value[index][i].visible) return false
  }

  // 捺
  for (let i: number = 0; i < boardList.value[rIndex].length; i++) {
    const index: number = rIndex - cIndex + i
    if (index >= 0 && index < boardList.value.length && boardList.value[index][i].visible) return false
  }

  return true
}

// 获取结果
function getResult(rIndex: number, cIndex: number) {
  const res: boolean = checkSeat(rIndex, cIndex)
  if (res) {
    boardList.value[rIndex][cIndex].visible = true
  } else {
    alert('当前位置不允许放置!')
  }
}

watch(boardList, newValue => {
  let count: number = 0
  newValue.forEach(E => {
    E.forEach(e => {
      if (e.visible) count++
    })
  })
  if (count === 8) {
    setTimeout(() => {
      alert('游戏已完成,确认后将自动刷新!')
      window.location.reload()
    }, 0);
  }
}, {deep: true})
</script>

<template>
  <div v-for="(row, rIndex) in boardList" :key="rIndex" class="board">
    <div v-for="(cell, cIndex) in row" :key="cIndex" class="board-box" @click="getResult(rIndex, cIndex)">
      <div style="color: #fff;" v-if="cell.visible">Queen</div>
    </div>
  </div>
  <button class="resetBtn" @click="resetBoard">重置</button>
</template>

<style lang="less" scoped>
.board {
  width: 480px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  .board-box {
    width: 60px;
    height: 60px;
    text-align: center;
    line-height: 60px;
    background-color: #c0c0c0;
    &:nth-child(2n) {
      background-color: gray;
    }
  }
  &:nth-child(2n) .board-box:nth-child(2n){
    background-color: #c0c0c0;
  }
  &:nth-child(2n) .board-box:nth-child(2n-1){
    background-color: gray;
  }
}
.resetBtn {
  background-color: #f5483b;
  color: #fff;
  border-radius: 5px;
  margin-top: 20px;
  width: 60px;
  height: 30px;
  border: none;
  cursor: pointer;
  &:active {
    background-color: #d82e25;
  }
}
</style>

完事完事,网修好了,摆子继续Timi去了(暴露了)