| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 696 人关注过本帖
标题:自己写的模拟发牌程序 请批评指点
只看楼主 加入收藏
代号215
Rank: 2
等 级:论坛游民
帖 子:40
专家分:80
注 册:2012-11-22
结帖率:83.33%
收藏
已结贴  问题点数:20 回复次数:7 
自己写的模拟发牌程序 请批评指点
程序代码:

#include<iostream>
#include<ctime>
using std::cout;
using std::endl;
using std::ostream;



//模拟发牌
class Card
{
public:
    Card(int n);
    //发牌
    void draw_card();

private:
    //已发的牌数
    int drawn_num;
    //要发的牌数
    int card_num;
    //手中剩余的牌
    int card_left;
    //工具数组
     int array[4][13];
     //工具函数
     void card_rand();
    //花色
    static char* suit[4];
    //面值
    static char* face[13];
    //重新洗牌
    void draw_card_again();
};

char* Card::suit[4]={"Hearts","Diamonds","Clubs","Spades"};
char* Card::face[13]={"Ace","Deuce","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"};



Card::Card(int n):card_num(n),card_left(52),drawn_num(0)
{
    for(int i=0;i<4;i++)
        for(int j=0;j<13;j++)
            array[i][j]=0;
}

void Card::card_rand()
{
      int row=rand()%4;
      int col=rand()%13;

        //如果已经发出去了
       while(array[row][col])
       {
           row=rand()%4;
           col=rand()%13;
       }
        array[row][col]=1;
        cout<<face[col]<<" of "<<suit[row]<<endl;
}


void Card::draw_card()
{
    srand(time(NULL));

    int& i=drawn_num;
    for(;i<card_num;i++,--card_left)
    {
        if(!card_left)
        {
            //重新洗牌
            draw_card_again();
        }
        else
        { card_rand();}

    }
}

void Card::draw_card_again()
{
    cout<<"Reshuffling"<<endl;

    //全部清零
    card_left=52;
    for(int k=0;k<4;k++)
        for(int j=0;j<13;j++)
            array[k][j]=0;


    int& i=drawn_num;
    for(;i<card_num;i++,--card_left)
    {
        //发牌
        if(!card_left)
            draw_card_again();
        else
        {    card_rand();}
    }
}




[ 本帖最后由 代号215 于 2013-5-9 20:29 编辑 ]
搜索更多相关主题的帖子: 发牌 color 
2013-05-09 20:28
yuccn
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:何方
等 级:版主
威 望:167
帖 子:6815
专家分:42393
注 册:2010-12-16
收藏
得分:5 
不错

我行我乐
公众号:逻辑客栈
我的博客:
https://blog.yuccn. net
2013-05-09 20:50
代号215
Rank: 2
等 级:论坛游民
帖 子:40
专家分:80
注 册:2012-11-22
收藏
得分:0 
回复 2楼 yuccn
谢谢   能指点一下吗

好久没把牛皮吹的这么清新脱俗了
2013-05-09 22:51
ljh8888
Rank: 2
等 级:论坛游民
帖 子:54
专家分:15
注 册:2013-5-4
收藏
得分:5 
不错
2013-05-10 00:08
lintaoyn
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:4
帖 子:606
专家分:2499
注 册:2009-4-8
收藏
得分:0 
程序代码:
void Card::card_rand()
{
      int row=rand()%4;
      int col=rand()%13;

        //如果已经发出去了
       while(array[row][col]) 
       {
           row=rand()%4;
           col=rand()%13;
       }
        array[row][col]=1;
        cout<<face[col]<<" of "<<suit[row]<<endl;
}


如果运气不好,你的while循环就不知道得运行这多少次,毕竟最坏的情况下,你每次随机出来的,都有可能是已经发出去的卡片。

迭代的是人,递归的是神。
2013-05-10 08:41
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9025
专家分:54030
注 册:2011-1-18
收藏
得分:10 
要我说,你这代码除了语法没有错误外,其他一无是处

using std::cout;
using std::endl;
using std::ostream;
跟着别人照搬着用的吧?!而那些人中其实九成九也不知道C++为什么这么设计。

class Card 的设计,令人看不懂,因为掺杂了无关的东西。
随便问一下,那注释“工具数组”“工具函数”的意义何在?
还有一些枝叶小问题,随便说一下
a. suit、face 起码要加个const
b. Card(int n); 必须要加 explicit
c. 如果你用int,那就的考虑int为负的情况

Card::Card(int n) 中 4、13和class Card中的数组长度冗余
void Card::card_rand() 中代码冗余。
最严重的是,其中竟然有cout输出
而对于算法,你这算法属于数学上的算法,但不属于计算机算法。后者相比较前者有两个限制:资源消耗的限制 和 时间的限制

void Card::draw_card() 中不可以用srand。你可能没明白C/C++中为什么要有个srand函数,而不是只有rand函数。C/C++要求函数对于特定的输入必须要求特定的输出或可推导的输出。

void Card::draw_card_again() 中又是一堆和void Card::draw_card()中重复得的代码。

总结一下,类设计一团糟,算法不严格,代码很烂。
如果要我设计,也没什么好写的,因为需求本来就极简单
程序代码:
// struct RandCardb 的定义部分
struct RandCard
{
    RandCard();
    size_t cards[4*13];

    static const char* suit[4];
    static const char* face[13];
};

