3. ※개인별업무
09김창헌 조장 : 회의록작성 및 보고서 작성, 일정 계획
09김정훈 관련사항 조사 및 복잡도계산
11김정무 관련사항 조사 및 복잡도계산
11김종진 프로그램 설계 및 알고리즘 구상
11김지환 프로그램 설계 및 알고리즘 구상
※일정계획
3월27일 업무분담 및 문제파악
3월29일 조사내용 정리 및 이해
4월 3일 프로그램 설계 문제점 파악 해결방안 모색 및 초안작성
4월 7일 최종 프로그램 설계 및 최종 보고서 작성
4. ※회의록
회의일시 2012년 3월 27일(화) 조 C1 작성자 09김창헌
참석자 09김창헌, 09김정훈, 11김정무, 11김종진, 11김지환
내용 비고
1.조원별 업무분담
조장과 프로그램설계 2명, 관련사항 조사 2명으로 팀을 구성했다.
2.일정 계획
다음 회의시간까지 자신이 맡은 업무를 수행해 와서 서로 어떻게 문제를 풀어나
갈 것 인지 토의하기로 함
3.보고서 계획
회의내용 소집단보고서작성 및 자신들이 참고한 자료들과 출처를 조장에게 보내주기로 함.
조장이 종합해서 보고서 초안 작성하기로 함.
4.알고리즘 계획
다음 회의시간에 서로 맡은 업무에 충실히 연구를 하여 어떻게 알고리즘을 짤 것
인지에 대해 토의하기로 함.
5. 회의일시 2012년 3월 29일(목) 조 C1 작성자 09김창헌
참석자 09김창헌, 09김정훈, 11김정무, 11김종진, 11김지환
내용 비고
1.조원별 업무 파악
각자 맡은 업무에 대해 조장이 자료들을 확인하여 프로젝트를 어떤 방향으로 진
행해야할지 초안에 대해 토의함.
2.일정 확인
회의시간이 끝나고 설계조원들이 초안을 작성한 뒤 주말에 모여서 프로젝트를 진
행하기로 함.
3.문제점 파악/해결법 토의
회의내용 스택, 큐, 백트래킹의 기본적 내용만 알고 있어서 어떻게 프로그램에 적용시킬 것
인지에 대해 많은 연구가 필요할 것 같다.
자료조사 하는 조원이 오늘밤까지 스택, 큐, 백트래킹의 종류와 적용법등을 조사
하여 온라인으로 설명을 해주기로 했다.
4.보고서 초안 토의
개인 소집단 보고서와 자료조사내용 및 출처와 프로그램 초안과 알고리즘, 프로
그램 설계중 문제점과 해결법을 추가하여 보고서 초안을 만들기로 토의함.
6. 회의일시 2012년 4월 3일(화) 조 C1 작성자 09김창헌
참석자 09김창헌, 09김정훈, 11김정무, 11김종진, 11김지환
내용 비고
1.조원별 업무 파악
자료조사 조원들은 임무를 거의 다 수행하여, 설계조원의 임무를 같이 도와주기
로 하였음.
2.일정 확인
이번 회의 마치고 설계 조원이 소스를 마무리하면 주말에 모여서 최종보고서 및
회의내용 소스파악 하기로 함.
3.문제점 파악 / 해결법 토의
스택을 사용하지 않고 소스를 설계해서 관련사항 조원들과 함께 어떤 식으로 접
목시켜야 할지 이야기 하기로 함.
4.보고서 확정
최종 소스 마무리 되고 나서 조원들과 모여 조장이 쓴 최종보고서를 읽어보고
수정 할 부분 수정 하고 최종보고서 확정 짓기로 함
7. ※기본자료
스택의 개념
스택의 구조는 매우 간단합니다. 스택은 밑이 막혀있는 긴 통이라고 보면 됩니다. 즉, 입구
와 출구가 같은 긴 통이므로 먼저 들어간 것은 밑에 있게 되고, 나중에 들어간 것은 제일
먼저 나오게 됩니다. 그래서 스택을 LIFO(Last In First Out)구조라 고 합니다.
스택을 조작하는 방법(연산이라고 합니다.) 은 두가지가 있습니다. 하나는 스택에 값을 집
어 넣는 연산인 push이고 다른 하나는 스택에서 값을 빼내는 pop 동작입니다. 위 그림을
보면 쉽게 이해가 될 것입니다.
배열로 스택 구현하기
배열을 이용하여 스택을 구현하는 것은 위의 그림과 같은 모양이 됩니다. 우선 스택의 긴
통을 정의 하고 스택의 마지막 데이터의 위치인 상단을 top이라는 배열 인덱스를 이용하겠
습니다.
배열의 성격상 스택 이라는 통의 크기는 정해 놓아야 합니다. 일단 10이라고 잡겠습니다.
스택에 들어갈 데이터는 정수형이라고 가정하면 다음과 같이 정의 할 수 있습니다.
#define MAXSIZE 10 // 스택의 크기 정의
int stack[MAXSIZE]; // 스택의 긴 통
int top; // 스택의 상단
여기서 top의 위치를 정확히 규정해 봅니다. 어떤 경우는 top이 스택의 가장 위 데이터가
아니라 그 위, 즉, 다음에 들어갈 데이터 저장 공간을 가리키기도 합니다. 여기서는 가장 위
의 데이터를 가리키는 것으로 정하겠습니다. 스택을 정의 할 때 두가지 중 하나를 선택해서
사용하여야 하며, 혼용되어서는 안됩니다.
그리고, 스택연산을 정의 할 때, 극단적인 경우, 즉, 데이터가 하나도 없을 때와 꽉 차있을
때에 약간 주의를 해야 합니다.
먼저, 스택이 비어 있는 경우 top은 -1의 값을 가져야 합니다. C에서 배열의 인덱스는 0
부터 시작하므로, top이 0이라면 스택에 데이터가 하나 있다는 의미입니다. 스택이 비어있
는 경우는 초기 스택이 생성되었을 때도 마찬가지 이므로 스택을 초기화 하려면 top을 -1
로 설정하면 됩니다.
push를 위해서는 값이 있어야 하므로 push의 함수 인자로 val이라는 양의 정수형을 사용하
겠습니다. 그 후 push는 top을 하나 증가시키고 배열의 인덱스 top에 val을 넣으면 됩니다.
그런데, 앞서 말씀드렸듯이 스택이 꽉차있는 경우에 push를 하게 되면 스택이 넘쳐나게 됩
니다. 이를 스택 오버플로우(Stack Overflow)라고 합니다. 그러므로 배열의 인덱스인 top이
8. MAX-1이 되었을 때 스택이 꽉차있는 경우이므로 예외 처리를 해야 합니다.
[[ 스택의 용도 ]]
컴퓨터에서 스택이 사용되는 가장 대표적인 부분은 바로 연산이다.
연산에는 우선 순위라는 것이 있기 때문에 연산 도중에 우선 순위가 높은 연산을 만나게 되면 그 동
안의 연산 결과를 잠시 보관해두고
우선 순위가 높은 연산을 먼저 처리하게 되는데 이때 또다시 더 높은 순위의 연산을 만나면 또 스택
에 보관해두고 현재의 연산을 한다.
그리고 순위가 높은 연산이 끝나면 다시 스택에서 그 전에 하던 연산을 가져와서 계속해서 연산을 수
행해 나가는 것이다.
이 것 이외에도 함수의 호출시에도 메인 함수에서 함수를 호출하게 되면 메인 함수에서 사용되던 지
역 변수들이 모두 스택에 저장된다.
그리고 해당 함수의 작업을 진행하게 되고 또 그 함수에서 다른 함수의 호출이 있게 되면 그 동안 사
용되던 모든 정보를 스택에 저장하고
다시 함수를 호출하여 작업을 수행하다가 그 함수가 종료되면 스택에서 그 전의 모든 정보를 가져와
함수 호출 다음의 작업을 재개한다.
이런 식의 작업들을 수행하기 위해서는 스택이라는 후입 선출의 기억 장치가 꼭 필요한 것이다.
큐의 개념
큐는 스택과 비슷한 모양을 하고 있지만, 조작방식은 다릅니다. 큐의 구조도 간단한데, 스
택과 달리 앞 뒤가 뚫린 통이라고 보시면 됩니다. 이 통은 뒤에서 뭔가를 집어넣고 앞에서
빼냅니다. 즉, 먼저 들어온 것은 먼저 나오는 구조로 FIFO(First In First Out)이라고 부릅니
다.
큐의 연산은 put과 get이 있습니다. 큐에 자료를 집어 넣을 때는 뒤(rear)에서 처리하고,
이를 put이라고 합니다. 반대로 큐에서 자료를 빼낼 때는 앞(front)에서 처리하고 이를 get
이라고 합니다.
배열로 큐 구현하기
배열을 이용한 큐의 구현은 스택의 구현과 비슷한 난이도일 것 같지만, 조금 더 생각해보
면 문제가 아주 많습니다. 먼저 저장할 자료의 앞과 뒤를 가리키는 변수를 선언하여 큐의
구조를 정의해 보겠습니다.
#define MAXSIZE 10 // 큐의 크기
int queue[MAXSIZE];
int front=-1, rear=-1;
다음으로 put과 get 연산을 정의해 보겠습니다.
int put (unsigned int val) {
9. if (rear >= MAXSIZE-1) {
printf (" Queue Overflow");
return (-1);
}
queue[++rear] = val;
}
int get () {
if (front <= 0) {
printf (" Queue Underflow");
return -1;
}
return queue[front++];
}
배열의 인덱스로 사용되는 front와 rear가 위 코드에서는 계속 증가하기만 합니다. 결국 몇
번의 연산을 한 후에 rear가 배열의 한계를 넘어 더이상 put연산이 Overflow에러를 발생시
킬 수 있습니다. 그러므로 rear가 배열의 한계에 다다랐을 때에 큐의 데이터를 배열의 앞부
분으로 옮기는 동작이 필요하게 됩니다.
int put (unsigned int val) {
if (rear >= MAXSIZE-1) {
if (!(rear-front)) {
return -1;
}
// 여기서 배열의 앞으로 옮겨야 한다.
memcpy (&queue[0], &queue[front], rear-front+1);
rear=rear-front;
front = 0;
}
queue[++rear] = val;
}
지금은 배열의 개수를 10으로 정의 했지만 만약에 5억개라면? 그런 데이터 이동이 put할
때마다 발생한다면? 당연히 비효율적이겠죠.
그래서 해결방법으로 나왔습니다. 환형 (또는 원형) 큐(Circular Queue)를 이용하는 것입니
다. 환형 큐는 뱀이 꼬리를 물고 있는 듯한 모양을 가지고 있습니다. 데이터가 순환하며 저
장되기 때문에 끝이라는 개념도 없습니다. 다음 그림을 보시죠.
[[ 큐의 용도 ]]
큐는 일련의 일들이 순차적으로 진행되는 가운데, 일의 진행이 조금 지체될때 큐에는 다음 일들이 계
속해서 쌓여가는 방식이다.
흔히 버퍼링이라 불리는 스트리밍의 로딩 작업 역시 큐에 자료가 쌓이고 플레이어는 큐의 앞부분부터
플레이를 하게 되는 것이다.
그러다 로딩이 늦어져서 큐에 쌓였던 자료가 모두 사용되고 나면 플레이어는 중지되고 다시 버퍼링
작업을 하게 되는 것이다.
이것 이외에도 프린트 작업을 할때 프린터는 처리 속도에 제한이 있기 때문에 여러가지의 출력을 지
시하게 되면 지시된 순서대로
큐에 자료를 저장하고 하나의 출력이 끝나면 큐에서 다음 자료를 받아와 출력하는 작업을 반복한다.
그러다 큐가 비면 대기 상태가 된다.
이외에도 큐의 용도는 다양하다. 기억할 점은 큐는 순차적인 업무 처리를 위해 다음 할 일을 기억해
두는 장치라는 것이다.
10. 스택은 하던 일을 잠시 접어둘때 사용되는 기억 장치라는 점이 큐와는 다른 점이다.
백트래킹
입력받은 배열의 값에 대해서 가능한 모든 순서조합을 만들어냅니다.
단, 모든 순서조합을 위해서는 최초에 배열의 수가 오름차순으로 정렬되어져 있어야 합니
다.
최종적인 형태는 내림차순정렬이 되어져 있으며, 이때 함수는 더이상 처리를 하지 않고 들
어온 값 그대로 리턴 시켜 버립니다.
내림차순 정렬이 완료 되었으나, 맞는 조합이 없었다면, 해당 문제는 해가 없는 것이 됩니
다.
매번 시도 마다 다음 조합으로 만들어 냅니다. (1차 배열만, 배열의 크기는 무관)
현재 배열의 순서가 답이 될수 없다면, 배열을 다시 백트랙 돌리면 바로 다음 배열 순서의
조합을 만들어냅니다.
1-2-3-4-5-6-7-8-9 의 항이 있었다고 가정할 때, 이 값의 순서가 해당 문제의 답으로서
맞지 않는다면 다음 항으로는 한칸 앞으로 돌아와서 순서를 바꾸어 볼수 있습니다.
입력받은 배열의 값에 대해서 가능한 모든 순서조합을 만들어냅니다.
단, 모든 순서조합을 위해서는 최초에 배열의 수가 오름차순으로 정렬되어져 있어야 합니
다.
최종적인 형태는 내림차순정렬이 되어져 있으며, 이때 함수는 더이상 처리를 하지 않고 들
어온 값 그대로 리턴 시켜 버립니다.
내림차순 정렬이 완료 되었으나, 맞는 조합이 없었다면, 해당 문제는 해가 없는 것이 됩니
다.
매번 시도 마다 다음 조합으로 만들어 냅니다. (1차 배열만, 배열의 크기는 무관)
현재 배열의 순서가 답이 될수 없다면, 배열을 다시 백트랙 돌리면 바로 다음 배열 순서의
조합을 만들어냅니다.
11. infix, prefix, postfix. (중위표기법, 전위표기법, 후위표기법)
일반적인 수식은 infix이다.
즉, 연산자가 피연산자(보통숫자나 문자)와 피연산자 사이에 존재한다. a + 1과 같은 형태
이다.
기준이 되는 것은 연산자의 위치이다.
+ a 1과 같이 연산자가 피연산자들 앞에 있다면 prefix라고 한다.
반대로 a 1 +과 같은 경우는 당연히 postfix라고 한다.
그럼 infix를 prefix or postfix 로 바꾸는 법을 알아보자.
우선 infix식을 하나 가져온다.
1 + ( a + 2 ) * 5 / 7
아무렇게나 쓴 식이다.
이 식에서 취할 수 있는 모든 괄호를 취해보자.
( 1 + ( ( ( a + 2 ) * 5 ) / 7 ) )
계산상의 순서의 변화는 없을 것이다. 그저 보조괄호를 취한 것뿐이니.
여기서 주목할 것은, 각 괄호 안에는 모두 "피연산자 + 연산자 + 피연산자" 의 구조를 갖고
있다는 것이다.
각 괄호를 기준으로 연산자를 뒤로 빼보자.
( 1 + ( ( ( a 2 )+ * 5 ) / 7 ) )
( 1 + ( ( ( a 2 )+ 5 )* / 7 ) )
( 1 + ( ( ( a 2 )+ 5 )* 7 ) / )
( 1 ( ( ( a 2 )+ 5 )* 7 ) / ) +
각 연산자가 자기 자신이 속해 있는 괄호의 뒤로 빠진 것이다.
이런 식으로 바꾸고 괄호를 모두 삭제해보자.
1 a 2 + 5 * 7 / +
위와 같은 모양의 식이 나오는데, 이게 제대로 만들어 진 건지를 확인해 보기 위해서
이 상태로 앞에서 부터 스택에 넣고 계산해 보자. 연산자를 만나면 스택에서 두개의 피연산
자를 빼서 계산하고 다시 넣는다.
+ : a + 2
* : (a + 2 ) * 5
/ : (a + 2 ) * 5 / 7
+ : 1 + ( a + 2 ) * 5 / 7
잘 된다.
그렇다면 prefix는? 위의 괄호에서 연산자를 앞으로 빼면 된다.
prefix의 경우에는 헝가리 표기법이라고도 한다는데 원래는 명제를 단순하게 표현하기 위해
서 씌였다고 한다.
12. 이를 가지고 스택으로 계산이 불가능한가?
그건 또 아니다. 단지 구현의 차이일뿐.
postfix에서 연산자를 만나면 스택에서 두개의 피연산자를 빼서 더하고 다시 넣어줬다면,
prefix에서는 만약에 스택에 연속 된 두개의 피연산자가 들어오면 두개의 피연산자를 빼주
고 바로 밑의 연산자를 꺼내
계산을 하고 이를 집어 넣어 준다.
예를 보는 게 가장 빠르겠지...
( a + b ) * c + d * k
물론 아무렇게나 쓴 식이다.
괄호로 묶는다.
( ( ( a + b ) * c ) + ( d * k ) )
변환 한다.
( ( + ( a b ) * c ) + ( d * k ) )
( * ( + ( a b ) c ) + ( d * k ) )
( * ( + ( a b ) c ) + * ( d k ) )
+ ( * ( + ( a b ) c ) * ( d k ) )
괄호 제거...
+ * + a b c * d k
와 같다. 이제 하나씩 넣어보자. 초반에는 연산자만 잔득이나 한번에 넣었다고 하자. 일일이
한줄씩 쓰기 귀찮으니.
+ * + a : b -> + * ( a + b ) // 3개의 연산자와 1개의
피연산자가 있는데 추가로 한개의 피연산자 삽입
+ * ( a + b ) : c -> + ( ( a + b ) * c )
+ ( ( a + b ) * c ) : * -> + ( ( a + b ) * c ) *
+ ( ( a + b ) * c ) * : d -> + ( ( a + b ) * c ) * d
+ ( ( a + b ) * c ) * d : k -> + ( ( a + b ) * c ) (d * k) - > ( ( a + b ) *
c ) + (d * k)
잘 된다~
각 표기법을 자료구조를 통해서 바꾸는 법.
<트리 형태>
가장 먼저 연산 되는 것부터 리프에서 부터 만들어서 타고 올라온다.
이를 전위 순회를 하면 prefix, 후위 순회를 하면 postfix 중위 순위를 하면 infix가 된다.
형태를 만들면, 스택을 이용하여 가능하다.
13. <스택과 큐를 사용>
요건 좀 중요한데, 우선 infix을 postfix로 만드는 방법을 보자.
스택과 큐를 사용한다. 스택은 infix를 postfix로 바꾸는 과정에서 연산자를 잠시 저장한다.
알고리즘은 아래와 같다.
각 연산자의 우선순위는 [ 괄호 < +,- < *,/ ] 의 순이다.
1. '(' 를 만나면 스택에 푸시한다. (푸시 => 저장)
2. ')' 를 만나면 스택에서 '('가 나올때까지 팝하여 큐에 넣고 '('는 팝하여 버린다.
3. 연산자를 만나면 스택에서 그 연산자보다 낮은 우선순위의 연산자를 만날 때까지 팝하
여 큐에 넣고 자신을 푸시한다.
4. 피연산자는 그냥 큐에 넣는다.
5. 모든 입력이 끝나면 스텍에 있는 연산자들을 모두 팝하여 출력한다.
예) (2*(3+6/2)+2)/4+3
문자 큐 스택(상단->하단) 설명
( (
'(' 스택에 푸시 (저장)
2 2 (
숫자는 화면에 출력
* 2 * ( '*'
가 '('보다우선순위가 높음
( 2 ( * ( '('
는 스택에 푸시( 저장)
3 2 3 ( * ( 숫자
는 화면에 출력
+ 2 3 + ( * ( '+'가
'('보다 우선순위가 높음
6 2 3 6 + ( * ( 숫자
는 화면에 출력
/ 2 3 6 / + ( * ( '/'가
'+'보다 우선순위가 높음
2 2 3 6 2 / + ( * ( 숫자
는 화면에 출력
) 2 3 6 2 / + * ( '('까지
는 팝하여 출력,'('는무시
+ 2 3 6 2 / + * + ( '*' 는
'+' 보다 높으므로 팝
2 2 3 6 2 / + * 2 + ( 숫자는
출력
) 2 3 6 2 / + * 2 + '(' 까지 팝
하여 출력
/ 2 3 6 2 / + * 2 + / 연산자는
푸시(저장)
14. 4 2 3 6 2 / + * 2 + 4 / 숫자는 출
력
+ 2 3 6 2 / + * 2 + 4 / + '/'는 '+'보다
높아서 출력하고'+'는저장
3 2 3 6 2 / + * 2 + 4 / 3 + 숫자는 출
력
끝 2 3 6 2 / + * 2 + 4 / 3 + 끝이므로 모두
팝(출력)
이제 큐에 있는 내용을 디큐(dequeue)하면서 스택에 넣으면서 위에 정리한 postfix방법으로
계산을 하면 된다.
15. ※알고리즘
1)장기판 좌표를 정수로 바꾸었을 경우.
①말의 좌표 x, y를 입력한다.
②x*10+y를 통해 각 좌표를 정수로 바꾸고 1차 배열로 구현하고 0으로 초기화한다.
③한 번 간 좌표는 1로 표시하여 중복을 피한다.
④움직일 때 마다 카운트를 올린다.
⑤움직일 곳 없이 모두 막혀 있다면 백트랙킹을 통해 다음 조건을 찾아본다.
⑥반복한다.
⑦카운터가 장기판 크기인 89까지 올라왔다면 처음부터 출력한다.
1-1)장기판 좌표를 정수로 바꾸었을 경우(수정).
①말의 좌표 x, y를 입력한다.
②x*10+y를 통해 각 좌표를 정수로 바꾼다.
③말이 움직인 좌표를 stack 배열에 넣는다.
④움직일 때 마다 카운트를 올린다.
④말이 있는 좌표에서 이동 가능한 전 좌표를 찾는다.
⑥스택 배열에 들어있는 좌표와 ④번에서 찾은 좌표를 처음부터 비교해 순서대로 중복되지
않았다면 첫 번째 좌표를 stack배열에 넣고 계속 반복한다.
⑤움직일 곳 없이 모두 막혀 있다면 백트랙킹을 통해 다음 조건을 찾아본다.
⑥반복한다.
⑦카운터가 장기판 크기인 89까지 올라왔다면 처음부터 출력한다.
1-2)장기판 좌표를 정수로 바꾸엇을 경우(수정).
①말의 좌표 x, y를 입력한다.
②x*10+y를 통해 각 좌표를 정수로 바꾼다.
②stack 2개 잡는다.
③stack1에 시작값을 저장.
④stack2에 이동경로를 저장.
④stack2의 top의 값으로 이동.
⑥stack2의 top의 값의 이동경로에 stack1의 값이 포함되지 않는다면 stack1에 top의 값을
버림.
⑤stack2의 top의 값이 이동경로에 stack1의 값이 포함된다면 stack2의 top의 값을 stack1
에 저장.
⑥stack2의 top의 값을 버림.
⑦stack2에 값이 없을 경우 stack1의 배열을 queue의 형태로 좌표 출력.
⑧stack2에 값이 있을 경우 stack1에 저장된 값과 비교 후 stack1에 없는 이동경로만
stack2에 저장(중복체크)
⑨④번으로 돌아가서 반복
2)장기판을 2차 배열로 구현했을 경우.
①말의 좌표 x, y를 입력한다.
②장기판의 각 점을 좌표라 생각하고 2차 배열로 장기판을 만든다.
③한 번 간 좌표는 1로 표시하여 중복을 피한다.
④움직일 때 마다 카운트를 올린다.
16. ⑤움직일 곳 없이 모두 막혀 있다면 백트랙킹을 통해 다음 조건을 찾아본다.
⑥반복한다.
⑦카운터가 장기판 크기인 89까지 올라왔다면 처음부터 출력한다.
17. ※초안
#include <stdio.h>
#include <stdlib.h>
#define ROW_SIZE 10
#define COL_SIZE 9
#define NUM_WAYS 8
typedef int board_t[ROW_SIZE][COL_SIZE];
int dr[NUM_WAYS] = {-2,-1,1,2,2,1,-1,-2};
int dc[NUM_WAYS] = {1,2,2,1,-1,-2,-2,-1};
void initialize_board(board_t board)
{
int i,j;
for(i=0;i<ROW_SIZE;i++)
{
for(j=0;j<COL_SIZE;j++)
{
board[i][j] = -1;
}
}
}
void print_board(board_t board)
{
int i,j;
for(i=0;i<ROW_SIZE;i++)
{
for(j=0;j<COL_SIZE;j++)
{
printf("%dt",board[i][j]);
}
printf("n");
}
}
int is_inside_board(int r, int c)
{
return r>=0 && r<ROW_SIZE && c>=0 && c<COL_SIZE;
}
int is_available(board_t board, int r, int c)
{
18. return is_inside_board(r,c) && board[r][c] == -1;
}
int num_next_moves(board_t board, int r, int c)
{
int i,result=0;
for(i=0;i<NUM_WAYS;i++)
{
if(is_available(board,r+dr[i],c+dc[i]))
{
result++;
}
}
return result;
}
int next_way_of(board_t board, int r, int c)
{
int i, min = NUM_WAYS, result=0;
for(i=0;i<NUM_WAYS;i++)
{
if(is_available(board, r+dr[i], c+dc[i]) &&
num_next_moves(board,r+dr[i],c+dc[i])<min)
{
min=num_next_moves(board,r+dr[i],c+dc[i]);
result=i;
}
}
return result;
}
int main()
{
int r,c,move,next_way;
board_t board;
initialize_board(board);
while(1)
{
printf("input start position r(0~9) c(0~8): ");
scanf("%d %d",&r, &c);
fflush(stdin);
if(is_inside_board(r,c))
{
break;
}
printf("Please put them again.n");
}
board[r][c] = 0;