U E D R , A S I H C RSS

JTD Study/첫번째과제/�명

실행코드

~cpp code
import javax.swing.JOptionPane;
public class BaseBall {	
	private int correctNumber;
	public static void main(String[] args) {
		BaseBall oneGame = new BaseBall();
		oneGame.setCorrectNumber();
		int guess = 0, result = 0;
		do
		{
			guess = oneGame.inputGuess();
			result = oneGame.compare(guess);
			if (result != 30)
				JOptionPane.showMessageDialog(null, (result / 10) + " Strike, " 
						+ (result % 10) + " Ball");
		}while (result != 30);
		oneGame.displayResult();
	}
	public void setCorrectNumber()
	{
		int setNumber = 0;
		do
		{
			setNumber = (int) (Math.random() * 10);
		}while (setNumber == 0);
		correctNumber = setNumber;
		do
		{
			setNumber = (int) (Math.random() * 10);
		}while (correctNumber == setNumber);
		correctNumber = correctNumber * 10 + setNumber;
		do
		{
			setNumber = (int) (Math.random() * 10);
		}while (((int)(correctNumber / 10)) == setNumber 
				|| ((int)(correctNumber % 10)) == setNumber);
		correctNumber = correctNumber * 10 + setNumber;
	}
	public int inputGuess()
	{
		String input =  JOptionPane.showInputDialog("Enter three different number\n");
		int guess = Integer.parseInt(input);
		return guess;
	}
	public int compare(int aGuess)
	{
		int compareResult = 0, cCorrect = correctNumber;
		int firstGuess = (int) (aGuess / 100);
		int secondGuess = ((int) (aGuess / 10)) % 10;
		int thirdGuess = aGuess % 10;
		if (((int)(cCorrect / 100) == firstGuess))
				compareResult ++;
		cCorrect = cCorrect % 100;
		if (((int)(cCorrect / 10) == secondGuess))
				compareResult ++;
		cCorrect = cCorrect % 10;
		if (cCorrect == thirdGuess)
				compareResult ++;
		compareResult *= 10;
		cCorrect = correctNumber;
		if (((int)(cCorrect / 100)) == secondGuess 
				|| ((int)(cCorrect / (100))) == thirdGuess)
			compareResult ++;
		cCorrect = cCorrect % 100;
		if (((int)(cCorrect / 10)) == firstGuess 
				|| ((int)(cCorrect / (10))) == thirdGuess)
			compareResult ++;
		cCorrect = cCorrect % 10;
		if ((cCorrect == firstGuess) || (cCorrect == secondGuess))
			compareResult ++;
		return compareResult;
	}
	public void displayResult()
	{
		JOptionPane.showMessageDialog(null, "You are right!\n Answer is " + correctNumber);
	}
}

잡담

  • 정답ì�„ int변수 3ìž�리 숫ìž�로 표현해서 만들어봤ë�”니 코드만 ë�” 길어졌네요 -0-;; - 문ì›�명

개선 시�

집�서 놀다가 우연히 여기를 와서 고�봅니다. 조금 � ��해 보시면 �지요. 저�게 재미있는 경험� 주었는�, 문�명 후배님� 보시�고 과정� 만들어 �었습니다. 선행학습으로 JUnit� 있어야 하는�, http://junit.org �서 �금하시면 관련문서를 보시고 선배들�게 물어보세요.

용기가 내셔서 저를 찾으면... ;;
--NeoCoin
  • 처ì�Œì—�는 Test-Driven Development ì—� ìž…ê°�하여 만들어 보려고 했으나, Java를 ê±°ì�˜ 처ì�Œ 시작하고 프로그래ë°� 경험ì�˜ 공백기간ì�´ 길었ë�˜ê²Œ í�° 타격ì�´ì—ˆìŠµë‹ˆë‹¤ã… ã… . ê²°êµ­ì—�는 문법과 알고리즘ì—�ë§Œ ì‹ ê²½ì�„ 쓰다보니 TDDë°©ì‹�으로 다루기가 쉽지 않네요. 개선 ì¡°ì–¸ì�„ í•´ 주신 류ìƒ�민 선배님 ê°�사합니다 ã…Žã…Ž -문ì›�명
    • 오해가 있ì�„ 것 같아서 코멘트 합니다. TDD는 별로 중요하지 않습니다. ê²°ì •ì �으로 저는 TDD로 하지 않았습니다. 그냥 Refactoring시 Regression Test를 위해서 JUnit ì�„ ì�¼ì�„ ë¿�ì�´ì—�ìš”.--NeoCoin
      • 네, 제가 TDDì�˜ ì�˜ë¯¸ë¥¼ 확실히 하지 못한 것 같습니다. TDDì±…ì�˜ 앞부분만 ì�½ì–´ 보았는ë�°, 계ì†�해서 ë�” ì�½ì–´ì•¼ 나가야겠다는 다ì§�ì�´ 드네요. 관심 가져주셔서 고맙습니다 ã…‹ -문ì›�명

과정

