Game Maker - создание игр | HellRoom Games
Ноябрь 17, 2025, 15:30:22 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.

Войти
Новости:
 
   Начало   Game Maker Помощь Правила форума Поиск Календарь Войти Регистрация  
Ссылки на события
  • Новый урок в школе GML: Октябрь 16, 2011 - Октябрь 19, 2011
Страниц: [1]   Вниз
  Печать  
Автор Тема: Урок 15. Оператор switch.  (Прочитано 32135 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Hummer
scio me nihil scire
GM Pro user
*

Репутация: 335
Offline Offline

Пол: Мужской
Награды:
2000 сообщений!За постоянность! [100 дней на форуме]За лояльность! [+300 репутации]Знаток Game Maker!За помощь новичкам!
API: Game Maker 8.0 Pro
Деятельность: GML, С++, OpenGL, Java. Бывший Директор бывшей школы GML
Сообщений: 2573


« : Октябрь 16, 2011, 08:42:44 »

Многие операторы являются практическими решениями проблем, связанных с операторами низкого класса.
Допустим в игре рано или поздно наступает ситуация, когда нужно выбрать одно из n (к примеру 7) развитий действия. Например однажды (не будем учитывать когда) нужно либо прибавить 1, либо отнять 4, либо умножить на 1.5, либо поделить на 5. Всего: 4 действия. Случайность достигается функцией random(4).
b=get_string('Введите число', 0)
a=irandom(3) // объясним в конце урока
if(a==0)//да, логичнее написать if !a, но этот способ нагляднее. По крайней мере оба метода разрешены
{
a+=1
}
else if(a==1)//аналогично if a
{
b-=4
}
else if(a==2)
{
b*=1.5
}
else if(a==3)
{
b/=5
}
show_message(string(b))

Много монотонных проверок могут замедлить выполнение программы, а также можно запутаться со скобками круглыми и фигурными. Модифицированным оператором if-else является оператор switch
Код:
switch(<выражение>)
{
case <случай1>: <операторы1> break;
case <случай2>: <операторы2> break;
default: <операторы3> break;
}
Выражение на множественную проверку стоит в скобках, рядом с ключевым словом switch. Как и у if выражение можно писать без скобок. Далее идёт "тело" оператора (ВНИМАНИЕ! фигурные скобки обязательны). Описание нового случая обозначается словом case. После идёт значение и обязательно двоеточие. Например
Код:
//
case 1:
//get_value() - скрипт
case get_value():
//
a=7
case a:
//
case 'QWERTY':
//
case object0:
// и т д
Итак, заготовка решения нашей проблемы уже есть
Код:
a=irandom(3)
switch(a)
{
case 0:
case 1:
case 2:
case 3:
}
Сначала, получим случайное число, затем при исполнении программа будет поочерёдно сравнивать a со всеми значениями, которые мы передали при помощи case. Как только нашлось совпадение, программа начинает выполняться от токи совпадения и вплоть до встречи слов break, continue или exit. По традиции (да и по здравому смыслу) используют break, потому что continue предназначено для другого (хотя и работает), а exit полностью выходит из кода. Для пущей уверенности код между break и case можно ограничить фигурными скобками
Вот наш итоговый вариант
Код:
switch(a)
{
case 0: a+=1 break;
case 1: a-=4
break;
case 2: {a*=1.5}
break;
case 3:
{a/=5}
break;
}
Прежде чем перейти к новой метке (метка - слово, выделяемое двоеточием, например case), я, пользуясь случаем, напомню о ещё одних операторах. Действие с присваиванием.
Допустим a=7, а b=1.
После действия b=a+1 переменная а останется с тем же значением, но запись
a+=1 её изменит на 1. Попроще это будет так:
a+=1 эквивалентно a=a+1
a-=1 экв. a=a-1
a*=1 экв. a=a*1 и т д,
НО! a-=1 неэкв. a=-1.
Также хочу обратить ваше внимание на то, что если вы используете изменение с присваиванием, то переменная, которую вы изменяете уже должны быть объявлена.
g/=2 // ошибка: эвк. g=g/2, но g ещё не объявлена.

Кроме case, switch принадлежит метка default. Она применяется только тогда, когда ни одного совпадения из case'ов не произошло. К примеру
Код:
a=irandom(100)
switch(a)
{
case 0: show_message('Ноль') break;
case 1: show_message('Один') break;
default: show_message('Очень много') break;
}
В принципе после последней метки break можно не указывать, так как там естественный выход из оператора.
Покажу преимущества оператора switch и этих нудных меток, а также почему важно ставить break.
Дело в том, что break в switch не является требованием языка. Он может и отсутствовать. Тогда всё равно смысл выполнения сохранится
Цитата: Чуть выше
программа будет поочерёдно сравнивать a со всеми значениями, которые мы передали при помощи case. Как только нашлось совпадение, программа начинает выполняться от токи совпадения и вплоть до встречи слов break
Приведу пример. Заранее скажу, что не стоит искать в нём глубокого смысла. Он приведён только для демонстрации синтаксиса.
Код:
a=irandom(9)
switch(a)
{
case 1:
case 3:
case 5:
case 7:
case 9: show_message('Нечётное число '+string(a)); break;
case 0:
case 2:
case 4:
case 6:
case 8: show_message('Чётное число '+string(a)) break;
default: show_message('Ошибка');
}
Как только найдёно совпадение, программа напролом будет выполнять все действия до break, независимо: есть совпадение дальше или нет.
Но несмотря на всё это, у if-else есть пара преимуществ.
Например в булевой логике. Вот две равносильные записи
Код:
if(a<b)//предполагается, что а и b уже объявлены
{
//
}
else
{
//
}
и
Код:
switch(a<b)
{
case true: //
break;
case false: //
break;
}
Производительнее и понятнее будет первая запись. Отсюда следует, что если выражение на множественную проверку может принимать только ture и false значения, то лучше (предпочтительнее) воспользоваться if-else.

Все операторы, имеющие тела (if, if-else, switch, while, for и т д) можно "вкладывать" друг в друга.
Код:
switch(a)
{
case 0: //
break;
case 7: //
break;
case 45: switch(b)
{
case 2: //
break;//прерывает только внутренний оператор
case 8: //
break;
default: //
}
break;//прерывает уже внешний
default: //
}

Примеры глупого использования switch
Код:
switch(константа)//всегда одно значение
switch(a)
{
case 5: //лучше воспользоваться if
}
switch(b)//всегда выполнится
{
default:
}
switch(a==b)//обговорено выше
{
case true:
break;
case false:
break;
default://вообще лишнее. никогда не выполнится
}

Также switch можно использовать в скриптах. Тогда return тоже будет выступать в качестве прерывания switch, но одновременно будет выходить из скрипта.

Чуть не забыл об одном важном преимуществе switch. Дело в том, что вычисление значения выражения будет происходить единожды, в отличии от множественного if. Особенно это важно в случайных числах.
Код:
a=irandom(4)
switch(a)
{

}
//равносильно
switch(irandom(4))

А если вы делаете множественную проверку случайного числа при помощи if-else, то сначала это число стоит занести в переменную.

Удачи!
Записан

Есть вещи, которые нельзя объяснить. Для всего остального есть Справка
Рандом-рандом-рандомище (с)

C++ & OpenGL
Nick
Участник
****

Репутация: 11
Offline Offline

Пол: Мужской
API: Game Maker 8.0 Pro
Сообщений: 113


Самый яркий из безмолвных


« Ответ #1 : Октябрь 16, 2011, 19:02:16 »

Отлично, спасибо. +1 Уважуха
Всегда путался в switch'ах, а щас вроде разобрался.
Записан
DarkWing [GB]
Посетитель
**

Репутация: 0
Offline Offline

API: 8.1 Standard
Сообщений: 35


« Ответ #2 : Октябрь 26, 2011, 23:29:54 »

Мне нужно что-бы по двум разных значениям выполнялся один и тот-же кусок кода.
 Т.е.:

Код:
switch(a)
{
case 0: (код 0); break
case 1: (код 1); break
case 2: (код 2); break
case 3: (тоже код 2); break
}

Понятно, что можно это решить простым копированием "кода 2" в case 3, но этот фрагмент кода очень большой, и постоянно редактируется-исправляется.
 Как это можно оптимизировать? Хотелось-бы что-то вроде конструкции:

Код:
case 2,3: (код 2); break
Записан
YellowAfterlife
Videogames, I'm afraid
Главный Модератор
*

Репутация: 440
Offline Offline

Пол: Мужской
Награды:
Добавление и перевод новостей о Game Maker!500 сообщений!За постоянность! [200 дней на форуме]За лояльность! [+300 репутации]Настоящий игродел!Знаток Game Maker!...
API: GameMaker Studio 2
Сообщений: 731



WWW
« Ответ #3 : Октябрь 26, 2011, 23:35:06 »

Мне нужно что-бы по двум разных значениям выполнялся один и тот-же кусок кода.
 Т.е.:

Код:
switch(a)
{
case 0: (код 0); break
case 1: (код 1); break
case 2: (код 2); break
case 3: (тоже код 2); break
}

Понятно, что можно это решить простым копированием "кода 2" в case 3, но этот фрагмент кода очень большой, и постоянно редактируется-исправляется.
 Как это можно оптимизировать? Хотелось-бы что-то вроде конструкции:

Код:
case 2,3: (код 2); break
Код:
switch(a)
{
// ...
case 2: case 3:
// code 2, 3
break;
}
Записан

Dmi7ry
Гл. Администратор
*

Репутация: 1379
Offline Offline

Пол: Мужской
Награды:
5000 сообщений!За постоянность! [200 дней на форуме]За лояльность! [+1000 репутации]За помощь в развитии форума!Знаток Game Maker!За помощь новичкам!
API: GameMaker Studio Master
Деятельность: Code, design
Сообщений: 6626



WWW
« Ответ #4 : Октябрь 26, 2011, 23:59:17 »

Угу, прям в справке такой пример есть:
Код:
switch (keyboard_key)
{
  case vk_left:
  case vk_numpad4:
    x -= 4; break;
  case vk_right:
  case vk_numpad6:
    x += 4; break;
}
Записан

- А какой, собственно, командой процессора колобок ест черта?
- Командой EAT...
Справка и FAQ в правом верхнем углу...
DarkWing [GB]
Посетитель
**

Репутация: 0
Offline Offline

API: 8.1 Standard
Сообщений: 35


« Ответ #5 : Октябрь 27, 2011, 00:34:27 »

Ага, спасибо! Работает.
Записан
Hummer
scio me nihil scire
GM Pro user
*

Репутация: 335
Offline Offline

Пол: Мужской
Награды:
2000 сообщений!За постоянность! [100 дней на форуме]За лояльность! [+300 репутации]Знаток Game Maker!За помощь новичкам!
API: Game Maker 8.0 Pro
Деятельность: GML, С++, OpenGL, Java. Бывший Директор бывшей школы GML
Сообщений: 2573


« Ответ #6 : Октябрь 27, 2011, 05:05:53 »

Покажу преимущества оператора switch и этих нудных меток, а также почему важно ставить break.
Дело в том, что break в switch не является требованием языка. Он может и отсутствовать. Тогда всё равно смысл выполнения сохранится
Цитата: Чуть выше
программа будет поочерёдно сравнивать a со всеми значениями, которые мы передали при помощи case. Как только нашлось совпадение, программа начинает выполняться от токи совпадения и вплоть до встречи слов break
Приведу пример. Заранее скажу, что не стоит искать в нём глубокого смысла. Он приведён только для демонстрации синтаксиса.
Код:
a=irandom(9)
switch(a)
{
case 1:
case 3:
case 5:
case 7:
case 9: show_message('Нечётное число '+string(a)); break;
case 0:
case 2:
case 4:
case 6:
case 8: show_message('Чётное число '+string(a)) break;
default: show_message('Ошибка');
}
Как только найдёно совпадение, программа напролом будет выполнять все действия до break, независимо: есть совпадение дальше или нет.
Обидно. Такое ощущение, что совсем не читал.  getlost
Записан

Есть вещи, которые нельзя объяснить. Для всего остального есть Справка
Рандом-рандом-рандомище (с)

C++ & OpenGL
Dmi7ry
Гл. Администратор
*

Репутация: 1379
Offline Offline

Пол: Мужской
Награды:
5000 сообщений!За постоянность! [200 дней на форуме]За лояльность! [+1000 репутации]За помощь в развитии форума!Знаток Game Maker!За помощь новичкам!
API: GameMaker Studio Master
Деятельность: Code, design
Сообщений: 6626



WWW
« Ответ #7 : Октябрь 27, 2011, 08:08:34 »

Код:
case 8: show_message('Чётное число '+string(a)) break;
default: show_message('Ошибка');
И правда ошибка. ; пропущено  
Записан

- А какой, собственно, командой процессора колобок ест черта?
- Командой EAT...
Справка и FAQ в правом верхнем углу...
Hummer
scio me nihil scire
GM Pro user
*

Репутация: 335
Offline Offline

Пол: Мужской
Награды:
2000 сообщений!За постоянность! [100 дней на форуме]За лояльность! [+300 репутации]Знаток Game Maker!За помощь новичкам!
API: Game Maker 8.0 Pro
Деятельность: GML, С++, OpenGL, Java. Бывший Директор бывшей школы GML
Сообщений: 2573


« Ответ #8 : Октябрь 27, 2011, 12:01:14 »

 Мда....
давно пора выучить, что ; в ГМ практически не играет никакой роли (только в операторе for, но об этом на следующем уроке)
Записан

Есть вещи, которые нельзя объяснить. Для всего остального есть Справка
Рандом-рандом-рандомище (с)

C++ & OpenGL
Dmi7ry
Гл. Администратор
*

Репутация: 1379
Offline Offline

Пол: Мужской
Награды:
5000 сообщений!За постоянность! [200 дней на форуме]За лояльность! [+1000 репутации]За помощь в развитии форума!Знаток Game Maker!За помощь новичкам!
API: GameMaker Studio Master
Деятельность: Code, design
Сообщений: 6626



WWW
« Ответ #9 : Октябрь 27, 2011, 12:14:22 »

М... Я был уверен, что несколько операндов в одной строке не разделённые ; вызовут ошибку. Буду знать, что нет.
Но лучше всё же использовать - как минимум, это вырабатывает хороший стиль программирования и будет гораздо меньше проблем при переходе на тот же Си...
Записан

- А какой, собственно, командой процессора колобок ест черта?
- Командой EAT...
Справка и FAQ в правом верхнем углу...
DarkWing [GB]
Посетитель
**

Репутация: 0
Offline Offline

API: 8.1 Standard
Сообщений: 35


« Ответ #10 : Октябрь 27, 2011, 14:18:14 »

Просто логику не уловил сходу...
 Думал, что раз встретился один "Case", который не подходит, то дальше ГМ пропускает весь код относящийся к этому Case, и ищет следующий Case, который подойдет.

И из приведенного примера я был уверен до сего момента, что программа даст сообщения ТОЛЬКО на значениях 9 и 8 !!!
 Неплохо-бы пояснять, что именно должен выдавать приведенный пример...

Записан
Hummer
scio me nihil scire
GM Pro user
*

Репутация: 335
Offline Offline

Пол: Мужской
Награды:
2000 сообщений!За постоянность! [100 дней на форуме]За лояльность! [+300 репутации]Знаток Game Maker!За помощь новичкам!
API: Game Maker 8.0 Pro
Деятельность: GML, С++, OpenGL, Java. Бывший Директор бывшей школы GML
Сообщений: 2573


« Ответ #11 : Октябрь 27, 2011, 18:06:15 »

Я попозже приведу фотографии с пояснением. Ждите.
Записан

Есть вещи, которые нельзя объяснить. Для всего остального есть Справка
Рандом-рандом-рандомище (с)

C++ & OpenGL
Peexal Studio
Посетитель
**

Репутация: 2
Offline Offline

Пол: Мужской
API: Game Maker 6.1
Деятельность: Создаю чёта
Сообщений: 17


"Лучше что-то проходить, чем что-то создать"


WWW
« Ответ #12 : Июль 17, 2017, 12:36:46 »

Можно ли применить этот самый свич для кода instance_create, чтобы расставить объекты по необходимым координатам в комнате?
Записан

Ничего не делай, отдыхай - твои работы не нужны никому, забудь об этом. Лучше поспи.
Solar Off Roader
Посетитель
**

Репутация: 1
Offline Offline

API: GameMaker Studio Standard
Сообщений: 31


« Ответ #13 : Ноябрь 30, 2023, 10:42:13 »

Добрый день! Подскажите пожалуйста, как такую логику завернуть в switch & case, это можно сделать?
      
Код:

if (level[i][k][0] = 100 and level[i][k][1] = 1) {
instance_create_layer(xx, yy, "Instances", Obj_construction_left);
}

if (level[i][k][0] = 100 and level[i][k][1] = 2) {
instance_create_layer(xx, yy, "Instances", Obj_construction_right);
}

if (level[i][k][0] = 100 and level[i][k][1] = 3) {
instance_create_layer(xx, yy, "Instances", Obj_construction_center);
}






Записан
Xageu
«Старожил форума»
******

Репутация: 208
Offline Offline

Пол: Мужской
Награды:
1000 сообщений!За постоянность! [50 дней на форуме]За лояльность! [+150 репутации]За отличную игру Peace, Death!Настоящий игродел!
API: GameMaker Studio Master
Деятельность: Гей-дизайнер
Сообщений: 1046


Хадей - Друг Детей


WWW
« Ответ #14 : Ноябрь 30, 2023, 15:26:40 »

Добрый день! Подскажите пожалуйста, как такую логику завернуть в switch & case, это можно сделать?
      
Код:

if (level[i][k][0] = 100 and level[i][k][1] = 1) {
instance_create_layer(xx, yy, "Instances", Obj_construction_left);
}

if (level[i][k][0] = 100 and level[i][k][1] = 2) {
instance_create_layer(xx, yy, "Instances", Obj_construction_right);
}

if (level[i][k][0] = 100 and level[i][k][1] = 3) {
instance_create_layer(xx, yy, "Instances", Obj_construction_center);
}


Код:
if level[i][k][0] == 100
{
switch level[i][k][1]
{
 case 1: //code
 break

 case 2: //code
 break

 case 3: //code
 break
}
}
Записан

69
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  

HellRoom Games © 2006-2012 All Rights Reserved
Powered by SMF 1.1.21 | SMF © 2013, Simple Machines
Страница сгенерирована за 0.112 секунд. Запросов: 35.