== Frame.java ==
package Main;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Frame
{
private JFrame mFrame;
private JTextArea mTextArea;
public Frame(KeyListener listener)
{
mFrame =new JFrame();
mFrame.setTitle("My Title");
mFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mFrame.setVisible(true);
mFrame.setSize(800, 600);
mFrame.setLocationRelativeTo(null);
mTextArea =new JTextArea();
mTextArea.setEditable(false);
mTextArea.addKeyListener(listener);
mTextArea.setFont(new Font("Serif", Font.PLAIN, 26));
mFrame.add(mTextArea);
mFrame.toFront();
mFrame.requestFocus();
}
public void SetText(String val)
{
mTextArea.setText(val);
}
public void AddText(String val)
{
mTextArea.append(val);
}
}
== Main.java ==
import Main.BlackJack;
public class Main
{
public static void main(String[] args)
{
new BlackJack();
}
}
== Card.java ==
package Main;
public class Card
{
private String mSuit;
private int mRank;
//A카드를 11로 취급할지, 1로 취급할지 결정하는 boolean 함수
//Rank(실제 값)을 변경하는것은 위험할 수 있다고 판단하여 boolean으로 기본 값은 건드리지 않기로 결정
private boolean mIsACalc11;
//기본적으로 A는 11로 취급한다.
public Card(String suit, int rank)
{
this.mSuit = suit;
this.mRank = rank;
this.mIsACalc11 =true;
}
public String GetSuit()
{
return mSuit;
}
//GetRank를 호출하면 10을 초과하는 값은 10으로 리턴하고
//A카드는 mIsACalc11의 참거짓에 따라 11, 1로 리턴한다.
//그 외는 Rank에 맞게 리턴
public int GetRank()
{
if(mRank >10)
{
return 10;
}
if(mRank ==1)
{
if(mIsACalc11)
{
return 11;
}
else
{
return 1;
}
}
return mRank;
}
public void SetACalcTo11(boolean flag)
{
mIsACalc11 = flag;
}
public String DisplayCard()
{
String tempRank =null;
switch(mRank)
{
case 1:
{
tempRank ="A";
break;
}
case 11:
{
tempRank ="J";
break;
}
case 12:
{
tempRank ="Q";
break;
}
case 13:
{
tempRank ="K";
break;
}
default:
{
tempRank = Integer.toString(mRank);
}
}
return tempRank +"("+ mSuit +") ";
}
}
== FinishCode.java ==
package Main;
public enum FinishCode
{
NONE, //승부가 나지 않은 상태
PLAYER, //플레이어가 승리
PLAYERBUSTED, //플레이어 BUSTED
DEALER, //딜러가 승리
DEALERBUSTED, //딜러 BUSTED
DRAW, //비김
NEEDCALC, //누가 이겼는지 비교해야함
}
== BlackJack.java ==
package Main;
import java.util.Vector;
import java.util.Random;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.LinkedList;
enum STATE {
LOADGAME, BET, INGAME, FINISH, PLYAER_SQUANDERD, PLYAER_NOT_SQUANDER,
}
public class BlackJack implements KeyListener {
private Frame mFrame;
FinishCode mCode;
STATE mState;
static public Integer MAX_CARD_COUNT =52;
static public Integer MAX_CARD_TYPE =4;
// 게임 중 사용할 카드를 집어넣는 큐
private LinkedList<Card> mCards;
// 게임 중 각 참가자의 카드를 저장하는 벡터
private Vector<Card> mPlayerCard;
private Vector<Card> mDealerCard;
private int mPlayerCost;
private int mDealerCost;
private int mCurrentBetCost;
private int mFlowCost;
private boolean mIsDataExist;
static Random Rand =new Random();
// 생성자
public BlackJack() {
mFrame =new Frame(this);
this.mPlayerCost =100;
this.mDealerCost =10000;
this.mFlowCost = mPlayerCost;
mState = STATE.LOADGAME;
SelectData();
}
private void LoadData() {
try {
BufferedReader in=new BufferedReader(new FileReader("data.txt"));
mPlayerCost = Integer.parseInt(in.readLine());
mDealerCost = Integer.parseInt(in.readLine());
mFlowCost = mPlayerCost;
in.close();
}
catch (IOException e) {
if (e.equals(e)) {
// 에러 발생 내용을 출력
e.printStackTrace();
// 종료
System.exit(0);
}
}
}
private void SaveData() {
BufferedWriter out =null;
try {
// OutputStreamWriter ? UTF-8 캐스팅
out =new BufferedWriter(new OutputStreamWriter(new FileOutputStream("data.txt", false), "UTF-8"));
out.write(mPlayerCost +System.lineSeparator());
out.write(mDealerCost +System.lineSeparator());
out.close();
}
catch (IOException e) {
e.printStackTrace();
System.err.println("Could not write to file");
}
}
private void SelectData() {
File checkFile =new File("data.txt");
if(checkFile.exists())
{
mIsDataExist =true;
}
else
{
mIsDataExist =false;
}
mFrame.SetText(null);
mFrame.AddText("\n\n");
mFrame.AddText(" --------------- Jack's BlackJack Game ---------------\n\n");
mFrame.AddText(" 1. START NEW GAME\n\n");
if (mIsDataExist) {
mFrame.AddText(" 2. CONTINUE GAME\n\n");
} else {
mFrame.AddText("\n\n");
}
mFrame.AddText(" -------------------------------------------------\n\n");
mFrame.AddText(" Select : ");
}
// 사용할 멤버변수들을 초기화한다
private void ContinueGame() {
mCurrentBetCost = (mPlayerCost /2);
mCurrentBetCost += mCurrentBetCost % 10;
mState = STATE.BET;
mCode = FinishCode.NONE;
mCards =new LinkedList<>();
mPlayerCard =new Vector<>();
mDealerCard =new Vector<>();
String tempSuit ="?";
for (int i =1; i <= MAX_CARD_COUNT / MAX_CARD_TYPE; ++i) {
for (int j =0; j < MAX_CARD_TYPE; ++j) {
switch (j) {
case 0: {
tempSuit ="◆";
break;
}
case 1: {
tempSuit ="♣";
break;
}
case 2: {
tempSuit ="♥";
break;
}
case 3: {
tempSuit ="♠";
break;
}
default: {
System.out.println("Index Error");
System.exit(0);
}
}
mCards.add(new Card(tempSuit, i));
}
}
int randPos;
// 딜러와 플레이어에게 중복되지 않은 카드를 각 두장씩 나눠준다.
// Queue의 Poll함수로 선두에있는 원소를 리턴하며 제거한다.
for (int i =0; i <2; ++i) {
randPos = Rand.nextInt(mCards.size());
mPlayerCard.add(mCards.get(randPos));
mCards.remove(randPos);
randPos = Rand.nextInt(mCards.size());
mDealerCard.add(mCards.get(randPos));
mCards.remove(randPos);
}
DealMoney();
}
private void DealMoney() {
mFrame.SetText(null);
mFrame.AddText("\n\n");
mFrame.AddText(" --------------- Jack's BlackJack Game ---------------\n\n");
mFrame.AddText(" # Dealer: ($"+ mDealerCost +")\n");
mFrame.AddText(" # Player: ($"+ mPlayerCost +")\n");
mFrame.AddText(" -------------------------------------------------\n\n");
mFrame.AddText(" How much money do you want to bet?\n\n");
mFrame.AddText(" "+ mCurrentBetCost +" (Up/Down/Enter)");
}
private void DisplayInfo() {
CalcBet();
CheckPlayerCost();
Card tempCard;
mFrame.SetText(null);
mFrame.AddText("\n\n --------------- Jack's BlackJack Game ---------------\n");
mFrame.AddText(" # Betting : $"+ mCurrentBetCost +"\n\n");
mFrame.AddText(" # Dealer: ($"+ mDealerCost +") \t");
// 0은 A로, 11이상은 각 J Q K로 출력한다 그 외는 정수 그대로
for (int i =0; i < mDealerCard.size() -1; ++i) {
tempCard = mDealerCard.get(i);
mFrame.AddText(tempCard.DisplayCard());
}
if (mCode == FinishCode.NONE) {
mFrame.AddText("XX");
}
else {
tempCard = mDealerCard.get(mDealerCard.size() -1);
mFrame.AddText(tempCard.DisplayCard());
}
mFrame.AddText("\n");
mFrame.AddText(" # Player: ($"+ mPlayerCost +") \t");
for (int i =0; i < mPlayerCard.size(); ++i) {
tempCard = mPlayerCard.get(i);
mFrame.AddText(tempCard.DisplayCard());
}
mFrame.AddText("\n");
mFrame.AddText(" -------------------------------------------------");
DisplayCurrentState();
}
// Hit을 하면 플레이어의 카드벡터에 전체카드큐에서 poll하여 추가한다.
private void Hit() {
int randPos = Rand.nextInt(mCards.size());
mPlayerCard.add(mCards.get(randPos));
mCards.remove(randPos);
// 만약 추가했을 때 총 값이 21을 초과하면 플레이어는 BUSTED한다.
if (CalcPrice(mPlayerCard) >21) {
mCode = FinishCode.PLAYERBUSTED;
}
}
// Stand을 하면 딜러의 카드벡터에 전체카드 큐를 17이상이 될때까지 전체카드큐에서 poll한다.
private void Stand() {
while (CalcPrice(mDealerCard) <17) {
int randPos = Rand.nextInt(mCards.size());
mDealerCard.add(mCards.get(randPos));
mCards.remove(randPos);
}
// 만약에 21보다 커지면 딜러는 BUSTED한다.
if (CalcPrice(mDealerCard) >21) {
mCode = FinishCode.DEALERBUSTED;
}
// 그것이 아니라면 플레이어와 딜러의 값을 비교할 필요가 있다.
else {
mCode = FinishCode.NEEDCALC;
}
}
private int CalcPrice(Vector<Card> cards) {
int sumRes =0;
Card tempCard =null;
for (int i =0; i < cards.size(); ++i) {
tempCard = cards.get(i);
sumRes += tempCard.GetRank();
}
// 21을 초과한 시점에서
// A 카드를 가지고 있고, 그 카드가 11로 계산되고 있을경우
if (sumRes >21) {
for (int i =0; i < cards.size(); ++i) {
// 랭크가 11이다? -> Calcto11이 True인경우?
if (cards.get(i).GetRank() ==11) {
// 해당 A카드의 11여부를 false로 하고
cards.get(i).SetACalcTo11(false);
// 11 -> 1로 했기에 10을 빼서 리턴한다.
sumRes -=10;
// 디버그용 출력
System.out.println("A 카드가 11에서 1로 값 변경됨");
}
}
}
return sumRes;
}
// 게임이 끝나면 누가 이겼는지 계산한다.
private void CalcWinner() {
int playerVal = CalcPrice(mPlayerCard);
int dealerVal = CalcPrice(mDealerCard);
if (playerVal >21 && dealerVal >21) {
mCode = FinishCode.DRAW;
}
else if (playerVal == dealerVal) {
mCode = FinishCode.DRAW;
}
else if (playerVal > dealerVal) {
mCode = FinishCode.PLAYER;
}
else {
mCode = FinishCode.DEALER;
}
}
// enum타입의 FinishCode에 따라 알맞은 결과를 출력한다.
@SuppressWarnings("incomplete-switch")
private void DisplayCurrentState() {
if (mCode == FinishCode.NEEDCALC) {
CalcWinner();
DisplayInfo();
return;
}
mFrame.AddText("\n\n ");
if (mState == STATE.PLYAER_SQUANDERD) {
mFrame.AddText("\n\n You lost EVERYTHING!! Quit Game !");
return;
}
switch (mCode) {
case NONE: {
mFrame.AddText("Hit or Stand? (H/S): ");
break;
}
case DRAW: {
mFrame.AddText("Equal points...");
break;
}
case PLAYER: {
mFrame.AddText("Player Wins...");
break;
}
case PLAYERBUSTED: {
mFrame.AddText("Player Busted...");
break;
}
case DEALER: {
mFrame.AddText("Dealer Wins...");
break;
}
case DEALERBUSTED: {
mFrame.AddText("Dealer Busted...");
break;
}
}
if (mState == STATE.PLYAER_NOT_SQUANDER) {
SaveData();
mFrame.AddText("\n\n Play Again? (Y/N)");
}
}
private void CalcBet()
{
switch (mCode) {
case DRAW: {
mPlayerCost += mCurrentBetCost;
break;
}
case PLAYER: {
mDealerCost -= mCurrentBetCost;
mPlayerCost += mCurrentBetCost *2;
break;
}
case PLAYERBUSTED: {
mDealerCost += mCurrentBetCost;
break;
}
case DEALER: {
mDealerCost += mCurrentBetCost;
break;
}
case DEALERBUSTED: {
mDealerCost -= mCurrentBetCost;
mPlayerCost += mCurrentBetCost *2;
break;
}
case NEEDCALC:
break;
case NONE:
break;
default:
break;
}
}
private void CheckPlayerCost() {
if (mCode == FinishCode.NONE)
return;
if (mPlayerCost <=0) {
if(mCode == FinishCode.DEALERBUSTED || mCode == FinishCode.PLAYER || mCode == FinishCode.DRAW)
{
mState = STATE.PLYAER_NOT_SQUANDER;
return;
}
mState = STATE.PLYAER_SQUANDERD;
File file =new File("data.txt");
if(file.exists())
{
file.delete();
}
} else {
mState = STATE.PLYAER_NOT_SQUANDER;
}
}
private void DisplayResult() {
int flow = mPlayerCost - mFlowCost;
mFrame.SetText(null);
mFrame.AddText("\n\n --------------- Jack's BlackJack Game ---------------\n\n");
if(flow >0)
{
mFrame.AddText(" You earned $"+ flow);
}
else if (flow <0)
{
mFrame.AddText(" You lost $"+ (-flow));
}
else
{
mFrame.AddText(" No $ changed");
}
mFrame.AddText("\n\n");
mFrame.AddText(" -------------------------------------------------");
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
switch (e.getKeyCode()) {
case KeyEvent.VK_H: {
if (mState != STATE.INGAME)
break;
Hit();
DisplayInfo();
break;
}
case KeyEvent.VK_S: {
if (mState != STATE.INGAME)
break;
Stand();
DisplayInfo();
}
case KeyEvent.VK_UP: {
if (mState != STATE.BET)
break;
if(mCurrentBetCost +10 > mPlayerCost) break;
mCurrentBetCost +=10;
DealMoney();
break;
}
case KeyEvent.VK_DOWN: {
if (mState != STATE.BET)
break;
if(mCurrentBetCost -10 <10) break;
mCurrentBetCost -=10;
DealMoney();
break;
}
case KeyEvent.VK_ENTER: {
if (mState != STATE.BET)
break;
mPlayerCost -= mCurrentBetCost;
mState = STATE.INGAME;
DisplayInfo();
break;
}
case KeyEvent.VK_Y: {
if (mState != STATE.PLYAER_NOT_SQUANDER)
break;
ContinueGame();
break;
}
case KeyEvent.VK_N: {
if (mState != STATE.PLYAER_NOT_SQUANDER)
break;
DisplayResult();
break;
}
case KeyEvent.VK_1: {
if (mState != STATE.LOADGAME)
break;
mState = STATE.BET;
ContinueGame();
break;
}
case KeyEvent.VK_2: {
if (mState != STATE.LOADGAME ||!mIsDataExist)
break;
LoadData();
ContinueGame();
break;
}
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
'기타 > univ. projects' 카테고리의 다른 글
[유니티] 게임엔진응용실습 Unit2 프로젝트 - 장애물 코스 피하기 게임 (0) | 2022.09.13 |
---|---|
[유니티] 게임엔진응용실습 Unit1 프로젝트 (Unity 기초) (0) | 2022.09.13 |
[자바] 멀티미디어자바프로젝트II ch.03 연습문제 (0) | 2022.09.13 |
[자바] 멀티미디어자바프로젝트II ch.02 연습문제 (0) | 2022.09.06 |
[자바] 블랙잭(BlackJack) 게임 구현 (0) | 2022.03.27 |