综合案例:斗地主
1.程序概述
这是一个模拟斗地主游戏发牌过程的C语言程序,实现了扑克牌的初始化、洗牌和发牌功能。
2.功能需求
2.1 扑克牌定义
- 使用结构体
Card
表示一张牌,包含:- 花色属性
suit
(0-3表示普通花色♥♠♦♣,4表示小王,5表示大王) - 点数属性
rank
(0-12对应3-A,2,-1表示大小王)
- 花色属性
2.2 主要功能
- 初始化牌组:
- 创建包含54张牌的牌组(52张普通牌+2张王牌)
- 普通牌按花色(♠,♥,♣,♦)和点数(3-2)排列
-
洗牌功能 :
- 使用随机数对牌组进行随机排序
- 确保每次运行洗牌结果不同(基于时间种子)
-
发牌功能 :
- 将洗好的牌发给3个玩家
- 每个玩家17张牌
- 剩余3张作为底牌
-
显示功能 :
- 打印每个玩家的手牌 打印底牌
- 打印底牌
3.数据结构
suits[]
: 存储4种花色符号的字符串数组ranks[]
: 存储13个点数等级的字符串数组jokers[]
: 存储大小王描述的字符串数组Card
结构体: 表示单张牌的数据结构- 牌组数组:
deck[54]
- 玩家手牌数组:
player1[17]
,player2[17]
,player3[17]
- 底牌数组:
bottomCards[3]
4.用户交互
程序运行后自动完成以下流程:
- 初始化牌组
- 洗牌
- 发牌
- 显示发牌结果(3个玩家的手牌和底牌)
5.输出格式
- 普通牌显示格式:花色+点数(如"♠ 3")
- 王牌显示格式:“小王"或"大王”
- 玩家手牌按顺序显示,每张牌用空格分隔
- 底牌同样格式显示
6.代码演示
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
// 定义扑克牌的花色和点数
const char *suits[] = {"♠","♥","♣","♦"}; // 花色
const char *ranks[] = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"}; // 点数
const char *joker[] = {"小王","大王"}; // 大小王
// 定义牌的结构体
typedef struct
{
int suit; // 花色(0-3:普通牌,4:小王,5:大王)
int rank; // 点数(0-12:普通牌,-1:大小王)
}Card;
// 声明函数原型
void initDeck(Card *deck);
void shuffeDeck(Card *deck, int len);
void dealCards(Card *deck, Card *player1, Card *player2, Card *player3, Card *bottomCards);
void printCard(Card card);
int main(int argc,char *argv[])
{
Card deck[54]; // 一副牌(54张,包含大小王)
Card player1[17], player2[17], player3[17]; // 三个玩家的手牌
Card bottomCards[3]; // 底牌
// 初始化牌
initDeck(deck);
// 洗牌
shuffeDeck(deck, 54);
// 发牌
dealCards(deck, player1, player2, player3, bottomCards);
// 打印玩家手牌和底牌
int i;
printf("玩家1的手牌:");
for(i = 0; i < 17; i++) printCard(player1[i]);
printf("\n");
printf("玩家2的手牌:");
for(i = 0; i < 17; i++) printCard(player2[i]);
printf("\n");
printf("玩家3的手牌:");
for(i = 0; i < 17; i++) printCard(player3[i]);
printf("\n");
printf("底牌:");
for(i = 0; i < 3; i++) printCard(bottomCards[i]);
printf("\n");
return 0;
}
/**
* 初始化一副牌(54张,包含大小王)
*/
void initDeck(Card *deck)
{
// 定义一个索引
int index = 0;
// 初始化普通牌
for(int suit = 0; suit < 4; suit++) // 遍历花色
{
for(int rank = 0; rank < 13; rank++) // 遍历点数
{
deck[index].suit = suit; // 每一张牌的花色(索引)
deck[index].rank = rank; // 每一张牌的点数(索引)
index++;
}
}
// 初始化大小王
deck[index].suit = 4; // 小王
deck[index].rank = -1;
index++;
deck[index].suit = 5; // 大王
deck[index].rank = -1;
}
/**
* 洗牌(打乱牌序)
*/
void shuffeDeck(Card *deck, int len)
{
// 设置随机种子
srand(time(NULL));
// 洗牌
for(int i = 0; i < len; i++)
{
int j = rand() % len; // 索引 0 ~ 53
// 将随机出来的牌序和原本的排序交换
Card temp = deck[i];
deck[i] = deck[j];
deck[j] = temp;
}
}
/**
* 发牌(3个玩家各自17张牌,最后3张牌作为底牌)
*/
void dealCards(Card *deck, Card *player1, Card *player2, Card *player3, Card *bottomCards)
{
int index = 0;
// 给玩家发牌
for(int i = 0; i < 17; i++)
{
player1[i] = deck[index++]; // 玩家1 等价于 deck[index]; index++;
player2[i] = deck[index++]; // 玩家2
player3[i] = deck[index++]; // 玩家3
}
// 最后3张留作底牌
for(int i = 0; i < 3; i++)
{
bottomCards[i] = deck[index++];
}
}
/**
* 打印牌(根据牌的索引,显示对应的字符串)
*/
void printCard(Card card)
{
if(card.suit == 4 || card.suit == 5)
{
// 大小王
printf("%s ", joker[card.suit - 4]);
}
else
{
// 普通牌
printf("%s %s ", suits[card.suit], ranks[card.rank]);
}
}
运行效果: