-
메소드를 더 강력하게Programming/JAVA 2010. 5. 3. 08:03
닷컴 가라앉히기 게임을 만들어 봅시다.
이 게임은 컴퓨터를 상대로 하는 게임입니다.
컴퓨터에 사이트명을 그리드 위에 배치하면 여러분은 가능하면 적은 횟수만큼 찍어서 닷컴을 침몰시켜야 합니다.
우선 고수준 설계부터 시작합니다.
게임의 전반적인 흐름을 확실히 규정해야겠죠?? 기본개념은 다음과 같습니다.
1.사용자가 게임을 시작시킵니다.
a.닷컴 세 개를 만듭니다.
b.닷컴 세 개를 가상 그리드에 배치합니다.
2.게임이 본격적으로 시작됩니다.
닷컴이 하나도 남지 않게 될 때까지 다음과 같은 과정을 반복합니다.
a.사용자가 예상 위치("A2","C0"등)를 입력하도록 프롬프트를 띄웁니다.
b.사용자가 입력한 위치가 맞는지, 틀리는지, 아니면 방금 찍은 것으로 인해 닷컴이 가라 앉았는지를 판별합니다. 상황에 따라 적절한 행동을 취합니다.
(맞았으면 셀("A2","D4"등)을 지우고 닷컴이 가라앉았으면 그 닷컴을 지웁니다.)
3.게임을 끝냅니다.
찍은 횟수를 바탕으로 사용자의 등급을 매깁니다.
※프로시저 보다는 프로그램에 있는 어떤 대상이나 물건 같은 것에 초점을 맞춰야 합니다.
클래스 개발
클래스에서 어떤 것을 해야하는지를 파악합니다.
인스턴스 변수와 메소드 목록을 작성합니다.
메소드를 만들기 위한 준비 코드를 만듭니다.
메소드에 대한 테스트 코드를 만듭니다.
클래스를 구현합니다.
메소드를 테스트합니다.
필요하면 디버그를 하거나 다시 구현합니다.
할일:
SimpleDotCom 클래스
준비코드 만들기
테스트 코드 만들기
최종 자바 코드 만들기
SimpleDotComGame 클래스
준비코드만들기
최종 자바코드만들기
준비코드 - 문법보다는 논리를 중점적으로 살펴보기 위해 유사코드 형태로 표현한 것입니다.
테스트 코드 - 실제 코드를 테스트하고 작업이 제대로 처리되는지 확인하기 위한 클래스 또는 메소드입니다.
실제 코드 - 클래스를 실제로 구현한 코드로써, 이 부분이 실제로 사용할 자바 코드입니다.
익스트림 프로그래밍(XP, eXtreme Programming)
익스트림 프로그래밍의 가장 큰 장점은 막판에 스펙이 변경되는 일이 있어도 클라이언트가 원하는 것을 원하는 기한에 맞춰서 제공할수 있다는 검이다.
XP는 서로 조화롭게 쓸 수 있도록 계획된 일련의 규칙이 있습니다.
조금씩, 하지만 자주 발표한다.
사이클을 반복해서 돌리면서 개발한다.
스펙에 없는 것은 절대 집어넣지 않는다(아무리 그 기능이 나중에 쓰일 것 같은 느낌이 들어도 그러지 않는 것이 좋다.)
테스트 코드를 먼저 만든다.
기회가 생기는 족족 언제 어디서든 코드를 개선한다.
모든 테스트를 통과하기 전에는 어떤 것도 발표하지 않는다.
조금씩 발표하는 것을 기분으로 하여 현실적인 작업 계획을 만든다.
모든일을 단순하게 처리한다.
SimpledotCom 클래스를 위한 테스트 코드만들기
이 준비 코드를 바탕으로 :
메소드:String checkYourself(String userGuess)
사용자가 추측한 위치를 String 매개변수 형태로 받아옵니다.
사용자가 추측한 위치를 int로 변환합니다.
int 배열에 있는 각 셀에 대해 다음 작업을 반복합니다.
//사용자가 추측한 위치를 닷컴이 들어있는 셀과 비교하는 부분
만약 사용자가 추측한 것이 맞으면
맞춘 개수를 증가시킵니다.
// 마지막 위치 셀인지 확인합니다.
만약 맞춘 회수가 3이면 "Kill" 을 결과로 리턴합니다.
그렇지 않으면 "Hit"를 리턴합니다.
만약 부분 끝
그렇지 않으면 틀린 것이므로 "Miss"를 리턴합니다.
만약 부분 끝
반복 부분 끝
메소드 끝
다음과 같은 것을 테스트해야합니다.
1.SimpleDotCom 객체의 인스턴스를 만듭니다.
2.위치를 대입합니다.
({2,3,4,}와 같은 int 값 세 개가 들어있는 배열)
3.사용자가 추측한 위치를 나타내는 String 을 만듭니다.
4.3단계에서 만들어낸 String 을 전달하면서 checkYourself()메소드를 호출합니다.
5.결과를 출력하여 옳은 결과가 나왔는지 확인합니다.
(결과가 맞으면"passed",틀리면"failed")
※ 테스트 코드에 대해 생각을 하고 만들다 보면 테스트 하고자 하는 메소드의 기능과 역할에 대한 개념을 더 깔끔하게 정리 할 수 있습니다.
그리고 실제 자신이 구현한 코드가 완성되면 바로 테스트 할 수 있다는 것도 장점이 될 수 있겠죠.
막상 나중에 테스트 코드를 만들어서 테스트할 시점이 되면 다른 더 중요한 일이 닥치곤 하니까요.
가장 이상적인 방법은 간단한 테스트 코드를 만들고 그 테스트를 통과하기 위한 부분만 구현하는 식으로 개발 과정을 조금씩 진척 시키는 것입니다.
그리고 같은 식으로 조금 더 복잡한 테스트 코드를 만들고 그 새로운 테스트를 통과하는데 필요한 부분만 또 구현하구요.
이렇게 테스트를 하는 과정에서 전에 만들어 둔 테스트 과정을 모두 반복적으로 테스트하게 되고, 그러면 나중에 추가한 코드 때문에 이전에 테스트를 끝낸 코드에 문제가 생기지는 않는지도 모두 테스트 할수 있겠죠.
SimpleDotCom 클래스용 테스트 코드
public class SimpleDotComTestDrive{
public static void main(Stinrg[] args) {
SimpleDotCom dot = new SimpleDotCom(); == SimpleDotCom 클래스의 인스턴스를 만듭니다.
int[] locations={2,3,4,} ; == 닷컴의 위치를 나타내기 위한 int 배열을 만듭니다.(0에서 6까지의 숫자 가운데 연속된 정수 세 개)
dot.setLocationCells(locations); == 닷컴에 대해 세터 메소드를 후출합니다.
String userGuess="2"; == 사용자가 추측한 위치 역할을 할 가짜 값을 만듭니다.
String result = dot.checkYourself(userGuess); == 닷컴 객체에 대해 checkYourself()메소드를 호출하고 그 메소드에 가짜 값을 전달 합니다.
String testResult="failed";
if(result.equals("hit")) {
testResult = "passed"; == 가짜 값(2)이 맞으면("hit"가 리턴되면) 제대로 작동한다는 것을 알 수 있습니다.
}
System.out.println(testResult); == 테스트 결과를 출력합니다.(passed 또는 failed)
}
}
checkYourself()메소드
준비코드는 코드에서 어떤 것을 해야하는지를 더 명백하게 파악하는 데 도움이 됩니다.
public String checkYourself(String stringGuess){
int guess = Integer.parseInt(stringGuess) ; == String 을 int로 변환 ㅎ바니다.
String result = "miss"; == 리턴할 결과를 저장할 변수를 만듭니다. 기본값은 "miss" 로 집어 넣습니다. 못맞추는 것을 기본으로 가정.
for(int cell : locationCells) { == 배열에 들어있는 각 원소(객체의 각위치 셀)에 대해 반복합니다.
if(guess ==Cells) { == 사용자가 추측한 값을 배열에 들어있는 원소(셀)와 비교합니다.
result="hit"; == 맞다면 증가시킵니다.
numOfHits++;
break; ==순환문을 빠져나옵니다. 다른 셀은 확인하지 않아도 됩니다.
}
}
if(numOfHits == locationCells.length) {
result="kill"; == 순환문 밖으로 나왔습니다. 하지만 그 객체가 죽었는지 (세번 맞았는지)확인해 보고, 그 경우에는 result라는 String 을"kill"로 바꿉니다.
}
System.out.println(result); == 사용자에게 결과를 보여줍니다.("hit"나"kill"로 바뀌지 않았다면 "miss" 가 출력 되겠죠?)
return result; == 이 메소드를 호출한 메소드로 결과를 리턴합니다.
}
String을 int로 변환합니다.
Integer.parseInt("3")
Integer = 자바에 기본적으로 내장된 클래스
parseInt = String 을 그 String이 나타내는 int로 파싱해 주는 방법을 알고 있는 Integer클래스에 들어있는 메소드
향상된 for문
for(int cell:locationCells) {}
이 for 순환문은 "locationCells배열에 들어있는 각원소에 대해서 반복함: 배열에 있는 다음항목을 가져와서 'cell'이라는 int변수에 대입함"으로 이해하면 됩니다.
콜론(:)은 왼쪽에 있는 변수에 오른쪽에 있는 것의 각우너소의 값이 대입된다는 것을 뜻합니다. 즉 locationCells에 들어있는 모든 int 값에 대해서 순환문을 돌린다고 보면 되죠.
int cell = 배열에 들어있는 한 원소의 값을 저장해둘 변수
locationCells = for문에서 순환문을 돌릴 대상이 되는 배열, 매번 순환문이 반복 될 때 마다 배열에 들어있느 ㄴ다음 원소가"cell"이라는 변수에 대입됩니다.
반복 작업용 변수 선언 - 순환문 본체 안에서 사용할 변수를 선언하고 초기화합니다. 순환문을 돌 때마다
※Integer.parseInt() 는 아스키코드값으로 구성된 String 에 대해서만 작동합니다. 일반적인 String이 들어갈시 예외를 던집니다.
SimpleDotCom 과 SimpleDotComTestDrive의 최종 코드
public class SimpleDotComTestDrive{
pulic static void main(Stinrg[] args){
SimpleDotCom dot = new SimpleDotCom();
int[] locations ={2,3,4};
dot.setLocationCells(locations);
String userguess="2";
String result = dot.checkYourself(userGuess);
}
}
public class SimpleDotCom{
int[] locationCells;
int numOfHits = 0;
public void setlocationCells(int[] locs) {
locationCells = locs;
}
public String checkYourself(String stringGuess) {
int guess = Integer.parseInt(stringGuess) ;
String result ="miss";
for(int i=0;i<locationCells.length;i++) {
if(guess == locationCells[i]) {
result="hit";
numOfHits++;
break;
}
}
if(numOfHits == locationCells.length) {
result="kill";
}
System.out.println(result);
return result;
}
}
핵심정리
자바 프로그램을 만들 때는 우선 고수준 설계부터 시작합니다.
새로운 클래스를 만들 때는 일반적으로 다음과 같은 세 가지를 만들어야 합니다.
준비코드,테스트 코드, 실제(자바) 코드
준비 코드에서는 어떻게 해야 할지 보다는 무엇을 해야 할지를 기술해야 합니다. 구현은 나중에 하면 됩니다.
테스트 코드를 설계 할 때는 준비 코드를 활용하면 좋습니다.
메소드를 구현하기 전에 테스트 코드를 만들어야 합니다.
순환문 코드 반복 횟수를 미리 알 수 있는 경우에는 while보다는 for를 쓰는 것이 좋습니다.
변수에 1을 더할 때는 선/후 증가 연산자를 쓰면 됩니다.
(x++;)
변수에 1을 뺄 때는 선/후 감소 연산자를 쓰면 됩니다.
(x--;)
String 을 int로 바꿀 때는 Integer.parseInt()를 쓰면 됩니다.
Integer.parseInt()는 숫자를 나타내는 String("0","1","2"등) 에 대해서만 사용할 수 있습니다.
순환문을 중간에 무조건(부울 테스트 조건이 아직 참인 경우에도)빠져나올 때는 break를 사용하면 됩니다.
random()
int randomNum = (int) (Math.random()*5)
Math 자바내장 클래스, random() Math클래스에 들어있는 메소드
(int) == 이런것을 '캐스트'라고 합니다. 그 뒤에 있는 것을 캐스트 하고자 하는 유형(괄호 안에 들어있는 유형)으로 바꿔줍니다.
Math.random은 double을 리턴하므로 int로 만들려면 캐스트 해야 합니다. 이 경우에는 캐스트 과정에서 double의 소수점 이하 부분이 없어집니다.
Math.random 메소드에서는 0이상 1미만의 숫자를 리턴합니다.
for 순환문
for(int i =0;i<100;i++){}
초기화 - 순환문 본체에서 사용할 변수를 선언하고 초기화 하는 부분이빈다. 보톤 이런 변수는 카운터로 쓰입니다.
부울테스트- 조건테스트가 들어가는 자리입니다. 그안에는 반드시 부울값(true 또는 false)이 나오는 코드가 들어가야 합니다. x>=4와 같은 테스트가 들어가도 되고 부울값을 리턴하는 메소드가 들어갈 수도 있습니다.
반복 표현식- 순호나문을 한 번 반복 할 떄마다 실행할 내용을 집어넣습니다. 이 표현식은 매번 반복이 끝날 때마다 한 번 씩 실행됩니다.
for 와 while의 차이점
while 순환문에는 부울 테스트만 있습니다. 초기화 및 반복 표현식이 내장되어 있지 않지요, while 순환문은 반복 횟수를 알 수 없을 때 어떤 조건이 만족되는 동안 게속 반복하는 경우에 유용합니다.
하지만 반복 ㅗ힛수를 알고 있다면 (배열의 길이가 7이라는 것을 알고 있다거나 하는 경우)
for 순환문이 더 깔 끕합니다.
for(int i=0;i<8;i++){
System.out.println(i);
}
int i=0;
while(i<8){
System.out.println(i);
i++;
}
'Programming > JAVA' 카테고리의 다른 글
JDBC API 를 이용한 프로그래밍. (0) 2010.05.03 클래스와 객체 (0) 2010.05.03 자바를 소개합니다. ^^ (0) 2010.05.03 원시 변수와 레퍼런스 (0) 2010.05.03 객체의 행동 (0) 2010.05.03