초기� 테스트 가능하�� �하는 값으로 무작위로 나오는 답안� 세팅하는 함수 추가.
~java
// ..�략
	void setCorrectNumber(int in) {
		correctNumber = in;
	}

	@Test
	public void test2() {
		BaseBall oneGame = new BaseBall();
		oneGame.setCorrectNumber(123);
		assertEquals(30, oneGame.compare(123));
		assertEquals(10, oneGame.compare(100, 123));
		assertEquals(2, oneGame.compare(310, 123));
	}
//..�략

setCorrectNumber 하기� 귀찮아서 compare 부분� 확장 , 내부�서 쓰��� 없는 함수로 제거 목�으로 코스 수정
~java
	@Test
	public void test2() {
		BaseBall oneGame = new BaseBall();
		assertEquals(30, oneGame.compare(123, 123));
		assertEquals(10, oneGame.compare(100, 123));
		assertEquals(2, oneGame.compare(310, 123));
	}

	public int compare(int aGuess) {
		return compare(aGuess, correctNumber);
	}
	public int compare(int aGuess, int answer) {
		correctNumber = answer;

		int compareResult = 0, cCorrect = correctNumber;
//�략
	}

readability 를 위해 필요없는 typecasting 문법들 제거 (Java Language Specification� 규칙들� 보세요. 해당 typecasting� 거�다 필요 없는�니다.) 유�미한 단위로 분리
~java
	public int compare(int aGuess, int answer) {
		correctNumber = answer;

		int compareResult = 0, cCorrect = correctNumber;
		int firstGuess = aGuess / 100 % 10;
		int secondGuess = aGuess / 10 % 10;
		int thirdGuess = aGuess % 10;



		if (cCorrect / 100 == firstGuess)
			compareResult++;
		cCorrect = cCorrect % 100;
		if (cCorrect / 10 == secondGuess)
			compareResult++;
		cCorrect = cCorrect % 10;
		if (cCorrect == thirdGuess)
			compareResult++;
		compareResult *= 10;



		cCorrect = correctNumber;
		if ((cCorrect / 100) == secondGuess || (cCorrect / 100) == thirdGuess)
			compareResult++;
		cCorrect = cCorrect % 100;
		if ((cCorrect / 10) == firstGuess || (cCorrect / 10) == thirdGuess)
			compareResult++;
		cCorrect = cCorrect % 10;
		if ((cCorrect == firstGuess) || (cCorrect == secondGuess))
			compareResult++;
		return compareResult;
	}
특정 �지션� 숫�를 얻어오기 위한 반복 부분들 발견, 특정 �지션� 얻어오는 함수 만들기
~java
	int positionNum(int value, int pos) {
		if (pos < 1)
			throw new IndexOutOfBoundsException("pos값� 1��� 넣어주세요.");
		int a = value % (int) Math.pow(10, pos);
		return a / (int) Math.pow(10, pos - 1);
	}

	@Test
	public void getPositionNum() {
		assertEquals(3, positionNum(123, 1));
		assertEquals(2, positionNum(123, 2));
		assertEquals(1, positionNum(123, 3));
	}

해당 함수를 알고리즘� �용, Test는 계� 녹색 .
결과 값� �미를 드러낼수 있�� 변경
��� 함수가 this.correctNumber� �존할 필요 없으므로 코드 개선
~java
public int compare(int aGuess, int cCorrect) {
		int firstGuess = positionNum(aGuess,3);
		int secondGuess = positionNum(aGuess,2);
		int thirdGuess = positionNum(aGuess,1);


		int strike=0;
		if (positionNum(cCorrect,3) == firstGuess)
			strike++;
		if (positionNum(cCorrect,2) == secondGuess)
			strike++;
		if (positionNum(cCorrect,1) == thirdGuess)
			strike++;


		int ball=0;
		if (positionNum(cCorrect,3) == secondGuess || positionNum(cCorrect,3) == thirdGuess)
			ball++;
		if (positionNum(cCorrect,2) == firstGuess || positionNum(cCorrect,2) == thirdGuess)
			ball++;
		if ((positionNum(cCorrect,1) == firstGuess) || (positionNum(cCorrect,1) == secondGuess))
			ball++;
		return ball + strike*10;
	}
코드� 약간 패턴� 보�다. inline시키면 보�것 같다. 그래서 xxxGuess 를 inline
~java
public int compare(int aGuess, int answer) {
		int cCorrect = answer;
		int strike=0;
		if (positionNum(cCorrect,3) == positionNum(aGuess,3))
			strike++;
		if (positionNum(cCorrect,2) == positionNum(aGuess,2))
			strike++;
		if (positionNum(cCorrect,1) == positionNum(aGuess,1))
			strike++;


		int ball=0;
		if (positionNum(cCorrect,3) == positionNum(aGuess,2) || positionNum(cCorrect,3) == positionNum(aGuess,1))
			ball++;
		if (positionNum(cCorrect,2) == positionNum(aGuess,3) || positionNum(cCorrect,2) == positionNum(aGuess,1))
			ball++;
		if ((positionNum(cCorrect,1) == positionNum(aGuess,3)) || (positionNum(cCorrect,1) == positionNum(aGuess,2)))
			ball++;
		return ball + strike*10;
	}

