当前课程知识点:C++语言程序设计基础 >  第3章 函数 >  函数调用 >  例3-6

返回《C++语言程序设计基础》慕课在线视频课程列表

例3-6在线视频

例3-6

函数调用例3-6

 

3-6投骰子的随机游戏

每个骰子有六面,点数分别为1、2、3、4、5、6。游戏者在程序开始时输入一个无符号整数,作为产生随机数的种子。

每轮投两次骰子,第一轮如果和数为7或11则为胜,游戏结束;和数为2、3或12则为负,游戏结束;和数为其它值则将此值作为自己的点数,继续第二轮、第三轮...直到某轮的和数等于点数则取胜,若在此前出现和数为7则为负。

 

rand函数

l  函数原型:int rand(void);

l  所需头文件:<cstdlib>

l  功能和返回值:求出并返回一个伪随机数

 

srand函数

l  void srand(unsigned int seed);

l  参数:seed产生随机数的种子

l  所需头文件:<cstdlib>

l  功能:为使rand()产生一序列伪随机整数而设置起始点。使用1作为seed参数,可以重新初化rand()。



下一节:函数的嵌套调用(例3-7)

返回《C++语言程序设计基础》慕课在线视频列表

例3-6课程教案、知识点、字幕

大家好

欢迎继续学习C++语言程序设计

这一节我们讲一个好玩的例子

一个投骰子的游戏

俗称色子 大家都见过

那么这个投骰子的游戏呢

规则有一点复杂

那么关键怎么分解这样的功能

怎么去实现它每一个部分功能呢

实际上我们可以思考

如果我把投骰子的过程

单独实现

或者说有人替我实现了

那剩下的事是不是就好办了呢

大家可以想想这个问题

还有怎么去模拟

这个投骰子的过程呢

你投一次骰子

落下来以后

上面的那个数它是个随机的

那么这就是一个

典刑的随机数的问题

在程序中怎么样去模拟

生成随机数

在C++中是有这样的函数的

接下来我会给大家介绍

随机数的函数

以及如何来模拟

这个投骰子的游戏

好 现在我们来看

这个投骰子游戏的规则

这个规则还是很好玩的

每一个骰子有六面

点数分别是1 2 3 4 5 6

这个大家是熟悉的

那游戏者在程序开始的时候

先输入一个无符号整数

作为什么呢

作为产生随机数的种子

那么这个要求呢

大家可能还不太理解

我们先放下

等一会就知道了

好 现在看游戏规则

每一轮投两次骰子

第一轮如果和数为7或者11

那么玩家就胜了 游戏结束

如果和数是2 3 或者12

那么玩家就输了 游戏也结束

如果既不赢又不输

那怎么办呢

好 把这个和数存下来

存下这个和数的值

作为这个玩家他自己的点数

那么继续第二轮

第三轮等等等等

一直继续玩

直到什么时候分出胜负呢

如果某一轮的和数

等于了刚才存下的点数

那么这个玩家赢了 游戏结束

如果还没到赢呢

就先遇到什么呢

先遇到和数是7的情况

那这个玩家他就输了

游戏也结束

我相信

你现在可能觉得哎呀

这个怎么这么麻烦呢

这个到底怎么写这个程序

从什么地方下手

其实它的关键问题在什么地方

在于你老想着

我怎么去模拟那个投骰子

这个问题一旦解决了

你会发现问题逻辑非常简单

所以我们分解一下功能

专门写一个函数

用来模拟投骰子的过程

它能模拟投骰子

并且计算出和数

并且把这个和数

返回给调用者

这样的话我们的主函数逻辑

只要专注于玩游戏就行了

有一个假设自动机器

一个独立的函数

是帮我们做投骰子的

好 那么现在还有一个问题

投骰子怎么模拟

这就需要随机数生成函数

在C++的标准库里面

是有一个rand函数了

这个rand是专门用来

产生随机数的

产生什么随机数呢

叫做伪随机数

也就是假的随机数

为什么说它是尾随机数呢

大家可以编个程序试一试

我建议大家课后去试试

很简单

你就写一个循环

多次调用这个rand函数

那你就会看到

每次调用rand函数

它就产生一个整数

每次调用它产生一个整数

然后你调用很多次

比如你循环一百次 一千次

你会发现 看起来

它产生的随机数都是均匀分布的

真的是看起来随机的

没有什么规律的

那不就很好吗

好 你记下你一次运行的结果

你把你的程序再运行一遍

你会发现它产生的随机数序列

是一模一样的

那么这样的随机数

就叫做伪随机数 假的嘛

每次运行产生同样的序列

那这个怎么能当游戏去玩呢

因为在游戏这样的程序中

是大量的需要产生随机数的

那么C++的解决途径是什么呢

有一个办法

它还要一个

叫做随机数种子的东西

这就是我们题目要求

一开始说的

在程序运行开始

让用户输入一个整数

作为产生随机数的种子

在C++中

专门有一个函数叫srand

是种那个种子的函数

我们在这里也给出了

srand函数的原型

以及它的参数

它需要的头文件

那么这个srand函数

它的功能就是专门为了rand

