Game Maker - создание игр | HellRoom Games

Game Maker | GameMaker: Studio [Game-Maker.ru] => Школа GML (архив) => Тема начата: Hummer от Октябрь 16, 2011, 08:42:44



Название: Урок 15. Оператор switch.
Отправлено: Hummer от Октябрь 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, то сначала это число стоит занести в переменную.

Удачи!


Название: Re: Урок 15. Оператор switch.
Отправлено: Nick от Октябрь 16, 2011, 19:02:16
Отлично, спасибо. +1 sm_respekt
Всегда путался в switch'ах, а щас вроде разобрался.


Название: Re: Урок 15. Оператор switch.
Отправлено: DarkWing [GB] от Октябрь 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


Название: Re: Урок 15. Оператор switch.
Отправлено: YellowAfterlife от Октябрь 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;
}


Название: Re: Урок 15. Оператор switch.
Отправлено: Dmi7ry от Октябрь 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;
}


Название: Re: Урок 15. Оператор switch.
Отправлено: DarkWing [GB] от Октябрь 27, 2011, 00:34:27
Ага, спасибо! Работает.


Название: Re: Урок 15. Оператор switch.
Отправлено: Hummer от Октябрь 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:


Название: Re: Урок 15. Оператор switch.
Отправлено: Dmi7ry от Октябрь 27, 2011, 08:08:34
Код:
case 8: show_message('Чётное число '+string(a)) break;
default: show_message('Ошибка');
И правда ошибка. ; пропущено  sm:)


Название: Re: Урок 15. Оператор switch.
Отправлено: Hummer от Октябрь 27, 2011, 12:01:14
 :facepalm:
давно пора выучить, что ; в ГМ практически не играет никакой роли (только в операторе for, но об этом на следующем уроке)


Название: Re: Урок 15. Оператор switch.
Отправлено: Dmi7ry от Октябрь 27, 2011, 12:14:22
М... Я был уверен, что несколько операндов в одной строке не разделённые ; вызовут ошибку. Буду знать, что нет.
Но лучше всё же использовать - как минимум, это вырабатывает хороший стиль программирования и будет гораздо меньше проблем при переходе на тот же Си...


Название: Re: Урок 15. Оператор switch.
Отправлено: DarkWing [GB] от Октябрь 27, 2011, 14:18:14
Просто логику не уловил сходу...
 Думал, что раз встретился один "Case", который не подходит, то дальше ГМ пропускает весь код относящийся к этому Case, и ищет следующий Case, который подойдет.

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



Название: Re: Урок 15. Оператор switch.
Отправлено: Hummer от Октябрь 27, 2011, 18:06:15
Я попозже приведу фотографии с пояснением. Ждите.


Название: Re: Урок 15. Оператор switch.
Отправлено: Peexal Studio от Июль 17, 2017, 12:36:46
Можно ли применить этот самый свич для кода instance_create, чтобы расставить объекты по необходимым координатам в комнате?


Название: Re: Урок 15. Оператор switch.
Отправлено: Solar Off Roader от Ноябрь 30, 2023, 10:42:13
Добрый день! sm_hi3 Подскажите пожалуйста, как такую логику завернуть в 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);
}








Название: Re: Урок 15. Оператор switch.
Отправлено: Xageu от Ноябрь 30, 2023, 15:26:40
Добрый день! sm_hi3 Подскажите пожалуйста, как такую логику завернуть в 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
}
}