Lua 和 Love 2d 教程 二十一点朴克牌 (上篇lua源码)

GitCode - 开发者的代码家园 Lua版完整原码

规则

庄家和玩家各发两张牌。庄家的第一张牌对玩家是隐藏的。

玩家可以拿牌(即拿另一张牌)或 停牌(即停止拿牌)。

如果玩家手牌的总价值超过 21,那么他们就爆掉了。

面牌(国王K、皇后Q 和 大臣J)的值为 10,而 A 的值为 11,除非这会使手牌的总值超过 21,在这种情况下,它们的值为 1。

在玩家停牌或爆掉后,庄家拿牌,直到他们的手牌总数达到 17 或以上。

然后回合结束,总分最高的手牌(如果总分为 21 或以下)赢得回合。

控制

左键单击点击拿牌或停牌按钮

概述

每张牌都由一个表格表示,该表格包含一个代表其花色的字符串和一个代表其等级的数字。大臣、皇后和国王由数字 11、12 和 13 表示。

一副牌由一个表格表示,该表格最初包含每张牌中的一张。

['梅花'] = {1,2,3,4,5,6,7,8,9,10,11,12,13}, ['方块'] = {1,2,3,4,5,6,7,8,9,10,11,12,13}, ['红桃'] = {1,2,3,4,5,6,7,8,9,10,11,12,13}, ['黑桃'] = {1,2,3,4,5,6,7,8,9,10,11,12,13}

编码

一副纸牌

每张牌都由一个表格表示,该表格包含一个代表其花色的字符串和一个代表其等级的数字。大臣、皇后和国王由数字 11、12 和 13 表示。

为每张牌创建一个包含一张牌的牌组表。

花色: 梅花, 点数: 1
花色: 梅花, 点数: 2
花色: 梅花, 点数: 3
花色: 梅花, 点数: 4
花色: 梅花, 点数: 5
花色: 梅花, 点数: 6
花色: 梅花, 点数: 7
花色: 梅花, 点数: 8
花色: 梅花, 点数: 9
花色: 梅花, 点数: 10
花色: 梅花, 点数: 11
花色: 梅花, 点数: 12
花色: 梅花, 点数: 13
花色: 方块, 点数: 1
花色: 方块, 点数: 2
花色: 方块, 点数: 3
花色: 方块, 点数: 4
花色: 方块, 点数: 5
花色: 方块, 点数: 6
花色: 方块, 点数: 7
花色: 方块, 点数: 8
花色: 方块, 点数: 9
花色: 方块, 点数: 10
花色: 方块, 点数: 11
花色: 方块, 点数: 12
花色: 方块, 点数: 13
花色: 红桃, 点数: 1
花色: 红桃, 点数: 2
花色: 红桃, 点数: 3
花色: 红桃, 点数: 4
花色: 红桃, 点数: 5
花色: 红桃, 点数: 6
花色: 红桃, 点数: 7
花色: 红桃, 点数: 8
花色: 红桃, 点数: 9
花色: 红桃, 点数: 10
花色: 红桃, 点数: 11
花色: 红桃, 点数: 12
花色: 红桃, 点数: 13
花色: 黑桃, 点数: 1
花色: 黑桃, 点数: 2
花色: 黑桃, 点数: 3
花色: 黑桃, 点数: 4
花色: 黑桃, 点数: 5
花色: 黑桃, 点数: 6
花色: 黑桃, 点数: 7
花色: 黑桃, 点数: 8
花色: 黑桃, 点数: 9
花色: 黑桃, 点数: 10
花色: 黑桃, 点数: 11
花色: 黑桃, 点数: 12
花色: 黑桃, 点数: 13
桌面所有的牌张数: 52

 玩家和庄家的手牌由表格表示,牌在随机位置从牌组中取出,并在他们拿牌时插入他们的手中。

建立一个名为“二十一点”的类,用以初始化游戏对象


   - 定义了一个名为`二十一点`的游戏类,其中包含了一些成员变量,如牌叠、玩家手牌数组(包含闲家和庄家)、当前玩家标识、点数(闲家点数、庄家点数)等。
   - 类中实现了多个方法:
     - `新`方法用于初始化一个新的游戏对象,并调用`洗牌`方法准备游戏。
     - `洗牌`方法首先清空牌叠,然后构建一副新的扑克牌,并对其进行随机化处理。
     - `发牌`方法负责从牌叠中取出一张牌分配给指定玩家,并可以选择是否显示这张牌的内容。
     - `计算点数`方法计算玩家手中的牌面总点数,注意A在这里被特殊处理,既可视为1也可视为11点。

