글. 오상문 sualchi@daum.net
소스 코드입니다.
///////////////////////////////////////////////////////////////////////////
// bj.mc - Auto Created by GNEX IDE
%{
#DEFINE PLAYERVER 4
#DEFINE LCDCLASS 255
#DEFINE IMAGETYPE 255
#DEFINE AUDIOTYPE 255
#DEFINE APPTYPE 1
#DEFINE APPCPID 60000
#DEFINE APPID 1
#DEFINE APPNAME "GNEX App"
#DEFINE COMPTYPE 0
#DEFINE AGENTTYPE 0
#DEFINE VALIDCOUNT 255
#DEFINE VALIDTERM 255
#DEFINE DIRECTRUN 0
#DEFINE STORETYPE 0
#DEFINE APPVER 1
%}
#include "C:\PROGRAM FILES\SINJISOFT\GNEX SDK\include\SScript.h"
//***************************************************************
// 블랙잭 게임 - 베타 1.0
//
// 작성자 : 오상문 (sualchi@yahoo.co.kr / sualchi@daum.net)
//
// 갱신년월: 2004. 5. 22
// 개발환경: GNEX, Mobile C
//
// 참고사항1 : GNEX 프로젝트의 기본 환경 옵션을 적용했습니다.
// 참고사항2 : 개선점이나 조언은 언제든지 환영합니다.
// 참고사항3 : Mobile C 개인 학습용으로 잘 활용하세요.
//***************************************************************
//------------------------------------------------------
// GameProcess 상태 변수에서 사용 (전체적인 진행 과정)
// 도움말 / 초기화,출력 / 플레이 / 승자 출력 / 게임종료
//------------------------------------------------------
#define INIT 0x01
#define HELP 0x02
#define START 0x04
#define PLAY 0x08
#define WINNER 0x10
#define GAMEOVER 0x20
#define WAIT 0x40
//------------------------------------------------------
// StageProcess 상태 변수에서 사용 (한판에서의 진행 과정)
// 비트0: 플레이어 종료 = 1
// 비트1: 딜러 종료 = 1
// 비트2: 플레이어 블랙잭 (비트2가 1이면 비트0 값도 1 처리)
// 비트3: 딜러 블랙잭 (비트3이 1이면 비트1 값도 1 처리)
//------------------------------------------------------
#define MAN_END 0x01
#define COM_END 0x02
#define MAN_BLACKJACK 0x04
#define COM_BLACKJACK 0x08
//------------------------------------------------------
// 게임에 사용되는 기타 매크로 값
//------------------------------------------------------
#define TRUE 1
#define FALSE 0
#define YES 1
#define NO 0
#define UNKNOWN -1
#define DEALER 1
#define PLAYER 2
#define ALL 3
// 받을 수 있는 최대 카드 수
#define MAX_CARD 7
// 카드 이미지 제작시 카드 크기
#define CardSizeX 26
#define CardSizeY 40
// 보드 구성
#define TitleX 3
#define TitleY 0
#define BoardStartX 1
#define BoardStartY 1
#define BoardEndX (swWidth - 2)
#define BoardEndY 115
#define ComStartX 4
#define ComStartY (BoardStartY+3)
#define ManStartX ComStartX
#define ManStartY (BoardStartY+60)
// 카드 이미지 제작시 무늬 시작 위치
#define FSX 1
#define FSY 1
#define FEX (CardSizeX - 10)
#define FEY (CardSizeY - 10)
// 전체 카드 숫자 (무늬당 13장씩 4종)
#define SUM_CARD 52
//------------------------------------------------------
// 게임에 사용되는 변수
//------------------------------------------------------
int GameProcess; // 게임 전체 진행 상태
int StageProcess; // 판(내부) 진행 상태
int Winner; // UNKNOWN(초기화값), DEALER, PLAYER, ALL, NO
// 카드 무늬
const string Shape[4] = {
"♠", "◆", "♥", "♣"};
const string NumToStr[14] = {
"X","A","2","3","4","5","6","7","8","9","10","J","Q","K"};
// 카드를 나열할 때 X 위치
const int Xpos[MAX_CARD+1] = {5,18,31,44,57,70,83,96};
int ShuffleCard[SUM_CARD]; // 섞어놓은 카드 데이터
int ComCard[MAX_CARD+1]={-1,-1,-1,-1,-1,-1,-1,-1}; // 딜러 받은 카드
int ManCard[MAX_CARD+1]={-1,-1,-1,-1,-1,-1,-1,-1}; // 플레이어 받은 카드
int ManCardNumber; // 현재까지 받은 플레이어의 카드 숫자
int ComCardNumber; // 현재까지 받은 딜러의 카드 숫자
int Money=19; // 플레이어가 가진 돈 (배팅값 포함하면 20)
int Bet=1; // 배팅 값 게임 초기치
int ManPoint, ComPoint; // 플레이어와 딜러가 얻은 카드 점수 합
image Card[5]; // 스페이드, 다이아몬드, 하트, 크로버 카드와 뒷면(Card[4])
//----------------------------------------------------
// 게임에 사용되는 기타 임시 변수
//------------------------------------------------------
int Time[4]; // 랜덤함수 초기화에 사용
string str; // 스트링
//----------------------------------------------------
// 화면에 출력할 문자열
//------------------------------------------------------
const string help[] = {
"*블랙잭파이터Beta1.0*",
"---------------------",
"21점에 가까우면 승리.",
"21점을 넘으면 패배.",
"2장 21점이면 블랙잭!",
"A는 1이나 11로 계산.",
"J,Q,K는 10으로 계산.",
"블랙잭이면 더블!",
"승자 5장 이상, 두배!" };
const string MenuText[] = {
"▲:금액+, ◀:1장 더!",
"▼:금액-, ▶:Go/Hit!" }; // 변경: 열어라! -> Go/Hit!
const string WinText[] = {
"(+.+;) 비겼네요!",
"(^O^) 자갸 이겼어!",
"(-_-;) 딜러 승리!" };
//************************************************************
// 게임 초기화 (프로그램 구동시 한번만 실행)
//------------------------------------------------------
void Init()
{
int i;
GameProcess = INIT;
// 무늬별 카드 이미지와 뒷면 이미지를 만들어서 변수에 저장한다.
for(i=0; i<5; i++) {
ClearWhite();
DrawRect(1, 1, CardSizeX, CardSizeY); // 카드 바탕
if(i==4) { // 뒷면
ShadeRect(4, 4, CardSizeX-3, CardSizeY-3, 4, 15); // 뒷면 무늬
GetDDB(Card[4], 1, 1, CardSizeX, CardSizeY, 0, 0); // 이미지 저장
} else { // 앞면 4종 0,1,2,3
if(i == 1 || i == 2)
SetFontColor(109, 0); // red, white
else
SetFontColor(3, 0); // black, white
DrawStr(FSX, FSY, Shape[i]);
DrawStr(FEX, FEY, Shape[i]);
GetDDB(Card[i], 1, 1, CardSizeX, CardSizeY, 0, 0); // 이미지 저장
}
}
SetFontColor(3, 0);
ClearWhite();
DrawBoard(); // 보드(바닥)를 그린 후에 버퍼에 저장한다.
SaveLCD();
}
//************************************************************
// 게임 시작시 나오는 도움말 출력하기
//------------------------------------------------------
void Help()
{
int i;
GameProcess = WAIT;
SetColor(23); // green
FillRect(0, 0, swWidth-1, swHeight-1);
SetColor(3); // black
for (i=0; i<9; i++)
DrawStr(1, i*15+2, help[i]);
Flush();
SetTimer(5000, S_TM_ONCE);
GameProcess = HELP;
}
//************************************************************
//------------------------------------------------------
// 보드(게임 화면 바탕)를 그린다.
//------------------------------------------------------
void DrawBoard()
{
SetColor(125); // GOLD
FillRect(0, 0, swWidth, swHeight);
SetColor(23); // green
FillRectRound(BoardStartX, BoardStartY, BoardEndX, BoardEndY, 3);
SetColor(3); // black
DrawMoney(); // 배팅액과 가진돈 출력
DrawStr(1, BoardEndY+3, MenuText[0]);
DrawStr(1, BoardEndY+18, MenuText[1]);
}
//------------------------------------------------------
// 카드를 섞는다. (판이 시작될 때 실행)
//------------------------------------------------------
void Shuffle()
{
int i, j, k, temp;
// 랜덤 함수 초기화 ...
GetTime(Time);
temp = (Time[1]<<8) | (Time[2]);
RandSeed(temp);
for (i=0; i < SUM_CARD; i++) // 0~12, 13~15, 16~28, 29~51
ShuffleCard[i] = i;
for (i=0; i < 100; i++) { // 100번 임의 자리 교환
j = Rand(0, SUM_CARD-1); // 자리 바꿀 랜덤 위치 1
k = Rand(0, SUM_CARD-1); // 자리 바꿀 랜덤 위치 2
if (j == k) { // 교환 위치가 같으면 다르게 처리
if ((j > 0) && (j != SUM_CARD-1)) j = SUM_CARD-1;
else j = 1;
}
temp = ShuffleCard[j]; // 카드 위치 서로 바꿈
ShuffleCard[j] = ShuffleCard[k];
ShuffleCard[k] = temp;
}
}
//--------------------------------------------------
// 플레이어가 가진 돈과 배팅 금액을 출력한다.
//--------------------------------------------------
void DrawMoney()
{
SetMediaSize(str, 0); // 메모리 해제할까?
MakeStr2(str, "BET:%2d칩 Money:%3d칩", Bet, Money);
SetColor(23); // green
FillRect(BoardStartX+2, BoardEndY-13, BoardEndX-1, BoardEndY-1);
SetColor(3); // black
DrawStr(4, BoardEndY-12, str);
if(GameProcess != INIT)
Flush();
}
//----------------------------------------------------
// 딜러의 n번째 카드를 한장 그린다.
// open = 공개여부, flush = Flush() 사용 출력 여부
//----------------------------------------------------
void DrawComCard(int n, int open, int flush)
{
int x, shape, num;
if (open == NO) { // 보여줄지 덮을지
PutDDB(Xpos[n], ComStartY, Card[4]);
} else {
shape = ComCard[n] / 13; // 카드 무늬 종류
num = ComCard[n] % 13 + 1; // 카드 번호 얻음
x = (num == 10) ? 12 : 18; // 두자리 숫자 10 출력 위치 조정
PutDDB(Xpos[n], ComStartY, Card[shape]); // 카드 기본 판
if(shape == 1 || shape == 2)
SetFontColor(109, 0); // red, white
else
SetFontColor(3, 0); // black, white
DrawStr(Xpos[n]+3, ComStartY+10, NumToStr[num]); // 숫자 출력
DrawStr(Xpos[n]+x, ComStartY+20, NumToStr[num]);
}
SetFontColor(3, 0); // red, white
if(flush==YES)
Flush();
}
//---------------------------------------------------
// 사람의 n번째 카드를 한장 그린다.
// open = 공개여부, flush = Flush() 사용 출력 여부
//----------------------------------------------------
void DrawManCard(int n, int open, int flush)
{
int x, shape, num;
if (open == NO) { // 보여줄지 덮을지
PutDDB(Xpos[n], ManStartY, Card[4]);
} else {
shape = ManCard[n] / 13; // 카드 무늬 종류
num = ManCard[n] % 13 + 1; // 카드 번호 얻음
PutDDB(Xpos[n], ManStartY, Card[shape]); // 카드 기본판
x = (num == 10) ? 12 : 18; // 두자리 숫자 10은 출력 위치 조정
if(shape == 1 || shape == 2)
SetFontColor(109, 0); // red, white
else
SetFontColor(3, 0); // black, white
DrawStr(Xpos[n]+3, ManStartY+10, NumToStr[num]); // 숫자 출력
DrawStr(Xpos[n]+x, ManStartY+20, NumToStr[num]);
SetFontColor(3, 0); // black, white
}
if(flush==YES)
Flush();
}
//------------------------------------------------
// 플레이어 카드를 한 장씩 더 받고 화면에 그린다.
//------------------------------------------------
void AddManCard(int open)
{
if (ManCardNumber < MAX_CARD) { // 허용 카드 개수까지 받음
ManCard[ManCardNumber] = ShuffleCard[ManCardNumber + ComCardNumber];
DrawManCard(ManCardNumber, NO, YES);
if(open == YES)
DrawManCard(ManCardNumber, YES, YES);
ManCardNumber++;
} else { // 최대 카드 수 넘으면 종료
StageProcess = StageProcess | MAN_END;
}
}
//----------------------------------------------
// 컴퓨터 카드를 한 장씩 더 받고 화면에 그린다.
//----------------------------------------------
void AddComCard(int open)
{
if (ComCardNumber < MAX_CARD) { // 허용 카드 개수까지 받음
ComCard[ComCardNumber] = ShuffleCard[ManCardNumber + ComCardNumber];
DrawComCard(ComCardNumber, NO, YES);
if(open == YES)
DrawComCard(ComCardNumber, YES, YES);
ComCardNumber++;
} else {
StageProcess = StageProcess | COM_END; // 최대 카드 수 넘으면 종료
}
}
//----------------------------------------------
// 딜러 또는 플레이어의 카드 점수 계산
//---------------------------------------------
int CheckPoint(int who)
{
int i, sum, ace, p;
sum = 0; // 점수 합
ace = 0; // A 카드 체크용
if (who == PLAYER) {
for(i=0; i < ManCardNumber; i++) {
p = ManCard[i] % 13 + 1; // 무늬별 14장씩 연속 번호에서 카드 숫자 얻음
if (p > 10) // J, Q, K는 10이다.
p = 10;
else if (p == 1) // A 카드인지 검사
ace++;
sum += p; // A를 1로 처리한 결과 합
}
} else if (who == DEALER) {
for(i=0; i < ComCardNumber; i++) {
p = ComCard[i] % 13 + 1;
if (p > 10) // J, Q, K는 10이다.
p = 10;
else if (p == 1) // A 카드인지 검사
ace++;
sum += p; // A를 1로 처리한 결과 합
}
} else
sum = -1;
if (ace > 0 && sum <= 11) // A를 11로 활용할 조건이면...
sum += 10;
return sum;
}
//-----------------------------------------------------------
// 블랙잭 체크
// [반환] DEALER: 딜러, PLAYER: 플레이어, TIE: 둘 다, NO: 없음)
//-------------------------------------------------------------
int CheckBlackjack()
{
int temp;
temp = NO; // 없음
if (CheckPoint(PLAYER) == 21)
temp = PLAYER; // 플레이어가 블랙잭이다.
if (CheckPoint(DEALER) == 21)
temp += DEALER; // 딜러가 블랙잭이다.
return temp;
}
//------------------------------------------------------
// 게임 한 판 진행할 때 마다 초기화하는 함수
//------------------------------------------------------
void Start()
{
GameProcess = WAIT;
StageProcess = 0;
ManCardNumber = 0; // 플레이어가 받은 카드 수는 0
ComCardNumber = 0; // 딜러가 받은 카드 수는 0
Bet = 1; // 초기 배팅 값
ManPoint = 0; // 플레이어가 얻은 카드 점수
ComPoint = 0; // 딜러가 얻은 카드 점수
Winner = UNKNOWN; // 승자는 아직 모름
Shuffle(); // 카드 섞기
RestoreLCD(); // 새 판 그리기
DrawMoney();
AddComCard(NO); // 딜러 카드 (뒤집은 것)
AddComCard(YES); // 딜러 카드 (열린 것)
AddManCard(YES); // 플레이어 카드 (열린 것)
GameProcess = START;
}
//****************************************************
// 게임 한 판 시작~
//---------------------------------------------
void Play()
{
GameProcess = PLAY;
if (Winner == UNKNOWN) { // 블랙잭은 첫 두장 때만 체크한다.
Winner = CheckBlackjack(); // 블랙잭 체크
if (Winner == PLAYER) {
StageProcess = MAN_BLACKJACK;
} else if (Winner == DEALER) {
StageProcess = COM_BLACKJACK;
} else if (Winner == PLAYER + DEALER) {
StageProcess = StageProcess & MAN_BLACKJACK;
StageProcess = StageProcess & COM_BLACKJACK;
}
if (Winner > 0)
Winner();
}
ManPoint = CheckPoint(PLAYER); // 플레이어 점수 계산
ComPoint = CheckPoint(DEALER); // 딜러 점수 계산
if(Winner == NO) {
// 플레이어가 21점 이상이면 딜러 작업 없이 무조건 패배
if (ManPoint < 21) {
if(ManPoint == 21) // 플레이어가 21점이면 딜러 카드 처리 GO!
StageProcess = StageProcess | MAN_END;
if (StageProcess & MAN_END) { // 플레이어가 끝났으면...
if(ComPoint >= 17 ) // 딜러가 17 이상이면 딜러 종료
StageProcess = StageProcess | COM_END;
else { // 딜러 플레이 마무리 진행
while ( ComPoint < 17 ) {
AddComCard(YES);
ComPoint = CheckPoint(DEALER);
}
StageProcess = StageProcess | COM_END; // 딜러 종료
}
}
} else {
StageProcess = StageProcess | (MAN_END + COM_END);
}
}
// 게임을 마친 상태이면... 승부 출력으로
if((StageProcess & MAN_END) && (StageProcess & COM_END))
Winner();
}
//******************************************************************
// 승패 결과 출력
//-------------------------
void Winner()
{
int i, d; // d = check double
string s1, s2;
GameProcess = WINNER;
d = 0;
for(i=0; i < ComCardNumber; i++)
DrawComCard(i, YES, NO);
Flush();
ManPoint = CheckPoint(PLAYER);
ComPoint = CheckPoint(DEALER);
// 블랙잭이 있으면
if(StageProcess & MAN_BLACKJACK || StageProcess & COM_BLACKJACK) {
switch(StageProcess & 0x0F) {
case MAN_BLACKJACK: // 플레이어 블랙잭 승리
Winner = PLAYER;
d = 1;
break;
case COM_BLACKJACK: // 딜러 블랙잭 승리
Winner = DEALER;
d = 1;
break;
default: // 양쪽 블랙잭은 무승부
Winner = ALL;
}
} else { // 얻은 포인트 계산
if(ManPoint > 21)
ManPoint = 0;
if(ComPoint > 21)
ComPoint = 0;
if(ManPoint > ComPoint) { // 플레이어 승리
Winner = PLAYER;
if(ManCardNumber > 4)
d = 1;
} else if(ComPoint > ManPoint) { // 딜러 승리
Winner = DEALER;
if(ComCardNumber > 4)
d = 1;
} else // 무승부
Winner = ALL;
}
// 점수 출력
SetFontColor(125,23);
IntToAscii(s1, ComPoint);
DrawStr(Xpos[ComCardNumber-1]+28, ComStartY+15, s1);
IntToAscii(s2, ManPoint);
DrawStr(Xpos[ManCardNumber-1]+28, ManStartY+15, s2);
SetFontColor(3,0); // black, white
SetMediaSize(s1, 0); // 메모리 해제? 메모리 누수가 어디에서???
SetMediaSize(s2, 0); // 메모리 해제? 메모리 누수가 어디에서???
SetFontColor(0,23);
switch(Winner) {
case ALL:
DrawStr(15, ComStartY+42, WinText[0]);
Money += Bet; // 배팅금 회수
break;
case PLAYER:
DrawStr(15, ComStartY+42, WinText[1]);
Money += (d ? (Bet*3) : (Bet*2));
break;
case DEALER:
DrawStr(15, ComStartY+42, WinText[2]);
Money -= d ? Bet : 0;
}
SetFontColor(3,0);
Flush();
if(Money < 1) { // 돈이 없으면 게임오버
GameOver();
} else {
--Money; // 배팅액 1 지불하고 다시 시작
Bet = 1;
SetTimer(2000, S_TM_ONCE);
}
}
//***************************************************************
// 게임 종료...
//-----------------------
void GameOver()
{
int i;
GameProcess = GAMEOVER;
ClearWhite();
DrawStr(30,40,"게임 종료!!");
Flush();
for(i=0; i < 8; i++) { // 끝날 때 심심하니까...
DrawManCard(i, NO, YES);
DrawManCard(i, YES, YES);
}
}
//***************************************************************
// 키 이벤트 처리
//--------------------------
void EVENT_KEYPRESS()
{
if (GameProcess==HELP) {
Start();
} else if (GameProcess == START) {
switch (swData) {
case SWAP_KEY_UP: // 위 키 (배팅액 증가)
if (Money > 0 && Bet < 10) {
Bet++;
Money++;
DrawMoney();
}
break;
case SWAP_KEY_DOWN: // 아래 키 (배팅액 감소)
if (Bet > 1) {
Bet--;
Money++;
DrawMoney();
}
break;
case SWAP_KEY_LEFT: // 왼쪽 키
case SWAP_KEY_RIGHT: // 오른쪽 키
AddManCard(YES);
Play();
}
} else if (GameProcess == PLAY) {
switch (swData) {
case SWAP_KEY_RIGHT: // 오른쪽 키 (계산)
if (Bet != 0) {
StageProcess |= MAN_END;
Play();
}
break;
case SWAP_KEY_LEFT: // 왼쪽 키 (카드 한 장 더)
AddManCard(YES);
Play();
}
}
else if (GameProcess==GAMEOVER) {
Exit();
}
}
//***************************************************************
// 이벤트 타임아웃 처리 함수
//------------------------------
void EVENT_TIMEOUT()
{
switch(GameProcess) {
case HELP:
case WINNER:
Start();
break;
case GAMEOVER:
Exit();
}
}
//***************************************************************
// 메인 함수
//-------------------------------
void main()
{
Init(); // 게임 초기 설정
Help(); // 도움말 출력
}
// 소스 끝
'Mobile APP' 카테고리의 다른 글
[모바일C] 블랙잭 게임 만들기 (1) (0) | 2011.03.27 |
---|---|
[모바일C] 블랙잭 게임 만들기 (2) (0) | 2011.03.27 |
256색상표 (모바일C) (0) | 2011.03.27 |
16색상표 (모바일C) (0) | 2011.03.27 |
만년력(달력) 프로그래밍 - Mobile C (GVM, GNEX) (0) | 2011.03.27 |