vue3+vite创建项目+扫雷

1、vite 创建vue3项目(没有router、axios、vuex等插件,需自行安装)

npm install -g create-vite-app
create-vite-app xxx项目名称
cd xxx项目名称
npm install
npm run dev  

2、router、vuex等插件 (使用)====>

npm i vue-router@4.0.0-beta.4 -S

npm i vuex@4.0.0-beta.4 -S

封装axios请求====>

npm install axios

报错uncaught TypeError: Cannot set properties of undefined (setting ‘baseURL’)

更改axios版本

3、Vue和Vue-template-compiler(@vue/compiler-sfc) 版本不一致

如果报vue本地有版本,但是Vue-template-compiler本地版本不一致

可以直接修改package.json里的版本号,再npm install

4、vue3.0 + vite 使用less报错解决方法

vite 使用less必须要将 package.json 中的 lessless-loader写在 devDependencies 里面

npm install less less-loader --save-dev

在这里插入图片描述

5、js创建二维数组

const state = reactive({
	list:[]
})
let temparr =Array(5).fill().map(()=>{
  return new Array(5).fill({
    value:'1',
    name:'1'
  })
})
state.list = reactive([...temparr])
//最终格式 list:[ [{},{}],[{},{}],[{},{}] ]

? : 修改数组某子数组的子元素(list[1][1].value)时,会修改整个子数组(list[1]所有item的value)。

A:将子数组的子元素赋值给一个中间元素,再赋值回给原数组即可

let targetone = {...list[1][1]};
targetone.value=123 
list[1][1] = targetone

6、扫雷

点击格子时的流程

if(格子已经被打开){
	返回   
}
if(左键){
   if(第一次点击){
      生成地雷
   }else{
     if(点到雷){
        显示所有雷,游戏结束
     }else{
       if(点到计数为0 的格子){
          将其周围所有计数为0且没被打开的格子打开
       }else{
          打开格子显示周围雷数
       }
     }
   }
}else{//右键
  标记为雷,剩余雷数-1
}
if(标记雷数足够){
   判断是否可以游戏结束
}

7、扫雷源码

<template>
  <el-container style=" border: 1px solid #eee">
    <el-container>
      <el-header style="text-align:left; padding-top:10px; font-size: 12px">
        <el-form :inline="true" ref="form" label-width="120px">
        <el-form-item label="游戏模式">
          <el-select v-model="state.grade" placeholder="Select">
            <el-option
              v-for="item in state.options"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="gamestart">开始游戏</el-button>
        </el-form-item>
        <el-form-item label="剩余地雷:">
          <span>{{state.thunder}}</span>
        </el-form-item>
      </el-form>
      </el-header>

      <el-main ondragstart='return false' oncontextmenu='self.event.returnValue=false'>
        <ul>
          <li v-for="(item,index) in list.thunderlist" :key="index">
            <ul class="row">
              <li v-for="(every,everyindex) in item" :key="everyindex" style="display:block;background-color:#999" @mousedown="clickone(index,everyindex,$event)">
                <span v-if="every.isopen" style="display:block;background-color:white">{{every.counter}}</span>
                <span v-if="every.isflag">💣</span>
              </li>
            </ul>
          </li>
        </ul>
      </el-main>
    </el-container>
  </el-container> 
</template>

