js井子棋
js (vue)如何实现井字琪游戏规则我想不用我多说了,本次dome仅仅是作者太无趣了, 写着玩的,不喜勿喷。先给大家看看样子吧。dome介绍:这里实现了 井字棋的博弈与胜负。可以一个人玩。 (自己是X 同时也是 O)不过这样难免显得无趣。我又加了个人机跟你下棋这里面的人机比较笨, 我就不优化了。 (可不要欺负人家呀)话不多说先上源代码。<template><div class=
·
js (vue)如何实现井字琪
下载链接 添加链接描述
游戏规则我想不用我多说了,
本次dome仅仅是作者太无趣了, 写着玩的,不喜勿喷。
先给大家看看样子吧。
dome介绍:
这里实现了 井字棋的博弈与胜负。
可以一个人玩。 (自己是X 同时也是 O)
不过这样难免显得无趣。
我又加了个人机跟你下棋
这里面的人机比较笨, 我就不优化了。 (可不要欺负人家呀)
话不多说先上源代码。
<template>
<div class="pages">
<h2>井字棋</h2>
<h2>
<el-input v-model="Xname" placeholder="请输X的名字"></el-input> VS <el-input v-model="Oname" placeholder="请输O的名字"></el-input>
</h2>
<div class="body">
<!-- 棋盘 -->
<div class="qihe-box" :class="{gameNo: isOver}">
<el-tooltip v-for="(item, index) in qiziArrShow" :key="index" :disabled="true" effect="dark" :content="isOver ? '请点击开始游戏' : rivalTxt" placement="top">
<div class="item" @click="playChessClick({rival,rivalPush: rival == 1 ? 2 : 1, index})">
<span v-if="item.v == 1" class="el-icon-close"></span>
<span v-if="item.v == 2" class="el-icon-check"></span>
</div>
</el-tooltip>
</div>
<!-- 菜单 -->
<div class="menus">
<div class="t t1">
<el-button v-if="isOver" @click="statusGame" type="warning">go game</el-button>
<el-button v-else @click="isOver = true" type="info"> restart </el-button>
</div>
<div class="t">
<el-button v-if="isOver" @click="statusGameAi" type="warning">Ai game</el-button>
<el-button v-else @click="isOver = true" type="info"> Ai restart </el-button>
</div>
<div class="t t2">
<el-switch v-model="rivalSAI" :disabled="!isOver" active-text="AI先行" inactive-text="AI后行" active-color="#ff4949" inactive-color="#13ce66">
</el-switch>
</div>
<!-- <div class="t t2">
<el-switch v-model="rival" :active-value="1" :inactive-value="2" :active-text="Xname + '下'" :inactive-text="Oname + '下'" active-color="#ff4949" inactive-color="#13ce66">
</el-switch>
</div> -->
<div class="t">请棋手 <el-tag :type="rival == 1 ? 'danger' : 'success'">{{rival == 1 ? (aiName ? 'ai电脑' : '' ) + Xname : Oname}}</el-tag> 落子</div>
<div class="t t4">游戏已进行 <span>{{gameTime}}s</span></div>
</div>
</div>
</div>
</template>
<script>
var gameTimeIndex;
export default {
components: {},
data() {
return {
// 游戏双方姓名
Xname: "X",
Oname: "O",
// 游戏进行时间 秒
gameTime: 0,
// 游戏是否结束
isOver: true,
// 落子方 1 X | 2 O
rival: 2,
// 落子方提示
rivalTxt: "你确定下这里嘛",
// v 0 未落子 | 1 落子x | 2 落子o
qiziArrShow: [
{ id: 0, v: 0 },
{ id: 1, v: 0 },
{ id: 2, v: 0 },
{ id: 3, v: 0 },
{ id: 4, v: 0 },
{ id: 5, v: 0 },
{ id: 6, v: 0 },
{ id: 7, v: 0 },
{ id: 8, v: 0 },
],
// ai
// 是否启用ai
isStatusAi: false,
// ai的角色
aiName: false,
// ai 是否给ai下
isAiPlay: true,
// ai 先行?
rivalSAI: true,
// ai是否在思考中?
aiHold: false,
};
},
computed: {},
watch: {
rival(val) {
if (val == 1) {
this.rivalTxt =
"你确定下这里嘛" + (this.aiName ? "ai电脑" : "") + this.Xname;
} else {
this.rivalTxt = "你确定下这里嘛" + this.Oname;
}
},
isOver(val) {
if (!val) {
clearInterval(gameTimeIndex);
gameTimeIndex = setInterval(() => {
this.gameTime++;
}, 1000);
} else {
clearInterval(gameTimeIndex);
}
},
// 存名字
Xname(val) {
localStorage.setItem("Xname", val);
},
Oname(val) {
localStorage.setItem("Oname", val);
},
},
methods: {
/**
* 点击落子
* 角色 rival
* 下一个角色 rivalPush
* 位置 index
*/
playChessClick(obj) {
if (this.aiHold && this.isStatusAi) {
return this.$message.warning("ai落子中, 请等等它");
}
if (this.isOver) return;
if (this.qiziArrShow[obj.index].v != 0)
return this.$message.warning("不可以重复落子哦");
// 落子ok
this.playChess(obj);
if (this.isStatusAi && this.isAiPlay) {
// 是否是和ai在下 并且ai是否落子
this.ai();
} else {
this.isAiPlay = true;
}
},
/**
* 落子
*
* 角色 rival
* 下一个角色 rivalPush
* 位置 index
*
*/
playChess(obj) {
// 落子
this.qiziArrShow[obj.index].v = obj.rival;
this.victory(this.qiziArrShow);
// 换人
this.rival = obj.rivalPush;
},
/**
*判断输赢
*
*
*/
victory(arr, simulate = false) {
// 节流
let qiziNum = 0;
this.qiziArrShow.forEach((el) => {
if (el.v != 0) {
qiziNum++;
}
});
if (qiziNum < 4) return false;
if (qiziNum == this.qiziArrShow.length && !simulate) return this.draw(); // 和
// 计算输赢
let boo = false;
for (let i = 0; i < this.qiziArrShow.length - 1; i++) {
// 横
if (i == 0 || i == 3 || i == 6) {
if (this.computHWX(i, i + 1, i + 2, { arr })) {
if (simulate) {
boo = true;
} else {
this.end(this.qiziArrShow[i].v);
}
}
}
// 竖
if (i == 0 || i == 1 || i == 2) {
if (this.computHWX(i, i + 3, i + 6, { arr }) && !simulate) {
if (simulate) {
boo = true;
} else {
this.end(this.qiziArrShow[i].v);
}
}
}
// x
if (i == 0 || i == 2) {
if (this.computHWX(i, 4, 8 - i, { arr }) && !simulate) {
if (simulate) {
boo = true;
} else {
this.end(this.qiziArrShow[i].v);
}
}
}
}
return boo;
},
/**
* 计算横竖X
*
*/
computHWX(num1, num2, num3, obj) {
let arr = obj.arr;
if (
arr[num1].v != 0 &&
arr[num2].v != 0 &&
arr[num3].v != 0 &&
arr[num1].v == arr[num2].v &&
arr[num1].v == arr[num3].v &&
arr[num2].v == arr[num3].v
) {
return true;
} else {
return false;
}
},
aiPlay(i) {
// 关闭 ai 落子
this.isAiPlay = false;
// 落子
this.aiHold = false; // ai思考end
this.playChessClick({
rival: this.rival,
rivalPush: this.rival == 1 ? 2 : 1,
index: i,
});
},
/**
* ai
*
*/
ai() {
if (!this.isAiPlay || !this.isStatusAi) return;
this.$message.warning("ai电脑思考中...");
this.aiHold = true; // ai思考status
setTimeout(() => {
// 中心优先
if (this.qiziArrShow[4].v == 0) {
this.aiPlay(4);
// console.log("落子ok, 固定 1.0");
return;
}
// 是否能赢
let Parr = this.qiziArrShow.filter((item) => {
return item.v == 0;
});
// 模拟棋手
let boo = false;
let Carr = JSON.parse(JSON.stringify(this.qiziArrShow));
for (let K = 0; K < Parr.length; K++) {
const item = Parr[K];
Carr[item.id].v = this.rival;
if (this.victory(Carr, true)) {
this.aiPlay(item.id);
// console.log("落子ok, 固定 1.2");
boo = true;
break;
}
}
if (boo) return;
for (let i = 0; i < this.qiziArrShow.length; i++) {
let el = this.qiziArrShow[i];
if (el.v == 0) {
this.aiPlay(i);
// console.log("落子ok, 固定");
break;
}
}
}, 400);
},
/**
* 一方获胜
*/
end(v) {
this.isOver = true;
this.$alert(
"获胜者:" +
(v == 1 ? (this.aiName ? "ai电脑" : "") + this.Xname : this.Oname),
"胜负以分",
{
confirmButtonText: "再来",
callback: (action) => {},
}
);
},
/**
* 和棋
*/
draw() {
this.isOver = true;
this.$alert("和棋", "胜负难分", {
confirmButtonText: "再来",
callback: (action) => {},
});
return true;
},
/**
* 重开
*/
statusGame() {
this.isStatusAi = false;
this.isOver = false;
this.aiName = false;
this.rival = 2;
this.qiziArrShow = [
{ id: 0, v: 0 },
{ id: 1, v: 0 },
{ id: 2, v: 0 },
{ id: 3, v: 0 },
{ id: 4, v: 0 },
{ id: 5, v: 0 },
{ id: 6, v: 0 },
{ id: 7, v: 0 },
{ id: 8, v: 0 },
];
},
/**
* ai 重开
*/
statusGameAi() {
this.isStatusAi = true;
this.isOver = false;
this.isAiPlay = true;
this.qiziArrShow = [
{ id: 0, v: 0 },
{ id: 1, v: 0 },
{ id: 2, v: 0 },
{ id: 3, v: 0 },
{ id: 4, v: 0 },
{ id: 5, v: 0 },
{ id: 6, v: 0 },
{ id: 7, v: 0 },
{ id: 8, v: 0 },
];
// ai 先行?
if (this.rivalSAI) {
this.aiName = true;
this.rival = 1;
} else {
this.aiName = true;
this.rival = 2;
}
// 启动ai
if (this.rivalSAI) {
this.ai();
} else {
// 开启ai落子
this.isAiPlay = true;
}
},
},
created() {
this.Xname = localStorage.getItem("Xname") || "X";
this.Oname = localStorage.getItem("Oname") || "O";
},
mounted() {},
};
</script>
<style lang='less' scoped>
h2 {
.el-input {
width: 100px;
}
}
.body {
margin: 100px auto;
width: 600px;
display: flex;
}
// 菜单
.menus {
margin-left: 100px;
.t {
margin: 20px 0;
}
.t4 {
span {
font-size: 1.1em;
color: #42b3e3;
}
}
}
// 棋盘
.qihe-box {
padding-top: 5px;
width: 315px;
height: 315px;
border: solid #8896ee 1px;
border-radius: 5px;
background-color: #909399;
display: flex;
justify-content: space-around;
flex-wrap: wrap;
.item {
cursor: pointer;
width: 100px;
height: 100px;
background: #606266;
span {
font-size: 60px;
line-height: 100px;
}
.el-icon-close {
color: #f56c6c;
}
.el-icon-check {
color: #67c23a;
}
}
.item:hover {
box-shadow: 0px 0px 9px rgba(64, 158, 255, 0.8);
}
}
.gameNo {
opacity: 0.3;
}
</style>
结尾:
1、这是vue项目, 里面使用了element的ui
element的ui
2、如何跑项目呢? 搭建一个vue环境 这个dome就是个页面。 记得引入element 的 ui
3、欢迎大家一起学习交流
更多推荐
已为社区贡献17条内容
所有评论(0)