之前 javaeye 网站上有人写过 3颗骰子能掷出多少种结果 的一道面试题,用了面向对象的思考方式,后来某天深夜自己想了又想,发现可以把这个问题转化为数学模型,用金字塔模型,再采用逆推推出了 N个骰子掷出的和的概率算法。
1颗骰子,一共6面,每一面掷出的概率都一样,在1维空间中表示,相当于造6层金字塔的一条边
2颗骰子,在2维空间中表示。。。 (画图画了好久,直接用画图板手工绘制的,没有3d效果,大家想象成3d的吧)
下面表示的是4颗骰子映射出来的4维空间模型。怎么理解呢? 就在3维空间上加一个时间吧,第一座金子公元前2000年开始建造,每年造一层,第二座金字塔公元前1999年开始建造,第三座金字塔公元前1998年开始建造,到了公园前1995年的时候,就变成下面这种状态了。
5颗骰子,依次类推,5维空间的表示,再加一个地点吧,公园前1995年的时候在埃及造了上面4维空间中的这些金字塔,一共126块砖,同年在玛雅造了5座金字塔,(假设玛雅比埃及晚造1年),其它地区的金子塔也在建造之中,都依次晚造1年。这样就形成了一个类似金子塔阶梯的5维空间。
同样,6维,7维……都和骰子投掷出来的和的概率相对应。如果把上面的每块砖都用数组来标记,就变成下面的形式:
再次提炼出数字规律
1颗:1,1,1,1,1,1
2颗:1,2,3,4,5,6
3颗:1,3,6,10,15,21
4颗:1,4,10,20,35,56
5颗:1,5,15,35,70,126
发现规律了吧,每组数中的数字都是上一组数字前几位数的和。
下面贴上java实现程序,灵感闪现,仓促下笔,算法不是很简洁,没有完全构造对象,用了数组和递归,可能阅读比较晦涩。
package org.vv.algorithm.number;
import java.util.Map;
import java.util.TreeMap;
/**
* 计算 骰子的组合 概率 问题
* @author 俞立全
* @version 2009-10-20
*/
public class A {
/**
* 初始化定义骰子的个数
*/
private static int[] n = {1,1,1,1,1,1};
//排列,组合
/*
* 骰子的组合就是求和的概率,如2颗骰子 出现和为2的概率是1,3的概率是2,4的概率是3,5的概率是4,6的概率是5,7的概率是6 ,概率的总和也就是骰子的组合。
*/
//1,1,1,1,1,1
//6,5,4,3,2,1
//21,15,10,6,3,1
//56,35,20,10,4,1
//126,70,35,15,5,1
//上面每一个结果都是
/**
* 计算骰子组合的总数(排列)
* @param n 骰子面数
* @param num 骰子数量
* @return
*/
public static int[] exec(int[] n,int num){
if(num>1){
num--;
System.out.println("递归:"+num);
for(int i=0;i<n.length;i++){
for(int j=0;j<n.length-i-1;j++){
//每次减少一位
n[i] += n[j+i+1];
}
}
exec(n,num);
}
return n;
}
/////////////////////////////////////////////////////////
/**
* 初始化骰子
* @param num1 骰子面数 一般为6面
* @param num2 骰子个数
*/
public static int[] get(int num){
int[] n = new int[num];
for (int i = 0; i < n.length; i++) {
n[i]=1;
}
return n;
}
/**
* 显示输出的行号
*/
private static int numbers=1;
/**
* 开始枚举数组时开始的位置,从n[0]递增,由于使用递归,只能定义为成员变量。
*/
private static int i=0;
/**
* n[0]位置是否满足条件 n[i]>=num 由于使用递归,只能定义为成员变量。
*/
private static boolean x = true;
/**
* 枚举出所有数组
* @param n 初始的数组,如{1,1,1,1}
* @param num 骰子的面数,一般为6
* @param x
*/
public static void verify(int[] n,int num){
if(x && (include(n) || isCalculateCount)){
printArray(n);
numbers++;
//是否统计骰子掷出的概论
if(isCalculateCount){
getCount(n);
}
}
if(!isEnd(n,num)){
if(n[i]>=num){
x=false;
n[i]=1;
i=i+1;
}else{
x=true;
n[i]++;
i=0;
}
verify(n,num);
}
}
/**
* 判断是否结束 ,即 6,6,6,6 形式
* @param n
* @param num
* @return
*/
public static boolean isEnd(int[] n,int num){
boolean rt = true;
for(int i=0;i<n.length;i++){
if(n[i]==6){
rt &= true; //只有都为true才返回true
}else{
rt &= false;
}
}
return rt;
}
/**
* 判断数组中相邻两位左边的值是否大于等于右边的值,大于等于有效,返回true,只要有一个组小于就返回false;
* @param n
* @return
*/
public static boolean include(int[] n){
boolean rt = true;
for(int i=0;i<n.length-1;i++){
if(n[i] >= n[i+1]){
rt &= true;
}else{
rt &= false;
}
}
return rt;
}
/**
* 打印数组中的元素到控制台
* @param source
*/
public static void printArray(int[] data) {
System.out.print(numbers+" : ");
for (int i : data) {
System.out.print(i + " ");
}
System.out.println();
}
/////////////////////////////////// 概论判断,使用概论判断就必须使用排列,包括重复的组合。
private static boolean isCalculateCount = true;
private static Map<Integer,Integer> map = new TreeMap<Integer,Integer>();
public static void getCount(int[] n){
Integer count = 0;
Integer number = 0;
for(int i=0;i<n.length;i++){
count +=n[i];
}
//判断比较
if(map.get(count)!=null)
{
number = map.get(count)+1;
map.remove(count);
map.put(count,number);
}else{
map.put(count, 1);
}
}
/**
* 执行计算
* @param args
*/
public static void main(String[] args) {
//定义骰子的数量
int count = 2;
//计算骰子组合的总数(无序)
int[] x = A.exec(n, count);
int sum = 0;
for(int i=0;i<x.length;i++){
System.out.println(x[i]);
sum+=x[i];
}
System.out.println("最后的总和:"+sum);
//遍历骰子(排列或组合由 isCalculateCount 属性控制)
A.isCalculateCount = false;
A.verify(A.get(count),6);
//概论统计
for(java.util.Map.Entry<Integer,Integer> entry : map.entrySet()){
Integer key = entry.getKey();
Integer value = entry.getValue();
System.out.println("骰子掷出的和: " + key + " 出现次数:" + value);
}
}
}
从中也总结出一条经验,就是循环的处理,并且在很多需求中屡试不爽。如果明确循环次数就用 for while 等,如果不明确循环次数,并且返回或处理对象结构相同就可以用递归,比如生成树形结构的目录。
最后运行代码的结果:(3颗骰子)
递归:2
递归:1
21
15
10
6
3
1
最后的总和:56
1 : 1 1 1
2 : 2 1 1
3 : 3 1 1
4 : 4 1 1
5 : 5 1 1
6 : 6 1 1
7 : 2 2 1
8 : 3 2 1
9 : 4 2 1
10 : 5 2 1
11 : 6 2 1
12 : 3 3 1
13 : 4 3 1
14 : 5 3 1
15 : 6 3 1
16 : 4 4 1
17 : 5 4 1
18 : 6 4 1
19 : 5 5 1
20 : 6 5 1
21 : 6 6 1
22 : 2 2 2
23 : 3 2 2
24 : 4 2 2
25 : 5 2 2
26 : 6 2 2
27 : 3 3 2
28 : 4 3 2
29 : 5 3 2
30 : 6 3 2
31 : 4 4 2
32 : 5 4 2
33 : 6 4 2
34 : 5 5 2
35 : 6 5 2
36 : 6 6 2
37 : 3 3 3
38 : 4 3 3
39 : 5 3 3
40 : 6 3 3
41 : 4 4 3
42 : 5 4 3
43 : 6 4 3
44 : 5 5 3
45 : 6 5 3
46 : 6 6 3
47 : 4 4 4
48 : 5 4 4
49 : 6 4 4
50 : 5 5 4
51 : 6 5 4
52 : 6 6 4
53 : 5 5 5
54 : 6 5 5
55 : 6 6 5
56 : 6 6 6
打开概率计算后的计算结果,(计算概率,就包括了重复,如 112 211 121 都要计算在内)
递归:2
递归:1
21
15
10
6
3
1
最后的总和:56
1 : 1 1 1
2 : 2 1 1
3 : 3 1 1
4 : 4 1 1
5 : 5 1 1
6 : 6 1 1
7 : 1 2 1
8 : 2 2 1
9 : 3 2 1
10 : 4 2 1
11 : 5 2 1
12 : 6 2 1
13 : 1 3 1
14 : 2 3 1
15 : 3 3 1
16 : 4 3 1
17 : 5 3 1
18 : 6 3 1
19 : 1 4 1
20 : 2 4 1
21 : 3 4 1
22 : 4 4 1
23 : 5 4 1
24 : 6 4 1
25 : 1 5 1
26 : 2 5 1
27 : 3 5 1
28 : 4 5 1
29 : 5 5 1
30 : 6 5 1
31 : 1 6 1
32 : 2 6 1
33 : 3 6 1
34 : 4 6 1
35 : 5 6 1
36 : 6 6 1
37 : 1 1 2
38 : 2 1 2
39 : 3 1 2
40 : 4 1 2
41 : 5 1 2
42 : 6 1 2
43 : 1 2 2
44 : 2 2 2
45 : 3 2 2
46 : 4 2 2
47 : 5 2 2
48 : 6 2 2
49 : 1 3 2
50 : 2 3 2
51 : 3 3 2
52 : 4 3 2
53 : 5 3 2
54 : 6 3 2
55 : 1 4 2
56 : 2 4 2
57 : 3 4 2
58 : 4 4 2
59 : 5 4 2
60 : 6 4 2
61 : 1 5 2
62 : 2 5 2
63 : 3 5 2
64 : 4 5 2
65 : 5 5 2
66 : 6 5 2
67 : 1 6 2
68 : 2 6 2
69 : 3 6 2
70 : 4 6 2
71 : 5 6 2
72 : 6 6 2
73 : 1 1 3
74 : 2 1 3
75 : 3 1 3
76 : 4 1 3
77 : 5 1 3
78 : 6 1 3
79 : 1 2 3
80 : 2 2 3
81 : 3 2 3
82 : 4 2 3
83 : 5 2 3
84 : 6 2 3
85 : 1 3 3
86 : 2 3 3
87 : 3 3 3
88 : 4 3 3
89 : 5 3 3
90 : 6 3 3
91 : 1 4 3
92 : 2 4 3
93 : 3 4 3
94 : 4 4 3
95 : 5 4 3
96 : 6 4 3
97 : 1 5 3
98 : 2 5 3
99 : 3 5 3
100 : 4 5 3
101 : 5 5 3
102 : 6 5 3
103 : 1 6 3
104 : 2 6 3
105 : 3 6 3
106 : 4 6 3
107 : 5 6 3
108 : 6 6 3
109 : 1 1 4
110 : 2 1 4
111 : 3 1 4
112 : 4 1 4
113 : 5 1 4
114 : 6 1 4
115 : 1 2 4
116 : 2 2 4
117 : 3 2 4
118 : 4 2 4
119 : 5 2 4
120 : 6 2 4
121 : 1 3 4
122 : 2 3 4
123 : 3 3 4
124 : 4 3 4
125 : 5 3 4
126 : 6 3 4
127 : 1 4 4
128 : 2 4 4
129 : 3 4 4
130 : 4 4 4
131 : 5 4 4
132 : 6 4 4
133 : 1 5 4
134 : 2 5 4
135 : 3 5 4
136 : 4 5 4
137 : 5 5 4
138 : 6 5 4
139 : 1 6 4
140 : 2 6 4
141 : 3 6 4
142 : 4 6 4
143 : 5 6 4
144 : 6 6 4
145 : 1 1 5
146 : 2 1 5
147 : 3 1 5
148 : 4 1 5
149 : 5 1 5
150 : 6 1 5
151 : 1 2 5
152 : 2 2 5
153 : 3 2 5
154 : 4 2 5
155 : 5 2 5
156 : 6 2 5
157 : 1 3 5
158 : 2 3 5
159 : 3 3 5
160 : 4 3 5
161 : 5 3 5
162 : 6 3 5
163 : 1 4 5
164 : 2 4 5
165 : 3 4 5
166 : 4 4 5
167 : 5 4 5
168 : 6 4 5
169 : 1 5 5
170 : 2 5 5
171 : 3 5 5
172 : 4 5 5
173 : 5 5 5
174 : 6 5 5
175 : 1 6 5
176 : 2 6 5
177 : 3 6 5
178 : 4 6 5
179 : 5 6 5
180 : 6 6 5
181 : 1 1 6
182 : 2 1 6
183 : 3 1 6
184 : 4 1 6
185 : 5 1 6
186 : 6 1 6
187 : 1 2 6
188 : 2 2 6
189 : 3 2 6
190 : 4 2 6
191 : 5 2 6
192 : 6 2 6
193 : 1 3 6
194 : 2 3 6
195 : 3 3 6
196 : 4 3 6
197 : 5 3 6
198 : 6 3 6
199 : 1 4 6
200 : 2 4 6
201 : 3 4 6
202 : 4 4 6
203 : 5 4 6
204 : 6 4 6
205 : 1 5 6
206 : 2 5 6
207 : 3 5 6
208 : 4 5 6
209 : 5 5 6
210 : 6 5 6
211 : 1 6 6
212 : 2 6 6
213 : 3 6 6
214 : 4 6 6
215 : 5 6 6
216 : 6 6 6
骰子掷出的和: 3 出现次数:1
骰子掷出的和: 4 出现次数:3
骰子掷出的和: 5 出现次数:6
骰子掷出的和: 6 出现次数:10
骰子掷出的和: 7 出现次数:15
骰子掷出的和: 8 出现次数:21
骰子掷出的和: 9 出现次数:25
骰子掷出的和: 10 出现次数:27
骰子掷出的和: 11 出现次数:27
骰子掷出的和: 12 出现次数:25
骰子掷出的和: 13 出现次数:21
骰子掷出的和: 14 出现次数:15
骰子掷出的和: 15 出现次数:10
骰子掷出的和: 16 出现次数:6
骰子掷出的和: 17 出现次数:3
骰子掷出的和: 18 出现次数:1
- 大小: 10.1 KB
- 大小: 15.2 KB
- 大小: 14.2 KB
- 大小: 6.2 KB
分享到:
相关推荐
在本项目中,"C#项目掷骰子——小游戏"是一个使用C#编程语言开发的简单游戏应用。这个游戏的核心机制是模拟掷骰子的过程,它可能包含多个回合或轮次,每个回合玩家或计算机都会投掷一个或多个骰子,然后根据骰子的...
4. **动画系统**:为了使游戏更加生动,骰子掷出后应有一个翻滚动画。Unity的动画系统可以制作骰子旋转的动画,通过`Animator`组件和关键帧设置实现。也可以利用Unity的物理引擎,让骰子自然地滚动到停止位置。 5. ...
想知道用MATLAB快速搞定掷骰子概率问题就下来研究吧!
2. **概率计算**:掷色子游戏涉及到各种概率问题,例如计算特定点数出现的概率。一个六面的标准色子,每个面出现的概率是1/6。对于两个或多个色子的组合,我们需要计算组合出现的概率,例如两个色子总点数为7的概率...
资源名:模拟掷色子_matlab 资源类型:matlab项目全套源码 源码说明: 全部项目源码都是经过测试校正后百分百成功运行的,如果您下载后不能运行可联系我进行指导或者更换。 适合人群:新手及有一定经验的开发人员
在代码组织上,可以采用面向对象编程(OOP)的思想,定义一个`DiceGame`类,包含`Player`对象和`Computer`对象,每个对象都有自己的点数属性和掷骰子方法。这样可以使代码结构清晰,易于维护和扩展。 最后,测试和...
【实践活动——掷一掷】是部编版课程中的一个实践环节,主要目的是通过掷骰子的游戏,让学生在实际操作中理解和应用概率与统计的相关知识。这个活动涉及的主要知识点包括: 1. **组合知识**:在活动中,学生需要...
在这个“微信小程序掷骰子掷色子.zip”项目中,我们可以看到一个用于创建趣味性游戏的小程序示例,用户可以通过这个小程序体验在线掷骰子或掷色子的乐趣。 首先,我们需要理解微信小程序的基本结构。一个小程序由多...
2. **JavaScript**:JavaScript是驱动这个游戏的核心语言,负责处理用户的交互、随机数生成、骰子的掷出结果计算以及画面更新等功能。例如,当用户点击掷骰子按钮时,JavaScript会触发一个事件处理器,生成1到6之间...
在这个“VB掷骰子游戏”项目中,我们看到的是如何利用VB来实现一个基本的随机数生成器,模拟真实的掷骰子过程。在这个过程中,VB的随机数生成功能扮演了核心角色。 在VB中,我们可以使用`Rnd`函数来生成0到1之间的...
Java的掷骰子游戏,游戏规则:1、此游戏中,游戏者将滚动两个骰子。每一个骰子有六个面, 分别代表1、2、3、4、5、6。当骰子停下以后,计算两个骰子 表面的点数和。如果第一轮掷的点数和等于7或11,则游戏者胜; ...
掷3个骰子游戏2.0.用C做的。掷3个骰子游戏2.0.用C做的。掷3个骰子游戏2.0.用C做的。掷3个骰子游戏2.0.用C做的。掷3个骰子游戏2.0.用C做的。
掷骰子游戏是一种常见的娱乐活动,它涉及到概率、随机性和策略。在这个“完整的掷骰子游戏”中,我们可以探讨以下几个IT相关的知识点: 1. 图片处理:描述中提到的“好看的图片”暗示了游戏可能使用了图形用户界面...
如果和是其他数字(4、5、6、8、9或10),就确定了一个点数,继续掷骰子,直到掷出一个7或者掷出与第一次相同的点数,如果掷出的是7,你就输了,如果掷出的点数与第一次掷出的点数相同,你就赢了。输一次或赢一次算一...
掷骰子是初中数学中一个常见且有趣的概率教学实例,它涉及到随机事件、可能性和概率等概念。在本文中,我们将深入探讨与这个主题相关的数学知识点,并结合使用FLSH(Flash)动画作为辅助教学工具的优势。 首先,让...
基于cyclone IV的板载资源,设计利用vhdl语言设计的小游戏的课程设计——模拟掷骰子
标签进一步明确了这个项目的主题:“matlab抛色子”、“matlab掷骰子”、“matlab编写dice”、“蒙特卡洛”和“骰子”。这些标签强调了MATLAB在实现骰子游戏模拟中的应用,以及蒙特卡洛方法在解决这个问题中的核心...
然后,一个角色说出以相同的60,466,176:1投掷10个骰子的概率。 答对了。 灵感。 因此,这个多线程模拟器诞生了。 我编写的代码简单易懂,并利用了多线程功能,并且希望对其他好奇的人有用。 此代码根据MIT许可...
标题中的“用Python编写一个掷骰子的小程序完整project”是指使用Python编程语言设计和实现一个模拟掷骰子的游戏。这个项目可能包含了用户界面、随机数生成以及结果显示等功能,是初学者学习Python GUI编程和游戏...
- **成员函数Player::Integral(int number)**:计算玩家的积分,包括积分的变化和掷骰子的次数。 - **成员函数Player::Initial()**:创建玩家链表,将所有玩家链接起来形成一个环。 - **成员函数Player::Game()**:...