local propEnum = {
None = 0,
Corn = 1,
Wheat = 2,
Soybean = 3,
Count = 4,
}
local PropEnum = propEnum
local numberOfProp = {
[propEnum.Corn] = 4,
[propEnum.Wheat] = 7,
[propEnum.Soybean] = 8,
}
local propToScore = {
[propEnum.Corn] = 4,
[propEnum.Wheat] = 3,
[propEnum.Soybean] = 2,
}
local CountToStartProducing = 3
local ScoreGetBingo = 30
local LoopCount = 10000
local DebugOut = false
if DebugOut then
LoopCount = 1
end
local InvalidNum = 0
local RowCount = 5
local ColumnCount = 5
local CellCount = RowCount * ColumnCount
math.randomseed(os.time())
local function shuffleTable(t, startIndex, endIndex)
if startIndex == nil then
startIndex = 1
end
if endIndex == nil then
endIndex = #t
end
for i = startIndex, endIndex do
local randomIndex = math.random(startIndex, endIndex)
local tempValue = t[i]
t[i] = t[randomIndex]
t[randomIndex] = tempValue
end
end
function table.contain(t, v)
for _, value in pairs(t) do
if value == v then
return true
end
end
return false
end
local EnergyToEmoji = {
[propEnum.Corn] = "��",
[propEnum.Wheat] = "��",
[propEnum.Soybean] = "��",
}
local function getOneCell(number)
local cell = { }
cell.cellNum = number
cell.tag = propEnum.None
function cell:resetTag()
self.tag = propEnum.None
end
function cell:setTag(tag)
self.tag = tag
end
function cell:getDescription()
local cellNumStr = "��"
if self.cellNum ~= InvalidNum then
cellNumStr = tostring(self.cellNum)
if string.len(cellNumStr) == 1 then
cellNumStr = cellNumStr .. " "
end
end
if self.tag == propEnum.None then
return string.format("{%s, }", cellNumStr)
else
return string.format("{%s, %s}", cellNumStr, EnergyToEmoji[self.tag])
end
end
function cell:beenTagged()
if self.cellNum == InvalidNum then
return false, 0
end
self.cellNum = InvalidNum
return true, self.tag
end
return cell
end
local function addTagToBoard(board)
local currentIndex = 1
for propId = PropEnum.None + 1, PropEnum.Count - 1, 1 do
local tagCount = numberOfProp[propId] or 0
while tagCount > 0 and currentIndex <= #board do
board[currentIndex].tag = propId
tagCount = tagCount - 1
currentIndex = currentIndex + 1
end
end
shuffleTable(board, 1, #board)
end
local function PrintCurrentState(board, currentScore, ballStr, extraMsg, ignore)
local str = ""
for i = 1, RowCount, 1 do
for j = 1, ColumnCount, 1 do
local cellIndex = (i - 1) * ColumnCount + j
local cell = board[cellIndex]
str = str .. string.format("%s ", cell:getDescription())
end
if i ~= RowCount then
str = str .. "\r\n"
end
end
if ballStr and ballStr ~= InvalidNum then
print("Read ball: ", ballStr)
end
if extraMsg and extraMsg ~= "" then
print(extraMsg)
end
print(str)
if currentScore then
print(string.format("Current score: %d/%d", currentScore, ScoreGetBingo))
end
if not ignore then
print()
end
end
local function simulateReadBall()
local balls = { }
for i = 1, CellCount do
table.insert(balls, i)
end
local board = { }
for i = 1, CellCount do
table.insert(board, getOneCell(i))
end
shuffleTable(board)
addTagToBoard(board)
local numToBoardIndex = { }
for cellIndex, cell in ipairs(board) do
if cell.cellNum ~= InvalidNum then
numToBoardIndex[cell.cellNum] = cellIndex
end
end
shuffleTable(balls)
local totalScore = 0
local theScoreWhen15 = 0
local readBallCount = 0
if DebugOut then
PrintCurrentState(board, nil, nil, nil, InvalidNum)
end
local cornIndexs = { }
local wheatIndexs = { }
local soybeanIndexs = { }
local machineProps = { }
while #balls > 0 do
readBallCount = readBallCount + 1
local ballNum = balls[1]
table.remove(balls, 1)
local readIndex = numToBoardIndex[ballNum]
assert(readIndex ~= nil, string.format("Cant find ball num index: %d", ballNum))
assert(board[readIndex].cellNum == ballNum or board[readIndex].cellNum == InvalidNum, "NumToBoardIndex Map Error!")
local success, propType = board[readIndex]:beenTagged()
if propType ~= PropEnum.None then
table.insert(machineProps, propType)
end
local ballStr = string.format("%d ----- %d", ballNum, readBallCount)
local str = "这个球读完后的机器: "
for _, propId in pairs(machineProps) do
if propId == PropEnum.Corn then
str = str .. "��"
elseif propId == PropEnum.Wheat then
str = str .. "��"
elseif propId == PropEnum.Soybean then
str = str .. "��"
end
end
if #machineProps == CountToStartProducing then
local bet = 2
for i = 2, #machineProps, 1 do
if machineProps[i] ~= machineProps[i - 1] then
bet = 1
break
end
end
local getScore = 0
for _, prop in pairs(machineProps) do
getScore = getScore + propToScore[prop] * bet
end
totalScore = totalScore + getScore
machineProps = { }
if DebugOut then
PrintCurrentState(board, totalScore, ballStr, str .. "。开始制作,分数为制作后的分数。", true)
print()
end
else
if DebugOut then
PrintCurrentState(board, totalScore, ballStr, str, true)
print()
end
end
if readBallCount <= 15 then
theScoreWhen15 = totalScore
end
if totalScore >= ScoreGetBingo then
break
end
end
assert(totalScore >= ScoreGetBingo and readBallCount <= CellCount, "Config cannot reach bingo.")
if theScoreWhen15 > ScoreGetBingo then
theScoreWhen15 = ScoreGetBingo
end
return readBallCount, theScoreWhen15
end
local bingoNeedReadBall = { }
for i = 1, CellCount do
bingoNeedReadBall[i] = 0
end
local allTotalScoreWhen15 = 0
for i = 1, LoopCount do
local ballCountCompleteBingo, snailNodePositionWhen15 = simulateReadBall()
bingoNeedReadBall[ballCountCompleteBingo] = bingoNeedReadBall[ballCountCompleteBingo] + 1
allTotalScoreWhen15 = allTotalScoreWhen15 + snailNodePositionWhen15
end
local bingoTotal = { }
bingoTotal[1] = 0
for i = 2, CellCount do
bingoTotal[i] = bingoNeedReadBall[i] + bingoTotal[i - 1]
end
local strH = ""
local str1 = ""
local str2 = ""
for i = 1, #bingoNeedReadBall, 1 do
local l1 = string.len(tostring(bingoNeedReadBall[i]))
local l2 = string.len(tostring(bingoTotal[i]))
local l = l1 > l2 and l1 or l2
if l < string.len(tostring(i)) then
l = string.len(tostring(i))
end
strH = strH .. string.format(string.format("%%%dd", l), i)
str1 = str1 .. string.format(string.format("%%%dd", l), bingoNeedReadBall[i])
str2 = str2 .. string.format(string.format("%%%dd", l), bingoTotal[i])
if i ~= #bingoNeedReadBall then
strH = strH .. ", "
str1 = str1 .. ", "
str2 = str2 .. ", "
end
end
print(" ", strH)
print("daub bingo count: ", str1)
print("cumulative bingo: ", str2)
print("aver score at 15: ", allTotalScoreWhen15 / LoopCount)