js斗地主记牌器

前言

最近一段时间,闲暇之余玩了几把斗地主,可惜的是自己没钱买记牌器,脑子又记不住那么多牌,经常翻车,震怒!遂写记牌器,逆天改命!

界面

不用多说,肯定是模仿斗地主的记牌器最实用好看啦。

image.png

ps:这个是最终稿的截图,前几版还有一些按钮,为什么去掉了可以看后面。

交互

首先,怎么设计这个记牌器的交互才是关键,因为我们只能手动记牌,其他牌友出了什么牌,我们就从一副牌里减去出掉的牌。

  • 想法1:键盘输入,回车|按钮出牌

    • 如果是1-9,那肯定是很快的,但是JQK大小王这个输入起来太麻烦,如果换成其他键盘上连续的字母来代替JQK大小王那么又需要记忆的成本了,我tm记忆力好还要个🔨记牌器。🙅‍!

  • 想法2:点击选取,然后回车|按钮出牌

    • 这个其实是比较符合我们的斗地主的操作逻辑的,但是有一个问题如果我出的是飞机的话,就要点很多下,非常麻烦!不太行。

  • 想法3:点击+滑动直接出牌,去除回车或者按钮,右键撤回

    • 这个就是最终的交互逻辑了,如果对手只出了1张,那么我们只需要点击就行,如果出连队,飞机,那我们只需要滑几下而已。因为去除了出牌按钮,所以容易点错,这里加入了一个右键给某张牌撤回一张的功能。

实现

很容易就可以想出思路:

  1. 画出界面,13种牌(4张/种)+大小王(2张,这里并未区分大小王,因为一般我只是怕炸弹而已,大小王缺一张怕锤子,而且缺了一张以后,不管是大王还是小王都是最大的,有区别吗?)
  2. 添加左键点击事件,以及左键按下滑动事件。
  3. 阻止默认右键事件,添加右键点击事件。
  4. 做一些细节的处理,比如说4张牌红色警告,0张牌,牌面变灰色等等。

实现1:画界面

这里实在太简单,不想说了。你可以手动写十几个div,也可以用js动态添加。

实现2:左键点击和滑动处理

我们这里应该分成两布,第一步是选,第二步是出牌。所以我们可以用一个数组来保存我们已经选择的牌的序号。

  • 左键点击

    • 直接将这个牌的序号添加进数组
    • 然后出牌

  • 滑动

    • 两种做法,一种是通过坐标定位,判断鼠标移动前后距离包含了哪几个牌来决定哪些牌应该被选取。第二种就是给每个牌添加mouseenter,mouseleave事件,鼠标经过的时候,就会触发,就把出发的牌的序号添加进数组。
    • 然后出牌

实现3:右键增加牌数

这里唯一要注意的是下面这个,首先屏蔽默认的右键事件。

document.oncontextmenu = function (event) {

event.preventDefault();

if (event.button == 2) {

addCardCount(event.target)

}

};

然后对event.target进行处理就好了。

实现4:状态改变

你看之前我们的界面设计,当牌还有4个的时候是红色加粗的,说明可能有炸弹;当没有炸弹时是灰色的;当出完牌以后是带透明的淡灰色。

这里我们只需要根据这个牌数来更改状态就好了。关键是我们怎么改这个牌数会更方便呢?

你可能会使用innerHTML,innerText?

CSS中的伪元素中的beforeafter里面有个content属性,而这个属性是可以跟元素上的自定义属性绑定的。比如说

.card::after {

content: attr(count);

position: absolute;

bottom: 2px;

right: 5px;

color: #999;

font-size: 18px;

}

那么这个content的值就会跟随元素的count属性。所以我们出牌的操作其实只需要更改这个属性值就好了,然后根据值来做一些相应的类名添加和删除即可。

适用人群

  • 没钱买记牌器的
  • 记忆力差的
  • 开电脑玩的

后记

使用这个记牌器以后,胜率并没有高多少阿,淦!

我发现是运气不行,别人把把超级加倍打🔨啊,每天登陆就领几千豆,一把归西!

后续可能写个运气更改器

|

|

|

|

|

|

当然不可能啦。淦!

源码

源码中已经添加诸多备注。复制粘贴即可,后续可能会放到博客上提供下载链接,不用复制那么辛苦啦。

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>记牌器</title>

<style>

#box {

display: flex;

justify-content: center;

align-items: stretch;

user-select: none;

}

.card {

position: relative;

border-radius: 10px;

width: 60px;

margin-top: 20px;

height: 100px;

background-color: #f5f5f5;

margin-right: 10px;

box-shadow: 0 5px 5px 0 #c9c9c9;

font-size: 28px;

padding-left: 10px;

}

.card--empty {

color: #c3c3c3;

opacity: 0.8;

}

