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.mzph.cn/news/793438.shtml

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

相关文章

Django源码之路由的本质(上)——逐步剖析底层执行流程

目录 1. 前言 2. 路由定义 3. 路由定义整体源码分析 3.1 partial实现path函数调用 3.2 图解_path函数 3.3 最终 4.URLPattern和Pattern的简单解析 5. 小结 1. 前言 在学习Django框架的时候&#xff0c;我们大多时候都只会使用如何去开发项目&#xff0c;对其实现流程并…

鸽哒言讯独家最新im即时通讯系统双端源码下载 (中越双语)带安卓未封装、苹果未封装、PC端(全开源)+部署教程

独家最新im即时通讯系统双端源码下载 &#xff08;中越双语&#xff09;带安卓未封装、苹果未封装、PC端&#xff08;全开源&#xff09;部署教程鸽哒IM即时通讯系统是一款类似于weixin的即时通讯软件&#xff0c;具有独立开发的特点。与网络其他聊天软件相比&#xff0c;即时聊…

文件同步工具哪个好

背景 今天介绍一款文件实时同步工具PanguFlow,它能够实时地监控源端文件夹的变化&#xff0c;然后将这种变化实时同步到目标端&#xff0c;对于文件灾备冗余的场景可谓是再合适不过了&#xff0c;一些老铁可能有这样的需求&#xff0c;比如两台服务器需要做文件的双机热备&…

模拟退火遗传算法GASA-附MATLAB代码

模拟退火遗传算法&#xff08;Simulated Annealing Genetic Algorithm&#xff0c;SAGA&#xff09;结合了模拟退火算法&#xff08;Simulated Annealing&#xff0c;SA&#xff09;和遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;的优点&#xff0c;用于解…

956: 约瑟夫问题的实现

【学习版】 【C语言】 #include <iostream> #include <string> #include <algorithm> #include <cmath> #include <cstdlib> using namespace std; typedef struct Lnode {int date;struct Lnode* next; }Lnode, * Linklist; int In(Linklist&…

如何开发创建自己的npm包并成功发布、维护至npm官方网站

npm&#xff0c;全称为Node Package Manager&#xff0c;是专为JavaScript生态系统设计的软件包管理系统&#xff0c;尤其与Node.js平台紧密关联。作为Node.js的默认包管理工具&#xff0c;npm为开发者提供了便捷的方式来安装、共享、分发和管理代码模块。 npm作为JavaScript世…

ROS 2边学边练(12)-- 创建一个工作空间

上一篇我们已经接触过工作空间的概念&#xff0c;并简单了解体验了一点构建包、测试包的流程&#xff0c;此篇会深入一点学习工作空间相关内容。 前言 一个工作空间是包含了ROS 2的功能包的目录&#xff08;文件夹&#xff09;&#xff0c;在使用ROS 2之前我们得激活一下目标工…

Codeforces CodeTON Round 8(Div.1 + Div.2) A~E

A. Farmer John’s Challenge (模拟) 题意&#xff1a; 构造一个长度为 n n n的数组&#xff0c;将这些数组围成一个圈&#xff08;顺时针&#xff09;从任意一个位置打开&#xff0c;有且仅有 k k k个非降序排列的数组。 分析&#xff1a; k 1 k1 k1时&#xff0c;升序输…

如何删除 iPhone 上的 iCloud 激活锁

Apple 在 iPhone 上通过不同的安全屏障来保护您的数据。 iCloud 激活锁可阻止外部人员访问您的手机。您可以通过打开“查找我的 iPhone”功能来激活此锁。 使用安全协议似乎是无害的&#xff0c;直到你到达门的另一边。如果您购买了带有激活锁的二手 iPhone 或忘记了 iCloud 凭…

「精细化管理」某物业集团精细化管理咨询项目纪实

实现工作例行化、定时化、程序化与可视化企业重视绩效考核&#xff0c;却总感觉考核不到点上&#xff1b;企业重视规划职责&#xff0c;却总感觉部门间职责不清&#xff1b;企业重视激励&#xff0c;却总感觉难以真正激励员工。到底是哪里出了问题&#xff1f;华恒智信指出&…