产生一个随机数序列

去设置种子的

设置整数的一个起始点

那么默认情况下呢

它种子都是一样的

所以随机数序列是一样的

我们只要每一次运行的时候

给一个不同的种子

它就可以产生不同的随机数序列

下面我们来看一下这个源代码

在这个投骰子游戏的程序中呢

我们先将投骰子的模拟过程

抛开一边

假设已经有这么一个函数

可以为我们调用了

rollDice这个函数

这个函数模拟

每次投两下骰子

并且计算那个和数返回

如果这个函数已经存在了

有了

那么主函数就专注于

游戏的逻辑就可以了

我们现在先来看这个主函数

好 在主函数中呢

我们首先要输入随机数的种子

然后将这个种子传递给rand

因为rand是一个伪随机数的函数

那么用srand种一下种子

这样每一次种子不同

它产生的随机数序列也就会不同

然后我们会用

这个switch case语句

来处理第一次玩游戏的这个逻辑

第一次玩游戏的时候

投骰子以后

如果这个和数是7或者11

玩家就胜了

所以大家看

这两个case标号共用了一组语句

case7和case11

这是两个标号

共用 将status设成WIN状态

设成赢

然后break 共用这个语句

那么如果是和数为2

3 12 那就输了

所以case2 case3 case12

这三个标号

又共用另外一组语句

就是把status设为LOSE

他输了

然后break退出switch case结构

如果是其他情况呢

那么就是不赢不输

这种情况下需要把它的和数

记下来作为自己的点数

所以我们看

在default这个分支里面

这个状态设成游戏中PLAYING

然后这个sum存到mypoint里面

作为游戏玩家的点数

好 那这样第一轮就算结束了

也许胜了 也许负了

也许未分胜负

接下来

我们就要进行后续的游戏了

判断这个状态是输是赢

还是继续呀

只要这个状态还是游戏中

我们看这个while后面

status只要等于PLAYING

那么就继续游戏

这个游戏过程

都在这个while循环体里面了

好 去调用rollDice函数

模拟一次投骰子

并且返回了这个和数

判断一下

这个和数如果等于我的点数

等于myPoint

那么就将WIN设置到status里面

赢了

如果这个和数是7

那么还没来得及赢 他就输了

已经和数是7了

那就将status设成LOSE

就输了

那么我们看

赢了或者输了

status都会被改变

如果既没有赢也没有输

status就还是原来的状态

还是PLAYING状态

所以转回到循环头上去

这个while就要判断

当前status是不是

依旧为PLAYING

如果它已经不等于PLAYING了

就说明游戏结束了

不管输赢反正结束了

退出这个游戏

好 那么循环往复

只要没分出输赢就继续游戏

当某个时刻如果退出while循环

一定是分出输赢了

所以在while循环之后呢

就要判断

为什么退出来

看这个status是WIN 是吗

如果等于WIN 就说明赢了

输出赢

否则呢 那一定是输了

不赢不输不会退出游戏的

所以如果不是WIN的话

那就是输出玩家输了

这个逻辑大家看是不是很简单

其实投骰子的游戏规则很清楚

主函数的逻辑也非常简单

那么现在是时候

要解决什么的问题呢

要解决

如何模拟投骰子的过程的问题了

现在我们来看

这个简单的函数

非常短 就这么几行

怎么模拟呢

调用rand函数

产生一个随机数

但是这个随机数

是整个整数取值范围之内

随机得到的一个数

而我们需要的投骰子的

在上面那个面的那个数

它是1到6之间的

怎么让

一个在整个整数范围之内的数

处于1到6之间呢

这个技巧就是除以6取余数

如果除以6取余数

这个数会是0到5

那怎么办呢

我们再加上1

它不就移动到1到6这个位置了吗

所以连续做两次这样的操作

就模拟投了两次骰子

然后把它们的数加起来

就得到这个和数

在这里呢

输出一下这个和数

然后将这个和数return

返回给调用者

那么这道题由于把功能分解开了

所以各自实现起来

逻辑都非常简单

很轻松就可以实现了

那么这里是某一次玩的时候

玩家得到的这么一个结果

C++语言程序设计基础课程列表:

第1章 绪论

-导学

--第1章导学

-计算机系统简介

--计算机系统简介

--计算机系统简介 测试题

-计算机语言和程序设计方法的发展

--计算机语言和程序设计方法的发展

--计算机语言和程序设计方法的发展 测试题

-面向对象的基本概念

--面向对象的基本概念

--面向对象的基本概念 测试题

-程序的开发过程

--程序的开发过程

--程序的开发过程 测试题

-信息的表示和储存

--计算机中的信息与存储单位

--计算机的数字系统

--数据的编码表示

--信息的表示和储存 测试题

-实验指导

--实验一:VS开发环境介绍

第2章 C++简单程序设计(一)

-导学

--第二章导学

-C++语言概述

--C++的特点和程序实例

--C++字符集和词法记号

--C++语言概述 测试题

-基本数据类型、常量、变量

--基本数据类型、常量、变量

--程序举例

--基本数据类型、常量、变量 测试题

-运算与表达式

