本教程探讨了基本洗牌以及如何在 Corona/Lua 中实现它。例如,考虑一个基本的纸牌游戏,其中,玩家抽一张随机的牌。最初的考虑可能是简单使用 math.random()
选择一张随机的牌,但是不同于重复出现多个数字的掷骰子,一张特定的牌在游戏过程中只应出现一次。
基本而言,每次需要从一个较大的集合中抽取一个项目并确保它从不重复时都可应用洗牌逻辑,例如
我们进一步探讨“牌组”场景,在该场景中,在每场游戏开始之前,牌组都会洗牌。在 Lua 中,可以通过对一个值表进行随机排序来实现这一点。下面基于标准扑克牌来看一个基本示例
local cardDeck = { "AS", "AH", "2S", "3S", "KH", "QD", "QS", "KD", "4D", "10H" }
显然,对于一个实际的纸牌游戏,你需要用全部 52 张扑克牌来填充该表,但为了本教程,我们将保持简单。
凭借这个
math.randomseed( os.time() ) -- Seed the pseudo-random number generator local function shuffleTable( t ) if ( type(t) ~= "table" ) then print( "WARNING: shuffleTable() function expects a table" ) return false end local j for i = #t, 2, -1 do j = math.random( i ) t[i], t[j] = t[j], t[i] end return t end cardDeck = shuffleTable( cardDeck )
更详细地检查此代码,我们执行以下任务
在第一行,我们设置main.lua
顶部附近的位置。
在函数内部,我们首先确认一个 Lua 表作为唯一的参数传递进来。如果不是,该函数将发出警告并返回 false
。
接下来,我们反向循环该表 (t
)。此处,循环索引 (i
) 是尚未洗牌的项目的计数。在循环内部,我们在 1
到 i
之间生成一个随机数,然后交换这两个表项目。此处理将重复进行,直至
最后一行调用该函数并有效地洗牌组,并将结果设置回表示牌组的 cardDeck
变量。
在对该表进行洗牌后,我们可以使用以下代码来从该组中选牌。由于该表本身已经按随机顺序排列,因此我们不必担心生成随机数,只须在列表中获取下一个数字即可。我们也不必“从currentIndex
来表示牌组顶部是什么牌。此变量在游戏开始时从 1
开始,在抽牌时,它以相同的值递增
local currentIndex = 1 -- Deck starts at top card (1) local function drawCards( num, deck ) local cardsDrawn = {} -- Empty table to begin for i = currentIndex, num do cardsDrawn[#cardsDrawn+1] = deck[i] end currentIndex = currentIndex + num return cardsDrawn end -- Deal 5 cards to a player local playerHand = drawCards( 5, cardDeck )
让我们更详细地看看此代码
如上所述,我们最初设置一个变量 currentIndex
为 1
来表示牌组顶部。
在 drawCards()
函数内的第一行,我们创建一个本地空表 (cardsDrawn
) 以存储要抽取的卡牌。
在随后的循环中,我们简单地从 currentIndex
循环 num
次并将卡牌存储在 cardsDrawn
表中。
在函数的结尾,我们将 currentIndex
增加 num
,有效地表明从牌组抽取了 num
张卡牌。
要抽取卡牌,只需用一定数量的卡牌(5
)和要从中抽取卡牌的牌组(上一部分代码中的 cardDeck
)调用 drawCards()
函数。
当牌组耗尽和/或您想开始新游戏时,您可以只洗牌、将 currentIndex
重置为 1
并重新开始。由于未从主卡牌表(cardDeck
)中“移除”卡牌,因此不需要
您可看到,创建一个