来自我朋友得原创小游戏、顺行棋
我朋友sa-admin等著作者,java资深从业者
<!DOCTYPE html>
<html>
<head>
<title>顺行棋</title>
<meta charset="UTF-8">
<style>
body{
background-color: #EEE;
}
.error-fox{margin: 50px auto; text-align: center; color: red;}
.game-fox,.qipan-fox{
width: 400px;
height: 400px;
border: 0px #000 solid;
margin: 0px auto;
box-shadow: 5px 5px 20px #000;
position: relative;
}
.qipan{
box-shadow: 0 0 1px #DDD;
position: absolute;
width: 100px;
height: 100px;
}
.card{
box-shadow: 0 0 0px #DDD;
position: absolute;
width: 100px;
height: 100px;
cursor: pointer;
}
.c-tran-4{transition: all 0.2s;}
.card-nr{
width: 50px;
height: 50px;
left: 25px;
top: 25px;
line-height: 15px;
text-align: center;
position: absolute;
background-color: #FFF;
background-size: 100% 100%;
cursor: pointer;
transition: all 0.2s;
}
.qipan-nr{
position: absolute;
width: 100px;
height: 100px;
cursor: pointer;
}
/* 飞跳洞 */
.card-ftd{
font-size: 0.5em;
}
/* 不同状态不同类 */
.card-cs-1{
background-image: url(img/card-bg.jpg);
}
.card-cs-4{
width: 60px;
height: 60px;
left: 20px;
top: 20px;
box-shadow: 0 0 30px #94D8F6;
z-index: 99;
}
/* 翻牌特效 */
.card-fanpai{
transform: rotateY(90deg);
}
.card-hover{
box-shadow: 0 0 20px #94D8F6;
}
/* 做标 */
.zuobiao{
width: 10px;
height: 10px;
border-radius: 50%;
background-color: green;
box-shadow: 0 0 10px green;
margin: 45px;
transition: all 0.5s;
transform: scale(0, 0);
}
.zuobiao-show{
transform: scale(1, 1);
}
/* 线段 */
.xd-td{
width: 100px;
height: 100px;
position: absolute;
border: 1px #aaa solid;
}
</style>
</head>
<body>
<div id="app">
规则:
井>丁>剪刀石头布<br>
吃了飞可以横着或者竖着飞<br>
吃了跳可以斜着飞<br>
吃了冬可以增加攻击力,同等级的话可以吃掉对方,但是不增加防御力<br>
<div class="error-fox">vs</div>
<div style=" text-align: center;">
<p style="color: red;">
<span v-if="game.p == game.p1"> --> P1 <-- </span>
<span v-if="game.p != game.p1">P1</span>
</p>
<p style="color: blue;">
<span v-if="game.p == game.p2"> --> P2 <-- </span>
<span v-if="game.p != game.p2">P2</span>
</p>
</div>
<div class="game-fox">
<!-- 棋子 -->
<div class="card-fox">
<div class="card"
v-for="(card, index) in card_array"
:class=" 'c-tran-' + card.status "
:style="{left: (card.x * 100) + 'px', top: (card.y * 100) + 'px'}">
<div class="card-nr"
:class="['card-cs-' + card.status, card.fanpai == true ? 'card-fanpai' : null, card.hover == true ? 'card-hover' : null]"
>
<br>
<span v-if="card.status != 1" :style="{color: card.color}">{{card.name}}</span>
<br>
<span class="card-ftd">{{card.tools}}</span>
</div>
</div>
</div>
<!-- 棋盘 -->
<div class="qipan-fox">
<div class="qipan">
<div class="qipan-nr"
v-for="qipan in qipan_array"
@mouseover="qipan_mouseover(qipan) "
@mouseout="qipan_mouseout(qipan) "
@click="click_qipan(qipan)"
:style="{left: (qipan.x * 100) + 'px', top: (qipan.y * 100) + 'px'}">
<div class="zuobiao" :class=" qipan.zb_show == true ? 'zuobiao-show' : '' "></div>
</div>
</div>
</div>
<!-- 棋盘线 -->
<div style="width: 300px; height: 300px; position: absolute; left: 50px; top: 50px; z-index: -1;">
<div class="xd-td" style="left: 0px; top: 0px;"> </div>
<div class="xd-td" style="left: 0px; top: 100px;"> </div>
<div class="xd-td" style="left: 0px; top: 200px;"> </div>
<div class="xd-td" style="left: 100px; top: 0px;"> </div>
<div class="xd-td" style="left: 100px; top: 100px;"> </div>
<div class="xd-td" style="left: 100px; top: 200px;"> </div>
<div class="xd-td" style="left: 200px; top: 0px;"> </div>
<div class="xd-td" style="left: 200px; top: 100px;"> </div>
<div class="xd-td" style="left: 200px; top: 200px;"> </div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<!-- <script src="../sa.js"></script> -->
<script>
var game = {
p1: {
g: 1,
color: 'red'
},
p2: {
g: 2,
color: 'blue'
}
}
game.p = game.p1; // 当前p
// 所有状态
/*
* 1 = 未翻开
* 2 = 已翻开
* 3 = 鼠标悬浮
* 4 = 已选中
*/
var card_array = [
{g: 1, color: 'red', id: 1, name: '井', x: 0, y: 0, status: 1, fanpai: false, hover: false, tools: ''},
{g: 1, color: 'red', id: 2, name: '丁', x: 1, y: 0, status: 1, fanpai: false, hover: false, tools: ''},
{g: 1, color: 'red', id: 3, name: '石头', x: 2, y: 0, status: 1, fanpai: false, hover: false, tools: ''},
{g: 1, color: 'red', id: 4, name: '剪刀', x: 3, y: 0, status: 1, fanpai: false, hover: false, tools: ''},
{g: 1, color: 'red', id: 5, name: '布', x: 0, y: 1, status: 1, fanpai: false, hover: false, tools: ''},
{g: 1, color: 'red', id: 6, name: '飞', x: 1, y: 1, status: 1, fanpai: false, hover: false, tools: ''},
{g: 1, color: 'red', id: 7, name: '跳', x: 2, y: 1, status: 1, fanpai: false, hover: false, tools: ''},
{g: 1, color: 'red', id: 8, name: '冬', x: 3, y: 1, status: 1, fanpai: false, hover: false, tools: ''},
{g: 2, color: 'blue', id: 1, name: '井', x: 0, y: 2, status: 1, fanpai: false, hover: false, tools: ''},
{g: 2, color: 'blue', id: 2, name: '丁', x: 1, y: 2, status: 1, fanpai: false, hover: false, tools: ''},
{g: 2, color: 'blue', id: 3, name: '石头', x: 2, y: 2, status: 1, fanpai: false, hover: false, tools: ''},
{g: 2, color: 'blue', id: 4, name: '剪刀', x: 3, y: 2, status: 1, fanpai: false, hover: false, tools: ''},
{g: 2, color: 'blue', id: 5, name: '布', x: 0, y: 3, status: 1, fanpai: false, hover: false, tools: ''},
{g: 2, color: 'blue', id: 6, name: '飞', x: 1, y: 3, status: 1, fanpai: false, hover: false, tools: ''},
{g: 2, color: 'blue', id: 7, name: '跳', x: 2, y: 3, status: 1, fanpai: false, hover: false, tools: ''},
{g: 2, color: 'blue', id: 8, name: '冬', x: 3, y: 3, status: 1, fanpai: false, hover: false, tools: ''},
];
// x坐标, y坐标, 状态
function getCard(x, y, status) {
return {x: x, y: y, status: status};
}
// 生成所有 card
function getCardArray() {
var arr = [];
}
new Vue({
el: '#app',
data: {
game: game, // 游戏
card_array: [], // 棋子
qipan_array: [ // 棋盘
{x: 0, y: 0, zb_show: false}, {x: 1, y: 0, zb_show: false}, {x: 2, y: 0, zb_show: false}, {x: 3, y: 0, zb_show: false},
{x: 0, y: 1, zb_show: false}, {x: 1, y: 1, zb_show: false}, {x: 2, y: 1, zb_show: false}, {x: 3, y: 1, zb_show: false},
{x: 0, y: 2, zb_show: false}, {x: 1, y: 2, zb_show: false}, {x: 2, y: 2, zb_show: false}, {x: 3, y: 2, zb_show: false},
{x: 0, y: 3, zb_show: false}, {x: 1, y: 3, zb_show: false}, {x: 2, y: 3, zb_show: false}, {x: 3, y: 3, zb_show: false}
],
card_native: {} // 当前选中的那个
},
methods: {
// 根据XY找棋盘
getQipanByXY: function(x, y) {
return this.qipan_array[x + y * 4 ];
},
// 根据棋盘找棋子
getCardByQP: function(qipan) {
for (var i = 0; i < this.card_array.length; i++) {
if(this.card_array[i].x == qipan.x && this.card_array[i].y == qipan.y) {
return this.card_array[i];
}
}
},
// 获得高亮棋子
getCardGao: function() {
for (var i = 0; i < this.card_array.length; i++) {
if(this.card_array[i].status == 4) {
return this.card_array[i];
}
}
},
// 棋盘悬浮 - 进入
qipan_mouseover: function(qipan) {
var card = this.getCardByQP(qipan);
if(card != null && card.status != 4) {
card.hover = true;
}
},
// 棋盘悬浮 - 出
qipan_mouseout: function(qipan) {
var card = this.getCardByQP(qipan);
if(card != null) {
card.hover = false;
}
},
// 点击棋盘
click_qipan: function(qipan) {
var card = this.getCardByQP(qipan);
// 检查是否动子
if(qipan.zb_show == true) {
var card_gao = this.getCardGao(card);
this.runCard(card_gao, qipan);
toggleP(); // 切换P
return;
}
// 所有zb消失高亮
this.setZbsNot();
// 所有card失去活动
this.setCardNot(card);
this.click_card(card);
},
// 点击卡片
click_card: function(card) {
if(card == null){
return;
}
// 如果是 1 == 未翻开 , 那就把它翻开
if(card.status == 1) {
card.fanpai = true; // 激发翻牌特效
setTimeout(function() {
card.fanpai = false;
card.status = 2;
}, 200);
toggleP(); // 切换P
return;
}
// 如果是 4 == 已选中 , 那就把它取消选中
if(card.status == 4) {
return card.status = 2;
}
// 验证是否为本p
if(game.p.g != card.g) {
return setError('这是对方的棋子');
}
// 如果是 2 == 已翻开 , 那就把它选中
if(card.status == 2) {
card.status = 4;
this.setZbs(card);
}
},
// 动子
runCard: function(card, qipan) {
var card_2 = this.getCardByQP(qipan); // 目标card
card.x = qipan.x;
card.y = qipan.y;
// 如果是空位, 直接移动
if(card_2 == null) {
} else {
// 如果同g
if(card.g == card_2.g) {
// 如果是吃装备
if(card.id <= 5 && card_2.id > 5) {
this.eatCard(card_2);
card.tools += card_2.name;
}
} else {
// 不同g
// 如果有冬, 通吃
if(card.tools.indexOf('冬') != -1) {
this.eatCard(card_2);
} else {
// 无冬
// 同id
if (card.id == card_2.id) {
this.eatCard(card);
this.eatCard(card_2);
setError('兑子:【' + card.name + '】');
} else {
// 根据前面的算法, 走到这一步必须是吃子
this.eatCard(card_2);
}
}
}
}
// 用此方法处理动画bug
// 在这200s间隙里,可以非法操作
setTimeout(function() {
this.setCardNot();
this.setZbsNot();
}.bind(this), 200)
},
// 所有card取消高亮, 并有一个例外
setCardNot: function(card) {
for(var i = 0; i < this.card_array.length; i++) {
if(this.card_array[i].status == 4 && this.card_array[i] != card) {
this.card_array[i].status = 2;
}
}
},
// 所有zb取消高亮
setZbsNot: function() {
this.qipan_array.forEach(function(item) {
item.zb_show = false;
});
},
// 推算一下zuobiao-show
setZbs: function(card) {
//var zbs_arr = []; // 做标show起数组
var x = card.x;
var y = card.y;
var zb_arr = [{x: x, y: y - 1}, {x: x + 1, y: y}, {x: x, y: y + 1}, {x: x - 1, y: y}]; // 所有坐标数组
var yx_arr = []; // 有效坐标
var qipan_arr = []; // 棋盘数组
// 如果有飞
if(card.tools.indexOf('飞') != -1) {
zb_arr.push({x: x, y: y - 2}, {x: x + 2, y: y}, {x: x, y: y + 2}, {x: x - 2, y: y});
zb_arr.push({x: x, y: y - 3}, {x: x + 3, y: y}, {x: x, y: y + 3}, {x: x - 3, y: y});
}
// 如果有跳
if(card.tools.indexOf('跳') != -1) {
zb_arr.push({x: x + 1, y: y + 1}, {x: x + 1, y: y - 1}, {x: x - 1, y: y + 1}, {x: x - 1, y: y - 1});
zb_arr.push({x: x + 2, y: y + 2}, {x: x + 2, y: y - 2}, {x: x - 2, y: y + 2}, {x: x - 2, y: y - 2});
zb_arr.push({x: x + 3, y: y + 3}, {x: x + 3, y: y - 3}, {x: x - 3, y: y + 3}, {x: x - 3, y: y - 3});
}
// 找出有效坐标
for (var i = 0; i < zb_arr.length; i++) {
var zb = zb_arr[i];
// 略过 无效坐标
if(zb.x < 0 || zb.x > 3 || zb.y < 0 || zb.y > 3 ) {
continue;
}
// 如果是空, 直接装
var card_2 = this.getCardByQP(zb); // 获得棋子
if(card_2 == null) {
yx_arr.push(zb);
continue;
}
// 略过 未翻开
if(card_2.status == 1) {
continue;
}
// 如果同 g
if(card.g == card_2.g) {
if(card.id <=5 && card_2.id >5) {
yx_arr.push(zb);
}
} else {
// 不同g
// 如果同id, 直接装
if(card.id == card_2.id) {
yx_arr.push(zb);
} else {
// 不同id
// 如果有冬, 全可杀
if(card.tools.indexOf('冬') != -1) {
yx_arr.push(zb);
} else {
// 没有冬
// 如果可杀
if(is_sha(card.id, card_2.id)) {
yx_arr.push(zb);
}
}
}
}
}
// alert(yx_arr.length);
// 使其高亮
yx_arr.forEach(function(item) {
var qipan = this.getQipanByXY(item.x, item.y);
if(qipan) {
qipan.zb_show = true;
}
}.bind(this));
},
// 吃子
eatCard: function(card) {
// 移除此子
var index = this.card_array.indexOf(card);
if (index > -1) {
this.card_array.splice(index, 1);
}
// 吃掉子:
setError("吃子:【" + card.name + "】!");
}
},
created: function(){
var zb_arr = [ // 坐标集合
{x: 0, y: 0}, {x: 1, y: 0}, {x: 2, y: 0}, {x: 3, y: 0},
{x: 0, y: 1}, {x: 1, y: 1}, {x: 2, y: 1}, {x: 3, y: 1},
{x: 0, y: 2}, {x: 1, y: 2}, {x: 2, y: 2}, {x: 3, y: 2},
{x: 0, y: 3}, {x: 1, y: 3}, {x: 2, y: 3}, {x: 3, y: 3}
]
var new_arr = [];
for (var i = 0; i < card_array.length; i++) {
var index = randomNum(0, card_array.length - 1); // 随机一个坐标
var index_zb = randomNum(0, card_array.length - 1); // 随机一个坐标
var card = card_array[index];
var zb = zb_arr[index_zb];
card_array.splice(index, 1); // 删除
zb_arr.splice(index_zb, 1); // 删除
i--;
card.x = zb.x;
card.y = zb.y;
new_arr.push(card);
}
card_array.forEach(function(item) {
var index = randomNum(0, zb_arr.length - 1);
var zb = zb_arr[index]; // 随机一个坐标
zb_arr.splice(index, 1); // 删除
// 赋值
item.x = zb.x;
item.y = zb.y;
})
//
// 动画添加到棋盘
var i = 0;
var time = setInterval(function() {
this.card_array.push(new_arr[i]);
// 如果没了
i++;
if(i == new_arr.length) {
clearInterval(time);
}
}.bind(this), 100);
}
})
// 判断a能否杀b
function is_sha(aid, bid) {
// 杀
var arr = [
[],
[2, 3, 4 , 6, 7, 8],
[4, 5 , 6, 7, 8],
[2, 4 , 6, 7, 8],
[5 , 6, 7, 8],
[1, 3 , 6, 7, 8],
[],
[],
[]
];
return arr[aid].indexOf(bid) != -1;
}
// 随机数
function randomNum(minNum, maxNum) {
return parseInt(Math.random()*(maxNum-minNum+1)+minNum,10)
}
// 写入错误提示
function setError(msg) {
document.querySelector('.error-fox').innerHTML = msg;
clearTimeout(window.err_js);
window.err_js = setTimeout(function() {
document.querySelector('.error-fox').innerHTML = 'vs';
}, 2000);
}
// 为game切换p
function toggleP() {
if(game.p == game.p1) {
game.p = game.p2;
} else {
game.p = game.p1;
}
}
</script>
</body>
</html>