在我嘗試以批處理格式創建的較大程式中,重要的是我學習如何將變數值設定為由另一個變數的數量確定的陣列值(如果可能在簡單的 .bat 檔案中)。我當前的測驗檔案代碼為
set a[1]=1
set a[0]=10000
set c=0
set b=%a[%%c]%
echo %b%
所有這些回傳是: ECHO 已關閉 我需要它回傳: 10000所以我可以使用類似的代碼
@echo off
setlocal enabledelayedexpansion
set Goblin[0]=5
set Goblin[1]=20
set Goblin[2]=7
set Goblin[3]=Goblin
set Zombie[0]=7
set Zombie[1]=15
set Zombie[2]=3
set Zombie[3]=Zombie
set Skeleton[0]=3
set Skeleton[1]=11
set Skeleton[2]=10
set Skeleton[3]=Skeleton
set Orc[0]=7
set Orc[1]=25
set Orc[2]=0
set Orc[3]=Orc
set Acrobat[0]=4
set Acrobat[1]=15
set Acrobat[2]=80
set Acrobat[3]=Acrobat
set PossibleEnemies[0]=!Goblin!
set PossibleEnemies[1]=!Zombie!
set PossibleEnemies[2]=!Skeleton!
set PossibleEnemies[3]=!Orc!
set PossibleEnemies[4]=!Acrobat!
set /a Enemy1=%random% %%5
set /a Enemy2=%random% %%5
set /a Enemy1.MaximumHealth=%PossibleEnemies[Enemy1[1]]%
set /a Enemy2.MaximumHealth=%PossibleEnemies[Enemy2[1]]%
set /a Enemy1.Damage=%PossibleEnemies[Enemy1[0]]%
set /a Enemy2.Damage=%PossibleEnemies[Enemy2[0]]%
set /a Enemy1.Dodge=%PossibleEnemies[Enemy1[2]]%
set /a Enemy2.Dodge=%PossibleEnemies[Enemy2[2]]%
set Enemy1.Name=%PossibleEnemies[Enemy1[3]]%
set Enemy2.Name=%PossibleEnemies[Enemy2[3]]%
隨機化你正在戰斗的敵人(你一次打兩個)。我也試過
set a[1]=1
set a[0]=10000
set c=0
set b=%a[%c%]%
echo %b%
和
set a[1]=1
set a[0]=10000
set c=0
set b=%a[!c!]%
echo %b%
也
set a[1]=1
set a[0]=10000
set c=0
set b=%a[c]%
echo %b%
無濟于事
uj5u.com熱心網友回復:
我相信還有其他技巧可以做到這一點,但基本方法是這樣的:
@ECHO OFF
SETLOCAL EnableDelayedExpansion
set a[1]=1
set a[0]=10000
set c=0
set b=!a[%c%]!
echo %b%
編輯:
斯蒂芬的評論有一個鏈接,其中包含我不記得的技巧,但我知道它使用過CALL(注意:呼叫成本時間并且可以減慢腳本速度。):
@ECHO OFF
set a[1]=1
set a[0]=10000
set c=0
CALL SET b=%%a[%c%]%%
echo %b%
uj5u.com熱心網友回復:
中沒有陣列cmd/batch。唯一的變數型別是 STRING(盡管可以在一定程度上模擬串列和陣列)。因此,我將從陣列(每個元素的獨立變數)更改為串列(一個包含所有元素的變數)并將所有“陣列/串列內容處理”放入子程式中,從而在主代碼中輕松獲取某個元素:
@echo off
setlocal enabledelayedexpansion
REM define readable names for indexes (for more readable code later)
set "MaxHealth=2"
set "Damage=1"
set "Dodge=3"
set "Name=4"
set "Goblin=1"
set "Zombie=2"
set "Skeleton=3"
set "Orc=4"
set "Acrobat=5"
REM define a list of properties for each creature
set "_Goblin=5,20,7,little Goblin"
set "_Zombie=7,15,3,angry Zombie"
set "_Skeleton=3,11,10,bony Skeleton"
set "_Orc=7,25,0,furious Orc"
set "_Acrobat=4,15,80,fast Acrobat"
REM define a list of all creatures
set "PossibleEnemies=Goblin,Zombie,Skeleton,Orc,Acrobat"
set /a Enemy1=%random% %%5
set /a Enemy2=%random% %%5
REM get properties
call :GetProperty %Enemy1% Name Enemy1
call :GetProperty %Enemy2% Name Enemy2
call :GetProperty %Enemy1% MaxHealth Enemy1
call :GetProperty %Enemy2% MaxHealth Enemy2
call :GetProperty %Enemy1% Damage Enemy1
call :GetProperty %Enemy2% Damage Enemy2
call :GetProperty %Enemy1% Dodge Enemy1
call :GetProperty %Enemy2% Dodge Enemy2
echo You fight against:
set Enemy
goto :eof
:GetProperty Type Property VarName ; resulting variable = [VarName].[Property]
echo DBG: EnemyType=%1
echo DBG: Property=%2
for /f "tokens=%1 delims=," %%a in ("%PossibleEnemies%") do set "Type=%%a"
echo DBG: Type=%Type%
echo DBG: ReturnVar=%3.%2
set "opt=tokens=!%2! delims=," & REM not possible to use delayed expansion in for /f "[options]"
for /f "%opt%" %%a in ("!_%Type%!") do set "%3.%2=%%a"
echo DBG: Returnval=!%3.%2!
echo DBG: -----
goto :of
示例輸出(不帶DBG行):
You fight against:
Enemy1=3
Enemy1.Damage=3
Enemy1.Dodge=10
Enemy1.MaxHealth=11
Enemy1.Name=bony Skeleton
Enemy2=1
Enemy2.Damage=5
Enemy2.Dodge=7
Enemy2.MaxHealth=20
Enemy2.Name=little Goblin
如果需要,您可以將REM get properties(所有這些call ...行)放入另一個子例程中,以獲得更易讀的主代碼。
要回答您的實際問題:每個深度層都需要一層擴展。你有一個變數包含一個變數包含一個變數,所以需要三層決議(原來的層再加兩層。多一層通常是通過延遲擴展實作的;三層稍微復雜一點:call用于增加一層。最里面的變數“照常”%c%用于下一層,你必須加倍 each %,因為一個%被額外的決議層(第二層call)消耗,最外層(第三層)也是如此(第一層call),導致四個 %,因為每一層的決議都將它們減半:
@echo off
setlocal
set a[2]=1000
set b[1]=2
set c=1
call call set d=%%%%a[%%b[%c%]%%]%%%%
echo %d%
結果:1000
關于效率的一些話:
正如@Darin 已經提到的那樣,call它很慢(因為它創建了另一個實體cmd。當然call call更慢。看看三個回圈所花費的時間(一個空回圈,一個“呼叫呼叫”回圈和一個使用另一個回圈的回圈強制進行另一層決議):
@echo off
setlocal
set a[2]=1000
set b[1]=2
set c=1
echo start empty loop %time%
for /l %%i in (1,1,10000) do (
REM
)
echo start call-call %time%
for /l %%i in (1,1,10000) do (
call call set d=%%%%a[%%b[%c%]%%]%%%%
)
echo (proof it worked: %d%)
echo start speed-optimized %time%
setlocal enabledelayedexpansion
for /l %%i in (1,1,10000) do (
for %%j in (!b[%c%]!) do set "x=!a[%%j]!"
)
echo (proof it worked: %x%)
endlocal
echo End %time%
輸出:
start empty loop 16:20:49,05
start call-call 16:20:49,06
(proof it worked: 1000)
start speed-optimized 16:21:02,51
(proof it worked: 1000)
End 16:21:03,06
(~0.1 秒/~12 秒/~0.6 秒)- YMMV 取決于硬體和處理器負載。好的,需要 10000 次迭代才能得到這些數字,但盡管如此 - 它是 ~20 的一個因素)
uj5u.com熱心網友回復:
我發現使用陣列是一個錯誤,我相信這可能是因為如果你像 a[0] 一樣使用它們,那么它會命名變數 a[0] 而不是創建一個陣列。所以我最終發現有一個更好的解決方案(至少對于我的問題)。
call set PossibleEnemies.Name.0=Goblin
call set PossibleEnemies.Name.1=Zombie
call set PossibleEnemies.Name.2=Skeleton
call set PossibleEnemies.Name.3=Orc
call set PossibleEnemies.Name.4=Acrobat
call set PossibleEnemies.Damage.0=5
call set PossibleEnemies.Damage.1=3
call set PossibleEnemies.Damage.2=3
call set PossibleEnemies.Damage.3=7
call set PossibleEnemies.Damage.4=4
call set PossibleEnemies.Health.0=20
call set PossibleEnemies.Health.1=15
call set PossibleEnemies.Health.2=11
call set PossibleEnemies.Health.3=25
call set PossibleEnemies.Health.4=15
call set PossibleEnemies.Dodge.0=7
call set PossibleEnemies.Dodge.1=3
call set PossibleEnemies.Dodge.2=10
call set PossibleEnemies.Dodge.3=0
call set PossibleEnemies.Dodge.4=80
:EnemySetup1
set /a Enemy1.Num=%random% %%5
set /a Enemy2.Num=%random% %%5
goto EnemySetup2
:EnemySetup2
call set "Enemy1.MaximumHealth=!PossibleEnemies.Health.%Enemy1.Num%!"
call set "Enemy2.MaximumHealth=!PossibleEnemies.Health.%Enemy2.Num%!"
call set "Enemy1.Health=!PossibleEnemies.Health.%Enemy1.Num%!"
call set "Enemy2.Health=!PossibleEnemies.Health.%Enemy2.Num%!"
call set "Enemy1.Damage=!PossibleEnemies.Damage.%Enemy1.Num%!"
call set "Enemy2.Damage=!PossibleEnemies.Damage.%Enemy2.Num%!"
call set "Enemy1.Dodge=!PossibleEnemies.Health.%Enemy1.Num%!"
call set "Enemy2.Dodge=!PossibleEnemies.Dodge.%Enemy2.Num%!"
call set Enemy1.Name=!PossibleEnemies.Name.%Enemy1.Num%!
call set Enemy2.Name=!PossibleEnemies.Name.%Enemy2.Num%!
是的,所以如果您需要使用陣列,可能會有更好的選擇。對我來說,它只是使用嵌套變數。因此,如果您是初學者,我建議您不惜一切代價避免使用變數!
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/478121.html
標籤:批处理文件