-- 使用模块化方法定义游戏类
局部 二十一点 = {}
二十一点.__index = 二十一点-- 初始化游戏对象
函数 二十一点.新()局部 游戏 = 设元({牌叠 = {},       -- 一副新朴克牌玩家 = {{}, {}}, -- 闲家和庄家当前玩家 = 1, -- 当前玩家闲家点数 = 0, -- 闲家点数庄家点数 = 0, -- 庄家点数输入值 = "",}, 二十一点)游戏:洗牌() -- 初始化洗牌返回 游戏
结束

首先、洗牌

在上述代码片段中,`二十一点:洗牌()` 函数是用来初始化一副新的扑克牌并进行洗牌操作的。以下是对此函数步骤的详细说明:

1. **初始化牌叠**:


    首先清空游戏对象(`self`)中的牌叠属性,将其设置为空表 `{}`。

2. **构建扑克牌集合**:


   - 使用一个循环遍历一个字典结构,该结构代表四种花色及其对应的序数(1到13,分别对应扑克牌的A到K)。这里的“匹配”可能是指 Lua 中的一种迭代机制,假设它能遍历键值对。
   - 对于每一种花色('梅花', '方块', '红桃', '黑桃'),其对应的序数列表会被逐个遍历。
   - 再次使用内部循环,通过"_ , 点数"遍历序数列表,将序数赋值给变量`点数`。

3. **添加扑克牌到牌叠**:


   - 对每个花色和点数组合,向`self.牌叠`表中插入一个新的记录,这个记录是一个包含花色和点数两个字段的表(Lua 中的哈希表)。

4. **初始化随机数种子**:


   - 使用系统当前时间作为随机数生成器的种子,确保每次洗牌时都能得到不同的随机序列。

5. **随机化牌叠**:

6. 最后调用`随机化数组`函数,

    传入刚刚构建好的牌叠`self.牌叠`,对整副牌进行随机排序,完成洗牌操作。

总结来说,这个函数完成了构建一副完整的扑克牌集合,并对其进行随机排列的过程,为接下来的游戏发牌阶段做准备。

-- 洗牌
函数 二十一点:洗牌()self.牌叠 = {}因为 花色, 序数 属于 匹配({['梅花'] = {1,2,3,4,5,6,7,8,9,10,11,12,13}, ['方块'] = {1,2,3,4,5,6,7,8,9,10,11,12,13}, ['红桃'] = {1,2,3,4,5,6,7,8,9,10,11,12,13}, ['黑桃'] = {1,2,3,4,5,6,7,8,9,10,11,12,13}}) 做因为 _, 点数 属于 序配(序数) 做表.insert(self.牌叠, {花色 = 花色, 点数 = 点数})结束结束数.randomseed(系统.time()) -- 初始化随机数生成器随机化数组(self.牌叠) -- 使用函数随机化表
结束
`随机化数组`函数,

这个函数 `随机化数组(t)` 是用来对输入的数组或表 `t` 进行原地随机排序的,通常也被称为 Fisher-Yates shuffle 或 Knuth shuffle。函数的工作原理如下:

1. 遍历数组或表 `t` 的索引,从最后一个元素开始向前遍历(即从 `i = #t` 到 `i = 2`,步长为 `-1`)。
2. 对于当前索引 `i`,生成一个随机索引 `j`,满足 `1 <= j <= i`。
3. 交换 `t[i]` 和 `t[j]` 的值,这样就将原本位于索引 `i` 处的元素移动到了一个随机位置。
4. 继续处理下一个索引,直到第一个元素(索引为 1)为止。

通过这样的过程,整个数组或表的顺序就被随机打乱了,实现了一个均匀随机分布的洗牌效果。这个算法保证了每一个元素都有均等的概率出现在任何一个位置上。

-- 定义一个用于随机化数组的函数
函数 随机化数组(t)因为 i = #t, 2, -1 做局部 j = 数.random(i)t[i], t[j] = t[j], t[i]结束
结束

