lovesaber157 2023-01-05 11:47 采纳率: 0%
浏览 49

一个奇怪的问题,number数组中存进去了string

试图利用Vue3+Vuex+TS利用一维数组来实现前端的简单扫雷。在判断地雷周围雷区拥有的地雷数量时,发现本来应该是计算后输出number数组的结果里面居然出现了string。
callMatrix(72,9)
预期:[62, 63, 71, 80, 81]
结果:[62, 63, 71, 728, '729']
VUE部分 设置游戏

<template>
    <div>
        雷区格数:{{mineField.fieldHeight*mineField.fieldWeight}}
        <p>雷区长度:<input placeholder="请输入雷区长宽,默认为4" v-model="mineField.fieldHeight"/></p>
        <p>雷区宽度:<input placeholder="请输入雷区长宽,默认为4" v-model="mineField.fieldWeight"/></p>
        <p>地雷数量:<input placeholder="请输入地雷数量,默认为1" v-model="mineField.mineNumber"/></p>
        <button @click="setDefaultValue">默认值</button><button @click="setStoreInfo">确认</button>
    </div>
</template>

<script lang="ts">
    import {useStore} from "vuex"
    import {ref} from 'vue'
    export default {
      name: "gameSetting",
      setup(){
          const store=useStore()
          //雷区属性
          const mineField=ref({
              fieldHeight:10,
              fieldWeight:10,
              mineNumber:1
          })
          function setDefaultValue() {
              mineField.value.fieldHeight=4
              mineField.value.fieldWeight=4
              mineField.value.mineNumber=1
          }
          function setStoreInfo() {
              if (Number(mineField.value.fieldHeight)){
                  if (Number(mineField.value.fieldWeight)){
                      if (Number(mineField.value.mineNumber)&&Number(mineField.value.mineNumber)){
                          store.commit('setFieldHeight',mineField.value.fieldHeight)
                          store.commit("setFieldWeight",mineField.value.fieldWeight)
                          store.commit('setMineNumber',mineField.value.mineNumber)
                          store.commit('setIs',!store.state.is)
                      }else {
                          alert(`无效雷数,合理范围[1-${Number(mineField.value.fieldHeight)*Number(mineField.value.fieldWeight)-1}]`)
                      }
                  }else {
                      alert('无效宽度')
                  }
              }else {
                  alert('无效长度')
              }
          }
          return{
              store,mineField,setDefaultValue,setStoreInfo
          }
      }
    }
</script>


VUE部分 游戏区域

<template>
    <div class="top">
        玩家名:{{store.state.playerName}}
    </div>
    <div class="center">
        <p>雷区地块:{{divNumber}}</p>
        <p>翻开区块:{{openedDivNumber}}</p>
        <p>预测地雷:{{minePrediction}}</p>
        <div class="chessboardCanvas">
            <div
                    v-for="item in divNumber"
                    :key="item"
                    :id="item"
                    class="noCheckBox"
                    @mousedown="clickThings"
            >
                {{item}}
            </div>
        </div>
    </div>
    <div class="footer">
        <button @click="resetThisGame">重置本局</button>
        <button>重新设置</button>
    </div>
</template>