--算术运算与赋值运算

--逗号运算、关系运算、逻辑运算和条件运算

--Sizeof运算、位运算

--运算优先级、类型转换

--运算与表达式 测试题

-实验二:简单程序设计(上)

--实验二:简单程序设计(上)

第2章 C++简单程序设计(二)

-数据的输入和输出

--数据的输入和输出

--数据的输入和输出 测试题

-选择结构

--if语句

--switch语句

--选择结构 测试题

-循环结构

--循环结构——while语句

--do-while语句

--for语句

--嵌套的控制结构、其他控制语句

--循环结构 测试题

-自定义类型

--自定义类型

--自定义类型

-第2章小结

--第二章小结

-实验二:C++简单程序设计(下)

--实验二C++简单程序设计(下)

第3章 函数

-导学

--导学

-函数定义

--函数定义

--函数定义 测试题

-函数调用

--函数调用(例3-1)

--例3-2

--例3-3

--例3-4

--例3-5

--例3-6

--函数调用 测试题

-嵌套与递归

--函数的嵌套调用(例3-7)

--函数的递归调用(例3-8)

--例3-9

--例3-10

--嵌套与递归 测试题

-函数的参数传递

--函数的参数传递

--函数的参数传递 测试题

-引用类型

--引用类型(例3-11)

--引用类型 测试题

-含有可变参数的函数

--含有可变参数的函数

--含有可变参数的函数 测试题

-内联函数

--内联函数(例3-14)

--内联函数 测试题

-constexpr函数

--constexpr函数

--CONSTEXPR函数课后习题

-带默认参数值的函数

--带默认参数值的函数

--默认参数值例(3-15)

--带默认参数值的函数 测试题

-函数重载

--函数重载(例3-16)

--函数重载 测试题

-C++系统函数

--C++系统函数(例3-17)

--C++系统函数习题

-第3章小结

--第三章小结

-实验三(上)函数的应用

--实验三(上)函数的应用

-实验三(下)函数的应用

--实验三(下)函数的应用

第4章 类与对象

-导学

--导学

-面向对象程序的基本特点

--面向对象程序的基本特点

--面向对象程序的基本特点 测试题

-类和对象

--类和对象的定义

--类和对象的程序举例

--类和对象 测试题

-构造函数

--构造函数基本概念

--构造函数例题(1)——例4-1

--构造函数例题(2)——例4-2

--委托构造函数

--复制构造函数

--复制构造函数调用举例

--构造函数 测试题

-析构函数

--析构函数

--析构函数 测试题

-类的组合

--类的组合

--类的组合程序举例

--前向引用声明

--类的组合 测试题

-UML简介

--UML简介

--UML简介课后习题

-结构体与联合体

--结构体(例4-7)

--联合体(例4-8)

--结构体与联合体 测试题

-枚举类

--枚举类

--枚举类 测试题

-第4章小结

--第四章小结

-实验四(上)

--实验四(上)

-实验四(下)

--实验四(下)

第5章 数据的共享与保护

-导学

--导学

-标识符的作用域与可见性

--标识符的作用域与可见性

--标识符的作用域与可见性 测试题

-对象的生存期

--对象的生存期

--对象的生存期 测试题

-类的静态成员

--静态数据成员(例5-4)

--静态函数成员(例5-5)

--类的静态成员 测试题

-类的友元

--类的友元(例5-6)

--类的友元 测试题

-共享数据的保护

--共享数据的保护(例5-7)

--共享数据的保护 测试题

-多文件结构和预编译命令

--多文件结构和预编译命令(例5-10)

--多文件结构和预编译命令 测试题

-第5章小结

--小结

-实验五

--实验五

第6章 数组、指针与字符串(一)

-导学

--导学

-数组的定义与初始化

--数组的定义与使用

--数组的储存与初始化

--一维数组应用举例

--数组的定义与初始化 测试题

-数组作为函数的参数

--数组作为函数参数(例6-2)

--数组作为函数的参数 测试题

-对象数组

--对象数组

--对象数组 测试题

-基于范围的for循环

--基于范围的for循环

-指针的定义和运算

--指针的概念、定义和指针运算

--指针的初始化和赋值

--指针的算术运算、关系运算

--指针的定义和运算 测试题

-综合实例

--综合实例

-实验六(上)

--实验六上

第6章 数组、指针与字符串(二)

-指针与数组

--用指针访问数组元素

--指针数组

--指针与数组 测试题

-指针与函数

--以指针作为函数参数

--指针类型的函数

--指向函数的指针

--指针与函数 测试题

-对象指针

--对象指针

--对象指针 测试题

-动态内存分配

--动态分配与释放内存

--申请和释放动态数组(一)

--申请和释放动态数组(二)

--动态内存分配 测试题

-智能指针

--智能指针

-vector对象

--vector对象

--vector对象 测试题

-对象复制与移动

--深层复制与浅层复制

--移动构造

--对象复制与移动 测试题

-字符串

--C风格字符串

--string类

--字符串 测试题

-第6章小结

--第六章小结

-综合实例

--综合实例

-实验六(下)

--实验六(下)

例3-6笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。