Проблема с цепочками операторов if в пакетном режиме

Я работаю над воссозданием The Elder Scrolls III: Morrowind в пакетном режиме, и в настоящее время я программирую создание персонажа, что включает в себя определение базовых характеристик игрока по расе и полу. Я последовательно связал операторы if, чтобы потребовать выполнения двух условий выбора для установки атрибута. Однако каждый раз, когда выбираются раса и пол, второе условие всегда игнорируется, и атрибут устанавливается так, как должно быть, если персонаж — мужчина. Я полагаю, что могу сделать простую ошибку где-то здесь (как я часто делаю). Вот полный код на случай, если я неожиданно допустил ошибку:

@echo off
:start
title Morrowind Build 6-21-19
echo Choose your character's race.
echo.
echo 1. Altmer
echo 2. Argonian
echo 3. Bosmer
echo 4. Breton
echo 5. Dunmer
echo 6. Imperial
echo 7. Khajiit
echo 8. Nord
echo 9. Orc
echo 10. Redguard
set /p p.race=
if %p.race%==1 set p.race=altmer
if %p.race%==2 set p.race=argonian
if %p.race%==3 set p.race=bosmer
if %p.race%==4 set p.race=breton
if %p.race%==5 set p.race=dunmer
if %p.race%==6 set p.race=imperial
if %p.race%==7 set p.race=khajiit
if %p.race%==8 set p.race=nord
if %p.race%==9 set p.race=orc
if %p.race%==10 set p.race=redguard
cls
echo Choose your character's gender.
echo.
echo 1. Male
echo 2. Female
choice /c 12 /n
if errorlevel 2 set p.sex=f
if errorlevel 1 set p.sex=m
if %p.race%==altmer if %p.sex%==m set /a p.strength=30
if %p.race%==altmer if %p.sex%==f set /a p.strength=30
if %p.race%==argonian if %p.sex%==m set /a p.strength=40
if %p.race%==argonian if %p.sex%==f set /a p.strength=40
if %p.race%==bosmer if %p.sex%==m set /a p.strength=30
if %p.race%==bosmer if %p.sex%==f set /a p.strength=30
if %p.race%==breton if %p.sex%==m set /a p.strength=40
if %p.race%==breton if %p.sex%==f set /a p.strength=30
if %p.race%==dunmer if %p.sex%==m set /a p.strength=40
if %p.race%==dunmer if %p.sex%==f set /a p.strength=40
if %p.race%==imperial if %p.sex%==m set /a p.strength=40
if %p.race%==imperial if %p.sex%==f set /a p.strength=40
if %p.race%==khajiit if %p.sex%==m set /a p.strength=40
if %p.race%==khajiit if %p.sex%==f set /a p.strength=30
if %p.race%==nord if %p.sex%==m set /a p.strength=50
if %p.race%==nord if %p.sex%==f set /a p.strength=50
if %p.race%==orc if %p.sex%==m set /a p.strength=45
if %p.race%==orc if %p.sex%==f set /a p.strength=45
if %p.race%==redguard if %p.sex%==m set /a p.strength=50
if %p.race%==redguard if %p.sex%==f set /a p.strength=40
if %p.race%==altmer if %p.sex%==m set /a p.intelligence=50
if %p.race%==altmer if %p.sex%==f set /a p.intelligence=50
if %p.race%==argonian if %p.sex%==m set /a p.intelligence=40
if %p.race%==argonian if %p.sex%==f set /a p.intelligence=50
if %p.race%==bosmer if %p.sex%==m set /a p.intelligence=40
if %p.race%==bosmer if %p.sex%==f set /a p.intelligence=40
if %p.race%==breton if %p.sex%==m set /a p.intelligence=50
if %p.race%==breton if %p.sex%==f set /a p.intelligence=50
if %p.race%==dunmer if %p.sex%==m set /a p.intelligence=40
if %p.race%==dunmer if %p.sex%==f set /a p.intelligence=40
if %p.race%==imperial if %p.sex%==m set /a p.intelligence=40
if %p.race%==imperial if %p.sex%==f set /a p.intelligence=40
if %p.race%==khajiit if %p.sex%==m set /a p.intelligence=40
if %p.race%==khajiit if %p.sex%==f set /a p.intelligence=40
if %p.race%==nord if %p.sex%==m set /a p.intelligence=30
if %p.race%==nord if %p.sex%==f set /a p.intelligence=30
if %p.race%==orc if %p.sex%==m set /a p.intelligence=30
if %p.race%==orc if %p.sex%==f set /a p.intelligence=40
if %p.race%==redguard if %p.sex%==m set /a p.intelligence=30
if %p.race%==redguard if %p.sex%==f set /a p.intelligence=30
echo Strength: %p.strength%
echo Intelligence: %p.intelligence%
pause
goto start

Лично я бы тоже заменил set /p на choice (используя 0...9 или A...J)

Stephan 23.06.2019 14:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
51
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Проблема заключается в том, как вы проверили значение errorlevel после команды chioce:

choice /c 12 /n
if errorlevel 2 set p.sex=f
if errorlevel 1 set p.sex=m

Условие if errorlevel number будет выполнено, когда значение errorlevel равно равно или больше, чем числа. Таким образом, выполненное условие if errorlevel 2 также будет удовлетворять if errorlevel 1

Вам нужно исключить последующие условия из оценки с помощью конструкции if...else и начать проверку errorlevel от самых высоких до самых низких значений.

choice /c 12 /n
if errorlevel 2 (
    set p.sex=f
) else if errorlevel 1 (
    set p.sex=m
) else (
   REM user canceled the choice by pressing CTRL-C
)

Как правило, строки if errorlevel ... должны располагаться в порядке убывания. sst уже назвал причину:

The condition if errorlevel number will be satisfied when the value of errorlevel is equal to or greater than the number. So a satisfied condition of if errorlevel 2 will also satisfy if errorlevel 1

Хотя в этом особом случае проще просто инвертировать этот порядок:

choice /c 12 /n
if errorlevel 1 set "p.sex=m"
if errorlevel 2 set "p.sex=f"

Когда вы нажимаете 1, выполняется первый if, и переменной присваивается значение m. Второй не выполняется, поэтому переменная остается m.
Когда вы нажимаете 2, выполняется первый if, и переменной присваивается значение m. Второй тоже выполняется, поэтому переменная меняется на f

Примечание. Я изменил синтаксис set на рекомендуемую форму, чтобы избежать пробелов в конце (трудно заметить в коде, но может вызвать неожиданное поведение (и некоторую головную боль при устранении неполадок) в других частях кода)

Другое предложение: Для удобства чтения вы можете заменить

if %p.race%==altmer if %p.sex%==m 

с участием

if "%p.race%-%p.sex%"= = "altmer-m"

и set /a может установить несколько переменных, поэтому вы можете сократить свой код с помощью:

if "%p.race%-%p.sex%"= = "altmer-m" set /a p.strength=30, p.intelligence=50

и - когда самцы и самки имеют одинаковые свойства - вы можете сделать их в одной строке (хотя могут быть причины не делать этого - например, сохранить возможность изменить свойства позже без слишком большого изменения кода):

if "%p.race%"= = "altmer" set /a p.strength=30, p.intelligence=50

Другие вопросы по теме