노노그램 토이 프로젝트 머릿속 순서대로 진행하기
안녕하세요! 오늘은 제가 최근에 진행하고 있는 노노그램 토이 프로젝트에 대해 이야기해보려고 합니다. 퍼즐을 풀고 만드는 것을 좋아하는 저는 평소에 노노그램을 자주 즐기곤 합니다. 그래서 이번에는 직접 노노그램 게임을 만들어보기로 했습니다. 이 프로젝트는 기획이나 정리 없이 머릿속에 떠오르는 대로 진행하고 있어서, 때로는 정신없이 흘러가기도 합니다.
프로젝트 시작 React와 TypeScript 설정
먼저, 프로젝트를 시작하기 위해 React와 TypeScript를 사용하여 기본적인 환경을 설정했습니다. 다음 명령어를 통해 프로젝트를 생성했습니다. bash
npx create-react-app nonogram --template typescript
절대경로 설정
프로젝트의 구조를 더 깔끔하게 관리하기 위해 절대경로를 설정했습니다. tsconfig.json
파일을 열어 다음과 같이 수정했습니다. json
{
"compilerOptions" {
"baseUrl" "src"
},
"include" ["src"]
}
Sass 설치 및 reset.css 적용
스타일링을 위해 Sass를 설치하고, 기본적인 스타일 리셋을 위해 reset.css
를 적용했습니다. bash
npm install sass
reset.css
파일의 내용은 다음과 같습니다. css
/* box-sizing 규칙을 명시합니다. */
*,
*before,
*after {
box-sizing border-box;
}
/* 폰트 크기의 팽창을 방지합니다. */
html {
-moz-text-size-adjust none;
-webkit-text-size-adjust none;
text-size-adjust none;
}
/* 기본 여백을 제거하여 작성된 CSS를 더 잘 제어할 수 있습니다. */
body,
h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd {
margin-block-end 0;
}
/* list를 role값으로 갖는 ul, ol 요소의 기본 목록 스타일을 제거합니다. */
ul[role='list'],
ol[role='list'] {
list-style none;
}
/* 핵심 body의 기본값을 설정합니다. */
body {
min-height 100vh;
line-height 1.5;
}
/* 제목 요소와 상호작용하는 요소에 대해 line-height를 더 짧게 설정합니다. */
h1,
h2,
h3,
h4,
button,
input,
label {
line-height 1.1;
}
/* 제목에 대한 text-wrap을 balance로 설정합니다. */
h1,
h2,
h3,
h4 {
text-wrap balance;
}
/* 클래스가 없는 기본 a 태그 요소는 기본 스타일을 가져옵니다. */
anot([class]) {
text-decoration-skip-ink auto;
color currentColor;
}
/* 이미지 관련 작업을 더 쉽게 합니다. */
img,
picture {
max-width 100%;
display block;
}
/* input 및 button 항목들이 글꼴을 상속하도록 합니다. */
input,
button,
textarea,
select {
font inherit;
}
/* 행 속성이 없는 textarea가 너무 작지 않도록 합니다. */
textareanot([rows]) {
min-height 10em;
}
/* 고정된 모든 항목에는 여분의 스크롤 여백이 있어야 합니다. */
target {
scroll-margin-block 5ex;
}
노노그램 데이터 생성
본격적인 개발에 앞서, 10x10 크기의 노노그램 데이터를 만들어보았습니다. 예시 데이터는 다음과 같습니다. javascript
const nonogram = [
[1, 1, 1, 1, 0, 0, 0, 0, 1, 1],
[1, 1, 1, 0, 0, 0, 0, 1, 1, 1],
[1, 0, 0, 0, 1, 1, 1, 1, 1, 1],
[0, 1, 0, 0, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
[1, 1, 0, 0, 0, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 0, 0, 0, 0, 1],
[1, 1, 1, 0, 0, 0, 0, 0, 1, 1]
];
노노그램 컴포넌트 구현
이제 이 데이터를 바탕으로 노노그램 컴포넌트를 구현해보았습니다. javascript
import './nonogram.scss';
function Nonogram() {
return (
<div>
{nonogram.map((y, indexY) => (
<div key={indexY} className="row">
{y.map((x, indexX) => (
<div key={indexX} className={`column ${x === 1 ? 'checked' ''}`}></div>
))}
</div>
))}
</div>
);
}
export default Nonogram;
// nonogram.scss
.row {
display flex;
}
.column {
display flex;
border 1px solid gray;
width 25px;
height25px;
&.checked {
background black;
}
}
styled-components 사용해보기
styled-components를 사용해보고 싶어서 부모 컴포넌트에서 nonogram 데이터를 props로 넘겨주고 styled-components를 사용해보았습니다. bash
npm install styled-components
javascript
// App.tsx
<Nonogram nonogram={nonogram} />
// Nonogram.tsx
import React from 'react';
import styled from 'styled-components';
interface ColumnProps {
checked boolean;
}
const Row = styled.div`
display flex;
`;
const Column = styled.div<ColumnProps>`
display flex;
border 1px solid gray;
width25px;
height25px;
background ${(props) => (props.checked ? 'black' 'none')};
`;
type NonogramArray = number[][];
interface NonogramProps {
nonogram NonogramArray;
}
const Nonogram React.FC<NonogramProps> = ({ nonogram }) => {
return (
<div>
{nonogram.map((y,indexY) => (
<Row key={indexY}>
{y.map((x,indexX) => (
<Column key={indexX} checked={x ===1} />
))}
</Row>
))}
</div>
);
};
export default Nonogram;
다음 단계
다음 회차에는 게임의 기본 기능을 만들어볼 예정입니다. 가장 중요한 퍼즐 검증 기능부터 구현할 계획입니다. 이 기능이 제대로 작동하면 나머지 기능들도 쉽게 구현할 수 있을 것입니다.
노노그램 풀이 공식
노노그램은 풀이 공식이 있습니다. 자세한 내용은 위키백과에서 확인할 수 있습니다. 노노그램 - 위키백과
자동 풀이 알고리즘
노노그램을 자동으로 풀어주는 알고리즘도 여러 가지가 있습니다. 관련 논문도 찾아볼 수 있습니다. 저는 시간을 절약하기 위해 공개된 코드를 사용하기로 했습니다. Nonogram solver - Rosetta Code 이 프로젝트에서는 파이썬 코드를 사용했습니다. 하지만 코드만 그대로 가져다 쓰는 것으로는 문제가 해결되지 않습니다. 힌트가 0
으로 되어있는 경우는 고려되지 않았기 때문에 힌트가 0
인 줄이 존재하면 의도대로 작동하지 않습니다.
문제 해결 및 디버깅
힌트가 0
인 경우를 처리하기 위해 코드를 디버깅하면서 분석했습니다. 이 과정에서 여러 가지 문제를 발견하고 해결했습니다.
결론
이번 포스트에서는 노노그램 토이 프로젝트의 진행 과정을 공유했습니다. 앞으로도 계속해서 이 프로젝트를 발전시켜 나갈 예정입니다. 여러분도 노노그램 게임을 만들어보면서 재미있게 코딩해보세요!