Powershell -Get-数组中值的随机组合,但遵循特定规则

tcbh2hod  于 2023-01-26  发布在  Shell
关注(0)|答案(1)|浏览(200)

大家好
我对脚本和Powershell还很陌生,所以我给自己一个小小的挑战来学习一些基础知识。我正在尝试为我的有氧跆拳道训练编写一个小数字调用系统。它基于"Bas Ruttens系统"。
这个想法是每隔几秒随机显示一个打击和踢的组合,例如...... 1,2,3,踢(左刺拳,右直拳,左钩拳,右踢)或...... 1,2,膝(左刺拳,右直拳,右膝)
到目前为止,我所做的是基本的数字标注,在组合之间随机中断。
以下是我目前掌握的情况:

#Number callout system for cardio kickboxing
#Version 1.0
#Created by Burger

#Add more exercises here
$Combo = @('1','2','3','4','Knee')

#For higher intensitiy decrease the gap between Minimum and Maximum or increase the duration
[int]$Minimum = 2
[int]$Maximum = 6
[int]$Duration = 1

#Create the timer
$TimeStart = Get-Date
$TimeEnd = $timeStart.addminutes($Duration)
Write-Host "Start Time: $TimeStart"
write-host "End Time:   $TimeEnd"

#Start the session until time runs out
Do { 

    $TimeNow = Get-Date
    
        if ($TimeNow -ge $TimeEnd) {
            Write-host "Great Work. It's time for your Cool Down. :)"
        } else {
            Write-Host (Get-Random $Combo)
        }
        Start-Sleep -Seconds (Get-Random -Minimum $Minimum -Maximum $Maximum)
   }
Until ($TimeNow -ge $TimeEnd)
#EOF

现在,我无法理解的是,我如何告诉Powershell创建随机组合,如"1,2,3,膝盖"或"1,1,4",并遵循一定的规则,例如防止组合破坏流,如"膝盖,4,2"。
"我所尝试的"
我考虑过创建一个文本文件,里面包含所有有效的组合,然后用"获取内容"从文件中随机选择组合。这确实有效,我在随机的秒数之间得到了随机组合。
Correct output with Get-Content
但是有效组合的数量是巨大的,只有当我想在未来添加某些有氧运动时才会增加,如burpees或跳膝等。所以我想只为阵列提供数据,让PS创建组合。
另外,我也尝试过至少生成包含更多变量的组合,就像这样。

$Combo_1 = (Get-Random $Combo)
$Combo_2 = (Get-Random $Combo),(Get-Random $Combo)
$Combo_3 = (Get-Random $Combo),(Get-Random $Combo),(Get-Random $Combo)
$Combo_4 = (Get-Random $Combo),(Get-Random $Combo),(Get-Random $Combo),(Get-Random $Combo)

#Combo Randomizer
$FullCombo = (Get-Random -InputObject $Combo_1, $Combo_2, $Combo_3, $Combo_4)

但我无法让它工作,因为我一直收到错误:无法将类型"System.Object []"的"System.Object []"值转换为类型"System.Double"。
然后我想到了IF语句,如 "If Number1 = 1 THEN(Get-Random from 1,2 or Knee)" 等。但这样我看到自己编写了几十个IF语句来获得所有有效的组合。
那么,有没有更优雅简单的方法来创建像这样具有特定规则的随机组合呢?

    • 伪代码**
While time has not run out
Do
Get-Random Combo with "1,2,3,4,Knee" BUT
Never start with 4,
Never start with knee,
Never follow 3 on 1,
Never 3 times knee in a row
Done
Write-Output "Time ran out. Session over."

如果有人能给我指明正确的方向,我会很高兴的。谢谢你的帮助
干杯

ffx8fchx

ffx8fchx1#

你的选择规则是有状态的--换句话说,为了选择序列中的下一个动作,你需要检查前面的动作并排除一些选项。
这里有一个方法可以做到这一点...
在它选择一个移动之前,它首先排除可能违反规则的选项,然后只对剩余的有效移动调用Get-Random...

function Get-Sequence
{

    param( $Length = 4 )

    if( $Length -lt 1 )
    {
        throw new-object InvalidOperationException("Length must be greater than zero.");
    }

    $moves = @("1", "2", "3", "4", "Knee");

    $sequence = @();

    # Never start with 4
    # Never start with Knee
    $allowed = $moves | where-object { $_ -notin @("4", "Knee") }
    $sequence += Get-Random $allowed;

    for( $i = 1; $i -lt $Length; $i++ )
    {

        $allowed = $moves;

        # Never follow 3 on 1
        if( $sequence[-1] -eq "1" )
        {
            $allowed = @( $allowed | where-object { $_ -ne "3" } );
        }

        # Never 3 times knee in a row
        $knees = @($sequence | select-object -last 2 | where-object { $_ -eq "Knee" }).Length;
        if( $knees -ge 2 )
        {
            $allowed = @( $allowed | where-object { $_ -ne "Knee" } );
        }

        $sequence += Get-Random $allowed;

    }

    return @(, $sequence);

}

示例用法:

PS> Get-Sequence
1
Knee
2
4

PS> Get-Sequence -Length 10
1
4
4
Knee
3
Knee
4
1
Knee
3

相关问题