第二、发牌

这段伪代码定义了一个名为“二十一点:发牌”的函数,该函数在二十一点游戏中负责给玩家发牌的操作。函数的主要逻辑如下:

- `局部 手牌 = 表.remove(self.牌叠, 1)`:从游戏状态中的公共牌堆(`self.牌叠`)中移除并返回最上面的一张牌作为玩家的新手牌。`表.remove`操作会改变原始牌堆的结构,确保每次只发一张且不重复。

- `表.insert(玩家, 手牌)`:将刚才从牌堆取出的那张手牌插入到指定玩家的手牌列表中。

- `如果 明牌 即`:检查是否需要公开显示此手牌(即明牌)。

- `输出((玩家 == self.玩家[1] 与 "闲家" 或 "庄家").."手牌 " .. 手牌.花色 ..', '.. 手牌.点数)`:如果玩家需要公开手牌,则根据玩家身份(假设`self.玩家[1]`代表闲家,否则self.玩家[2]可能是庄家或其他玩家标识)输出相应的消息,包含玩家类型、手牌的花色和点数。

总结起来,这个函数实现了从公共牌堆中抽取一张牌分配给玩家,并在需要时显示这张牌的信息。在实际应用中,它会在每轮游戏开始或者玩家请求补牌时被调用。

-- 发牌
函数 二十一点:发牌(玩家, 明牌)局部 手牌 = 表.remove(self.牌叠, 1)表.insert(玩家, 手牌)如果 明牌 即输出((玩家 == self.玩家[1] 与 "闲家" 或 "庄家").."手牌 " .. 手牌.花色 ..', '.. 手牌.点数)结束
结束

闲家手牌 梅花, 11
闲家手牌 黑桃, 13
庄家手牌 梅花, 1

第三、计算点数

这段伪代码描述了一个名为“二十一点:计算点数”的函数,用于计算玩家手中所有牌的总点数。在二十一点游戏中,每个玩家手牌的点数之和不能超过21点。函数逻辑分解如下:

1. 初始化两个局部变量:

`合计` 设置为0,用于累计玩家手牌的点数总和。
`尖儿` 设置为假(False),用于标记玩家手中是否有A(Ace)牌且未确定其点数是1还是11。

2. 遍历玩家手中的每张牌(通过`序配(玩家)`得到一个序列):

对于每张牌,如果牌的点数大于10(通常表示是J、Q、K),则将其视为10点加到合计中。
若牌的点数不是大于10,则直接将其点数加到合计上。
如果当前牌的点数等于1(即A牌),则设置`尖儿`为真(True),表示有可以计为1或11点的A牌。

3. 检查是否有A牌并且当前合计点数小于12:

如果满足条件,则将合计点数加上10点,因为在这种情况下A牌可以视为11点而不至于爆牌(超过21点)。

4. 最后,函数返回累计的点数合计值。

整个函数的作用就是计算玩家手牌的最佳点数总和,在处理A牌时考虑其可能作为1点或11点的灵活性。

目前,键盘用于输入,而不是屏幕上的按钮。

当按下h键时,玩家从牌组中取出一张牌。

输出("拿牌请按h, 停牌请按s, 退出请按q")
输入 = 端口.read("*line") 
如果 输入 == "h" 即发牌(闲家,"闲家")计算点数(闲家,"闲家")输出("拿牌请按h, 停牌请按s, 退出请按q")输入 = 端口.read("*line") 
结束

第四、闲家发牌逻辑 (闲家操作) 判断游戏是否结束

这段代码定义了一个名为“二十一点:游戏结束吗”的函数,该函数用于判断游戏是否因闲家点数超过21点而结束。下面是详细的解释:

1. `self.闲家点数 = self:计算点数(self.玩家[1])`: 首先,通过调用“计算点数”函数计算闲家(玩家1)当前手中的牌的总点数,并将该点数赋值给类实例变量`self.闲家点数`。

2. `如果 self.闲家点数 > 21 即`: 检查闲家的点数是否超过了21点。

3. `返回 真`: 如果闲家点数确实超过了21点,那么函数返回`真`(即`true`),表示游戏结束,闲家输了(爆牌)。

