스도쿠 배열을 C로 만들어봅시다!!
Posted 2007/02/26 02:47아... 진짜 눈물난다. 진짜 간신히 만들었네 ㅜ_ㅜ
스도쿠 배열을 C로 만들어봅시다.
인터넷은 정보의 바다라지만, 요즘들어서 느끼는 것은 내가 원하는 정보로 가득찬 바다는 아니더군요. 스도쿠 배열 만들기에 대한 질문글은 상당히 많은 편이지만, 정작 완성된 소스코드는 찾기가 힘들고 그 전에 간신히 한번 찾은것도 주석도 없는데, 따로 설명도 없고... 그래서 그냥 내가 만들고 말지 뭐, 이러고 만들기 시작해서 오늘에야 간신히 완성했네요 허허.
사실 C++로 짠건데 이거 printf만 cout로 했지, 완전 C입니다. 거기다가 만들고 싶을때만 하고 나머지 시간은 다른 것을 해서, 오랜만에 잡으면 내가 선언한 변수도 잘 모르는 일이 생기더군요...-_- 아무튼 고생해서 결국 짜기는 짰습니다... 그렇지만, 아직 고쳐야 할 부분이 산더미입니다.
아무튼 코드를 설명드리겠습니다. 저처럼 누군가 인터넷에서 마구 찾아봐도 나오지 않으면 참 고생일테지요 ;;;;;;
일단 기본적인 main함수 외에 make_sdk함수와 makecheck함수 두 개가 있습니다.
main()의 설명.
main()에서는 중요한 배열변수가 array_sdk[9][9], check[9][9], check_sort[9][9], sdkline[9][9] 이렇게 4개가 있습니다.
array_sdk[9][9]
이 배열이 최종적으로 스도쿠 배열이 들어가는 배열입니다. 한 줄씩 들어가서 모두 9줄이 채워지면 스도쿠 배열이 완성됩니다.
check[9][9]
여기에는 제가 멋대로 이름붙인 '가능성 테이블'이 들어가는 배열입니다.
스도쿠를 풀때는 만약, 첫 줄에 숫자가 들어가 있으면 두 번째 줄에서는 들어갈 수 있는 모든 숫자를 작게 적어놓지 않습니까? 그걸 이 2차원 배열에 집어넣는 겁니다. 그러니까, 6번째 줄의 가능성 테이블은 1~5줄의 숫자를 참고로 만들 수 있는 것이죠.
check_sort[9][9]
'가능성 테이블'을 랜덤하게 정렬하고 그 랜덤한 가능성 테이블을 이 check_sort에 집어넣습니다. 이게 필요한 이유는, 제가 한 줄을 만들 때 그게 가능하든 불가능하든 모든 조합으로 체크하도록 만들었는데, 섞지 않으면 숫자가 작은 쪽에서 높은 쪽으로, 혹은 반대 순서대로 나올까봐 아예 섞고 시작한겁니다. 이 배열을 이용해서 조합하고 한 줄을 만듭니다.
sdkline[9]
랜덤 가능성 테이블을 참고로 가능한 한 줄을 이 배열에 담습니다. 그리고 이 배열을 array_sdk의 한 줄에 옮깁니다.
makecheck()의 설명.
이 함수는 array_sdk[9][9]를 이용해서 가능성 테이블 check[9][9]를 만들고 이것을 이용해서 랜덤한 가능성 테이블 check_sort[9][9]를 만듭니다.
9 6 4 3 2 8 5 7 1 첫째 줄
0 0 0 0 0 0 0 0 0 둘째 줄
...
의 경우 둘째줄의 첫번째 0, 즉 9 밑의 0에서 들어갈 수 있는 수를 생각해 보면, 일단 9와 6, 4는 안들어가니까 check[0][3], check[0][5], check[0][8] 에는 1값을 넣어놓는 식으로 만들었습니다. 나중에 검사해서 특정 인덱스에 0값이 있으면 그 인덱스가 가리키는 값은 숫자가 들어갈 수 있다는 것이겠지요. 그런데 첫째 줄을 만들고 가능성 테이블을 보면
0 0 1 1 1 0 0 0 0
0 0 1 1 1 0 0 0 0
0 0 1 1 1 0 0 0 0
1 1 0 0 0 1 0 0 0
1 1 0 0 0 1 0 0 0
1 1 0 0 0 1 0 0 0
0 0 0 0 0 0 1 1 1
0 0 0 0 0 0 1 1 1
0 0 0 0 0 0 1 1 1
의 경우, 가능성 테이블로 만들 수 있는 숫자는 처음 조합으로 1,1,1,3,3,3,1,1,1,인데(밑의 배열의 왼쪽 끝 세로 숫자.) 이러면 모든 조합을 찾을때 저 위쪽의 1까지 바뀌는 것을 봐야 합니다. 시간이 엄청나게 오래 걸려서 이걸 전부 랜덤으로 재배치 하기로 하였습니다. 어떻게 보면 임기응변으로 때운건데, 이 시간을 단축시키는게 이제부터의 목표입니다.
1 2 6 7 8 9 0 0 0
1 2 6 7 8 9 0 0 0
1 2 6 7 8 9 0 0 0
3 4 5 7 8 9 0 0 0
3 4 5 7 8 9 0 0 0
3 4 5 7 8 9 0 0 0
1 2 3 4 5 6 0 0 0
1 2 3 4 5 6 0 0 0
1 2 3 4 5 6 0 0 0
이걸 한번 섞어서 다시 재배치하면
7 6 1 2 8 9 0 0 0
1 8 9 2 7 6 0 0 0
...
이렇게 바뀌므로 조합하는 방식에 있어서는 시간이 꽤 단축된다고 볼 수 있겠지요.(그래도 오래 걸리는 것은 마찬가지입니다.) 랜덤으로 배치할 적에 세로를 신경써서 배치하면 시간이 더 단축될라나. 아무튼 이렇게 이 함수는 끝나고 이제 다음 함수로 넘어가겠습니다.
make_sdk()의 설명.
check_sort[9][9]를 이용해서 sdkline[9]를 만드는 함수입니다. 이 sdkline이 만들어지면, 이 한줄을 array_sdk에 담겠지요.
일단 아까부터 계속 나왔던 그 문제의 '조합'이 뭔지를 설명드리면, 일단 숫자를 계속 1씩 더해서 자리수를 올리는 방식입니다. 그러니까, 처음에는 00000000, 00000001, 000000002, ... ,000000008, 000000010, 이런 식으로 나가는겁니다. 이 숫자는 check_sort[9][9]의 인덱스 값입니다. 이러니까 시간이 엄청나게 걸리더군요. 안좋은 방법이지만 왜 굳이 이런 방법을 택했냐 하면, 진짜 며칠을 고생하면서 여러가지 방법, 한 4가지 정도의 방법으로 숫자를 만들었는데, 다 완성이 안되는겁니다. 스스로 가능성 테이블을 0을 만들어버려서 다음 숫자가 안 만들어지니 무한루프에 빠지고, 또 빠지고...의 반복. 그래서 아예 순수하게 조합으로 승부를 보자!! 해서 이런 방식을 택했네요 -_- 이래서 랜덤한 가능성 테이블을 만들 수 밖에 없었습니다. 이렇게라도 해야 속도가 조금이라도 줄어드니 말이죠.
그 조합의 인덱스는 일단 number[9]에 랜덤한 가능성 테이블 각 라인의 0이 아닌 숫자의 갯수를 넣어놨습니다. 그리고 temp[9]에는 check_sort[9][9]의 인덱스를 담아놨습니다. temp[9]를 조사해서 number[9]에 기록된 수보다 더 커지면, 즉 자리수를 올려야 하는 상황이 오면 자리수를 올릴 수 있게 만들었습니다. 그렇게 해서 조합을 완성시킵니다. 가면 갈수록 가능성 테이블에 들어갈 수 있는 숫자는 적어지고, 이것은 조합의 경우의 수를 줄여주므로 점점 라인 한개를 완성시키는데 걸리는 시간은 줄어들게 되는 것이죠.
문제점.
1. 속도의 문제
만드는 방식이 조잡한 짜맞추기 방식이라서, 처음 부분에 수많은 조합이 나오다 보니 꽤 시간이 걸리더군요. 뭐 한줄 두줄 생기다 보면 가능한 숫자가 점점 줄어서 속도는 점점 빨라집니다만, 이거는 첫 줄 내지 둘째 줄까지 그냥 랜덤으로 만들게 시키고, 세번째 줄부터 그냥 조합으로 하면 해결될 것 같군요. 거기다가 랜덤한 가능성 테이블에 숫자를 배치할 적에 조금 더 고려해서 집어넣을 수 있다면 시간은 더욱 더 줄어들 겁니다.
2. 미완성-_-이 되는 문제.
이거는 수많은 방법을 동원해서도 해결하기가 쉽지는 않았는데, 지금 완성한 방법으로도 잘 해결되지 않는군요. 그나마 많이 줄어든겁니다. 스도쿠 배열을 만드는 방법을 약 4가지 정도를 생각했었는데, 그게 다 한번에 떠오른 것이 아니라, 어느 방법이 막히면 또 한참 스도쿠를
들여다보면서 다른 방법을 생각해내고(시간 꽤 걸림), 그게 막혀서 또 다른 방법을 생각하고...(또 시간 꽤 걸림) 이러니까 정말 미쳐버리는줄 알았습니다. 도대체 할 줄 아는 것이 뭔가... 하는 생각도 들고 ;;;; 왜 자꾸 막혔냐 하면 자꾸 스스로 숫자를 완성해가면서 가능성 테이블의 숫자를 하나도 없게 만들어 버리는 데에 있습니다. 그러면 다음 숫자를 만들어야 하는데 가능성 테이블에 가능한 수가 없으니, 다시 뒤로 가고 또 뒤로 가고... 무한루프. 일단 이 방법으로 그런 상황은 많이 줄었는데, 조금 손 보면 아예 없앨 수도 있을 것 같습니다.
3. 코드의 지저분함.
이건 뭐... 에일리언 코드가 되어버린 이 상황을 보면 참 한숨밖에 나오지가 않네요. 쓸데없는 변수도 너무 많고, 전역변수로 해도 될 것을 괜히 함수에 전달해주고... 아주 보고 있으면 제가 짰지만 그래도 열받네효*^^*
친구 중에 제가 참 좋아하는 프로그래밍의 천재가 있는데, 이 친구가 외국으로 가기 전 제게 조언해 준 것중 하나가 "너무 어려우면 변수를 많이 선언해라, 니가 선언한 변수의 숫자만큼 완성하기가 쉬워질꺼다." 였고 이건 사실이라고 생각합니다. 그래도 너무 많이 선언했네요 -_- 일단 전역으로 돌릴 수 있는거 모두 전역으로 바꾸고, 쓸데없는 변수 다 지우고 해야겠네요.
소스코드
'Programming > SUDOKU' 카테고리의 다른 글
| 스도쿠 배열을 C로 만들어봅시다!! 3 (2) | 2007/02/27 |
|---|---|
| 스도쿠 배열을 C로 만들어봅시다!! 2 (0) | 2007/02/26 |
| 스도쿠 배열을 C로 만들어봅시다!! (6) | 2007/02/26 |
- Filed under : Programming/SUDOKU
- Tag : 스도쿠, 스도쿠 난수 생성, 스도쿠 랜덤, 스도쿠 배열 생성, 스도쿠 테이블
- 6 Comments Trackback
이올린에 북마크하기
이올린에 추천하기
NaCl
| 2007/02/26 12:02 | PERMALINK | EDIT | REPLY |이렇게 프로그램 짜시는분들 보면 신기해요 어헝헝;;
꿈이 프로그래머지만 이런거하나 못짜니 ;;;
sparkstar
| 2007/02/27 12:08 | PERMALINK | EDIT |이건 제가 느낀 겁니다만,
기본적인 문법을 아는 상황이라면 실력은 경험과 생각의 깊이에 따라 나뉘는 것 같습니다. 프로그램을 잘 짠다는 것은 많은 경험이 있어서 필요한 부분을 그만의 방법으로 구현해 내는 것에 있는 것인거 같아요~
계속 정진하시라는~ 저도 배울게 무지막지하게 많습니다.
빠리소년
| 2007/02/26 22:41 | PERMALINK | EDIT | REPLY |헉... 스도쿠 몇 번 해봤지만 하는 것도 머리아프던데;;
만들기까지...
저와는 통~ 인연이 없는 분야군요. 먼 소린지...;;
sparkstar
| 2007/02/27 12:10 | PERMALINK | EDIT |에에... 인터넷에 스도쿠 난수 만드는 소스나 설명이 전혀 없어서 말이죠. 엉망진창이지만 그냥 올린거에요~
누군가에게 조금이라도 도움이 될까 해서 말이죠.
undo
| 2007/08/01 15:11 | PERMALINK | EDIT | REPLY |저도 몇개월전에 스도쿠 만들어 봤는데요...;
일단 답을 먼저 완성해야 한다는건 같네요~ㅋ
배열에 답을 셋팅할 때 전 우선순위를 둬서 검색했구요.
먼저 보드 안의 작은 보드 3*3 배열에 겹치는 숫자가 있는지...없다면...
전체적인 보드에 가로 세로 검사를 하죠...
겹친다면 시작하는 구간으로 이동해서 숫자를 다시 셋팅을 했어요,,,
결론적으로....
완성도 되고 게임도 되지만~
똑같은 답이 두개 나오는 상황이 sparkstar님과 같네요ㅋ
sparkstar
| 2007/08/03 09:17 | PERMALINK | EDIT |어흐, Undo님과 저는 같은 고민을 했군요 ;;
그나저나 Undo님 블로그에 괜찮은 프로그래밍 문제들이 많은데, 이거 동아리 알고리즘 문제풀이에 가져다 써도 될런지요? -_- 좋은 문제들 많던데요 헤헤 *^^*