숫� 패턴� 파악하고 중복 개선, magic number 제거
~java
	public int compare(int aGuess, int cCorrect) {
		final int START_POS = 1,END_POS = 3;

		int strike = 0;
		for (int pos = END_POS; pos >=START_POS; pos--) {
			if (positionNum(cCorrect, pos) == positionNum(aGuess, pos))
				strike++;
		}

		int ball = 0;
		for (int corPos = END_POS; corPos >=START_POS; corPos--) {
			for (int guePos = END_POS; guePos > 0; guePos--) {
				if (corPos != guePos && positionNum(cCorrect, corPos) == positionNum(aGuess,guePos))
					ball++;
			}
		}
		return ball + strike * 10;
	}

�개� 루프� 정확한 �미 파악, 합침
~java
	public int compare(int aGuess, int cCorrect) {
		final int START_POS = 1, END_POS = 3;

		int strike = 0, ball = 0;

		for (int corPos = END_POS; corPos >= START_POS; corPos--) {
			for (int guePos = END_POS; guePos >= START_POS; guePos--) {
				if (positionNum(cCorrect, corPos) == positionNum(aGuess, guePos)) {
					if (corPos == guePos)
						strike++;
					else
						ball++;
				}
			}
		}
		return ball + strike * 10;
	}

해당 루틴� 지날때 마다 result 값� 10과 1� �해주는 방�으로 바꿈
~java
	public int compare(int aGuess, int cCorrect) {
		final int START_POS = 1, END_POS = 3, STRIKE_DELTA = 10, BALL_DELTA = 1;

		int result = 0;  //10�리가 strike, 1�리고 ball 값
		for (int corPos = END_POS; corPos >= START_POS; corPos--)
			for (int guePos = END_POS; guePos >= START_POS; guePos--)
				if (positionNum(cCorrect, corPos) == positionNum(aGuess, guePos))
					result += (corPos == guePos) ? STRIKE_DELTA : BALL_DELTA;
		return result;
	}

기타 overloading� 무�미한 compare를 정리. 소스� setCorrectNumber를 �성�로 옮김.
ë�” 개선하고 ì‹ìœ¼ë‚˜ 그냥 하기 ì§€ì³�서 여기서 그만..
~java
package test;

import static org.junit.Assert.assertEquals;
import org.junit.Test;
import javax.swing.JOptionPane;

public class BaseBall {
	private int correctNumber;

	public static void main(String[] args) {
		final int END_GAME_NUM = 30;

		BaseBall oneGame = new BaseBall();
		while (true) {
			int result = oneGame.runOneTurn();
			if (result == END_GAME_NUM)
				break;
			else
				JOptionPane.showMessageDialog(null,
					String.format("%d Strike, %d Ball", result / 10, result % 10));
		}
		oneGame.displayResult();
	}

	public int runOneTurn() {
		return compare(this.correctNumber, inputGuess());
	}

	public BaseBall() {
		int setNumber = 0;
		do {
			setNumber = (int) (Math.random() * 10);
		} while (setNumber == 0);
		correctNumber = setNumber;
		do {
			setNumber = (int) (Math.random() * 10);
		} while (correctNumber == setNumber);
		correctNumber = correctNumber * 10 + setNumber;
		do {
			setNumber = (int) (Math.random() * 10);
		} while (correctNumber / 10 == setNumber
				|| correctNumber % 10 == setNumber);
		correctNumber = correctNumber * 10 + setNumber;
	}

	public int inputGuess() {
		String input = JOptionPane
				.showInputDialog("Enter three different number\n");
		int guess = Integer.parseInt(input);
		return guess;
	}

	int positionNum(int value, int pos) {
		if (pos < 1)
			throw new IndexOutOfBoundsException("pos값� 1��");
		int a = value % (int) Math.pow(10, pos);
		return a / (int) Math.pow(10, pos - 1);
	}

	public int compare(int aGuess, int cCorrect) {
		final int START_POS = 1, END_POS = 3, STRIKE_DELTA = 10, BALL_DELTA = 1;

		int result = 0; // 10�리가 strike, 1�리가 ball 값
		for (int corPos = END_POS; corPos >= START_POS; corPos--)
			for (int guePos = END_POS; guePos >= START_POS; guePos--)
				if (positionNum(cCorrect, corPos) == positionNum(aGuess, guePos))
					result += (corPos == guePos) ? STRIKE_DELTA : BALL_DELTA;
		return result;
	}

	public void displayResult() {
		JOptionPane.showMessageDialog(null, "You are right!\n Answer is "
				+ correctNumber);
	}

	@Test
	public void getPositionNum() {
		assertEquals(3, positionNum(123, 1));
		assertEquals(2, positionNum(123, 2));
		assertEquals(1, positionNum(123, 3));
	}

	@Test
	public void test2() {
		BaseBall oneGame = new BaseBall();
		assertEquals(30, oneGame.compare(123, 123));
		assertEquals(10, oneGame.compare(100, 123));
		assertEquals(2, oneGame.compare(310, 123));
	}
}
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:23:29
Processing time 0.0074 sec