[教你做小游戏] 展示斗地主扑克牌,支持按出牌规则排序!支持按大小排序!

我是HullQin,公众号线下聚会游戏的作者(欢迎关注公众号,发送加微信,交个朋友),转发本文前需获得作者HullQin授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费没广告。还开发了《Dice Crush》参加Game Jam 2022。喜欢可以关注我 HullQin 噢~我有空了会分享做游戏的相关技术。

问题描述

我们想做一个斗地主游戏,其中最重要的一点是,把扑克牌展示出来。

一副牌有54张,我们给每张牌1个编号(id),取值1-54。如果涉及到2副牌,就取id为1-108。

展示牌,其实就是给你一个id列表,按需展示列表中的牌即可。

而展示牌有3种排序方式:

  1. 不排序,列表是什么,就展示什么。(发牌、底牌常用)
  2. 按照大小排序。(手牌常用)
  3. 按照出牌规则排序。(出牌常用,规则比如顺子、连对、飞机、四带二、炸弹等)

今天,我们就来实现它们!

第1步,展示1张牌

准备素材

牌有54种,加上牌背面,有55种图案。我们先准备好素材:

1.png

如果要展示1张牌,以它为背景,使用background-positionwidthheight对整个大图片裁剪即可。

不要拆开这个大图,让用户一次性下载55张图片,那样速度会肉眼可见的慢。因为大多数浏览器不能并发55个请求下载图片,它可能一次最多建立8个TCP连接来下载,你可能需要8次RTT才能下载完。(55除以8向上取整=8)

所以,做Web开发,一定要尽量拼接多个小素材成为一个大图片,再去裁剪它展示素材。

写好css做裁剪

我们利用class,定义一个.poker写所有扑克牌共用的样式,再给每个扑克牌定义一个background-position(裁剪位置)即可。

.poker {
   
  position: absolute;
  background-image: url('./card.png');
  background-clip: content-box;
  background-repeat: no-repeat;
  width: 116px;
  height: 159px;
  transform-origin: 0 0 0;
  transition: left .2s ease-out, top .2s ease-out;
}

例如,这是id为1的扑克牌的样式。每个扑克牌单独的样式很简单,只有1行,定义background-position即可。因为其它样式都是一模一样的,用.poker复用即可。

.poker-1 {
   
  background-position: -238px -646px;
}

不再罗列了,可以参考style.css源码: github.com/HullQin/poker_fe

定义 扑克牌ID->图片ID 的映射

开头我们提到,可能有2幅牌,而他们的图片样式应该是一样的。所以需要通过取余数,把108个ID映射到54个值。

const mapPokerIdToCardId = (id) => {
   
  // 映射扑克id(可能有多幅牌)至卡片id(只有0-54)
  return (id - 1) % 54 + 1;
};

代码中,我用id = 0表示扑克牌的背面。

封装一个组件

你可以封装为React组件或Vue组件,或其它你采用框架支持的组件。

我代码使用了React,所以封装为React组件。

import cn from 'classnames';

const Poker = (props) => {
   
  const {
    id, className, ...otherProps } = props;
  if (typeof id !== 'number') return;
  const cardId = mapPokerIdToCardId(id);
  return (
    <div
      className={
   cn('
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是用C语言编写的一个简单的单机斗地主游戏按规则出牌的源代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define NUM_CARDS 54 #define NUM_PLAYERS 3 // 定义扑克牌结构体 typedef struct { int value; // 牌面值,1-13表示A-K,14表示小王,15表示大王 char suit; // 花色,'S'表示黑桃,'H'表示红心,'C'表示梅花,'D'表示方块,'J'表示王牌 } Card; // 洗牌函数 void shuffle(Card* deck) { srand(time(NULL)); for (int i = 0; i < NUM_CARDS; i++) { int j = rand() % NUM_CARDS; Card temp = deck[i]; deck[i] = deck[j]; deck[j] = temp; } } // 初始化牌组 void initDeck(Card* deck) { char suits[4] = {'S', 'H', 'C', 'D'}; int values[13] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; for (int i = 0; i < NUM_CARDS; i++) { if (i < 52) { deck[i].value = values[i % 13]; deck[i].suit = suits[i / 13]; } else if (i == 52) { deck[i].value = 14; deck[i].suit = 'J'; } else if (i == 53) { deck[i].value = 15; deck[i].suit = 'J'; } } } // 发牌函数 void dealCards(Card* deck, Card* players[]) { int currentCard = 0; for (int i = 0; i < NUM_PLAYERS; i++) { players[i] = (Card*)malloc(17 * sizeof(Card)); // 每个玩家17张牌 for (int j = 0; j < 17; j++) { players[i][j] = deck[currentCard++]; } } } // 按规则出牌函数 void playCards(Card* cards, int numCards) { printf("出牌: "); for (int i = 0; i < numCards; i++) { printf("%c%d ", cards[i].suit, cards[i].value); } printf("\n"); } int main() { Card deck[NUM_CARDS]; Card* players[NUM_PLAYERS]; initDeck(deck); shuffle(deck); dealCards(deck, players); // 玩家1按规则出牌 playCards(players[0], 3); // 释放内存 for (int i = 0; i < NUM_PLAYERS; i++) { free(players[i]); } return 0; } ``` 这个示例代码实现了一个简单的单机斗地主游戏,包括洗牌、发牌和按规则出牌的功能。其中,`shuffle`函数用于洗牌,`initDeck`函数用于初始化牌组,`dealCards`函数用于发牌,`playCards`函数用于按规则出牌。 请注意,这只是一个简单的示例代码,可能不包含所有的规则和功能,你可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hull Qin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值