<script>
import { defineComponent, reactive } from 'vue'
import { ElMessageBox } from 'element-plus'
export default defineComponent({
  name: 'App',
  setup() {
    const state = reactive({
      grade:0,
      thunder:0,
      row:10,
      col:10,
      options: [
      {
        value: 0,
        label: '简单模式',
      },
      {
        value: 1,
        label: '一般模式',
      },
      {
        value: 2,
        label: '困难模式',
      }],
      item:{
        isopen:false,
        isthunder:false,
        counter:0,
        isflag:false
      },
      isfirstclick:true,
    })
    const list = reactive({
      thunderlist:[]
    })
    //开始游戏
    const gamestart = ()=>{
      state.isfirstclick = true;
      switch (state.grade) {
        case 0:
          state.thunder = 30;
          state.row = 10;
          state.col = 10;
          break;
      
        case 1:
          state.thunder = 45;
          state.row = 15;
          state.col = 15;
          break;
      
        case 2:
          state.thunder = 60;
          state.row = 20;
          state.col = 20;
          break;
      
        default:
          break;
      }  
      //制作格子
      let temparr =Array(state.row).fill().map(()=>{
        return new Array(state.col).fill({
            isopen:false,
            isthunder:false,
            counter:0,
            isflag:false
          })
      })
      list.thunderlist = reactive([...temparr])
    }
    //鼠标按下格子
    const clickone = (row,col,e)=>{
      let targetone = {...list.thunderlist[row][col]};
      //打开格子
      function open(blocki,blockj) {
        targetone.isopen=true 
        list.thunderlist[blocki][blockj] = targetone
      }
      //标记为炸弹
      function block(blocki,blockj) {
        targetone.isflag=true 
        list.thunderlist[blocki][blockj] = targetone
      }
      //已经点开
      if(targetone.isopen){
        return
      }
      if(e.button===0){
        //左键
        if(state.isfirstclick){
          // 第一次//全部没有雷,然后随机数布雷
          state.isfirstclick = false;
          open(row,col)
          //布雷
          for (let i = 0; i < state.thunder; i++) {
            //随机坐标
            let randomi = Math.floor(Math.random()*state.row)
            let randomj = Math.floor(Math.random()*state.col)
            
            let target = {...list.thunderlist[randomi][randomj]}
            //不为初始点 且 没有被布雷
            if(!(randomi===row && randomj===col) && !target.isthunder){
              target.isthunder=true
              list.thunderlist[randomi][randomj]={...target}
              //雷的周围格子计数加一,除了边界
              for (let m = randomi - 1; m < randomi + 2; m++) {
                for (let n = randomj - 1; n < randomj + 2; n++) {
                  //判断坐标防越界
                  if (m > -1 && n > -1 && m < state.row && n < state.col) {
                    //计雷数+1
                    let mubiao = {...list.thunderlist[m][n]}
                    mubiao.counter++;
                    list.thunderlist[m][n] = {...mubiao}
                  }
                }
              }
            }else{
              i-=1
            } 
          }
        }else{
          if(targetone.isthunder){
            //踩雷//标记炸弹位置 结束游戏重新开始
            for (let i = 0; i < state.row; i++) {
              for (let j = 0; j < state.col; j++) {
                if(list.thunderlist[i][j].isthunder){
                  block(i,j)
                }
              }
            }
            msgalert('*********** !!!game over!!! ***********','game over')
          }else{
            //点到为0的格子,将其周围为0的格子一起打开
            if(list.thunderlist[row][col].counter===0){
              open(row,col)
              for (let m = row - 1; m < row + 2; m++) {
                for (let n = col - 1; n < col + 2; n++) {
                  //判断坐标防越界 且 无雷、没被打开 、计数为0
                  if (m > -1 && n > -1 && m < state.row && n < state.col && !list.thunderlist[m][n].isthunder && !list.thunderlist[m][n].isopen&& !list.thunderlist[m][n].counter) {
                    clickone(m,n,{button:0})
                  }
                }
              }
            }else{
              //正常的
              open(row,col)
            }        
          }
        }
      }else{//右键标记 //并记标记的雷总数
        if(!targetone.isopen){
          targetone.isflag=!targetone.isflag 
          targetone.isflag?state.thunder--:state.thunder++
          list.thunderlist[row][col] = targetone
        }
      }
      //标记雷数足够
      if(state.thunder===0 ){
        //遍历 判断标记位置以及雷的位置重合个数
        let count = 0
        for (let i = 0; i < state.row; i++) {
          for (let j = 0; j < state.col; j++) {
            if(list.thunderlist[i][j].isthunder && list.thunderlist[i][j].isflag){
              count++
            }
          }
        }
        //重合一致即为胜利✌️
        if(state.row*3 === count){
          msgalert('************** !!!win!!! **************','win')
        }
      }
      
    }
    const msgalert=(text,title)=>{
      ElMessageBox.alert(text, title, {
        confirmButtonText: 'OK',
        center: true,
        callback: () => {
          gamestart()
        },
      })

    }
      
    return {
      state,
      list,
      gamestart,
      clickone,
      msgalert
    }
  },
})
</script>
<style lang='less'>
.el-header {
  background-color: #b3c0d1;
  color: var(--el-text-color-primary);
  line-height: 60px;
}
li{
  list-style: none;
}
.row{
  display: flex;
  li{
    width: 50px;
    height: 50px;
    line-height: 50px;
    border: 1px solid #b3c0d1;
  }
  li:hover{
    background-color: #8ab6f0;
  }
}

</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值