개인 자료란 (JE)

  서버 커뮤니티

한국 마인크래프트 포럼

마인크래프트 자료 및 커뮤니티 플랫폼

전체 회원수 127,039명 ( +15명 )

※ 장기간 미활동 회원 제외

Profile 브혼 개발자

Vhone dc73ee51d49946dabf4f634c6e3ce5c6

Profile

자료란new 공통new 리뷰, 강좌 스크립트

[알고리즘] 게임 시작 대기시간 구현하기 (반복문 단일실행 패턴)

2020.09.16 조회 수 329 추천 수 1
자료글 링크 http://버킷 

여는 글

이번 포스팅에서는 스크립트의 특성을 활용한 반복문 단일시행 패턴에 대해서 알아보겠습니다.

게임 시작 대기시간을 구현할 때는 두가지를 염두해야 합니다.
첫번째는 플레이어가 하는 일과 게임이 하는 일을 각각 나누어 생각해야 합니다.
두번째는 여러명의 플레이어가 하나의 게임에 참가하기 때문에 게임은 단 한번만 실행된다는 겁니다.

플레이어가 게임에 참가하고 바로 게임을 시작한다면 크게 문제 될 것이 없지만
대기시간을 구현해야한다면 중복 실행되는 것이 문제가 될겁니다.

플레이어가 몇명이 참가하든 시작해야 할 게임은 한개입니다.
그렇기 때문에 게임이 해야하는 일도 딱 한번만 실행되어야 하죠.
만약 플레이어가 들어올대 마다 게임이 시작을 준비하게 된다면 서로 같은 게임을 할 수 없을 겁니다.

게임 시작 대기시간 알고리즘은 이런 중복 실행 될 수 있는 환경에서 단 한번만 실행되게 하고,
한번의 실행을 통해 모든 유저에게 공통된 정보를 제공하는 일을 수행해야 합니다.


구성 요소

  • Expression
    - [Amount] : 리스트 타입에서 값의 개수를 반환합니다.


알고리즘

  1. 플레이어가 게임에 참여합니다.
  2. 플레이어가 참여하면 게임은 게임을 시작할 수 있는지 확인합니다.
  3. 시작할 수 있으면 대기시간을 가지고, 대기시간 동안 시작이 취소될 수 있는지 확인합니다.
  4. 취소되지 않고 대기시간이 종료되면 게임이 시작됩니다.


예제실습


options:
    최대인원: 2
    시작인원: 2
    대기시간: 10
    플레이시간: 30

수치를 쉽게 변경하기 위해서 options를 사용하겠습니다.
options는 variables.csv파일에 저장되지 않고, 다른 skript에 공유되지 않고, 문서 내 모든 위치에서 사용 할 수 있습니다.
options는 구분자로 @를 사용합니다. ( ex. {@최대인원} )


command /game.join:
    trigger:
        
        # [입장조건1] 플레이어가 게임을 참여했는지 확인
        if {play::%player%} is set:
            send "이미 게임에 입장했습니다."
            stop
        
        # [입장조건2] 게임 최대인원 확인
        if number of {game::players::*} >= {@최대인원}:
            send "인원이 모두 찼습니다."
            stop
        
        # [게임 입장] 플레이어가 게임에 참여함을 기록
        set {play::%player%} to true
        add Player to {game::players::*}
        send "게임에 입장합니다. (%number of {game::players::*}%/{@최대인원})" to {game::players::*}
        
        # [시작조건1] 시작할 수 있는 인원이 되었는지 확인
        if number of {game::players::*} >= {@시작인원}:
            
            # [단일시행 패턴1] task변수가 없어야 코드 실행
            if {game::task} is not set:
                
                # [단일시행 패턴2] task변수를 세팅하여 코드가 중복실행이 되지않도록함
                set {game::task} to true
                
                set {_wait} to {@대기시간}
                
                # [시작조건2] 대기시간 동안 시작조건을 만족하는지 확인
                # [단일시행 패턴3] task변수가 true인 경우만 반복
                while {game::task} is true:
                    send "%{_wait}%초 후 게임이 시작됩니다." to {game::players::*}
                    remove 1 from {_wait}
                    wait 1 seconds

                    # [시작조건2-1] 대기시간 동안 시작인원보다 적어지면 대기취소
                    if number of {game::players::*} < {@시작인원}:
                        delete {game::task}
                        send "인원이 부족하여 게임이 중단됩니다." to {game::players::*}
                    
                    # [단일시행 패턴4] task변수를 false로 전환하여 대기시간 종료
                    if {_wait} <= 0:
                        set {game::task} to false
                
                # [게임 시작] 게임 시작
                if {game::task} is false:
                    send "게임을 시작합니다." to {game::players::*}
                    execute command "/game.start" by console

