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
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
vite 使用
less
必须要将package.json
中的 less 和less-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>