4. `结束`: 结束“如果”条件判断。

5. `返回 假`: 如果闲家点数没有超过21点,函数返回`假`(即`false`),表示游戏尚未结束。

总之,这个函数主要是用来检测闲家是否爆牌,如果爆牌则返回`true`,否则返回`false`。在实际游戏流程中,游戏会根据这个函数的返回结果来判断是否应该继续进行下一轮发牌或宣布游戏结果。

-- 闲家发牌逻辑 (闲家操作) 判断游戏是否结束
函数 二十一点:游戏结束吗()self.闲家点数 = self:计算点数(self.玩家[1])如果 self.闲家点数 > 21 即返回 真结束返回 假
结束

第五、检查玩家是否停牌,并处理相关逻辑

这段代码定义了一个名为“二十一点:要牌吗”的函数,该函数负责处理玩家是否选择要牌(hit)或停牌(stand)的逻辑,同时也处理重新开始游戏(new game)和退出游戏(quit)的选项。以下是函数逻辑的具体说明:

1. 输出提示信息,告知玩家可选操作:

“h-要牌”,“s-停牌”,“b-重新开始”,“q-退出”。

2. 通过`端口.read("*line")`读取玩家从控制台输入的命令,并将其保存在`self.输入值`变量中。
3. 根据玩家输入的指令进行不同操作:

- 如果输入是"h",则调用`self:发牌`函数给当前玩家发一张牌,并显示牌面(`真`表示明牌)。
- 如果输入是"s",则:
- 如果当前玩家是闲家(`self.当前玩家 == 1`),切换到庄家回合(`self.当前玩家 = 2`)。
- 如果输入是"b",则:
- 不进行洗牌操作(注释掉了`self:洗牌()`)。
- 直接调用`self:新游戏()`开始新一轮游戏。
- 输出提示信息“-----------------再来!--------------”。
- 如果输入是"q",则:
- 将闲家点数和庄家点数设置为非有效值(这里是字符串"虚")。
- 使用`系统.exit()`退出当前程序。
- 如果输入既不是"h"也不是"s"、"b"或"q",则认为是无效输入,输出错误提示信息,并返回`假`。

4. 输入有误,跳出程序

在任何情况下,如果没有提前返回,最后默认返回`假`。这是因为在实际游戏中,此函数需要配合其他逻辑判断跳出游戏的循环。

-- 检查玩家是否停牌,并处理相关逻辑
函数 二十一点:要牌吗()输出("请选择:h-要牌,s-停牌,b-重新开始,q-退出")self.输入值 = 端口.read("*line")如果 self.输入值 == "h" 即self:发牌(self.玩家[self.当前玩家], 真)要么 self.输入值 == "s" 即如果 self.当前玩家 == 1 即self.当前玩家 = 2 -- 更改为庄家回合结束要么 self.输入值 == "b" 即--self:洗牌()--self.当前玩家 = 1self:新游戏()输出("-----------------再来!--------------")要么 self.输入值 == "q" 即闲家点数 = "虚"庄家点数 = "虚"   系统.exit() -- 退出程序否则输出("无效输入,请重新输入。")返回 假结束返回 假
结束

第六、庄家发牌逻辑 (电脑自动操作)

这段代码定义了一个名为“二十一点:庄家发牌”的函数,用于在游戏中庄家自动发牌的逻辑。以下是该函数的具体解析:

在二十一点游戏中,庄家发牌遵循一定规则,通常是直到点数达到17点或更高时停止拿牌。在此函数中:

1. 使用一个“当...做...结束”循环结构,只要庄家(`self.玩家[2]`)的点数(通过调用`self:计算点数(self.玩家[2])`计算得出)小于17点,循环就会继续执行。

2. 在循环体内,调用`self:发牌(self.玩家[2], 假)`函数给庄家发一张牌,并且不显示庄家收到的这张牌(`假`表示暗牌)。

3. 循环结束后,意味着庄家的点数已经达到或超过17点,庄家不再拿牌。

总结来说,这个函数实现的功能是自动为庄家发牌,直到庄家的点数达到或超过17点为止。在实际游戏中,庄家这一自动发牌逻辑有助于确保游戏公平且符合二十一点的基本规则。