.card--chosen {

margin-top: 0;

}

.card::after {

content: attr(count);

position: absolute;

bottom: 2px;

right: 5px;

color: #999;

font-size: 18px;

}

.card--warning::after {

color: red;

font-weight: bold;

}

#btn-box {

text-align: center;

margin-top: 30px;

}

button {

padding: 10px 30px;

border-radius: 60px;

background-color: orangered;

color: #fff;

font-size: 32px;

border: 0;

cursor: pointer;

transition: all ease .3s;

margin-right: 20px;

outline: none;

}

button:hover {

background-color: red;

transform: scale(1.1);

}

.info {

font-size: 14px;

margin-top: 70px;

color: #999;

}

</style>

</head>

<body>

<div id="box"></div>

<div class="info">

<p>作者: <a href="http://www.leelei.info">leelei</a></p>

<p>用法: 鼠标【点击】直接出牌,或者【点击滑动】出牌,右键单击某张牌可以增加牌数(用于防止点错)</p>

<p>适用于: 斗地主新手,并且没有钱买记牌器,并且经常开着电脑的时候顺便手机玩斗地主</p>

</div>

</body>

<script>

//常量

const arr = [3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A', 2, '👻'];

const nums = [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2];

const TYPE_CHOSEN = ' card--chosen';

const TYPE_WARNING = ' card--warning';

const TYPE_EMPTY = ' card--empty';

//储存已经选择

let chosenArr = [];

//添加类名

function addClass(e, name) {

if (e.className.indexOf(name) == -1) {

e.className += name;

}

}

//移除类名

function removeClass(e, name) {

e.className = e.className.replace(name, '')

}

//初始化卡片

function initCards() {

let box = document.getElementById('box');

let frag = document.createDocumentFragment();

for (let i = 0; i < 14; i++) {

let ele = document.createElement('div');

ele.className = 'card' + TYPE_WARNING;

ele.innerText = arr[i];

ele.setAttribute('count', nums[i]);

ele.setAttribute('index', i);

frag.append(ele)

}

box.append(frag);

}

//初始化输入

function initSlideInput() {

let cards = document.getElementsByClassName('card');

//鼠标按下时注册

box.addEventListener('mousedown', installSlideInput)

//鼠标抬起卸载

box.addEventListener('mouseup', uninstallSlideInput)

box.addEventListener('mouseleave', uninstallSlideInput)

//注册滑动输入

function installSlideInput() {

Array.from(cards).forEach((e) => {

e.addEventListener('mouseenter', slideSelect)

e.addEventListener('mouseleave', slideSelect)

})

}

//卸载滑动输入

function uninstallSlideInput() {

Array.from(cards).forEach((e) => {

e.removeEventListener('mouseenter', slideSelect)

e.removeEventListener('mouseleave', slideSelect)

})

submit();

}

//点击输入,一直有效

Array.from(cards).forEach((e) => {

e.addEventListener('click', function (event) {

slideSelect(event);

submit();

})

})

//滑动输入

function slideSelect(event) {

let idx = event.currentTarget.getAttribute('index');

if (event.currentTarget.className.indexOf(TYPE_CHOSEN) == -1) {

addClass(event.currentTarget,TYPE_CHOSEN)

chosenArr.push(idx);

}

}

}

//重置全部牌的状态,凸起->对齐

function reset() {

chosenArr = [];

let cards = document.getElementsByClassName('card');

Array.from(cards).forEach((v, i) => {

removeClass(v,TYPE_CHOSEN)

});

}

//出牌

function submit() {

let cards = document.getElementsByClassName('card');

chosenArr.forEach((v, i) => {

cards[v].setAttribute('count', cards[v].getAttribute('count') - 1);

removeClass(cards[v],TYPE_WARNING);

if (cards[v].getAttribute('count') < 1) {

//最小为0,设置为空状态

cards[v].setAttribute('count', 0);

addClass(cards[v],TYPE_EMPTY)

}

});

//重置状态

reset();

}

//右键加牌,防止出错牌

function addCardCount(e) {

if (e.getAttribute('count') != undefined) {

e.setAttribute('count', e.getAttribute('count') - 0 + 1);

}

if (e.getAttribute('count') >= nums[e.getAttribute('index')]) {

e.setAttribute('count', nums[e.getAttribute('index')]);

addClass(e,TYPE_WARNING)

} else if (e.getAttribute('count') > 0) {

removeClass(e,TYPE_EMPTY);

}

}

window.onload = function () {

document.oncontextmenu = function (event) {

event.preventDefault();

if (event.button == 2) {

addCardCount(event.target)

}

};

initCards();

initSlideInput();

}

</script>

</html>

以上是 js斗地主记牌器 的全部内容, 来源链接: utcz.com/a/18141.html

回到顶部