真郁闷 面试的时候被21点游戏的题目给淘汰了

traso 2008-07-25 01:37:09
郁闷啊,概率真的有那么重要么?
初试,复试都通过了.3试没过.

我跟踪过随机函数,
发现里面不过是个加密算法,根据种子来制定的.
那么计算它的概率到底有多大意义.
真搞不清楚.
我当初认为做数值嘛,就是设计公式,把几个需要出现的时间段的数值用个公式链接起来就可以了.

当时被面试要求设计21点游戏,尽量多赢玩家.

游戏规则:

游戏开始先由系统指定庄家并开始发牌,闲家分别与庄家对抗。发牌后,闲家先要牌力争使自己接近21点且不“爆牌”,即“不超过21点”,闲家选择完毕后,轮到庄家按照规则要牌,庄家结束选择后按照双方的牌点是否接近21点判断输赢。

2-9:牌面数值与分值相同。
10、J、Q、K:均为10分值
A:可为1或者11分值,当计算11分值时会爆牌,则自动记为1分值。

庄家与玩家同点或同爆时庄家胜利.

21点VS爆点时 赔率加倍.


*****************************************************************************

游戏流程设定:

玩家胜利计数器playerwin=0;//判断是否使用作弊AI
电脑胜利计数器ownerwin=0;
牌组初始化:把52张扑克牌赋值到数组b[52]上.
计数器a=0;
AI计数器a4=16 a5=36; a5为牌卡大于4的牌卡数量、a4为牌卡小于5的牌卡数量.
0,初始化庄家数组owner[5],初始化玩家数组player[5].

1,给庄家1张牌(暗)发牌函数(*owner).if(b[a]>4)a5--;else a4--; //AI计数判断,每次发牌加入AI计数判断下同如2所示
计数器a++

2,给玩家1张牌.发牌函数(*player) if(b[a]>4)a5--;else a4--; //AI计数判断
计数器a++

3,玩家下注.(玩家输入交互)

4.给庄家1张牌 发牌函数(*owner) 计数器a++

5,给玩家1张牌 发牌函数(*player) 计数器a++

6,玩家决定:a:要牌(if(点数计算(*player)>21)玩家判负 goto 9;else 给玩家发牌 goto 6)计数器a++;b:gotu 7
//点数判断函数(*char) 略.
//发牌函数()略
7, 庄家决定:a:要牌(if(playerwin>ownerwin) 作弊AI();else 判断AI() ) //玩家赢的比我多我就赖皮 ^_ ^
(if(点数计算(*owner)>21)gotu 8;else 给玩家发牌 goto 7)计数器a++;b:goto 8


8,比较玩家与庄家的点数决定胜负.if((点数计算(*player)>点数计算(*owner))ownerwin++;
else playerwin++;

9,牌余判断 if(计数器a>=42) gotu 牌组初始化; else goto 0 //2人玩此游戏所以是a>=42;3人玩次游戏则是37

********************************************************************************

庄家AI:


bool 判断AI()//判断是否要牌
{
判断临界点a=17;
owner=点数计算(*owner);

player=点数计算(*(player+1))+10;//电脑AI算牌 玩家桌面点数计算

if(player[1]='a')player-10; // 当玩家第2张抽到A时的情况

if(owner>=player)) return 不要牌;
//牌面上点数绝对大于玩家时,不要牌.
if(a5/a4>1)判断临界点a--; //算牌AI修正临界点值
else if(a5/a4<1)判断临界点a++;
else;

if(owner>=判断临界点a)return 不要牌;

return 要牌;

}

bool 作弊AI() //判断是否要牌
{
owner=点数计算(*owner);
player=点数计算(*player);
if(owner>=player) return 不要牌;

发牌函数(*owner);a--;//假装发牌,之后C--计数器a还原
if(点数计算(*owner)>21) return 不要牌

return 要牌;
}

3试:
当时把这个给他们,结果他们问我为什么临界点时17点.要从数学的角度来分析.
为什么能保证17点的胜率高过玩家.
说实话我也想不通16点啊,暴率蛮高的按每抽过牌的时候也有8/13 (我靠 还刚刚好是黄金分割点).

当时是参考大航海时代2里面酒吧小游戏的21点设计的,几次测试发现是17点.
但是没有那个比较牌面值的AI. 我加上了比较.

后来分析出由于10点牌数最多,所以影响胜率最大的应该是第1张牌拿到10.