-- 庄家发牌逻辑 (电脑自动操作)
函数 二十一点:庄家发牌()当 self:计算点数(self.玩家[2]) < 17 做self:发牌(self.玩家[2], 假) -- 不显示庄家手牌结束
结束

第七、添加一个用于统一打印玩家手牌的函数

这段代码定义了一个名为“二十一点:开牌”的函数,用于打印展示两位玩家(闲家和庄家)各自的手牌信息。以下是函数的具体解释:

1. 函数开始时,首先输出一行提示信息 "\n闲家手牌:",表示即将展示闲家的手牌。

2. 使用一个“因为...做...结束”循环结构遍历闲家(`self.玩家[1]`)的手牌。这里的“序配”应理解为遍历数组或表中的元素,依次取出闲家手牌列表中的每一张牌。

3. 在循环体内,输出每张牌的花色和点数,格式为“花色, 点数”,如“梅花, 10”。

4. 输出完闲家的手牌后,紧接着输出一行提示信息 "\n庄家手牌:",表示即将展示庄家的手牌。

5. 同样使用一个“因为...做...结束”循环结构遍历庄家(`self.玩家[2]`)的手牌,并逐一输出每张牌的花色和点数。

6. 循环结束后,所有的闲家和庄家手牌信息都被打印出来,展示了当前每位玩家手中持有的所有扑克牌详情。

总之,这个函数的主要功能是在游戏过程中展示两位玩家的手牌,便于玩家了解当前局势。

-- 添加一个用于统一打印玩家手牌的函数
函数 二十一点:开牌()输出("\n闲家手牌:")因为 _, 手牌 属于 序配(self.玩家[1]) 做输出(手牌.花色 .. ', ' .. 手牌.点数)结束输出("\n庄家手牌:")因为 _, 手牌 属于 序配(self.玩家[2]) 做输出(手牌.花色 .. ', ' .. 手牌.点数)结束结束

 第八、计算并显示二十一点游戏中的闲家和庄家的点数的函数

函数“二十一点:合计点数”主要负责输出两位玩家(闲家和庄家)的当前点数,并给出游戏菜单选项。以下是详细解读:

1. 函数首先输出闲家的点数,格式为“闲家点数 [具体点数值]”。这里使用了预先计算并存储在`self.闲家点数`中的点数值。

2. 接着,调用`self:计算点数(self.玩家[2])`方法来计算庄家的当前点数,并将结果存入`self.庄家点数`变量中。

3. 输出庄家的点数,格式为“庄家点数 [具体点数值]”。

4. 最后,输出一段游戏菜单,提示用户可以输入'b'重新开始游戏,或输入'q'退出游戏,以供玩家作出下一步操作的选择。

需要注意的是,这个函数并没有处理用户输入的逻辑,只是单纯地展示了当前的点数状况以及游戏菜单选项。在实际游戏中,可能会有另外的函数或逻辑来处理用户根据这些选项作出的决策。

函数 二十一点:合计点数()输出("\n闲家点数", self.闲家点数)self.庄家点数 = self:计算点数(self.玩家[2])输出("庄家点数", self.庄家点数)输出('--------------------b-重新开始!--------------------q-退出游戏!--------------------')结束   

第九、游戏主循环

这段代码定义了一个名为“二十一点:开局”的函数,它实现了二十一点游戏的主循环逻辑,具体步骤如下:

1. 给闲家发两张牌,并显示这两张牌(`self:发牌(self.玩家[1], 真)`两次)。
2. 给庄家发两张牌,其中第一张牌不显示(`self:发牌(self.玩家[2], 假)`),第二张牌显示(`self:发牌(self.玩家[2], 真)`)。

3. 进入玩家回合循环,当当前玩家是闲家(`self.当前玩家 == 1`)且游戏尚未结束(`非 self:游戏结束吗()`)时,询问玩家是否要牌(`self:要牌吗()`)。

