old_blog 剑圣无敌斩的编程模型
来源:互联网 发布:淘宝图文编辑软件 编辑:程序博客网 时间:2024/04/29 17:29
想必大家都jugg都是十分了解的,其大招无敌斩更是他享有“河道杀手”的称号。但是随机性攻击也成为jugg不稳定击杀的隐患。下面我们来考虑一个问题,jugg追杀敌方单位,准备开大,这时突然冒出来一坨小兵(很常见的情形)。这时jugg是否应该继续放大呢?或者放大后有多大的概率击杀对手呢?
显然我们将会通过编程来处理这个问题。在此之前,我想介绍关于面向对象的编程(因为我和我们一些同学正在学习Java以及Android开发,了解面向对象的机制还是很有帮助的)。
面向过程的程序设计我们为了简洁代码量,以函数的方式进行封装,来实现相同的功能。与面向过程的程序设计不同,面向对象的程序设计是以数据而不是功能为核心,将数据以及这些数据的操作以“类”的形式封装为一个整体,以“类”的对象作为程序的基本元素,通过对象发送消息,进而由对象启动相关的方法完成各种功能。形象的说,“类”就是一个包裹,里面放置着数据和函数(方法)。数据与函数分为动态和静态,动态的数据、函数必须实例化才能访问或者运行,而静态的数据、函数至只与类有关,与对象无关。静态函数类似于面向过程,此时类的作用仅仅是归类、打包。
下面来讲讲开始提出的例子,如果我们现在是面向过程,那么我们需要写一个函数,它的参数是jugg剩余攻击次数、近程小兵个数、远程小兵个数,经过函数内部的模拟或者计算,可以通过返回值的形式传出概率结果,也可以通过指针、引用参数的方式为形参赋值。但是,如果我们现在是面向对象,我们需要写一个“概率模拟器”或者是“概率计算器”,实例化“模拟器”或“计算器”对象并设置必要参数、运行得到概率结果。大家可以参考我们现实当中的计算器,通过键入数据、点击运行按钮,从而获得相应的结果,当然前提是你必须先买一个计算器,即实例化计算器对象。
为了解决jugg的无敌斩问题,我们提出几点必要的假设,使之完全成为数学问题:
1.jugg在无敌斩期间忽略普通攻击;
2.jugg无敌斩的劈斩对象概率均相等(这一点假设是必要的,其实jugg是随机一个角度在进行角度劈斩,不能保证劈斩每个人的概率相等);
3.随机数的产生视为真随机数(其实C++模拟随机数、魔兽软件产生的随机数都是伪随机数);
4.jugg的第一次攻击也是随机的(其实是必中的,我们可以通过将剩余次数、劈斩次数同时减一的方法模拟或计算)
4.近程兵能够承受3次攻击,远程兵能够承受2次攻击(实验得来的,但是随着小兵的成长承受次数会增加)。
我们规定在构造函数当中传入必要参数(近程小兵个数、远程小兵个数、剩余攻击次数),并可以人为地设置劈斩次数、模拟次数。最后通过run()函数获得模拟成功概率。
下面我们编写“概率计算器”类,保存在文件calculate.h中:
最后,我们通过main()函数进行测试,由于类的封装性,用户不需详知类的工作原理只要会使用就行了。
这里我们实例化对象并初始化、设置、运行。当然还计算出模拟准确度。
如果jugg可以劈6下,劈到就死(如程序设置),那么运行结果如下:
simulate probability= 76%
calculate probability= 75.974%
accuracy of simulating: 99.9658%
请按任意键继续. . .
如果jugg可以劈9下,那么
simulate probability= 90.9%
calculate probability= 91.4825%
accuracy of simulating: 99.3632%
请按任意键继续. . .
如果只能劈三下。。。。
simulate probability= 45.5%
calculate probability= 49%
accuracy of simulating: 92.8571%
请按任意键继续. . .
可见,模拟概率与计算概率的吻合度还是很高的,证明程序基本正确。
jugg的大招模型可以运用到很多相似的地方:
1.与弹射有关的模型:如lich的大招、WD的弹弹乐
2.准弹射模型:三国杀陆伯言的技能烧营
3.很多概率模型:如多次抽签、判定、拼点等
4.其实jugg的大招概率计算是一个NP问题,经过恰当的算法改造,可以定义公钥密码体制。
等等。
显然我们将会通过编程来处理这个问题。在此之前,我想介绍关于面向对象的编程(因为我和我们一些同学正在学习Java以及Android开发,了解面向对象的机制还是很有帮助的)。
面向过程的程序设计我们为了简洁代码量,以函数的方式进行封装,来实现相同的功能。与面向过程的程序设计不同,面向对象的程序设计是以数据而不是功能为核心,将数据以及这些数据的操作以“类”的形式封装为一个整体,以“类”的对象作为程序的基本元素,通过对象发送消息,进而由对象启动相关的方法完成各种功能。形象的说,“类”就是一个包裹,里面放置着数据和函数(方法)。数据与函数分为动态和静态,动态的数据、函数必须实例化才能访问或者运行,而静态的数据、函数至只与类有关,与对象无关。静态函数类似于面向过程,此时类的作用仅仅是归类、打包。
下面来讲讲开始提出的例子,如果我们现在是面向过程,那么我们需要写一个函数,它的参数是jugg剩余攻击次数、近程小兵个数、远程小兵个数,经过函数内部的模拟或者计算,可以通过返回值的形式传出概率结果,也可以通过指针、引用参数的方式为形参赋值。但是,如果我们现在是面向对象,我们需要写一个“概率模拟器”或者是“概率计算器”,实例化“模拟器”或“计算器”对象并设置必要参数、运行得到概率结果。大家可以参考我们现实当中的计算器,通过键入数据、点击运行按钮,从而获得相应的结果,当然前提是你必须先买一个计算器,即实例化计算器对象。
为了解决jugg的无敌斩问题,我们提出几点必要的假设,使之完全成为数学问题:
1.jugg在无敌斩期间忽略普通攻击;
2.jugg无敌斩的劈斩对象概率均相等(这一点假设是必要的,其实jugg是随机一个角度在进行角度劈斩,不能保证劈斩每个人的概率相等);
3.随机数的产生视为真随机数(其实C++模拟随机数、魔兽软件产生的随机数都是伪随机数);
4.jugg的第一次攻击也是随机的(其实是必中的,我们可以通过将剩余次数、劈斩次数同时减一的方法模拟或计算)
4.近程兵能够承受3次攻击,远程兵能够承受2次攻击(实验得来的,但是随着小兵的成长承受次数会增加)。
下面我们编写“概率模拟器”类,保存在文件simulate.h中:
#include<iostream.h>#include<stdlib.h>#include<time.h>class Simulator{private: int anum; int bnum; int leftattack; int *p1,*p2; int times; int cut; int p;public: Simulator(int a,int b,int lefta) { anum=a; bnum=b; leftattack=lefta; times=1000; p1=new int[a]; p2=new int[b]; for(int i=0;i<anum;i++) p1[i]=0; for(i=0;i<bnum;i++) p2[i]=0; p=leftattack; cut=6; } void setTimes(int t) { times=t; } void setCut(int c) { cut=c; } double run() { int x,count=0; int n; for(int i=0;i<times;i++) { n=0; while(p&&n!=cut) { x=rand()%(anum+bnum+1); if(x<anum) { if(p1[x]==3) continue; else p1[x]++; } else if(x<anum+bnum) { if(p2[x-anum]==2) continue; else p2[x-anum]++; } else { p--; } n++; } if(!p) count++; for(int i=0;i<anum;i++) p1[i]=0; for(i=0;i<bnum;i++) p2[i]=0; p=leftattack; } cout<<"simulate probability=\t"<<(double)count/times*100<<"%"<<endl; return (double)count/times; }};
我们规定在构造函数当中传入必要参数(近程小兵个数、远程小兵个数、剩余攻击次数),并可以人为地设置劈斩次数、模拟次数。最后通过run()函数获得模拟成功概率。
下面我们编写“概率计算器”类,保存在文件calculate.h中:
#include<iostream.h>#include<stdlib.h>#include<time.h>#include<string.h>class Node{public: char *ar; Node *next; int pro; bool success; Node(int c,char *a) { ar=new char[c]; int l=strlen(a); strcpy(ar,a); next=NULL; pro=1; success=false; }};class Calculator{private: Node* first; char* temp; int anum; int bnum; int leftattack; int cut; int n; int *array; double getRes() { double res=0; for(Node* p=first;p;p=p->next) { if(p->success) res+=1.0/p->pro; } return res; } void calSuccess() { for(Node* p=first;p;p=p->next) { int i=0; for(int j=0;j<(int)strlen(p->ar);j++) if(p->ar[j]-'0'==anum+bnum) i++; if(i==leftattack) p->success=true; } } void visitLink() { for(Node* p=first;p;p=p->next) cout<<p->ar<<"\tpro="<<p->pro<<"\t"<<p->success<<endl; } int calLive(int *p) { int s=0; for(int i=0;i<anum+bnum+1;i++) { if(i<anum) { if(p[i]<3) s++; } else if(i<anum+bnum) { if(p[i]<2) s++; } else { if(p[i]<cut) s++; } } return s; } void calProbability() { int *alive=new int[anum+bnum+1]; for(Node* p=first;p;p=p->next) { int s=1; for(int i=0;i<anum+bnum+1;i++) alive[i]=0; for(int j=0;j<(int)strlen(p->ar);j++) { s*=calLive(alive); alive[p->ar[j]-'0']++; } p->pro=s; } } void Insert(int *a,int l) { char *str=new char[cut]; for(int i=0;i<l;i++) str[i]=a[i]+'0'; str[i]=0; if(strcmp(temp,str)!=0) { if(n==0) first=new Node(cut,str); else { Node* q=new Node(cut,str); q->next=first; first=q; } strcpy(temp,str); } else strcpy(temp,str); n++; } bool pass(int *a,int step) { int count=0; for(int i=0;i<step;i++) if(a[i]==a[step]) count++; count++; if(a[step]<anum) { if(count==4) return false; else return true; } else if(a[step]<anum+bnum) { if(count==3) return false; else return true; } else return true; } void print(int *a,int l) { for(int i=0;i<l;i++) cout<<a[i]<<" "; cout<<endl; } void print(int *a) { for(int i=0;i<cut;i++) cout<<a[i]<<" "; cout<<endl; } void fillArray(int *a,int step) { int count=0; for(int j=0;j<step-1;j++) if(a[j]==anum+bnum) count++; if(!pass(a,step-1)) return; if(count==leftattack) { Insert(a,step-1); return; } if(step==cut) { Insert(a,cut); return; } for(int i=0;i<anum+bnum+1;i++) { a[step]=i; fillArray(a,step+1); } }public: Calculator(int a,int b,int lefta) { anum=a; bnum=b; leftattack=lefta; times=1000; cut=6; n=0; temp=new char[cut]; first=NULL; } ~Calculator() { for(Node *p=first->next;p;p=p->next) { delete first; first=p; } } void setCut(int c) { cut=c; } double run() { array=new int[cut]; fillArray(array,0); calProbability(); calSuccess();// visitLink(); double x=getRes(); cout<<"calculate probability=\t"<<x*100<<"%"<<endl; return x; }};我们规定在构造函数当中传入必要参数(近程小兵个数、远程小兵个数、剩余攻击次数),并可以人为地设置劈斩次数。最后通过run()函数获得计算成功概率。程序通过链表的存储方式存储劈斩次序,变量pro存放的是某一种情况概率的倒数值。
最后,我们通过main()函数进行测试,由于类的封装性,用户不需详知类的工作原理只要会使用就行了。
#include"simulate.h"#include"calculate.h"#include<math.h>void main(){ Simulator sim(3,1,1); Calculator cal(3,1,1); sim.setCut(6); cal.setCut(6); srand((unsigned)time(NULL)); double ps=sim.run(); double pc=cal.run(); cout<<"accuracy of simulating:\t"<<100-fabs(ps-pc)/pc*100<<"%"<<endl; system("pause");}
这里我们实例化对象并初始化、设置、运行。当然还计算出模拟准确度。
如果jugg可以劈6下,劈到就死(如程序设置),那么运行结果如下:
simulate probability= 76%
calculate probability= 75.974%
accuracy of simulating: 99.9658%
请按任意键继续. . .
如果jugg可以劈9下,那么
simulate probability= 90.9%
calculate probability= 91.4825%
accuracy of simulating: 99.3632%
请按任意键继续. . .
如果只能劈三下。。。。
simulate probability= 45.5%
calculate probability= 49%
accuracy of simulating: 92.8571%
请按任意键继续. . .
可见,模拟概率与计算概率的吻合度还是很高的,证明程序基本正确。
jugg的大招模型可以运用到很多相似的地方:
1.与弹射有关的模型:如lich的大招、WD的弹弹乐
2.准弹射模型:三国杀陆伯言的技能烧营
3.很多概率模型:如多次抽签、判定、拼点等
4.其实jugg的大招概率计算是一个NP问题,经过恰当的算法改造,可以定义公钥密码体制。
等等。
0 0
- old_blog 剑圣无敌斩的编程模型
- old_blog 回杨振宇的日志
- old_blog 《赤印》的文本提取
- old_blog 说好的复制呢?
- 3d编程的无敌组合
- old_blog 简单的矩阵赋值问题
- 无敌大帅杜的编程之道0
- old_blog 皇后
- 委托的无敌解释
- 接口的无敌解释!
- 委托的无敌解释
- 无敌的批处理
- 接口的无敌解释!
- 接口的无敌解释!
- 接口的无敌解释!
- 接口的无敌解释!
- 接口的无敌解释!
- 接口的无敌解释!
- NumberPicker组件
- 网络爬虫(Spider)Java实现原理(转载)
- android背景选择器selector用法
- 双向循环列表的增加和删除结点
- Quartz实现定时任务(一)
- old_blog 剑圣无敌斩的编程模型
- hdu 1255 覆盖的面积(线段树+扫描线)
- Ubuntu Server 14下搭建PHP与Java的运行环境
- 58同城加载动画的实现( Android属性动画)
- java中的集合类
- ZigBee OTA镜像页升级
- Oracle EBS:PO 采购订单类型(单据类型)
- STM32F407的串口采用DMA收发数据
- Android InputMethodManager输入法简介