<script lang="ts">
    import {useStore} from "vuex"
    import {watch,computed,ref,nextTick} from 'vue'
    export default {
        name: "gameArea",
        setup(){
            const store=useStore()
            //存放雷区地块数量
            const divNumber=ref<number>(0)
            //翻开区块数量
            let openedDivNumber=ref<number>(0)
            //存放雷区属性
            let fieldHeight:number
            let fieldWeight:number
            //存放地雷数组ID
            let saveMines:number[]=[]
            //存放有周围地雷数量的DIV块
            let saveHaveMineNumber:{id:number,haveMath:number}[]=[]
            //暂时存放DIV的element类
            let element:HTMLDivElement
            //记录预测地雷数量
            let minePrediction=ref<number>(0)
            //画布的还原以及初始化样式
            function fatherStyle() {
                element=document.getElementsByClassName('chessboardCanvas')[0] as HTMLDivElement
                element.style.display='grid'
                element.style.width=`${40*fieldWeight+fieldWeight+1}`
                element.style.height=`${40*fieldHeight+fieldHeight+1}`
                element.style.gridTemplateColumns=`repeat(${fieldWeight},40px)`
                element.style.gridTemplateRows=`repeat(${fieldHeight},40px)`
                element.style.paddingBottom='2px'
            }
            function mineInitialization(mineNumber:number) {
                openedDivNumber.value=0
                //父元素设置样式
                fatherStyle()
                //存放地雷数组置为空
                saveMines=[]
                //临时存放minesID
                let mineSet=new Set()
                while(mineSet.size<mineNumber){
                    mineSet.add(Math.floor(Math.random()*divNumber.value+1))
                }
                saveMines=Array.from(mineSet) as number[]
                havemineMath(fieldWeight)
                console.log('地雷数组')
                console.log(saveMines)
            }
            //监测用户是否确定改动
            watch(computed(()=>{return store.state.is}),()=>{
                divNumber.value=store.getters.mineFieldSize
                fieldWeight=store.state.fieldWeight
                fieldHeight=store.state.fieldHeight
                mineInitialization(store.state.mineNumber)
                // console.log(store.state.fieldWeight)
                // console.log(`测试代码${callMatrix(saveMines[0],Number(store.state.fieldWeight))}`)
            })
            //重置本局
            function resetThisGame() {
                mineInitialization(store.state.mineNumber)
                for (let item of document.getElementsByClassName('noCheckBox')){
                    (item as HTMLDivElement).style.backgroundColor='#999999',
                    (item as HTMLDivElement).textContent=item.id,
                    (item as HTMLDivElement).style.pointerEvents='auto'
                }
                alreadyMath=saveMines
            }
            //不同点击来触发事件
            function clickThings(event:any) {
                element=event.path[0] as HTMLDivElement
                //禁用全局菜单
                document.oncontextmenu=()=>{
                    return false
                }
                switch (event.button) {
                    case 0:
                        if (saveMines.includes(Number(element.id))){
                            element.innerText=""
                            //触发地雷 红色->等待1s->弹出提示框,进入下一轮
                            element.style.backgroundColor='red'
                            setTimeout(function () {
                                alert('你触发了地雷,游戏结束,即将回退')
                                resetThisGame()
                            },100)
                        }else {
                            recursizeLookup(Number(element.id),fieldWeight)
                            setTimeout(function () {
                                isWin()
                            },200)
                        }
                        break
                    case 1:
                        if (element.style.backgroundColor==="rgb(153, 255, 204)"){
                            element.style.backgroundColor='#999999'
                            element.innerText=element.id
                            alreadyMath=alreadyMath.filter(item=>{
                                return item!==Number(element.id)
                            })
                            minePrediction.value--
                        }else{
                            element.style.backgroundColor='#99FFCC'
                            element.innerText='预测地雷'
                            alreadyMath.push(Number(element.id))
                            minePrediction.value++
                        }
                        break
                    default:
                        break
                }
            }
            //点击遍历周围是否存在地雷并赋值
            //3*3规律
            // y-(x+1)    y-x        y-(x-1)
            // y-(x-2)    y        y+(x-2)
            // y+(X-1)    y+x        y+x+1
            function callMatrix(id:number,size:number):number[]{
                //对数组边界的判断来决定返回值
                if((id-1)%size===0){
                    //DIV左边界
                    return [id-size,id-size+1,id+1,id+size,id+size+1]
                }else if (id%size===0){
                    //DIV右边界
                    return [id-size-1,id-size,id-1,id+size-1,id+size]
                }else {
                    //非DIV左右边界
                    return [id-size-1,id-size,id-size+1,id-1,id+1,id+size-1,id+size,id+size+1]
                }
            }
            //存放地雷周边区域DIV相关信息
            function havemineMath(size:number) {
                saveHaveMineNumber=[]
                for (let i of saveMines){
                    let matrix=callMatrix(i,fieldWeight)
                    //**
                    //**应该输出的是number[] 但是在数组中输出的有string
                    //**
                    console.log(matrix)
                    console.log(typeof matrix[matrix.length-1])
                    //**
                    //**
                    //**
                    for (let j of matrix){
                        if (j>0&&j<=divNumber.value&&!saveMines.includes(j)){
                            saveHaveMineNumber.push({
                                id:j,
                                haveMath:1
                            })
                        }
                    }
                }
                // 如果存在相同元素则只留下唯一一个,同时改变haveMath,过滤操作
                for (let i = 0;i<saveHaveMineNumber.length;i++){
                    let count=1
                    for (let j = i+1;j<saveHaveMineNumber.length;j++){
                        if (saveHaveMineNumber[i].id===saveHaveMineNumber[j].id){
                            saveHaveMineNumber[j].id=0
                            count++
                            break
                        }
                    }
                    saveHaveMineNumber[i].haveMath=count
                }
                saveHaveMineNumber=saveHaveMineNumber.filter((item)=>{
                    return item.id!=0
                })
                console.log(saveHaveMineNumber)
            }
            //以点击处为中心,递归寻找3*3,翻找到有地雷数量的区域就停止
            //存储已经递归的ID以及改变过颜色的ID,避免重复递归
            let alreadyMath:number[]=saveMines
            function recursizeLookup(checkID:number,size:number) {
                element.style.backgroundColor='#FFFFFF'
                element.style.pointerEvents='none'
                if (checkID>0&&checkID<=divNumber.value&&!alreadyMath.includes(checkID)){
                    let controlMath=1
                    element=document.getElementById(checkID.toString()) as HTMLDivElement
                    for (let i of saveHaveMineNumber){
                        if (checkID===i.id){
                            controlMath--
                            element.innerText=i.haveMath.toString()
                            alreadyMath.push(checkID)
                            openedDivNumber.value++
                        }
                    }
                    if (controlMath){
                        element.innerText=""
                        let divArr=[]
                        alreadyMath.push(checkID)
                        divArr=callMatrix(checkID,size)
                        for (let i of divArr){
                            recursizeLookup(i,size)
                        }
                        openedDivNumber.value++
                    }
                }
            }
            function isWin() {
                if (openedDivNumber.value+saveMines.length===divNumber.value){
                    alert('恭喜你胜利啦!即将重新开始!')
                    resetThisGame()
                }
            }
            return{
                minePrediction,store,saveMines,divNumber,resetThisGame,clickThings,saveHaveMineNumber,openedDivNumber
            }
        }
    }