{play::*}리스트는 플레이어의 일을 하기위한 변수입니다.
{game::*}리스트는 게임의 일을 하기위한 변수입니다.


[입장조건1]

플레이어가 게임에 입장 할 수 있는지 확인합니다.
{play::%player%}변수의 값이 있으면 이미 게임에 입장했거나, 플레이 하고 있는 유저입니다.


[입장조건2]

게임이 플레이어가 입장 할 수 있는지 확인합니다.
{game::players::*}리스트는 게임에 입장한 플레이어를 가지고 있습니다.
number of 익스프레션으로 참가인원이 최대인원이거나 넘어간다면 입장이 거절됩니다.

[게임 참가]

플레이어가 입장조건을 만족하여 입장하게 되면 {play::%player%}변수에 값을 세팅하여 입장함을 기록합니다.
게임은 플레이어가 입장 했음을 기록하기 위해 {game::players::*}리스트에 플레이어를 추가합니다.


[시작조건1]

입장조건을 모두 만족하여 게임의 참가인원이 변동되었다면
게임을 시작할 수 있는 인원이 모였는지 확인합니다.


[단일시행 패턴1~4]

 {game::task}변수를 가지고 뒤에 있을 while 반복문이 중복시행 되지 않도록 합니다.
변수에 값이 없으면 실행된 반복문이 없는 상태이고,
변수가 true를 가진다면 반복문이 실행된 상태이고,
변수가 false를 가진다면 반복문이 종료된 상태입니다.

[1] 변수가 아무 값을 가지지 않을때 조건을 통과할 수 있고

[2] 조건을 통과하면 변수에 true를 세팅함으로써 변수가 제거되지 않는다면 중복 실행에서 조건을 통과하지 못하게 됩니다.

[3] 또한 변수가 true인 동안 while을 반복해서 [시작조건]을 확인합니다.

[4] 무사히 {_wait} 변수가 0이되어 대기시간을 모두 소모하면 변수를 false로 변경하여 while을 빠져나갑니다.

[시작조건2]

{game::task}변수가 true인 대기시간 동안  반복하여 false가 되면 빠져나옵니다.
중간에 플레이어가 빠져나간다면 [시작조건2-1]에 의해서 {game::task}변수가 제거됩니다.
변수에 값이없으면 실행된 코드가 없는 상태이므로,  다시 대기시간 로직이 시작될 수 있는 상태가 됩니다.


[게임 시작]

[시작조건2]에서 무사히 대기시간이 종료되면 {game::task}변수가  false가 되므로,
false일 때 게임을 시작합니다.


command /game.exit:
    trigger:
    
        # [퇴장조건] 플레이어가 게임에 입장했는지 확인
        if {play::%player%} is not set:
            send "게임에 참여하지 않았습니다."
            stop
        
        # [게임 퇴장] 
        delete {play::%player%}
        remove player from {game::players::*}
        send "%player%가 퇴장했습니다." to {game::players::*}
        send "게임에서 퇴장했습니다."

위의 입장 명령어를 이해하셨다면 퇴장 명령어는 설명하지 않아도 이해 할 수 있을겁니다.
게임에서 퇴장하면 플레이어는 입장하지 않았음을 기록하고, 게임은 플레이어가 참여하지 않았음을 기록합니다.


command /game.start:
    executable by: console
    trigger:
    
        send "게임을 시작했습니다." to {game::players::*}
        
        wait {@플레이시간} seconds
        
        send "게임이 종료됐습니다." to {game::players::*}
        delete {play::*}
        delete {game::*}

게임이 종료되면 플레이어의 데이터와 게임의 데이터 모두 제거해줍니다.



닫는 글

Skript의 변수는 참조형인 Object이기 때문에
Boolean타입도 true, false 두가지가 아닌 null까지 세가지 상태를 표현 할 수 있습니다.
이것을 활용하여 반복문이 실행 된적이 있는지, 실행되고 있는지, 실행이 완료됐는지를 판단할 수 있습니다.






Warning
댓글이 없습니다.

새로운 댓글을 등록해 주세요!

컨텐츠
https://www.koreaminecraft.net/files/thumbnails/952/941/002/262x150.crop.jpg?20211128203943

답안지

한마탐 수능 / 등급컷 + 해설 8

베개냥이

2021-11-25

2

https://www.koreaminecraft.net/files/thumbnails/670/940/002/262x150.crop.jpg?20211124215847

답안지

한마탐 5주차 / 정오표 + 해설 1

베개냥이

2021-11-24

2

https://www.koreaminecraft.net/files/thumbnails/133/938/002/262x150.crop.jpg?20211123001841
마인크래프트로 만든 움직이는 루디브리엄 3

LittleCharlotte

2021-11-22

7