모바일 맞고 게임6-2(기본 게임 룰 및 점수 계산 구현)
DevSource/맞고 2012. 12. 27. 19:00 |구현은 앞서 살펴본 맞고의 규칙 순서대로 구현을 해 나가도록 하겠습니다.
오광. |
먼저 광 처리를 다시 한번 살펴보면,
광은 기본적으로 위의 5개가 있습니다.
그 중에, 광이 3개 있다면, 3점 이지만, 비광이 있으면 2점이라고 했죠.
그 외에는 비광의 포함 유무에 관계 없이, 4광이면 4점, 5광이면 15점을 획득합니다.
자, 그럼 광의 점수 계산 코드를 어디에 삽입하면 좋을까요?
당연히, 광을 획득하는 그 순간, 광에 대한 점수 계산을 해 주어야 하겠지요?
광의 획득은 addKwang() 이라는 함수를 따로 지정 해놓고 광을 추가 해주었었던 것을 기억하실 겁니다.
그러니, 당연히, addKwang() 함수에 광의 점수 계산 코드를 삽입해야 하겠지요.
/** * 광을 추가함. * @param userType * @param cardIdx */ public void addKwang(byte userType, int cardIdx) { int numOfKwang = 0; // 비광을 먹었다면, 비광의 소유 여부 기록. if(gCard.getType((byte)cardIdx) == CARDTYPE_BIKWANG) bHaveBiKwang[userType] = true;
switch(numOfKwang) { case 3: // 광이 3개라면, /* 비광이 있다면, */ if(bHaveBiKwang[userType] == true) { addPoint(userType, 2); bCalculatedBiKwang = true; // 비광 때문에 2점을 추가했음. } else // 비광이 없다면, addPoint(userType, 3); // 3점 추가. break; case 4: // 광이 4개라면, if(bCalculatedBiKwang) // 비광때문에 2점을 더해주었었다면, { /* * 비광의 유/무에 상관 없이, * 카드가 4장일 때에는, 4점 이므로, * 비광 때문에 2점을 더해주었었다면, * 1점을 더해준다. */ addPoint(userType, 1); bCalculatedBiKwang = false; } // 광이 하나 추가되었으므로, 1점 추가. addPoint(userType, 1); break; case 5: // 오광 이라면, /* * 오광의 경우, 15점이 추가 된다. * 광이 4개일때의 점수가 4점이었으므로, 11점을 추가 해준다. */ addPoint(userType, 11); } // switch(numOfKwang). } // end public void addKwang(byte userType, int cardIdx). |
위 소스에서 회색 음영 처리 된 부분은 예전에 이미 설명했던 내용이므로, 부가 설명은 않겠습니다.
그럼 추가 된 부분을 한번 보도록 하지요.
먼저, 광의 점수를 정확히 계산하기 위해서는,
플레이어의 슬롯에 비광이 포함되어 있는지 확인하는 것이 반드시 필요하겠지요.
그래서 함수의 두번째 줄에,
// 비광을 먹었다면, 비광의 소유 여부 기록. if(gCard.getType((byte)cardIdx) == CARDTYPE_BIKWANG) bHaveBiKwang[userType] = true; |
위와 같이 해주어서, 현재 먹은 카드(cardIdx)가 비광인지 비교 해서 맞다면,
전역으로 선언된 bHavaeKwang 이라는 boolean 변수에 true를 대입합니다.
그 다음 부분은, 광이 3장째 일때에, 광 3장 중에 비광이 있다면, 2점을 추가해주고,
bCalculatedBiKwang 을 true로 만들어 줍니다.
bCalculatedBiKwang 은 광이 4장일때에, 비광이 있어서 2점이 추가 되었었는지 체크하기 위한 변수이며,
광이 4장일때에, 비광 때문에, 2점을 추가해 주었다면, 먼저 1점을 더해주어서 3점을 만든후,
다시 1점을 추가 해 주어서, 광이 4장일때에, 4점이 추가되도록 해줍니다.
즉, 광이 3장일때 비광이 없었다면,
3점(광 3장) + 1점(추가 한장) = 4점. 이렇게 계산이 되지만,
광이 3장일때 비광이 있었다면,
2점 + 1점 + 1점(추가 한장) = 4점. 이렇게 계산이 되는 것이지요.
또, 광이 5장인, 즉, 오광일 때에는 15점이 추가 되어야 하지만, 이미 앞에서 4점이 추가되었었으므로,
단순히 그 뒤에 11점을 추가 해주면 되겠지요. 그래서 11점을 더 해주는 것입니다.
열끗. |
이제, 열끗 처리를 한번 또 구현해 볼까요?
열끗 처리 역시 광의 처리와 거의 흡사합니다.
열끗의 경우, 아래 보이는것과 같이 모두 9장이며, 5장부터 점수로 계산이 됩니다.
5장일때 1점, 6장일때 2점, 7장일때 3점, .... 이렇게 한장이 추가될때마다 1점씩 추가됩니다.
또 7장 이상이라면, 멍따로 처리 되며, 승리시 두배의 금액을 획득하게 됩니다.
또, 열에서는 한가지 더 생각해 주어야 할 것이 있습니다. 바로 고도리이죠!
고도리는 다음의 3장의 카드를 모두 소유 하고 있다면, 플레이어의 점수에 5점이 합산됩니다.
역시 이 열끗의 처리 역시, 열끗을 먹는 동시에 처리하는 것이 좋겠죠?
광과 마찬가지로 addYeul() 함수에 해당 코드를 구현합니다.
/** * 열을 추가함. * @param userType * @param cardIdx */ public void addYeul(byte userType, int cardIdx) { int numOfYeul = 0; /* 지금 먹은 열이 고도리 패중 하나라면, */ if(gCard.getType((byte)cardIdx) == CARDTYPE_GODORI) { incCntGodori(userType); } // 고도리 패가 3장 있다면, -> 고도리. if(bGodori[userType] == false && getCntGodori(userType) == 3) { addPoint(userType, 5); // 5점 추가. bGodori[userType] = true; }
// 열은 5장 부터 1점씩 추가. if(numOfYeul >= 5) addPoint(userType, 1); } |
마찬가지로 회색 음영 처리 된 부분은 이전시간에 이미 설명했던 부분입니다.
가장 먼저 고도리패를 체크 해줍니다.
고도리 패는 GostopCard.java에 CARDTYPE_GODORI라고 정의해놓았었죠?
따라서, 현재 먹은 카드(cardIdx)의 종류를 체크후, 고도리 패면, 먹은 고도리 패의 갯수를 증가시킵니다.
그리고 그 다음 문장 처럼, 고도리의 패장이 3장 있다면, 고도리를 모두 획득한 것이므로,
bGodori를 true로 만들어 주어, userType의 사용자가 고도리 했음을 표시하고, 5점을 추가합니다.
그리고 마지막에서는 열이 5장이 되는 순간부터, 점수를 1점씩 추가시켜 주면 열의 처리는 모두 끝납니다.
그런데 위의 코드에 멍따에 대한 부분은 없는데요. 멍따의 처리는 최종 점수에 두배를 곱해 주는 것이니,
멍따를 포함한 피박, 고박, 광박 등등의 벌칙 룰은 나중에 게임 결과 처리시 처리 해 주는 것이 좋겠지요.
띠. |
띠 역시 광이나 열끗과 마찬가지 방식으로, addYeul() 함수에서 처리하는 것이 좋겠지요.
띠에는 다음과 같이 총 10개의 띠가 있습니다.
앞에서부터 3장을 소유하고 있다면, 홍단. 그 다음 3장은 초단. 그리고 그 다음은 청단이라고 했죠.
비에 초단 비슷한 띠가 달려 있는 패는 초단이 아닙니다.
/** * 띠를 추가함. * @param userType * @param cardIdx */ public void addDdee(byte userType, int cardIdx) { /* 지금 먹은 띠가... */ switch(gCard.getType((byte)cardIdx)) { case CARDTYPE_CHUNGDAN: // 청단 패 중 하나라면, incCntChungDan(userType); break; case CARDTYPE_HONGDAN: // 홍단 패 중 하나라면, incCntHongDan(userType); break; case CARDTYPE_CHODAN: // 초단 패 중 하나라면, incCntChoDan(userType); break; } // 만약 청단 패가 3개 라면, -> 청단. if(bChungDan[userType] == false && getCntChungDan(userType) == 3) { addPoint(userType, 3); // 3점 추가. bChungDan[userType] = true; } // 만약 홍단 패가 3개 라면, -> 홍단. if(bHongDan[userType] == false && getCntHongDan(userType) == 3) { addPoint(userType, 3); // 3점 추가. bHongDan[userType] = true; } // 만약 초단 패가 3개 라면, -> 초단. if(bChoDan[userType] == false && getCntChoDan(userType) == 3) { addPoint(userType, 3); // 3점 추가. bChoDan[userType] = true; } int numOfDdee=0;
// 띠는 5장 부터 1점씩 추가. if(numOfDdee >= 5) addPoint(userType, 1); } |
앞의 열끗에서 고도리를 처리해 주었던과 동일 합니다.
단순히, 종류가 고도리 처럼 하나가 아니라, 청단, 홍단, 초단 3개나 되므로,
3번의 체크가 수행 되어야 하므로 함수가 조금 길어졌을 뿐이죠.
현재 먹은 띠(cardIdx)가 청단이라면 청단, 홍단이라면 홍단, 초단이라면 초단 카운트를 +1 증가시키고,
청단이 3개 라면 청단, 홍단이 3개 라면 홍단, 초단이 3개 라면 초단으로 처리 해 주면되겠죠.
어느 것이든 단을 했다면, 각 단은 3점이므로, 3점의 점수를 추가 시켜주어야 하겠죠?
그리고 마지막 부분에서는 열과 마찬가지로 5장이 되는 순간부터 1점씩 점수를 추가시켜줍니다.
피. |
피는 지금까지의 것들과 달리 특정 피가 여러개 모였을때 발상하는 추가 점수 따위는 없습니다.
그러므로, 단순히, 피가 10장 이상이 되는 그 순간부터, 피 한장당 1점씩 추가를 시켜주면 되겠네요.
그러나! 가장 한가지 중요한 것이 하나있죠.
피가 11장이 있다고 1점을 추가시켜주는 것은 아니겠지요?
피가 11장이라해도, 그 중 쌍피나 쓰리피가 있다면, 쌍피는 두장, 쓰리피는 세장으로 계산을 해야합니다.
/** * 피를 추가함. * @param userType * @param cardIdx */ public void addPee(byte userType, int cardIdx) {
// 피가 10장 이상일때부터 피 1개당 1점씩 추가. if(getNumOfPee(userType) >= 10 ) { if(cardIdx == gCard.CARD_GOOKJIN) // 국진이 피 슬롯에 있다면, addPoint(userType, 2); // 2점 추가. else switch(gCard.getType((byte)cardIdx)) { case CARDTYPE_PEE: // 일반 피라면, addPoint(userType, 1); // 1점 추가. break; case CARDTYPE_SSANG_PEE: // 쌍피라면, addPoint(userType, 2); // 2점 추가. break; case CARDTYPE_THREE_PEE: // 쓰리피라면, addPoint(userType, 3); // 3점 추가. break; } } } |
그냥 단순히 위와 같이 실제 피의 개수가 10개 이상이라면,
현재 먹은 피가 쌍피라면 피를 두장으로, 쓰리피라면 세장으로 처리해서 점수를 더해줍니다.
이걸로 맞고의 기본 점수 계산은 모두 끝냈습니다.
눈치 빠르신 분은 벌써 이상하다고 생각하시고 계실 수도 있겠네요. 아직 한가지 구현 안한게 있습니다.
국진 패를 처리를 안했죠. 국진은, 열끗으로 처리할 수도, 쌍피로 처리할 수도 있지요.
국진 패를 먹는 순간, 국진 패를 열끗으로할지, 쌍피로 처리할 지 사용자에게 입력을 받는게 필요하겠죠.
물론 addYeul() 함수에서 처리를 하면 좋겠지만, addYeul에서 처리를 하려고 하면,
국진패를 획득했는지를 저장한 변수를 이 함수 저 함수 계속 전달해야 하는 수고가 발생합니다.
보통 열패를 플레이어가 획득하게 되면 addPae() 함수를 거쳐, 해당패의 종류에 따라 패를 추가하죠.
그러므로, addPae() 함수에서 해당패가 국진인지 체크를 해주는 것이 낳겠네요.
/** * 패를 추가 한다. * @param userType * @param cardNum */ public void addPae(byte userType, byte cardNum) { /* 지금 먹으려는 열이 국진이라면, */ if(cardNum == CARD_GOOKJIN) { if(bSelectGookjin == false) { // 국진을 열로 쓸지, 피로 쓸지 물어 봄. bSelectGookjin = true; return; } }
|
현재 추가하려는(먹으려는) 패가 국진이라면, 먹지 않고, bSelectGookjin만 true로 만들고 리턴합니다.
그런데 이 addPae를 호출 하는 부분이 GameView.throwCard() 함수인데,
throwCard() 함수에서 addPae()를 호출하고 난 뒤에, bSelectGookjin이 true로 변경되었다면,
국진을 피로 쓸지 열로 쓸지 선택하라는 메시지를 출력해 주어야하겠지요?
throwCard() 함수에서 모든 이벤트를 처리하고 나서, 마지막으로 턴을 변경하기 바로 직전에,
bSelectGookjin이 true인지 체크해서 curViewState를 변경해 줍시다.
// 국진 선택 중이라면, if(room.bSelectGookjin == true) { curViewState = State.GAME_SELECTGOOKJIN; repaints(); return; } |
위와 같이 해주면, 국진의 선택 중이라면, 턴을 변경하지 않고, curViewState만 변경하고 리턴하겠지요.
State 클래스에 GAME_SELECTGOOKJIN이라는 새로운 상수가 추가 되었으니,
GAME_SELECTGOOKJIN에 해당하는 keyPressed()와, paint() 이벤트를 처리해 주어야하겠네요.
/** * 키 입력. */ public void keyPressed(int keyCode) { |
다른 키 입력 처리는 지난 시간까지 모두 다뤄본 내용이므로 생략 했습니다.
별 다른 내용은 없습니다.
curViewState 가 State.GAME_SELECTGOOKJIN일때, 즉, 국진의 사용을 선택중일 때,
1번을 누르면, addYeul()로, 국진을 열에 추가하고,
2번을 누르면, addPee()로, 국진을 피로 추가하는 간단한 내용이죠.
이걸로 맞고 게임의 기본 규칙들은 대부분 완성 했네요.
여기까지만 구현을 해도, 제법 맞고 게임 같은 분위기가 충분히 흘러 나오지만,
뻑이나, 쪽, 따닥, 고/스톱 등의 추가 규칙이 아직 남았죠.
'DevSource > 맞고' 카테고리의 다른 글
모바일 맞고 게임7-1(디스플레이 요소 추가 #1) (0) | 2012.12.27 |
---|---|
모바일 맞고 게임6-3(추가 규칙과 벌칙, 그리고 결과 출력 구현 ) (0) | 2012.12.27 |
모바일 맞고 게임6-1(맞고 게임룰 설명) (0) | 2012.12.27 |
모바일 맞고 게임5-4(획득 카드 보기 화면 구현) (0) | 2012.12.27 |
모바일 맞고 게임5-3(게임 내 카드 처리 구현) (0) | 2012.12.27 |