...全文
1204 72 打赏 收藏 转发到动态 举报
写回复
用AI写文章
72 条回复
切换为时间正序
请发表友善的回复…
发表回复
traso 2011-06-27
  • 打赏
  • 举报
回复
多年以后回来一看,这帖子确实有些怀念了.
现在已经是一个2年经验的游戏策划了.
wpyadsh 2009-05-28
  • 打赏
  • 举报
回复
我主要是不会呀...老师要求是用C语言写的.我也没办法哦
能帮我写下吗?
wpyadsh 2009-05-27
  • 打赏
  • 举报
回复
我也要写这个21点游戏,谁帮帮我呀???????要用C语言写,不是用C++写的
有会的吗?
ex_dijkstra 2009-05-27
  • 打赏
  • 举报
回复
[Quote=引用 70 楼 wpyadsh 的回复:]
我也要写这个21点游戏,谁帮帮我呀???????要用C语言写,不是用C++写的
有会的吗?
[/Quote]


...c和c++不是都差不多嘛,要是你觉得改不好就。。。就可以死了,请原谅我嘴毒一点

wslfjnu 2008-08-08
  • 打赏
  • 举报
回复
记号
xianyuxiaoqiang 2008-08-07
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 weiai_chongsheng 的回复:]
这个问题我也遇到过,我现在加了一个群,这个群人气较好,也的确有高手,不但可以交流问题,而且还可以接项目赚钱,QQ群号是:壹-柒-叁-零-叁-陆-玖-陆,不要说我做广告,看看便知,如需要的话加入试试,如果你发现好的交流群也别忘了告诉我啊!呵呵!
[/Quote]
这个群每个人说的话都一模一样。搞欺诈????
n_yHHy_n 2008-07-31
  • 打赏
  • 举报
回复
ding
wangdeqie 2008-07-31
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 mygod343434 的回复:]
同情你,这个问题好难
[/Quote]
roadblossom 2008-07-31
  • 打赏
  • 举报
回复
学习一下,我对算法也不行啊
fireguyww 2008-07-31
  • 打赏
  • 举报
回复
这个。。2个月不用学 MFC这些吗????
flygreen628 2008-07-31
  • 打赏
  • 举报
回复
学习一下
coolylau 2008-07-31
  • 打赏
  • 举报
回复
http://www.douban.com/group/topic/3453073/
你如果无所为, 不要牌了, 等庄家爆死, 你自动赢, 几率是23%, 而你要牌不会爆, 即你要牌会赢的几率为46.2%, 结论你还是应该要牌。
jzbem 2008-07-31
  • 打赏
  • 举报
回复
面试的时间不会很长吧?
要做这个。。。。。。
SeanHwang 2008-07-31
  • 打赏
  • 举报
