用于防止玩家获得同一张牌的算法
Algorithm used to prevent a player from getting their same card
我有一个正在桌面模拟器中编码的游戏,其中所有玩家 (P) 都会获得一张卡片 (C)。记住所有玩家后,将卡片放回牌组 (D)、洗牌,然后所有玩家都会收到同一副牌 (D) 中的一张牌。我正在尝试编写最简单的算法来防止玩家获得自己的卡。现在说到编码,我假设这应该很简单,而不是创建对 运行 的模拟,直到它成功。
假设您有以下内容:
deck
,包含所有牌(包括玩家看过的牌)的随机牌组。
seen_card_id_by_player
,一个查找 table,为您提供玩家看到的卡片的 GUID。
那么解决方法就是
local card_ids = {}
for i, card_data in ipairs(deck.getObjects()) do
table.insert(card_ids, card_data.guid)
end
for player, seen_card_id in pairs(seen_card_id_by_player) do
local card_id = table.remove(card_ids)
if card_id == seen_card_id then
local i = math.random(1, #card_ids)
card_ids[i], card_id = card_id, card_ids[i]
end
-- Deal the specific card.
deck.takeObject({
guid = card_ids[i],
position = player.getHandTransform().position,
flip = true,
})
end
当我们挑选玩家已经看过的牌时,它会被放回剩余牌中的随机位置。这样可以确保每张牌都有相同的机会被下一位玩家抽到。这是Fisher-Yates shuffle.
的基本原理
完整演示
function broadcast_error(msg)
broadcastToAll(msg, { r=1, g=0, b=0 })
end
function get_cards_seen_by_players()
local player_ids = Player.getAvailableColors()
local error = false
local seen_card_by_player = {}
for i, player_id in ipairs(player_ids) do
local player = Player[player_id]
local hand_objs = player.getHandObjects()
local player_error = false
if #hand_objs > 1 then
player_error = true
elseif #hand_objs == 1 then
local card = hand_objs[1]
if card.tag ~= "Card" then
player_error = true
else
seen_card_by_player[player] = card
end
end
if player_error then
broadcast_error(player_id .. " doesn't have a valid hand.")
error = true
end
end
if error then
return nil
end
return seen_card_by_player
end
function run()
local deck = getObjectFromGUID("...")
local seen_card_by_player = get_cards_seen_by_players()
if seen_card_by_player == nil or next(seen_card_by_player) == nil then
return
end
local seen_card_id_by_player = {}
for player, card in pairs(seen_card_by_player) do
local card_id = card.guid
seen_card_id_by_player[player] = card_id
card.putObject(deck)
end
deck.randomize()
local card_ids = {}
for i, card_data in ipairs(deck.getObjects()) do
table.insert(card_ids, card_data.guid)
end
for player, seen_card_id in pairs(seen_card_id_by_player) do
local card_id = table.remove(card_ids)
if card_id == seen_card_id then
local i = math.random(1, #card_ids)
card_ids[i], card_id = card_id, card_ids[i]
end
deck.takeObject({
guid = card_ids[i],
position = player.getHandTransform().position,
flip = true,
})
end
end
用一副纸牌创建一个游戏。将上述代码放在全局中,将 ...
替换为牌组的 GUID。要 运行 演示,向任意数量的玩家发一张牌,然后在聊天中使用 /execute Global.call("run")
window。
我有一个正在桌面模拟器中编码的游戏,其中所有玩家 (P) 都会获得一张卡片 (C)。记住所有玩家后,将卡片放回牌组 (D)、洗牌,然后所有玩家都会收到同一副牌 (D) 中的一张牌。我正在尝试编写最简单的算法来防止玩家获得自己的卡。现在说到编码,我假设这应该很简单,而不是创建对 运行 的模拟,直到它成功。
假设您有以下内容:
deck
,包含所有牌(包括玩家看过的牌)的随机牌组。seen_card_id_by_player
,一个查找 table,为您提供玩家看到的卡片的 GUID。
那么解决方法就是
local card_ids = {}
for i, card_data in ipairs(deck.getObjects()) do
table.insert(card_ids, card_data.guid)
end
for player, seen_card_id in pairs(seen_card_id_by_player) do
local card_id = table.remove(card_ids)
if card_id == seen_card_id then
local i = math.random(1, #card_ids)
card_ids[i], card_id = card_id, card_ids[i]
end
-- Deal the specific card.
deck.takeObject({
guid = card_ids[i],
position = player.getHandTransform().position,
flip = true,
})
end
当我们挑选玩家已经看过的牌时,它会被放回剩余牌中的随机位置。这样可以确保每张牌都有相同的机会被下一位玩家抽到。这是Fisher-Yates shuffle.
的基本原理完整演示
function broadcast_error(msg)
broadcastToAll(msg, { r=1, g=0, b=0 })
end
function get_cards_seen_by_players()
local player_ids = Player.getAvailableColors()
local error = false
local seen_card_by_player = {}
for i, player_id in ipairs(player_ids) do
local player = Player[player_id]
local hand_objs = player.getHandObjects()
local player_error = false
if #hand_objs > 1 then
player_error = true
elseif #hand_objs == 1 then
local card = hand_objs[1]
if card.tag ~= "Card" then
player_error = true
else
seen_card_by_player[player] = card
end
end
if player_error then
broadcast_error(player_id .. " doesn't have a valid hand.")
error = true
end
end
if error then
return nil
end
return seen_card_by_player
end
function run()
local deck = getObjectFromGUID("...")
local seen_card_by_player = get_cards_seen_by_players()
if seen_card_by_player == nil or next(seen_card_by_player) == nil then
return
end
local seen_card_id_by_player = {}
for player, card in pairs(seen_card_by_player) do
local card_id = card.guid
seen_card_id_by_player[player] = card_id
card.putObject(deck)
end
deck.randomize()
local card_ids = {}
for i, card_data in ipairs(deck.getObjects()) do
table.insert(card_ids, card_data.guid)
end
for player, seen_card_id in pairs(seen_card_id_by_player) do
local card_id = table.remove(card_ids)
if card_id == seen_card_id then
local i = math.random(1, #card_ids)
card_ids[i], card_id = card_id, card_ids[i]
end
deck.takeObject({
guid = card_ids[i],
position = player.getHandTransform().position,
flip = true,
})
end
end
用一副纸牌创建一个游戏。将上述代码放在全局中,将 ...
替换为牌组的 GUID。要 运行 演示,向任意数量的玩家发一张牌,然后在聊天中使用 /execute Global.call("run")
window。