옛날 옛적 핸드폰용 마인크래프트에 레드스톤 회로가 없던 시절, 저는 자체적으로 회로 시스템인 "반짝이는 블록"이라는 것을 만들었어요.
폰마크가 BE가 아니라 PE였던 시절 이야기에요.
예전에 만든 회로 시스템
전등, 전선, 피스톤, 스위치 구현
스위치를 터치하면 스위치와 이어진 전선, 그 전선과 이어진 전등들은 켜지거나 꺼지고, 피스톤도 주변 블록들을 밀거나 당김
단, 전선은 무조건 한 가닥으로만 배치 가능
전선을 두 가닥 이상으로 배치하면 한쪽 경로에 연결된 회로만 작동
전선을 두 가닥 이상 나뉘었다가 다시 하나로 합쳐지는 구간이 있으면, 정상적으로 작동할 수도 있고 게임이 멈출 수도 있음
작동 방식
1. 스위치를 터치하면 상하전후좌우를 확인, 전선이 발견되면 해당 위치로 이동
2. 전선이 있는 위치에서 상하전후좌우를 확인, 전등이나 피스톤이 있다면 작동시키고, 전선이 있다면 해당 위치로 이동
- 직전 위치로 다시 돌아가는 것을 방지하기 위해, 직전에 있었던 곳으로는 돌아가지 않도록 설정
3. 2를 무한 반복. 주변에 더 이상 이동할 전선이 있다면 반복 종료
회로가 나뉘면 안되던 이유?
가장 먼저 발견한 전선으로만 이동하였기에, 다른 전선은 확인조자 하지 않음. 따라서 한 가닥으로만 배치해야 정상 작동
과거의 저는 어차피 내가 내 맵에서 사용하려고 만든 것이기에, 그냥 한 가닥으로 배치했어요.
게임이 멈췄던 이유?
"직전 위치로 다시 돌아가는 것을 방지하기 위해, 직전에 있었던 곳으로는 돌아가지 않도록 설정"이라, 아래와 같이 배치하면, 저 네모난 곳 안에서 무한히 빙빙 돌기 시작.
그 무한반복이 게임이 멈추던 이유

현재의 지식으로 판단해보면, 직전 방문 노드만 저장하는 유사 깊이우선탐색.
그래서 방문했던 모든 전선 블록들의 위치를 저장해서, 다시 돌아가지 않도록 구현했다면 게임이 멈추는 현상은 해결할 수 있었어요
다시 구현한 회로 시스템
전등, 전선, 스위치 구현
스위치를 터치하면 스위치와 이어진 전선, 그 전선과 이어진 전등들은 켜지거나 꺼짐. 피스톤 미구현
정상 작동하는 회로 구현이 목적이라, 굳이 피스톤은 구현하지 않음

스위치 블록을 터치하면 전등이 켜지거나 꺼짐

동일한 구조를 레드스톤 회로로 표현한 모습

전선을 두 가닥 이상으로 배치해도 상관 없고, 나뉘었다가 다시 합쳐지도록 배치해도 정상 작동
![]() |
![]() |
작동 방식 (깊이우선탐색, DFS)
1. 스위치를 터치하면 상하전후좌우를 확인, 전선이 발견되면 해당 위치로 이동. 빈 방문 목록을 만들어둠
2. 방문 목록에 현재 위치가 있다면 이전으로 돌아감
- 방문 목록에 현재 위치가 없다면, 방문 목록에 현재 위치 추가
- 현재 위치에서 상하전후좌우를 확인, 전등이나 피스톤이 있다면 작동시키고, 전선이 있다면 해당 위치로 이동
3. 2를 무한 반복. 모든 전선을 방문했다면 종료
대충 이런 순서대로 방문

따라서, 이렇게 개판으로 막 배치해도

정상 작동

그저 각 노드마다 간선이 최대 6개까지 연결 가능한 그래프를 탐색하는 것과 다를 바 없어요.
알고리즘 관련 지식이 없던 시절에는 열심히 머리 터지면서 구현해도 버그 2개가 있었는데, 지금 다시 구현해보니 DFS 딸깍해서 1시간 만에 완성
저 블록 이미지 그린 시간이랑 오류 수정한 시간 포함해서 1시간 안에 끝났어요.
사실 너비우선탐색 사용하려고 했는데, 완성하고 보니 깊이우선탐색이네요.
소스코드 (자바스크립트)
// 기존 MCPE에 존재하지 않은 새로운 블록을 추가하는 부분
Block.defineBlock(234, 'Sparkling Powder', [['sparkling_powder', 0]], 1, false, 11); //전선
Block.setDestroyTime(234, 1);
Block.setRenderLayer(234, 5);
Block.setLightOpacity(234, 0);
Block.defineBlock(235, 'Light Stone (on)', [['light_stone', 0]], 0, false, 0); //켜진 전등
Block.setLightLevel(235, 15);
Block.setDestroyTime(235, 1);
Block.defineBlock(236, 'Light Stone (off)', [['light_stone', 1]], 0, false, 0); //꺼진 전등
Block.setDestroyTime(236, 1);
Block.defineBlock(237, 'Switch', [['switch', 0]], 0, false, 0); //스위치
Block.setDestroyTime(237, 1);
// 숙이지 않은 상태로 스위치를 터치하면 탐색 시작
function useItem(x, y, z, itemId, blockId) { //블록 터치하면 작동
if (blockId == 237) { //터치한 블록이 스위치라면
if (Entity.isSneaking(Player.getEntity())) return; //터치한 사람이 숙이고 있다면 실행 중단
dfs([], x, y, z, true); //탐색 시작
preventDefault(); //기존에 실행될 내용 제거 (블록 설치 방지)
}
}
// 깊이우선탐색
function dfs(checked, x, y, z, isStart) {
var pos = x + ',' + y + ',' + z;
// 이미 방문한 곳이면 아무것도 하지 않음
// 깊이우선탐색.includes();가 없는 옛날에 만들어진 환경에서 구동하기에, .indexOf(); 사용
if (checked.indexOf(pos) != -1) return;
// 방문 목록에 추가
checked.push(x + ',' + y + ',' + z);
// 현재 위치에 있는 블록 확인
var blockId = getTile(x, y, z);
// 현재 위치에 있는 블록이 전등이라면 끄거나 켜기
if (blockId == 235) {
setTile(x, y, z, 236);
} else if (blockId == 236) {
setTile(x, y, z, 235);
}
// 현재 위치에 있는 블록이 전선이라면, 상하전후좌우 블록 전부 확인
// 탐색 1회차인 경우(스위치 터치)도 상하전후좌우 블록 전부 확인
if (blockId == 234 || isStart) {
dfs(checked, x + 1, y, z);
dfs(checked, x - 1, y, z);
dfs(checked, x, y + 1, z);
dfs(checked, x, y - 1, z);
dfs(checked, x, y, z + 1);
dfs(checked, x, y, z - 1);
}
}
다운로드는 및 적용은 깃허브 참고
https://github.com/sinz32/MCPE-SparklingPowder
GitHub - sinz32/MCPE-SparklingPowder: 옛날 마인크래프드 PE 회로 스크립트 리메이크
옛날 마인크래프드 PE 회로 스크립트 리메이크. Contribute to sinz32/MCPE-SparklingPowder development by creating an account on GitHub.
github.com