4. 检查闲家是否爆牌(点数超过21):
   - 如果闲家爆牌,则:
     - 展示所有玩家的手牌(`self:开牌()`)。
     - 显示所有玩家的点数(`self:合计点数()`)。
     - 输出“闲家爆牌,庄家赢”。
   - 否则(闲家未爆牌):
     - 庄家自动发牌直到点数达到17或以上(`self:庄家发牌()`)。
     - 展示所有玩家的手牌(`self:开牌()`)。
     - 显示所有玩家的点数(`self:合计点数()`)。
     - 根据闲家和庄家点数判断游戏胜负:
       - 如果庄家爆牌,则输出“庄家爆牌,闲家赢”。
       - 如果闲家点数大于庄家点数,则输出“闲家赢”。
       - 如果庄家点数大于闲家点数,则输出“庄家赢”。
       - 如果两者点数相等,则输出“平局”。

5. 读取玩家输入(`self.输入值 = 端口.read("*line")`),如果玩家输入的是“b”,则重新开始游戏(`self:新游戏()`)。

这个函数涵盖了游戏的主要流程,包括发牌、玩家决策、庄家自动发牌、胜负判断以及游戏重置等功能。

-- 游戏主循环
函数 二十一点:开局()self:发牌(self.玩家[1], 真) -- 给闲家发第一张牌并显示self:发牌(self.玩家[1], 真) -- 给闲家发第二张牌并显示self:发牌(self.玩家[2], 假) -- 给庄家发第一张牌(不显示)self:发牌(self.玩家[2], 真) -- 给庄家发第二张牌并显示当 self.当前玩家 == 1 与 非 self:游戏结束吗() 做self:要牌吗() -- 玩家选择是否要牌结束如果 self.闲家点数 > 21 即-- 在闲家爆牌或停牌后展示闲家和庄家的所有牌self:开牌() -- 展示所有玩家手牌self:合计点数() -- 展示所有玩家点数输出("闲家爆牌,庄家赢")否则self:庄家发牌() -- 庄家自动发牌到点数达到17或以上self:开牌() -- 展示所有玩家手牌self:合计点数() -- 展示所有玩家点数-- 判断胜负如果 self.庄家点数 > 21 即输出("庄家爆牌,闲家赢")要么 self.闲家点数 > self.庄家点数 即输出("闲家赢")要么 self.庄家点数 > self.闲家点数 即输出("庄家赢")否则输出("平局")结束结束self.输入值 = 端口.read("*line") -- 读取玩家输入如果 self.输入值 == "b" 即self:新游戏() -- 如果输入b,则重新开始游戏结束结束

 第十、重新开始游戏及初始化游戏并开始

这段代码中包含两个函数定义及一个游戏初始化的调用:

1. **函数二十一点:新游戏()**:
   - 此函数用于重启新的一局游戏。首先,它调用`self:洗牌()`方法重新洗牌,确保下一局游戏开始时使用全新的、随机排列的牌堆。
   - 然后,清空闲家(`self.玩家[1]`)和庄家(`self.玩家[2]`)的手牌,将它们重置为空列表。
   - 设置当前玩家为闲家,即`self.当前玩家 = 1`。
   - 输出欢迎信息“--------------------再来!--------------------”,提示玩家新的一局即将开始。
   - 最后,调用`self:开局()`方法开始新一局游戏。

2. **初始化游戏并开始**:
   - 创建一个`二十一点`类的新实例,命名为`游戏`,通过调用`二十一点.新()`方法初始化游戏。
   - 初始化完成后,立即调用`游戏:开局()`方法启动游戏的第一局。

综上所述,这段代码实现了游戏的初始化和重启功能,确保每一局游戏开始时所有状态都被正确重置,并能够顺利进入游戏循环。

-- 重新开始游戏
函数 二十一点:新游戏()self:洗牌() -- 重新洗牌self.玩家[1] = {} -- 重置闲家手牌self.玩家[2] = {} -- 重置庄家手牌self.当前玩家 = 1输出("--------------------再来!--------------------")self:开局() -- 开始新一局游戏
结束-- 初始化游戏并开始
局部 游戏 = 二十一点.新()
游戏:开局()

总结:

这段伪代码描述了一个基于Lua编写的二十一点游戏的核心逻辑实现,其中包括了构建扑克牌集合、洗牌、发牌、计算点数、玩家决策处理、庄家发牌逻辑、显示玩家手牌、总计点数以及游戏主循环等功能。游戏的主要流程如下:

1. **初始化游戏对象**:
   - 创建一个`二十一点`类的对象,该类包含了游戏所需的数据结构和方法。
   - 初始化牌堆,构建一副扑克牌,并使用Fisher-Yates shuffle算法对其洗牌。

