반응형
우선 맵을 만들어봅시다.
const sz = 9;
const [mp, setMp] = useState(Array.from({ length: sz }, () => Array.from({ length: sz }, () => 0)));
const [ms, setMs] = useState(Array.from({ length: sz }, () => Array.from({ length: sz }, () => 0)));
지뢰가 있는 위치를 설정할 mp변수와 근처 지뢰의 개수를 설정할 ms변수를 만들었습니다.
const setMap = () => {
const initMp = Array.from(mp);
initMp[0][2] = 1;
initMp[2][1] = 1;
initMp[2][2] = 1;
initMp[1][0] = 1;
initMp[1][1] = 1;
initMp[3][5] = 1;
initMp[7][6] = 1;
initMp[1][9] = 1;
setMp(initMp);
};
const setMineswiper = () => {
const dir = [
[1, 0],
[0, 1],
[-1, 0],
[0, -1],
[1, -1],
[1, 1],
[-1, 1],
[-1, -1],
];
const initMs = Array.from(ms);
for (let i = 0; i < sz; i++) {
for (let j = 0; j < sz; j++) {
let f = 0;
for (let k = 0; k < 8; k++) {
if (i + dir[k][0] < 0 || i + dir[k][0] >= sz || j + dir[k][1] < 0 || j + dir[k][1] >= sz) continue;
if (mp[i + dir[k][0]][j + dir[k][1]]) f++;
}
initMs[i][j] = f;
}
}
setMs(initMs);
};
useEffect(() => {
setMap();
setMineswiper();
}, []);
일단 지정된 위치에 지뢰를 넣고, 각 칸마다 근처 지뢰 수를 계산했습니다.
const setMap = () => {
const initMp = Array.from(mp);
for (let i = 0; i < sz; i++) {
let x = Math.floor(Math.random() * sz);
let y = Math.floor(Math.random() * sz);
while (initMp[x][y] !== 1) {
x = Math.floor(Math.random() * sz);
y = Math.floor(Math.random() * sz);
initMp[x][y] = 1;
}
}
setMp(initMp);
};
랜덤한 위치에 sz변수만큼의 지뢰를 깔아놓습니다. 맨 가운데 칸은 무조건 비워둡니다.
const setMineswiper = () => {
const initMs = Array.from(ms);
for (let i = 0; i < sz; i++) {
for (let j = 0; j < sz; j++) {
let f = 0;
for (let k = 0; k < 8; k++) {
if (i + dir[k][0] < 0 || i + dir[k][0] >= sz || j + dir[k][1] < 0 || j + dir[k][1] >= sz) continue;
if (mp[i + dir[k][0]][j + dir[k][1]] === 1) {
f++;
}
}
initMs[i][j] = f;
}
}
setMs(initMs);
};
ms 변수에 각 칸마다 주변에 있는 지뢰의 수를 체크하여 넣습니다.
const open = (xx: number, yy: number) => {
const a = [[xx, yy]];
const initMo = Array.from(mo);
if (mo[a[0][0]][a[0][1]]) return;
initMo[a[0][0]][a[0][1]] = true;
if (mp[a[0][0]][a[0][1]] === 0 && ms[a[0][0]][a[0][1]] === 0)
while (a.length > 0) {
let x = a[0][0],
y = a[0][1];
a.splice(0, 1);
for (let k = 0; k < 4; k++) {
if (x + dir[k][0] < 0 || x + dir[k][0] >= sz || y + dir[k][1] < 0 || y + dir[k][1] >= sz) continue;
if (initMo[x + dir[k][0]][y + dir[k][1]]) continue;
initMo[x + dir[k][0]][y + dir[k][1]] = true;
if (ms[x + dir[k][0]][y + dir[k][1]] === 0) a.push([x + dir[k][0], y + dir[k][1]]);
}
}
setMo(initMo);
};
주변에 지뢰가 없을 경우 주변 4방향 칸을 열고, 열린 칸 중 또 주변에 지뢰가 없는 칸이 있다면 a에 push하여 돌립니다.
이제 예쁘게 디자인을 입혀 봅니다.
그럴싸하죠?
반응형
'Web > Frontend' 카테고리의 다른 글
[Next.js] AWS Polly API를 사용해 TTS 서비스 만들기 (2) | 2023.11.15 |
---|---|
[Next.js] Naver Map API 이용해서 현재 위치 지도 띄우기 (1) | 2023.11.15 |
[Figma] 좌충우돌 Figma i18n 플러그인 제작기 (3) | 2021.05.04 |
[Next JS] Next JS 시작하기 (4) | 2021.02.06 |
[리액트] Scroll indicator 만들기 (2) | 2020.10.31 |
댓글