win11安装WSL UbuntuTLS

win11安装WSL WSL 简介WSL 1 VS WSL 2先决要求安装方法一键安装通过「控制面板」安装 WSL 基本命令Linux发行版安装Ubuntu初始化相关设置root用户密码网络工具安装安装1panel面板指导 WSl可视化工具问题总结WSL更新命令错误Ubuntu 启动初始化错误未解决问题 WSL 简介 Windows …

【QT+QGIS跨平台编译】056:【pdal_kazhdan+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

点击查看专栏目录 文章目录 一、pdal_kazhdan介绍二、pdal下载三、文件分析四、pro文件五、编译实践一、pdal_kazhdan介绍 pdal_kazhdan 是 PDAL(Point Data Abstraction Library)相关的 Kazhdan 算法的实现。PDAL 是一个用于处理和分析点云数据的开源库,而 Kazhdan 算法通常…

C语言 | Leetcode C语言题解之第9题回文数

题目&#xff1a; 题解&#xff1a; bool isPalindrome(int x) {if(x < 0)return false;long int sum0;long int nx;while(n!0){sumsum*10n%10;nn/10;}if(sumx)return true;elsereturn false; }

LLaMA-Factory微调(sft)ChatGLM3-6B保姆教程

LLaMA-Factory微调&#xff08;sft&#xff09;ChatGLM3-6B保姆教程 准备 1、下载 下载LLaMA-Factory下载ChatGLM3-6B下载ChatGLM3windows下载CUDA ToolKit 12.1 &#xff08;本人是在windows进行训练的&#xff0c;显卡GTX 1660 Ti&#xff09; CUDA安装完毕后&#xff0c…

前端路径问题总结

1.相对路径 不以/开头 以当前资源的所在路径为出发点去找目标资源 语法: ./表示当前资源的路径 ../表示当前资源的上一层路径 缺点:不同位置,相对路径写法不同2.绝对路径 以固定的路径作为出发点作为目标资源,和当前资源所在路径没关系 语法:以/开头,不同的项目中,固定的路径…

【Godot4自学手册】第三十四节来回无限滚动的伤害铁刺球

本节主要学习给地宫添加来回滚动的铁刺球&#xff0c;铁刺球共有两个方向&#xff0c;一个是左右方向&#xff1b;另一个是上下方向。如果主人公不小心碰到球&#xff0c;就会收到伤害。这是地宫的第一个机关。 一、新建场景并布局节点 把我们准备好的铁球图片素材拖入到文件…

基于单片机的测时仪系统设计

**单片机设计介绍&#xff0c;基于单片机的测时仪系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的测时仪系统设计是一个结合了单片机技术与测时技术的综合性项目。该设计的目标是创建一款精度高、稳定性强且…

【数据结构】复杂度(长期维护)

本篇博客主要是浅谈数据结构概念及时间复杂度&#xff0c;并做长期的维护更新&#xff0c;有需要借鉴即可。 复杂度目录 一、初识数据结构1.基础概念2.如何学好数据结构 二、复杂度1.复杂度2.时间复杂度①有限数的时间复杂度②函数的时间复杂度③二分查找时间复杂度④递归拓展练…

汇编语言作业(二)

目录 一、实验目的 二、实验内容 三、实验步骤以及结果 四、实验结果与分析 五、实验总结 一、实验目的 1、巩固debug命令 2、使用 debug 来进行寄存器、内存中内容的查看和修改 3、使用 debug 来进行程序的调试 二、实验内容 上图是一段指令代码 &#xff0c;机器码和汇编…

ubuntu更换国内镜像源,下载增速

方法一&#xff1a;通过脚本更换源 1.备份原来的源 sudo cp /etc/apt/sources.list /etc/apt/sources_init.list 将原来的源保留一下&#xff0c;以后想用还可以继续用 2.更换源 sudo gedit /etc/apt/sources.list 使用gedit打开文档&#xff0c;将下面的阿里源复制进去&am…