If / Else GoTo VBA Excel

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20957187/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 17:31:14  来源:igfitidea点击:

If / Else GoTo VBA Excel

excelvbaexcel-vba

提问by augusthippo

Very new to VBA. Tried searching to no avail. I have the following code:

VBA 非常新。尝试搜索无果。我有以下代码:

monsterRollingForHit: rollForMonsterHit = (Int(2 * Rnd))
MsgBox rollForMonsterHit, 0, "Monster Hit Roll"
If rollForMonsterHit = 1 Then
    GoTo monsterRollingForDmg
Else
    GoTo playerRollingForHit
End If

'if monster hits we then roll for his base damage
'using a working around for randBetween due to Analysis Toolpak being required for that     function
monsterRollingForDmg: rollForMonsterDmg = ((Int((6 * Rnd) + 1)))
MsgBox rollForMonsterDmg, 0, "Monster Dmg Roll"
GoTo monsterRollingForCrit

'we then add crit if the monster critically hits
monsterRollingForCrit: rollForMonsterCrit = (rollForMonsterDmg + ((Int(2 * Rnd)) * 8))
MsgBox rollForMonsterCrit, 0, "Monster Crit Roll"
GoTo rollingForPlayerArmor

'finally we reduce the monster's dmg with potential crit by the player's armor
rollingForPlayerArmor: finalMonsterDmg = (rollForMonsterCrit * (((Int((26 * Rnd) + 75)))     / 100))
MsgBox finalMonsterDmg, 0, "Monster Final Dmg"
GoTo reducePlayerHealth

reducePlayerHealth: currentPlayerHP = (currentPlayerHP - finalMonsterDmg)
MsgBox currentPlayerHP, 0, "Current Player HP"
If currentPlayerHP > 0 Then
    GoTo playerRollingForHit
Else
    MsgBox "Monster Wins"
    Exit Sub
End If

The problem is that even on a rollForMonsterHit value of 0 it never goes to playerRollingForHit. Instead it just rolls until it gets a 1 and then proceeds.

问题是,即使 rollForMonsterHit 值为 0,它也永远不会进入 playerRollingForHit。相反,它只是滚动直到得到 1,然后继续。

Problem: Need way to skip a body of code for the Else condition

问题:需要跳过 Else 条件的代码体的方法

回答by SeanC

Use of Option Explicithelps with finding typo's in variable names.

使用Option Explicit帮助查找变量名称中的拼写错误。

this would be the psedo-code for what you appear to be trying. also notice that there are no goto's or labels.

这将是您似乎正在尝试的伪代码。还要注意没有转到或标签。

Set MonsterHP and HeroHP
while monsterHP>0 and HeroHP>0
    if MonsterHit then
        work out monsterdmg
        decide if critical
        deduct from heroHP, accounting for any armor/dodge/etc
    endif
    if HeroHit then
        work out HeroDmg
        decide if critical
        deduct from MonsterHP, accounting for any armor/dodge/etc
    endif
wend
if monsterdmg>0 then
    print "Monster Wins"
elseif heroHP>0 then
    print "Hero wins"
else
    print "They killed each other with their final blow!"
endif

回答by Floris

You did not define the label playerRollingForHit... at least not in the code you are showing. This is a problem.

您没有定义标签playerRollingForHit……至少在您显示的代码中没有。这是个问题。

As was pointed out by others, not having an idea of code structure is a much bigger problem. A GoTostatement, while legal should be used sparingly. And you should consider making your code more re-usable. For example, you can create your own data type:

正如其他人指出的那样,不了解代码结构是一个更大的问题。一个GoTo声明,而法律应该尽量少用。并且您应该考虑使您的代码更具可重用性。例如,您可以创建自己的数据类型:

Public Type player
  health As Integer
  strength As Integer
  ' whatever other properties you might have...
End Type

And then you can create an array of players:

然后你可以创建一个玩家数组:

Dim players( 1 To 2 ) as player

This means you will be able to loop over the players, and "player 1 attacks player 2" can use the same code as "player 2 attacks player 1" (if they have the same rules). Similarly, you might want to create your own function "rollBetween" which allows you to roll different dice with a simple instruction.

这意味着您将能够遍历玩家,并且“玩家 1 攻击玩家 2”可以使用与“玩家 2 攻击玩家 1”相同的代码(如果它们具有相同的规则)。同样,您可能希望创建自己的函数“rollBetween”,它允许您通过简单的指令掷出不同的骰子。

Function rollBetween(n1 As Integer, n2 As Integer)
' roll a number between n1 and n2, inclusive
rollBetween = Round(Rnd * (n2 - n1 + 1) - 0.5, 0) + n1
End Function

Putting it all together, for fun, I created some code that may help you understand what I'm talking about. Note - the rules here are not the same rules you used, but it's the same principle; as players get more strength, they become more immune to attack, and their attacks become stronger. I hope you can learn something from it, and have fun creating your game!

综合起来,为了好玩,我创建了一些代码,可以帮助您理解我在说什么。注意——这里的规则和你使用的规则不一样,但原理是一样的;随着玩家的力量越来越大,他们对攻击的免疫力也越来越强,他们的攻击也会变得更强。我希望你能从中学到一些东西,并享受创造你的游戏的乐趣!

Option Explicit

Public Type player
  health As Integer
  strength As Integer
End Type

Sub monsters()
' main program loop
' can have more than two players: just change dimension of array
' and rules of "who attacks whom"
Dim players(1 To 2) As player
Dim attacker As Integer
Dim defender As Integer