2. **发牌过程**:
   - 玩家(闲家)和庄家各发两张牌,闲家的两张牌全部公开,庄家的第一张牌隐藏。
   - 玩家可以通过输入决定是否要牌(hit)或停牌(stand)。
   - 当玩家选择停牌后,庄家根据预设规则自动拿牌至点数达到17或以上。

3. **计算点数**:
   - 实现了一个计算点数的方法,特别处理A牌的点数为1或11以避免爆牌的情况。

4. **游戏流程控制**:
   - 玩家可以选择重新开始游戏(new game)或退出游戏(quit)。
   - 游戏主循环会一直持续到玩家选择结束或满足游戏结束条件(例如闲家爆牌)。

5. **判定胜负**:
   - 游戏结束后,比较闲家和庄家的点数,点数接近但不超过21的玩家获胜;若双方点数相同则是平局;若玩家爆牌,则庄家胜出。

6. **用户交互**:
   - 通过键盘输入控制玩家行为,如'h'表示要牌,'s'表示停牌,'b'表示重新开始游戏,'q'表示退出游戏。

7. **输出信息**:
   - 游戏中适时输出相关信息,如玩家手牌、点数、游戏菜单选项等。

通过这套逻辑框架,可以构建起一个基本的二十一点游戏,但仍需配合适当的用户输入/输出接口(如命令行或图形用户界面)才能成为一个可玩的完整游戏应用程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/295418.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构——红黑树详解

一、红黑树的定义 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路径会比其他路径长出两倍&#xff0c…

数据库加载驱动问题(java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver)

java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver 遇到此问题&#xff0c;首先检查IDEA外部库中是否有mysql数据库驱动。如下所示&#xff1a; 如果发现外部库中存有mysql数据库驱动&#xff0c;需要在数据库配置文件中查看是否设置有时区mysql8.0以上版本需要设…

【机器学习】机器学习创建算法第3篇:K-近邻算法,学习目标【附代码文档】

机器学习&#xff08;算法篇&#xff09;完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;机器学习算法课程定位、目标&#xff0c;K-近邻算法定位,目标,学习目标,1 什么是K-近邻算法,1 Scikit-learn工具介绍,2 K-近邻算法API。K-近邻算法&#xff0c;1.4 …

rhce复习2

HTTPS协议 https简介 超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息。HTTP协议以明文方式发送内容&#xff0c;不提供任何方式的数据加密&#xff0c;如果攻击者截取了Web浏览器和网站服务器之间的传输报文&#xff0c;就可以直接读懂其中的信息&#xf…

Canal1.1.5整Springboot在MQ模式和TCP模式监听mysql

canal本实验使用的是1.1.5&#xff0c;自行决定版本&#xff1a;[https://github.com/alibaba/canal/releases] canal 涉及的几个角色 canal-admin&#xff1a;canal 后台管理系统&#xff0c;管理 canal 服务canal-deployer&#xff1a;即canal-server&#xff08;客户端&…

某眼实时票房接口获取

某眼实时票房接口获取 前言解决方案1.找到veri.js2.找到signKey所在位置3.分析它所处的这个函数的内容4.index参数的获取5.signKey参数的获取运行结果关键代码另一种思路票房接口:https://piaofang.maoyan.com/dashboard-ajax https://piaofang.maoyan.com/dashboard 实时票房…

Meta 推出Ego-Exo4D:一个研究视频学习和多模态感知的基础数据集

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

安全架构设计理论与实践相关知识总结

一、安全架构概述 常见信息威胁介绍&#xff1a; 1. 信息泄露&#xff1a;信息被泄露或透露给某个非授权实体 2. 破坏信息完整性&#xff1a;数据被非授权地进行增删改查货破坏而受到损失 3. 拒绝服务&#xff1a;对信息会其他资源的合法访问被无条件的组织 4. 非法使用&#x…

IDE/VS2015和VS2017帮助文档MSDN安装和使用

文章目录 概述VS2015MSDN离线安装离线MSDN的下载离线MSDN安装 MSDN使用方法从VS内F1启动直接启动帮助程序跳转到了Qt的帮助网页 VS2017在线安装MSDN有些函数在本地MSDN没有帮助&#xff1f;切换中英文在线帮助文档 概述 本文主要介绍了VS集成开发环境中&#xff0c;帮助文档MS…