回复
要俺也不会~纯粹帮顶`
traso 2008-07-31
  • 打赏
  • 举报
回复
wuroy27496
的代码编译后一大堆错误哦.
哎,这次程序我的数据初始化,牌卡编码,牌卡的值得判断,都写好了。
目前就缺游戏流程了.
太乙 2008-07-29
  • 打赏
  • 举报
回复
mark一下!
meihuiyu 2008-07-29
  • 打赏
  • 举报
回复
up
wangdeqie 2008-07-29
  • 打赏
  • 举报
回复
jf
wuroy27496 2008-07-28
  • 打赏
  • 举报
回复
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

class CCard
{
private:
int naPip[5]; //定义一个数组,一共是5张牌。
int nNumber; //发了多少张牌。
int nDollar; //有多少钱
int nGamble; //赌注
int nWin; //赢局数
int nLose; //输局数
int nDraw; //输局数
public:
CCard(); //构造函数
void FirstPlayTwo();//最初两张牌
int GetNumber();//返回牌张数
int GetPip(); //返回点数
void DisplayPip();//一次全部显示牌面点数。
void DisplayPip(int ); //除了第一张牌,一次全部显示牌面点数(针对计算机牌的显示)
void TurnPlay();//出了一张牌
void Win();//赢了计算赌注
void Lose();//输了
void Draw();//平局
int setGamble(int );//设置赌注,赌本不够返回1
int getMoney();//返回钱数
void DisplayInfo();//打印必要的信息
int GetCurrentCard();//返回当前牌点。
};
CCard::CCard()
{
nNumber=0;//开始没有发牌
nDollar=100;//初始赌本为0
for(int i=0;i<5;i++)
naPip[i]=0; //五张牌全部为0
nGamble=0;
nWin=nLose=nDraw=0; //没输没赢没有平局
}

int CCard::getMoney()
{return nDollar;}

void CCard::DisplayInfo()//打印相关信息。
{
cout<<"您一共玩了"<<nWin+nLose+nDraw<<"局"<<endl;
cout<<"其中输了"<<nWin<<"局"<<endl;
cout<<"赢了"<<nLose<<"局"<<endl;
cout<<"平了"<<nDraw<<"局"<<endl;
cout<<"您还有赌本"<<nDollar<<endl;
}
int CCard::setGamble(int gamble)
{
if(nDollar-gamble<0)
return -1;
if(gamble<0)
{
if(nDollar-20<0)
return -1;
nGamble=20;
}
else
nGamble=gamble;
nDollar-=nGamble;
return 0;

}
void CCard::FirstPlayTwo()
{
naPip[0]=rand()%13+1;
naPip[1]=rand()%13+1;
nNumber=2; //现在有两张牌
}
int CCard::GetCurrentCard()
{return naPip[nNumber-1];}

int CCard::GetNumber() //返回牌数
{return nNumber;}
int CCard::GetPip() //返回点数
{
int nPip=0;
for(int i=0;i<nNumber;i++)
{if(naPip[i]>=10)
nPip=nPip+10;
else
nPip+=naPip[i];}
return nPip;
}
void CCard::DisplayPip() //依次显示牌面点数
{
for(int i=0;i<nNumber;i++)
cout<<naPip[i]<<"\t";
cout<<endl;
}

void CCard::TurnPlay() //出一张牌面
{
nNumber++;
naPip[nNumber-1]=rand()%13+1;
}
void CCard::Win()
{
cout<<"赢家牌面";
DisplayPip();
cout<<"牌面点数"<<GetPip()<<endl;
nDollar=nDollar+2*nGamble;
nWin++;
cout<<"赌本:$"<<nDollar<<" 赢了"<<nWin<<"次 "<<"输了"
<<nLose<<"次 "<<"平局"<<nDraw<<"次 "<<endl;
cout<<endl<<endl<<endl;
}

void CCard::Lose()
{
nLose++;
cout<<"输家牌面:";
DisplayPip();
if(GetPip()>21)
cout<<"暴了!"<<endl;
else
cout<<"牌面点数:"<<GetPip()<<endl;
cout<<"赌本:$"<<nDollar<<" 赢了"<<nWin<<"次 "<<"输了"
<<nLose<<"次 "<<"平局"<<nDraw<<"次 "<<endl;
cout<<endl<<endl<<endl;
}
void CCard::Draw()
{
nDraw++;
nDollar+=nGamble;
cout<<"平局牌面"<<endl;
DisplayPip();
if(GetPip()>21)
cout<<"暴了!"<<endl;
else
cout<<"牌面点数:"<<GetPip()<<endl;
cout<<"赌本:$"<<nDollar<<" 赢了"<<nWin<<"次 "<<"输了"
<<nLose<<"次 "<<"平局"<<nDraw<<"次 "<<endl;
cout<<endl<<endl<<endl;
}
void CCard::DisplayPip(int n)
{
cout<<"
  • "<<"\t";
    cout<<"
  • "<<"\t";
    for
  • (int i=2;i<nNumber;i++)
    cout<<naPip[i]<<"\t";
    cout<<endl;
    }


    //非成员函数区域
    void DisplayRule()
    {
    cout<<"\t欢迎进入21点游戏世界!\n\n"<<endl;
    cout<<"\t游戏规则\n";
    cout<<"\t玩家最多可以要五张牌\n";
    cout<<"\t如果牌的总点数超过21点则自动判输\n";
    cout<<"\t赢家可得双倍赌注\n";
    cout<<"\t计算机在大于等于16点时不要牌\n";
    cout<<"\t祝您好运!\n";
    cout<<endl<<endl;
    }
    void Judge(CCard &cpu,CCard &player)
    {
    cout<<endl;
    if((cpu.GetPip()>21&&player.GetPip()>21)||cpu.GetPip()==player.GetPip())
    {
    cout<<"\n\n平局\n!";
    cout<<"计算机数据:\t";
    cpu.DisplayPip();
    cout<<"牌面点数:"<<cpu.GetPip()<<endl;
    cout<<"\n您的数据\t";
    player.Draw();
    cout<<endl;
    }
    else if((cpu.GetPip()>21||(player.GetPip())>cpu.GetPip()&&player.GetPip()<=21))
    {
    cout<<"\n\n恭喜您,您赢了\n!";
    cout<<"计算机数据:\t";
    cpu.DisplayPip();
    cout<<"牌面点数:"<<cpu.GetPip()<<endl;
    cout<<"\n您的数据\t";
    player.Win();
    cout<<endl;
    }
    else
    {
    cout<<"\n\n很遗憾,您输了\n!";
    cout<<"计算机数据:\t";
    cpu.DisplayPip();
    cout<<"牌面点数:"<<cpu.GetPip()<<endl;
    cout<<"\n您的数据\t";
    player.Lose();
    cout<<endl;
    }
    }

    void playTurn(CCard &cpu,CCard &player)
    {
    char chChoice;
    int blCpu=1,blPlayer=1;
    cpu.FirstPlayTwo();
    do
    {
    cout<<"您的牌点为:\t"<<endl;
    player.DisplayPip();
    cout<<"计算机的牌点为"<<endl;
    cpu.DisplayPip(1);
    cout<<"您的牌面点数是"<<player.GetPip()<<endl;
    if(blPlayer)
    {
    cout<<"\n\n您是否继续要牌?(Y/N)"<<endl;
    cin>>chChoice;
    if((chChoice=='Y'||chChoice=='y'))
    { if(player.GetNumber()<5)
    { player.TurnPlay();
    cout<<"您要的这张牌是"<<player.GetCurrentCard()<<endl;
    if(player.GetPip()>21)
    blPlayer=0;
    }
    else
    {
    cout<<"对不起,您已经要了五张牌了!"<<endl;
    blPlayer=0;
    }
    }
    }

    if(chChoice=='N'||chChoice=='n')
    blPlayer=0;
    if(cpu.GetPip()<16&&cpu.GetNumber()<5)
    {
    cpu.TurnPlay();
    cout<<"计算机要牌,牌点是:"<<cpu.GetCurrentCard()<<endl;
    }
    else
    blCpu=0;
    if(blCpu&&player.GetNumber()<5&&player.GetPip()<21)
    blPlayer=1;
    }while(blCpu||blPlayer);
    Judge(cpu,player);
    }

    int main(int argc, char *argv[])
    {
    srand((unsigned)time(NULL));
    CCard cpu,player; //人和计算机赌
    int blLogic;
    int nMoney; //下注的数目
    DisplayRule();//打印规则
    char chChoice;
    cout<<"是否开始游戏 (Y/N)?\n";
    cin>>chChoice;
    while(chChoice=='Y'||chChoice=='y')
    {
    do
    {
    cout<<"您现在有的赌本:"<<player.getMoney()<<endl;
    cout<<"请下注:(赌注不能超过赌本)"<<endl;
    cin>>nMoney;
    blLogic=player.setGamble(nMoney);
    if(blLogic)
    cout<<"您的赌本不够!请重新下注:"<<endl;
    }while(blLogic); //注意do while的使用,后面有分号。

    playTurn(cpu,player); //玩一局
    cout<<"是否继续玩游戏(Y/N)"<<endl;
    cin>>chChoice;
    }
    player.DisplayInfo();//显示赌完之后的结果。
    cout<<"\\您的选择是明智的,赌博有害身体健康!"<<endl;
    cout<<"我们不欢迎你再次使用本程序!"<<endl;
    return 0;
    }
laiwing 2008-07-27
  • 打赏
  • 举报
回复
庄家只是在坑玩家的钱~~~
所以你不用考虑庄家是赢还是输~~~

你说在游戏中 ,只有人类玩家跟ai庄家
这游戏就有这几种情况
(1)庄家爆点,把玩家枝压的注吐出来
(2)玩家爆点,把赌注全部输掉
(3)庄家有 A ,问玩家要不要买保险 // 这是无偿性的,只要庄家手中第一张牌是A,那就必须问玩家要不要保险
1 :要 在加注 (a) 若庄家点数加起来 = 21 ,把买保险的2倍钱给玩家
(b) 把赌注全部输掉(包括买保险的)
2 :不要 (a) 若庄家点数加起来 = 21 ,把赌注全部输掉
(b) 继续玩下去
(4)玩家点数比庄家的小 ,把赌注全部输掉
(5)庄家跟玩家的点数一样(21点除外),把玩家枝压的注吐出来
(5)玩家点数是21点,把赌注的1.5倍给玩家
(6)庄家根玩家都是21点,把赌注全部输掉
(7)玩家的点数庄家多,把玩家枝压的注吐出来



加载更多回复(52)

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