initPlayers players
attacker = rollBetween(1, 2) ' who goes first: player 1 or 2
Debug.Print "Player " & attacker & " gets the first roll"

While stillAlive(players)
  defender = (attacker Mod 2) + 1
  playTurn players, attacker, defender
  attacker = defender  ' person who was attacked becomes the attacker
Wend

MsgBox winner(players())

End Sub

'------------------------------
' functions that support the main program loop 'monsters':

Function rollBetween(n1 As Integer, n2 As Integer)
' roll a number between n1 and n2, inclusive
rollBetween = Round(Rnd * (n2 - n1 + 1) - 0.5, 0) + n1
End Function

Sub initPlayers(ByRef p() As player)
' initialize the strength of the players etc
Dim ii
For ii = LBound(p) To UBound(p)
  p(ii).health = 10
  p(ii).strength = 1
Next

End Sub

Function stillAlive(p() As player) As Boolean
' see whether players are still alive
' returns false if at least one player's health is less than 0
Dim ii
For ii = LBound(p) To UBound(p)
  If p(ii).health <= 0 Then
    stillAlive = False
    Exit Function
  End If
Next ii
stillAlive = True
End Function

Sub playTurn(ByRef p() As player, n As Integer, m As Integer)
' attack of player(n) on player(m)
Dim roll As Integer

' see if you can attack, or just heal:
roll = rollBetween(1, 2)
Debug.Print "player " & n & " rolled a " & roll

If roll = 1 Then
  ' roll for damage
  roll = rollBetween(1, 4 + p(n).strength)  ' as he gets stronger, attacks become more damaging
  Debug.Print "player " & n & " rolled a " & roll & " for attack"
  If p(m).strength > roll Then
    p(n).strength = p(n).strength - 1 ' attacker gets weaker because attack failed
    p(m).strength = p(m).strength + 2 ' defender gets stronger
  Else
    p(n).strength = p(n).strength + 1 ' attacker gains strength
    p(m).health = p(m).health - roll  ' defender loses health
  End If
Else
  ' roll for healing
  roll = rollBetween(1, 3)
  Debug.Print "player " & n & " rolled a " & roll & " for health"
  p(n).health = p(n).health + roll
End If
Debug.Print "statistics now: " & p(1).health & "," & p(1).strength & ";" & p(2).health & "," & p(2).strength

End Sub

Function winner(p() As player)
Dim ii, h, w
' track player with higher health:
h = 0
w = 0

For ii = LBound(p) To UBound(p)
  If p(ii).health > h Then
    w = ii
    h = p(ii).health
  End If
Next ii

winner = "Player " & w & " is the winner!"

End Function

Output of a typical game might be:

典型游戏的输出可能是:

Player 2 gets the first roll
player 2 rolled a 2
player 2 rolled a 2 for health
statistics now: 10,1;12,1
player 1 rolled a 1
player 1 rolled a 2 for attack
statistics now: 10,2;10,1
player 2 rolled a 2
player 2 rolled a 1 for health
statistics now: 10,2;11,1
player 1 rolled a 2
player 1 rolled a 3 for health
statistics now: 13,2;11,1
player 2 rolled a 2
player 2 rolled a 1 for health
statistics now: 13,2;12,1
player 1 rolled a 1
player 1 rolled a 6 for attack
statistics now: 13,3;6,1
player 2 rolled a 2
player 2 rolled a 2 for health
statistics now: 13,3;8,1
player 1 rolled a 2
player 1 rolled a 3 for health
statistics now: 16,3;8,1
player 2 rolled a 1
player 2 rolled a 5 for attack
statistics now: 11,3;8,2
player 1 rolled a 1
player 1 rolled a 4 for attack
statistics now: 11,4;4,2
player 2 rolled a 2
player 2 rolled a 1 for health
statistics now: 11,4;5,2
player 1 rolled a 2
player 1 rolled a 2 for health
statistics now: 13,4;5,2
player 2 rolled a 1
player 2 rolled a 4 for attack
statistics now: 9,4;5,3
player 1 rolled a 2
player 1 rolled a 1 for health
statistics now: 10,4;5,3
player 2 rolled a 1
player 2 rolled a 6 for attack
statistics now: 4,4;5,4
player 1 rolled a 2
player 1 rolled a 2 for health
statistics now: 6,4;5,4
player 2 rolled a 2
player 2 rolled a 3 for health
statistics now: 6,4;8,4
player 1 rolled a 1
player 1 rolled a 6 for attack
statistics now: 6,5;2,4
player 2 rolled a 2
player 2 rolled a 1 for health
statistics now: 6,5;3,4
player 1 rolled a 2
player 1 rolled a 1 for health
statistics now: 7,5;3,4
player 2 rolled a 2
player 2 rolled a 3 for health
statistics now: 7,5;6,4
player 1 rolled a 1
player 1 rolled a 6 for attack
statistics now: 7,6;0,4

Final output - message box that declares player 1 the winner.

最终输出 - 声明玩家 1 获胜者的消息框。

回答by PermaNoob

Try this instead: monsterRollingForHit: rollForMonsterHit = Application.WorksheetFunction.RoundDown(2 * Rnd(), 0)

试试这个: monsterRollingForHit: rollForMonsterHit = Application.WorksheetFunction.RoundDown(2 * Rnd(), 0)

回答by user7495253

For i = 1 To ActiveWorkbook.Worksheets.Count
  If Worksheets(i).Name = "Table B" Or Worksheets(i).Name = "Table C" Then GoTo line1
  If Worksheets(i).Name = "Table N" Then GoTo line3
  If Worksheets(i).Name = "Table O" Then GoTo line2
Next i