hibernate session接口

hibernate session接口 Session接口是hibernate向应用程序提供的操纵数据库的最主要的接口&#xff0c;提供了保存、更新、删除和加载Java对象的方法。 session具有一个缓存&#xff0c;位于缓存中的对象成为持久化对象&#xff0c;和数据库中的相关记录对应。session能够在某些…

【御控物联】JavaScript JSON结构转换(17):数组To对象——键值互换属性重组

文章目录 一、JSON结构转换是什么&#xff1f;二、核心构件之转换映射三、案例之《JSON数组 To JSON对象》四、代码实现五、在线转换工具六、技术资料 一、JSON结构转换是什么&#xff1f; JSON结构转换指的是将一个JSON对象或JSON数组按照一定规则进行重组、筛选、映射或转换…

MES可视化管理,提高制造业工厂管理水平

在制造业中&#xff0c;生产过程的可视化管理对于提高生产效率、降低成本以及提升决策的准确性和及时性至关重要。MES系统作为制造执行过程中的核心管理工具&#xff0c;为实现生产过程的可视化管理提供了有力支持。 生产车间应用MES生产管理系统之后&#xff0c;能通过电子屏幕…

异地文件如何共享访问?

异地文件共享访问是一种让不同地区的用户能够快速、安全地共享文件的解决方案。人们越来越需要在不同地点之间共享文件和数据。由于复杂的网络环境和安全性的问题&#xff0c;实现异地文件共享一直是一个挑战。 为了解决这个问题&#xff0c;许多公司和组织研发了各种异地文件共…

集成电路企业tapeout,如何保证机台数据准确、完整、高效地采集?

Tapeout即流片&#xff0c;集成电路行业中将CDS最终版电路图提交给半导体制造厂商进行物理生产的过程。在芯片设计与制造的流程中&#xff0c;Tapeout是非常重要的阶段&#xff0c;包括了布局&#xff08;Layout&#xff09;、连线&#xff08;Routing&#xff09;、分析&#…

基于SSM的“汽车销售分析与管理系统”的设计与实现(源码+数据库+文档+PPT)

基于SSM的“汽车销售分析与管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统功能结构图 销售经理系统首页图 客户管理图 车辆…

数据采集工具如何使用呢?那么设置数据采集的方法又是什么呢?

数据采集工具将能够非常有效地解决面临的各种问题。这款工具被设计成一种自动化数据采集工具&#xff0c;特别适用于对日志文件数据的采集。一旦完成设置&#xff0c;该工具将在后台实时进行数据采集&#xff0c;并自动对收集到的数据进行清洗&#xff0c;以确保最终保存到的数…

Redis简介、常用命令

目录 一、关系数据库​​与非关系数据库​​ 1.1. 关系型数据库 1.2 非关系型数据库 1.3.关系数据库与非关系型数据库区别 1.3.1. 数据存储方式不同 1.3.2. 扩展方式不同 1.3.3.对事务性的支持不同 1.4.非关系型数据库产生背景 二、Redis 2.1.Redis简介 2.2.Redis的…

CentOS 7 下离线安装RabbitMQ教程

CentOS 7 下安装RabbitMQ教程一、做准备&#xff08;VMWare 虚拟机上的 CentOS 7 镜像 上安装的&#xff09; &#xff08;1&#xff09;准备RabbitMQ的安装包&#xff08;rabbitmq-server-3.8.5-1.el7.noarch&#xff09;下载地址mq https://github.com/rabbitmq/rabbitmq-se…

【OpenCV-颜色空间】

OpenCV-颜色空间 ■ RGB■ BGR■ HSV■ HSL■ HUE■ YUV ■ RGB ■ BGR BGR 就是RGB R和B调换位置。 OpenCV 默认使用BGR ■ HSV ■ HSL ■ HUE ■ YUV

实验四 微信小程序智能手机互联网程序设计(微信程序方向)实验报告

请编写一个用户登录界面&#xff0c;提示输入用户名和密码进行登录&#xff1b; 代码 index.wxml <view class"user"> <form bindreset""> <view>用户名&#xff1a;</view><input type"text"name""/>…