메뉴 건너뛰기

창작에 관련된 질문이나 간단한 팁, 예제를 올리는 곳

-- 플레이어 위치를 저장하는 변수
-- 초기 시작지점은 5, 5로 설정.
playerx = 5
playery = 5

-- 박스의 위치를 저장하는 배열.
box = {}

-- 박스 목표 지점의 위치를 저장하는 배열.
goal = {}

-- 움직인 횟수 저장
moves = 0

-- 맵 데이터를 저장하는 8*8의 2차원 배열 Map 생성
map = {}
for a = 1, 8 do
    map[a] = {}
    for b = 1, 8 do
        map[a][b] = 0
    end
end

function makebox(x, y)
-- 새 박스를 만든다.
    box[#box + 1] = {}
    box[#box]["x"] = x
    box[#box]["y"] = y
end

function makegoal(x, y)
-- 새 목표 지점을 만든다.
    goal[#goal + 1] = {}
    goal[#goal]["x"] = x
    goal[#goal]["y"] = y
end

function successed()
-- 모든 박스가 목표 지점 위에 놓여 있는가?
for a = 1 , #goal do
    if boxexist(goal[a]["x"], goal[a]["y"]) == 0 then
        return false
    end
end
return true
end

function printmap()
-- 맵을 표시하는 printmap 함수
    tempstr = ""

    for a = 1, 8 do
        for b= 1, 8 do
            tempbuffer = ""
            if (map[a][b] == 0) then
                tempbuffer = " "
            elseif (map[a][b] == 1) then
                tempbuffer = "#"
            end
            
        for c = 1, #box do
            if (box[c]["x"] == b and box[c]["y"] == a) then
                tempbuffer = "o"
                break
            end
        end
        
        for c = 1, #goal do
            if (goal[c]["x"] == b and goal[c]["y"] == a) then
                if (tempbuffer == "o") then -- 상자와 목표 지점이 겹친다면 @로 표시
                    tempbuffer = "@"
                else
                    tempbuffer = "."
                end
                break
            end
        end
            
        if (playerx == b and playery == a) then
            tempbuffer = "P"
        end
        
        tempstr = tempstr..tempbuffer
        end
        print(tempstr)
        tempstr = ""
    end
end

-- 맵 데이터 초기화
for a = 1, 8 do
    for b = 1, 8 do
        if (a == 1 or a == 8 or b == 1 or b == 8) then
            map[a][b] = 1
        end
    end
end

makebox(4,3)
makebox(4,6)

makegoal(5, 3)
makegoal(5, 6)

function boxexist(x, y)
    for a = 1, #box do
        if (box[a]["x"] == x and box[a]["y"] == y) then
            return a
        end
    end
    return 0
end

while(true) do
    -- 메인 무한 루프
    os.execute("clear") -- 화면을 지운다. OS가 아닌 Scite 환경에서는 제대로 동작하지 않음.
    printmap()
    print("")
    print("움직임: "..moves)
    if (successed() == true) then -- 모든 상자를 목표 지점으로 옮김.
        print("축하합니다!")
        print("당신은 주어진 과업을 무사히 완수하였습니다!")
        io.read()
        return
    else --아직 더 옮겨야 함! 게임이 안 끝났음...
        print("어느 방향으로 이동할까요?")
        print("a: 왼쪽 d: 오른쪽 w: 위 s: 아래 q: 종료 :")
        choose = io.read()
        if (choose == "a") then
            if (map[playery][playerx - 1] == 0) then
                if (boxexist(playerx - 1, playery) ~= 0) then
                    if (boxexist(playerx - 2, playery) == 0) then
                        if map[playerx - 2][playery] == 0 then
                            box[boxexist(playerx - 1, playery)]["x"] = box[boxexist(playerx - 1, playery)]["x"] - 1
                            playerx = playerx - 1
                            moves = moves + 1
                        end
                    end
                else
                    playerx = playerx - 1
                    moves = moves + 1
                end
            end
        elseif (choose == "s") then
            if (map[playery + 1][playerx] == 0) then
                if (boxexist(playerx, playery + 1) ~= 0) then
                    if (boxexist(playerx, playery + 2) == 0) then
                        if map[playerx][playery + 2] == 0 then
                            box[boxexist(playerx, playery + 1)]["y"] = box[boxexist(playerx, playery + 1)]["y"] + 1
                            playery = playery + 1
                            moves = moves + 1
                        end
                    end
                else
                    playery = playery + 1
                    moves = moves + 1
                end
            end
        elseif (choose == "d") then
            if (map[playery][playerx + 1] == 0) then
                if (boxexist(playerx + 1, playery) ~= 0) then
                    if (boxexist(playerx + 2, playery) == 0) then
                        if map[playerx + 2][playery] == 0 then
                            box[boxexist(playerx + 1, playery)]["x"] = box[boxexist(playerx + 1, playery)]["x"] + 1
                            playerx = playerx + 1
                            moves = moves + 1
                        end
                    end
                else
                    playerx = playerx + 1
                    moves = moves + 1
                end
            end
        elseif (choose == "w") then
            if (map[playery - 1][playerx] == 0) then
                if (boxexist(playerx, playery - 1) ~= 0) then
                    if (boxexist(playerx, playery - 2) == 0) then
                        if map[playerx][playery - 2] == 0 then
                            box[boxexist(playerx, playery - 1)]["y"] = box[boxexist(playerx, playery - 1)]["y"] - 1
                            playery = playery - 1
                            moves = moves + 1
                        end
                    end
                else
                    playery = playery - 1
                    moves = moves + 1
                end
            end
        elseif (choose == "q") then
            os.execute("clear")
            print("그럼 안녕!")
            io.read()
            return
        end
    end
end


코드는 요약글로,


-- 박스 목표 지점의 위치를 저장하는 배열.
goal = {}


목표지점에 관한 코드는 박스에 관한 코드와 상당히 유사합니다.


function makegoal(x, y)
-- 새 목표 지점을 만든다.
    goal[#goal + 1] = {}
    goal[#goal]["x"] = x
    goal[#goal]["y"] = y
end

귀찮아서 복붙하고 이름만 바꿨다.


function successed()
-- 모든 박스가 목표 지점 위에 놓여 있는가?
for a = 1 , #goal do
    if boxexist(goal[a]["x"], goal[a]["y"]) == 0 then
        return false
    end
end
return true
end


모든 목표 지점 위에 박스가 놓여 있는지를 확인한다.

주석이랑은 말이 살짝 다른데, 그거나 그거나...


if (goal[c]["x"] == b and goal[c]["y"] == a) then
                if (tempbuffer == "o") then -- 상자와 목표 지점이 겹친다면 @로 표시
                    tempbuffer = "@"
                else
                    tempbuffer = "."
                end
                break
            end


목표 지점과 상자가 겹칠 경우, 알기 쉽게 저렇게 표시한다.


makegoal(5, 3)
makegoal(5, 6)


맵 위에 목표 지점을 만든다.


    if (successed() == true) then -- 모든 상자를 목표 지점으로 옮김.
        print("축하합니다!")
        print("당신은 주어진 과업을 무사히 완수하였습니다!")
        io.read()
        return
    else --아직 더 옮겨야 함! 게임이 안 끝났음...


모든 목표 지점 위에 박스가 올라가있다면 축하한다고 메세지를 보여주고 끝낸다.


이제 게임의 뼈대는 다 만들어졌습니다. 갖고 놀 수 있어요.

그리고, 방금 게임을 더 재미있게 만들기 위해서 생각난 기능이 있습니다.

첫번째는 맵 에디터와 맵 고르기 기능입니다. 맵 하나만 플레이하자니 지루하고

또 코드를 직접 뜯어고치자니 번거로우므로 맵 데이터 프로그램을 하나 만들어서 맵을 만들고

만들어진 맵을 읽어와서 플레이 할 수 있게 하는 것도 좋을 것 같고요.

또 하나는 랭킹입니다.

최대한 적은 움직임 수로 상자를 옮긴 사람 순으로 기록해서 플레이어들에게 경쟁심을 유발시키는 겁니다.


뭐.. 이런 게 생각났다는 것이지, 만들 생각은 아직 없습니다.

(언제는 무슨 맵에디터 만들 것 처럼 굴더니만!)

나중에 잉여력이 넘치면 만들어보도록 하겠습니다.


첨부 파일은 완성된 파일입니다. (본 글에는 포함되어 있지 않음.)

nokoban.lua 라는 것으로 exe가 아니라 아쉽게도 실행할 수 없습니다.

lua 인터프리터를 설치하면 PC에서도 맥에서도 리눅스에서도(제가 리눅스입니다!), 심지어 안드로이드나 ios 환경에서도 실행이 가능합니다.. 만 여러분은 lua 인터프리터도 없고 그걸 깔지도 않으시겠죠.

그러므로 리눅스 환경에서의 구동 스크린샷을 보여드리겠습니다. (본 글에는 포함되어 있지 않음.)

조회 수 :
754
등록일 :
2013.09.17
08:33:59 (*.209.135.92)
엮인글 :
게시글 주소 :
https://hondoom.com/zbxe/index.php?mid=study&document_srl=703465
List of Articles
번호 제목 글쓴이 조회 수 추천 수sort 날짜 최근 수정일
165 cocos2d-x 2.2.2 UILabelBMFont 메모리 누수 해결법 [2] 똥똥배 783   2014-03-10 2014-05-31 19:30
만약 CocoStudio로 UI를 만든 후 GUIReader를 써서 지정 폰트를 불러오면 엔진 버그로 인해서 메모리 누수가 생긴다. 이걸 고치려면 LabelBMFont.cpp를 아래와 같이 수정해야 한다. void LabelBMFont::setFntFile(const char *fileName) { if (!fileName || st...  
164 cocos2d-x 2.2.2 윈도우 환경 기본 메모리 누수 똥똥배 640   2014-03-10 2014-03-11 03:51
cocos2d-x 2.2.2를 윈도우에서 실행시키고 나서 종료하면 기본으로 4바이트의 메모리 누수가 발생한다. 이건 CCScriptEngineManager가 원인인데 CCObject들은 delete를 실행할 때마다 CCScriptEngineManager의 sharedManager를 호출하기 때문이다. 결국 모든 C...  
163 Cocostudio의 ActionNode 메모리 누수 해결법(cocos2d-x 2.2.2) [2] 똥똥배 776   2014-03-09 2014-05-31 19:26
Cocostudio로 액션을 만들고 액션매니저를 이용해서 ActionManager::shareManager()->playActionByName 아래와 같이 실행을 해주면 액션이 실행되는 경우 메모리 누수가 발생한다. (액션을 실행하지 않았을 때는 메모리 누수 없음) 이 메모리 누수를 없애려면 ...  
162 CCTextFieldTTF 0바이트 메모리 누수 버그 해결법 똥똥배 692   2014-01-13 2014-01-13 10:38
CCTextFieldTTF::textFieldWithPlaceHolder("", FONT_NAME, FONT_SIZE); 이런 식으로 텍스트필드를 생성하면 ""가 0바이트라서 해체를 못하고 0바이트 누수가 발생한다. 그냥 스페이스(" ")라도 넣어주면 누수는 발생하지 않는다. 이 버그가 발생하는 버전은 2...  
161 Lua 소코반 EX: 포팅: 3 (머나먼 여행길 안녕 친구여) 노루발 913   2013-09-18 2013-09-18 08:05
안녕하세요, 노루발입니다. 오늘로 그래픽 소코반을 끝내기로 했습니다. 아쉽지만 끝내야죠. 일단 걸음수와 이것저것을 뿌려주기로 합니다. 그런데 이미 화면이 꽉 차버려서 뿌려줄 공간이 없네요... 없으면 만들면 되지. 창을 늘립시다. conf.lua를 수정. fun...  
160 Lua 소코반 EX: 포팅: 2 (키가 눌리면 이동하게 해 보자) 노루발 832   2013-09-18 2013-09-18 08:04
-- 플레이어 위치를 저장하는 변수 -- 초기 시작지점은 5, 5로 설정. playerx = 5 playery = 5 -- 박스의 위치를 저장하는 배열. box = {} -- 박스 목표 지점의 위치를 저장하는 배열. goal = {} -- 움직인 횟수 저장 moves = 0 -- 맵 데이터를 저장하는 8*8의...  
159 Lua 소코반 EX: 포팅: 1 노루발 856   2013-09-18 2013-09-18 08:03
-- 플레이어 위치를 저장하는 변수 -- 초기 시작지점은 5, 5로 설정. playerx = 5 playery = 5 -- 박스의 위치를 저장하는 배열. box = {} -- 박스 목표 지점의 위치를 저장하는 배열. goal = {} -- 움직인 횟수 저장 moves = 0 -- 맵 데이터를 저장하는 8*8의...  
158 Lua 소코반 EX: 그래픽 준비 노루발 1084   2013-09-18 2013-09-18 08:00
안녕하세요, 노루발입니다. 얼마 전 만든 Lua 소코반을 게임다운 게임을 만들기 위해 그래픽을 씌워보려고 합니다. 저번에 한 Love2D로 살펴본 뭐가 뭔지 모르는 복잡한 그리기 함수들도 사실은 모두가 소코반을 그래픽으로 만들기 위한 훼이크였습니다. 후후....  
157 게임의 기본 설정을 담당하는 love.conf 노루발 763   2013-09-17 2013-09-17 08:39
안녕하세요, 노루발입니다. 여태까지 이것저것 많이 Love2D를 다뤄와서 제가 만든 소코반에 그래픽을 씌울 수준까지 되었지만 (물론 키 입력은 논외로 치죠, 나중에 다룰게요.) 아직 이걸로 정식 게임을 만든다면 모자라도 한참 모자랍니다. 창의 이름도 실행...  
156 이미지 그리는 방법: 2편. 부제: 쿼드! 노루발 821   2013-09-17 2013-09-17 08:37
(역시 이미지가 중요한 글인데 이미지가 모두 잘렸습니다. 문화재 손실에 슬픔을 표합니다.) Quad에 대해 알아본댔습니다. 쿼드? 쿼드가 뭐지? 생소한 개념인데? 하나의 큰 그림을 로드해서 쪼개서 쓰는 겁니다. 타일 깔듯이요. 우리가 포켓몬스터 같은 걸 하...  
155 이미지 그리는 방법 1편 노루발 812   2013-09-17 2013-09-17 08:35
이미지가 중요한 글인데 이미지가 다 짤렸네요. 압박. 준비물은 일단 이미지입니다. 예제 이미지로 럭키♥를 준비했습니다. 럭키! 럭키! 럭키! 와아아아! 어쨌든 이 럭키를 가지고 예제를 진행하겠습니다! 와아아! 글쓸 맛 난다! 일단 Love2D에서 뭔가 그린다는...  
» Lua 소코반: 목표 지점을 만들고, 상자가 모두 옮겨지면 게임을 끝내자! 노루발 754   2013-09-17 2013-09-17 08:33
-- 플레이어 위치를 저장하는 변수 -- 초기 시작지점은 5, 5로 설정. playerx = 5 playery = 5 -- 박스의 위치를 저장하는 배열. box = {} -- 박스 목표 지점의 위치를 저장하는 배열. goal = {} -- 움직인 횟수 저장 moves = 0 -- 맵 데이터를 저장하는 8*8의...  
153 Lua 소코반: 상자를 만들고 옮기고 상자와 상자가 겹치거나 상자와 벽이 겹치지 않게 해 보자! 노루발 677   2013-09-17 2013-09-17 08:32
-- 플레이어 위치를 저장하는 변수 -- 초기 시작지점은 5, 5로 설정. playerx = 5 playery = 5 -- 박스의 위치를 저장하는 배열. box = {} -- 움직인 횟수 저장 moves = 0 -- 맵 데이터를 저장하는 8*8의 2차원 배열 Map 생성 map = {} for a = 1, 8 do     ma...  
152 Lua 소코반: 벽을 뚫고 나가지 않게 해보자! 노루발 696   2013-09-17 2013-09-17 08:31
전체 코드입니다.슬슬 길어지니 요약글 기능이 필요해진달지.. -- 플레이어 위치를 저장하는 변수 -- 초기 시작지점은 5, 5로 설정. playerx = 5 playery = 5 -- 움직인 횟수 저장 moves = 0 -- 맵 데이터를 저장하는 8*8의 2차원 배열 Map 생성 map = {} for ...  
151 Lua 소코반: 플레이어를 그리고 움직이게 해보자 노루발 758   2013-09-17 2013-09-17 08:30
오늘자 전체 코드입니다. 어제처럼 바뀐 부분만 설명해 봅니다. -- 플레이어 위치를 저장하는 변수 -- 초기 시작지점은 5, 5로 설정. playerx = 5 playery = 5 -- 움직인 횟수 저장 moves = 0 -- 맵 데이터를 저장하는 8*8의 2차원 배열 Map 생성 map = {} for...  
150 Lua 소코반: 맵을 뿌리자. 노루발 833   2013-09-17 2013-09-17 08:29
-- 맵 데이터를 저장하는 8*8의 2차원 배열 Map 생성 map = {} for a = 1, 8 do     map[a] = {}     for b = 1, 8 do         map[a][b] = 0     end end -- 맵 데이터 초기화 map[1][1] = 1 map[1][2] = 1 map[1][3] = 1 map[1][4] = 1 map[1][5] = 1 map[1]...  
149 소코반: 맵을 초기화하자. 노루발 588   2013-09-17 2013-09-17 08:27
8*8 맵의 데이터가 담길 2차원 배열(테이블)을 초기화하는 코드이다. Map = {} for a = 1, 8 do     Map[a] = {}     for b = 1, 8 do         Map[a][b] = 0     end end Map 테이블의 [1][1]부터 [8][8]까지 모두 0이라는 값이 담기고 Map[0][0]이나 Map[1][...  
148 [Love2D] 일단 뭔가 해보자 노루발 457   2013-09-17 2013-09-17 08:27
감기를 딛고 다시 재기... Lua로 초 간단한 원시적인 게임을 만들려고 합니다. 뭐냐하면 소코반이라고, 이렇게 말하시면 모르지만 푸쉬푸쉬라면 아시는 분들이 엄청 많으실겁니다. 이걸 그래픽조차 씌우지 않은 아스키로. ########## #    ..      # #    o  o...  
147 Love2D: 콜백 함수들 노루발 538   2013-09-17 2013-09-17 08:25
Love의 콜백 함수들은 love.run(가장 메인이 되는 겁니다.)에 의해 호출되며, 많은 작업들을 수행합니다. 이것들이 없다고 게임이 실행되지 않는다거나 하지는 않지만 좋은 게임을 만들기 위해선 이것들을 적재적소에 활용해야 합니다. 이미 아시는 분들도 있...  
146 love.graphics.print 한국어 출력 노루발 431   2013-09-17 2013-09-17 08:24
Love2D 사용 시 한국어가 ㅁㅁㅁ이나 ??? 등으로 깨져 나와 해결책을 수소문하여 겨우 찾았다. 원래 중국어 등을 출력하기 위한 것이었으니 적절한 폰트를 쓴다면 한자나 히라가나등도 출력할 수 있을 것이다. function love.load() korfont = love.graphics....