// struct RandCard 的实现部分
#include <algorithm>

const char* RandCard::suit[4]  = { "Hearts","Diamonds","Clubs","Spades" };
const char* RandCard::face[13] = { "Ace","Deuce","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King" };

RandCard::RandCard()
{
    for( size_t i=0; i<sizeof(cards)/sizeof(cards[0]); ++i )
        cards[i] = i;
    std::random_shuffle( cards+0, cards+sizeof(cards)/sizeof(cards[0]) );
}

// 测试部分
#include <ctime>
#include <iostream>
using namespace std;

int main()
{
    srand( (unsigned)time(NULL) );

    RandCard rc;
    for( size_t i=0; i<sizeof(rc.cards)/sizeof(rc.cards[0]); ++i )
    {
        size_t card = rc.cards[i];
        cout << RandCard::face[card%13] << " of " << RandCard::suit[card/13] << '\n';
    }

    rc = RandCard();
    size_t card = rc.cards[51];
    cout << RandCard::face[card%13] << " of " << RandCard::suit[card/13] << '\n';

    return 0;
}

2013-05-10 09:23
代号215
Rank: 2
等 级:论坛游民
帖 子:40
专家分:80
注 册:2012-11-22
收藏
得分:0 
回复 5楼 lintaoyn
确实是存在的  怎么改进呢

好久没把牛皮吹的这么清新脱俗了
2013-05-10 18:35
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9025
专家分:54030
注 册:2011-1-18
收藏
得分:0 
(不小心粘贴了一些别的内容,重新编辑)

下次有问题发在帖子中,别用消息
1.关于名字空间
类(普通函数也一样)分成定义和实现,调用者需要知道类的定义(无需知道类的实现)
当调用者引入(#include)类的定义时,不应该影响到其名字空间(这是没必要的,且有害的),所以在类的定义中不应该使用using来引入任何名字空间或名字空间中的成员。
而对于类的实现部分,因为处在不同的编译模块中,因此,你想怎么搞都可以。但对于一个不变态者而言,肯定是越简单越好,对不?
随便举个例子
// foo.hpp
#include <string>
std::string foo( int n );
// foo.cpp
#include "foo.hpp"
#include <others……>
using namespace std;
string foo( int n )
{
   ……;
}
有时候,也会在一些大师的代码中看到 using std::cout; 等用法。这有两种可能
a. 这些代码中只用了某名字空间中一两个成员,即 using std::cout; using std::endl; 并没有比 using namespace std; 多敲太多的键盘
b. 可能有数个名字空间,为了避免大面积的名字冲突,只引入自己需要的成员。

2.“为什么类中有cout输出你会觉得很惊讶”
关于模块化和正交分解,一个模块只有功能单一,才具有可复用性。就拿你的代码来举个反例
void Card::card_rand()
{
    ……
    cout<<face[col]<<" of "<<suit[row]<<endl;
}
你这个函数随机取了一张牌,并将牌面显示在屏幕上。
假如我现在需要将这张牌作为参数传递给另一个函数,你得重写代码;假如我现在需要将这张牌的牌面输出到某个文件中,你得重写代码;……

3. “size_t 是什么类型 为什么不定义int”
这个问题问得很奇怪,你用过 strlen 和 sizeof 等等没有?它们的返回类型/表达式类型就是size_t呀,你当时有没有问过它们为什么不定义为int?^_^
size_t 从名字上看就是用来表示size(尺寸)的类型,int对其而言,可能不足以达到size需要的范围,也可能超过其范围,总之,不能保证100%正确或移植性就是错误的。

4. “为什void Card::draw_card() 中不可以用srand”
C/C++要求函数是可重现的,即使对于rand随机函数也是如此,对于给定的随机种子,rand其后产生的随机序列是一致的。
而你的void Card::draw_card()呢?因为srand(time(NULL))的存在,根本无法预测其出输出什么。这违反了C/C++的原则。
即使你对代码的要求不是那么高,不要求遵循C/C++原则,srand(time(NULL))在这里也是多余的(实际上,因为加了这一句,反而不能算作随机算法了);
即使你对代码的要求不是那么高,可以容忍多余的代码,srand(time(NULL))放在这里在算法上也是个漏洞,若让你写博彩软件,黑客想要什么牌就要什么牌(题外话而已,具体的不解释了。记住随机函数的属性:srand保证其后的序列是伪随机的,但不保证每个随机种子所产生随机序列间也是伪随机的)。

5. “random_shuffle函数是std中的吗?#include <algorithm>这个头文件是干什么的”
这个你得看书,我没法几句话把这些内容复述出来

最后,我想提醒你的是,你忽略掉的5楼lintaoyn的所讲,是你算法中最大最严重的一个问题
因为懒得打字,我当时只简单说了句“
而对于算法,你这算法属于数学上的算法,但不属于计算机算法。后者相比较前者有两个限制:资源消耗的限制 和 时间的限制”。
你的这个算法不能保证在耗尽了全宇宙的能量和时间后,一定可以完成而跳出Card::card_rand,虽然有 99.9999999999999……% 的机会都可以在有限资源和有限时间内完成,但既然不是100%,那你这个算法就只属于数学算法,而非计算机算法。

[ 本帖最后由 rjsp 于 2013-5-11 10:21 编辑 ]
2013-05-11 10:20
快速回复:自己写的模拟发牌程序 请批评指点
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.025905 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved