斗地主

1、完成一个控制台程序

知识点:

srand(time(NULL)):这是两个函数,一个是srand函数,这是在调用rand()这个函数之前使用的,rand()是一个产生随机数的函数,而srand是一个设置随机数种子的函数,通常这两个函数是一起使用的,来完成产生随机数的功能。

而time(NULL)这个函数的返回值是作为srand函数的参数的,意思是以现在的系统时间作为随机数的种子来产生随机数,至于NULL这个参数,因为这个话就返回到现在时间时候的long秒,只有设置成NULL才能获得系统的时间。

斗地主发牌规则:

一副牌有54张,大小王各一张,牌分为黑桃、梅花、红桃、方块四种,1~10各4张共40张,JQK各四张共12张。

一共54张扑克牌,玩家抽完牌后剩余3张底牌。题目要求将54张牌发给三个玩家,并给每个玩家手中的扑克牌进行排序。

扑克牌大小顺序(从左往右依次递增):"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2",“小王”,“大王”。

每个人17张牌,共51张,加3张底牌 54张。

 

定义数组存储牌的花色

string hs[4]={"黑桃","桃心","梅花","方块"};

double hsnumer[4] = { 0.4,0.3,0.2,0.1};//对应hs里面每个牌面的数值大小

定义数组来存储数字

string number[13]={"3","4","5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};

定义数组来给number里面的牌面赋予数值大小

int numer[13]={3,4,5,6,7,8,9,10,11,12,13,14,15};

定义数组来存储组后后的牌

string numbr[54];

一、制作扑克牌

采用for循环,来进行组合将花色与牌的面值用字符串进行结合,再用数值对其进行赋值,为后面的排序做铺垫。

//制作扑克牌

 void CPoker::Combination()

{

int k = 0;//记录牌面数值的数组序号

int num = 0;//记录制作的第几张牌

for (int i = 0; i < 13; i++) {

for (int j = 0; j < 4; j++) {

string temp = hs[j] + m_number[i];    //将花色和数字组合

num++;

m_numbr[k] = temp;   //牌面

m_sum[k] = m_numer[i]+ m_hsnumer[j];   //牌面数值

k++;

}

}

//添加 大王、小王

string tmp1 = "大王";

m_numbr[k] = tmp1;  //存储牌面

m_sum[k] = 17;  //添加牌面数值大小

num++;

k++;

string tmp2 = "小王";

m_numbr[k] = tmp2;

m_sum[k] = 16;

num++;

}

}

  • 三名玩家和底牌

采用随机函数来产生随机数,交换牌的位置,从而打乱牌

//随机打乱扑克牌数组顺序

void CPoker::RandomPoker()

{

int index=0;//随机数

double  p;

string tmp;  //用于置换数组的

srand(time(NULL));//产生随机数前的函数

int n = sizeof(m_numbr) / sizeof(m_numbr[0]);//存储牌所占数组空间的大小

for (int i = 0; i < n; i++) {

index = rand() % (n - i) + i;//产生0~53的随机数

if (index != i) {

//交换扑克在数组中的位置

tmp = m_numbr[i];

m_numbr[i] = m_numbr[index];

m_numbr[index] = tmp;

//交换牌的数值顺序

p = m_sum[i];

m_sum[i] = m_sum[index];

m_sum[index] = p;

}

}

}

三、发牌

一共三个玩家,按每个玩家每人每次摸1张牌的顺序发牌,最后每人手里都有17张牌。最后剩余3张底牌。发牌时除了把面值赋予,还要把数值赋予。

//发牌

void CPoker::SendPoker()

{

int i = 0, x = 0, y = 0, z = 0;

for (int l = 0; l < 54; l++) {

if (l >= 51) {   //最后剩余3张底牌

bottomPoker[i] = m_numbr[l];

sumBottom[i] = m_sum[l];

i++;

}

else {  //i对3取模,对应3个玩家抽牌

if (l % 3 == 0) {

player1[x] = m_numbr[l];

sum1[x] = m_sum[l];

x++;

}

else if (l % 3 == 1) {

player2[y] = m_numbr[l];

sum2[y] = m_sum[l];

y++;

}

else if (l % 3 == 2) {

player3[z] = m_numbr[l];

sum3[z] = m_sum[l];

z++;

}

}

}

}

}四、输出三位玩家的牌和底牌

给发到的牌进行排序,三个人的牌需要由牌的大小由大到小排序;.主要利用指针来保存各数组的首地址,然后通过函数的调用来减少代码的复用性。也有使用this指针来指定调用类内函数的对象。

  1. 给牌进行排序

void CPoker::Sort(string *p, double *s, int len)

{

for (int i = 0; i < len; i++) {

for (int j = i + 1; j < len; j++) {

if (s[i] < s[j]) {

//交换牌面数值

double temp = s[i];

s[i] = s[j];

s[j] = temp;

//交换牌面字符

string str = p[i];

p[i] = p[j];

p[j] = str;

}

}

}

}

  1. 输出牌

void CPoker::Print(string *p,  double *s,int len)

{

for (int i = 0; i < len; i++)

{

cout << p[i] << " ";

}

cout << endl;

}

  1. 输出三位玩家的牌

void CPoker::SortAndPrintPoker()

{

//一号玩家的牌的排序

this->Sort(player1, sum1, 17);

//二号玩家的牌的排序

this->Sort(player2, sum2, 17);

//三号玩家的牌的排序

    this->Sort(player3, sum3, 17);

//四号玩家的牌的排序

    this->Sort(bottomPoker, sumBottom, 3);

//输出牌

cout << "号玩家的牌为:" << endl;

this->Print(player1,  sum1,17);

cout << "号玩家的牌为:" << endl;

this->Print(player2,  sum2,17);

cout << "三号玩家的牌为:" << endl;

this->Print(player3,  sum3,17);

cout << "底牌为:" << endl;

this->Print(bottomPoker, sumBottom,3);

}

主函数的测试代码:

#include <iostream>

using namespace std;

#include<string>

#include "CPoker.h"

int main()

{

CPoker p;

//制作扑克牌

    p.Combination();

//将制作好的扑克牌打乱

p.RandomPoker();

//发牌给玩家

p.SendPoker();

//将每位玩家的牌以及底牌进行排序,并打印

p.SortAndPrintPoker();

  system("pause");

  return 0;

}

心得:这次是我对此次作业的第三次改良,第一次是将代码全部放在了同一个文件夹里,感觉有点乱,所以在第一次改良后将代码分别放在了.h和.cpp文件中。后来有发现对于变量的定义太多都在主函数里面,按照目前所学的知识,对于宏的使用不是很懂,所以就没有使用宏常量来定义string数组,而是把变量都定义在了类里面。实现了第二次改良,代码相对又增加了很多,就是在输出牌的时候,不是很方便,后来查看了相关资料,以及在vs中测试类内属性在类内函数的使用以及类内函数之间的调用。知道如何去使用,从而大大减少了代码的复用性,这就是第三次改良。可能还有很多不足,希望可以在以后学的知识中再优化这个项目。

如果有小可爱需要完整代码,可以私信我哦~