</script>

<style scoped>
    .noCheckBox{
        background: #999999;
        width: 40px;
        height: 40px;
        border: 1px solid black;
    }
</style>

VUEX


```typescript

import { createStore } from 'vuex'

export default createStore({
  state: {
    playerName:undefined,
    //雷区属性
    fieldHeight:0,
    fieldWeight:0,
    mineNumber:0,
    //确定是否初始化
    is:false
  },
  getters: {
    //雷区大小
    mineFieldSize:function (state):number{
      return state.fieldHeight*state.fieldWeight
    }
  },
  mutations: {
    setPlayerName:function (state:any,newName:string):void {
      state.playerName=newName
    },
    setFieldHeight:function (state:any,newHeight:number):void {
      state.fieldHeight=newHeight
    },
    setFieldWeight:function (state:any,newWeight:number):void {
      state.fieldWeight=newWeight
    },
    setMineNumber:function (state:any,newNumber:number):void {
      state.mineNumber=newNumber
    },
    setIs:function (state,newBoolean:boolean):void {
      state.is=newBoolean
    }
  },
})

```

  • 写回答

1条回答 默认 最新

  • 於黾 2023-01-05 13:42
    关注

    js是弱类型的编程语言,你的函数里虽然声明了参数是number型,但是这只起到注释的作用,不能强制要求输入就是number,你需要仔细检查输入的参数到底是什么类型,该强制转int就强制转换一下,不要直接+,否则变成字符串拼接了

    评论

报告相同问题?

问题事件

  • 创建了问题 1月5日

悬赏问题

  • ¥15 CDH6.3 运行hive -e hive -e "show databases;"报错:hive-env.sh:行24: hbase-common.jar: 权限不够
  • ¥15 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 java 的protected权限 ,问题在注释里