티스토리 뷰
[주제]
- 기존에 구현한 블랙잭 게임을 업그레이드하기
[수정된 내용]
- 각 기능별 클래스로 분할
- 계정, 로그인 기능 추가
- 베팅 기능 추가
- 계정 정보(ID, 칩 개수)를 파일로 저장, 게임 시작 시 불러오기
[소스]
■ gamePlay.java
package blackjackGame; import java.util.ArrayList; import java.util.Scanner; public class gamePlay { private int minBetChip; private int maxBetChip; public gamePlay() {} ///// 게임 반복 루프 public gamePlay(ArrayList<memDTO> arrlist, String playID[]) { Scanner sc = new Scanner(System.in); minBetChip = 10; // 베팅 최소 개수 maxBetChip = 100; // 베팅 최대 개수 System.out.println("[게임 시작]"); System.out.println(); ////////// TODO 초기화, 기본셋팅 // 베팅 memDTO loginID = loginIDInfo(arrlist, playID); System.out.println("베팅을 받겠습니다."); System.out.println("현재 " + playID[0] + "님의 칩 개수는 " + loginID.getChip() + "개"); int betChip = 0; while (true) { System.out.print("칩 개수 입력(10~100): "); betChip = sc.nextInt(); if (betChip >= 10 && betChip <= 100 && betChip <= loginID.getChip()) { break; } else { System.out.println("다시 입력해주세요."); } } System.out.println(); boolean gameWin = true; // 게임 결과 판단. 승리로 초기화 int comCardSet[] = new int[52]; // 무작위로 결정된 숫자를 저장 comCardSetInit(comCardSet); // 공용 카드set 생성 및 초기화 // 테스트: 공용 카드set 출력 // // comCardSetPrint(comCardSet); boolean uBJWin = false; // 유저의 블랙잭 승리 상태 초기화 boolean dBJWin = false; // 딜러의 블랙잭 승리 상태 초기화 String uCardSet[] = new String[11]; // 유저의 카드set 준비 String dCardSet[] = new String[3]; // 딜러의 카드set 준비 cardSetInit(uCardSet, dCardSet); // 유저과 딜러의 카드set 생성 // 각자 기본카드 2개 배분 drawCardOne(comCardSet, uCardSet); drawCardOne(comCardSet, uCardSet); drawCardOne(comCardSet, dCardSet); drawCardOne(comCardSet, dCardSet); // 테스트: 기본카드 블랙잭 셋팅 // // '0 = A, 1 = K || 0 = K, 1 = A'만 블랙잭 승리로 판단 // uCardSet[0] = "A"; uCardSet[1] = "K"; // dCardSet[0] = "A"; dCardSet[1] = "K"; // 각자 기본카드의 블랙잭 판단 ※ 'A'와 'K' 1장씩 보유하고 있으면 블랙잭 승리로 판단 uBJWin = chekBJ(uCardSet); dBJWin = chekBJ(dCardSet); // 최초에 배분된 기본 카드 2장을 각각 공개 System.out.println("유저에게 배분된 카드"); cardSetNum(uCardSet, 1); System.out.println("딜러에게 배분된 카드"); cardSetNum(dCardSet, 2); System.out.println(); ////////// TODO 반복진행 시작 while (true) { // 버스트: 카드를 뽑은 후 유저의 점수가 '21'을 초과하면 즉시 게임 패배 if (pointResult(uCardSet) > 21) { gameWin = false; break; } // 유저 or 딜러가 '블랙잭'이면 즉시 게임 종료 if (uBJWin || dBJWin) { break; } else if (!gameWin) { break; } else { ///// 계속 진행 or 카드 오픈 System.out.print("무엇을 하시겠습니까? Hit(1), Stay(2): "); int decision = sc.nextInt(); System.out.println(); // 'Hit' 결정 시 추가 카드 1장 받음 if (decision == 1) { // 대상의 카드set이 비어있으면 카드 뽑기 if (!cardFull(uCardSet)) { drawCardOne(comCardSet, uCardSet); } else { // 카드가 꽉 찾을 경우 강제로 'Stay'로 판단 System.out.println("더 이상 카드를 받을 수 없습니다. 강제로 'Stay'됩니다."); decision = 2; } // 각 점수 비교 후 딜러의 점수가 유저보다 낮으면, 딜러 추가 카드 1장 ※ 현재 3장이면 받지 않음 if (pointResult(dCardSet) < pointResult(uCardSet) && !cardFull(dCardSet)) { drawCardOne(comCardSet, dCardSet); } // 카드를 뽑은 후 유저의 점수가 '21'을 초과하면 즉시 게임 패배 if (pointResult(uCardSet) > 21) { gameWin = false; break; } System.out.println("유저에게 배분된 카드 숫자"); cardSetNum(uCardSet, 1); System.out.println("딜러에게 배분된 카드 숫자"); cardSetNum(dCardSet, 2); // 'Stay' 결정 시 반복 종료 } else if (decision == 2) { // 각 점수 비교 후 딜러의 점수가 유저보다 낮으면, 딜러 추가 카드 1장 ※ 현재 3장이면 받지 않음 if (pointResult(dCardSet) < pointResult(uCardSet) && !cardFull(dCardSet)) { drawCardOne(comCardSet, dCardSet); } break; } else { System.out.println("잘못 입력하셨습니다. 다시 입력해주세요"); System.out.println(); } } } System.out.println("출력 전 베팅 개수 = " + betChip); ///// 결과 출력 gameResult(uCardSet, dCardSet, uBJWin, dBJWin, gameWin, arrlist, playID, betChip); // 테스트: 공용 카드set 출력 // // comCardSetPrint(comCardSet); } ////////// TODO 기타 메소드 ///// 로그인된 ID에 저장된 정보를 반환(ID, 칩 개수) public memDTO loginIDInfo(ArrayList<memDTO> arrlist, String playID[]) { memDTO selLoginID = new memDTO(); int idIdx = 0; // 배열 리스트에 저장된 현재 로그인된 ID의 인덱스 위치 찾기 for (int i = 0; i < arrlist.size(); i++) { if (playID[0].equals(arrlist.get(i).getId())) { idIdx = i; break; } } selLoginID = arrlist.get(idIdx); return selLoginID; } ///// 로그인된 ID가 배열 리스트에 저장된 인덱스 번호를 반환 public int loginidIdx(ArrayList<memDTO> arrlist, String playID[]) { int idIdx = 0; // 배열 리스트에 저장된 현재 로그인된 ID의 인덱스 위치 찾기 for (int i = 0; i < arrlist.size(); i++) { if (playID[0].equals(arrlist.get(i).getId())) { idIdx = i; break; } } return idIdx; } /* * 52장이 들어있는 트럼프 공용 카드set을 생성 및 초기화 * 동일한 카드는 중복불가(스페이드,다이아몬드,하트,클로버 13장씩 4쌍 존재) * 순서 상관없이 무작위로 섞음 */ public void comCardSetInit(int comCardSet[]) { boolean noSame[] = new boolean[52]; for(int i = 0; i < noSame.length ; i++) { noSame[i] = false; } int rLoop = 0; int rIdx; while(rLoop < 52) { rIdx = (int)(Math.random() * 52); if(noSame[rIdx] == false) { noSame[rIdx] = true; comCardSet[rLoop] = rIdx + 1; rLoop++; } } } ///// 각자의 카드set 초기화 public void cardSetInit(String uCardSet[], String dCardSet[]) { for (int i = 0; i < uCardSet.length; i++) { uCardSet[i] = "0"; } for (int i = 0; i < dCardSet.length; i++) { dCardSet[i] = "0"; } } ///// 특정 카드 번호를 영문자로 변환 public String checkNum(int cardNum) { String result = ""; if (cardNum % 13 == 0) { cardNum = 13; } else { cardNum = (cardNum % 13); } switch (cardNum) { case 1: result = "A"; return result; case 11: result = "J"; return result; case 12: result = "Q"; return result; case 13: result = "K"; return result; } result = Integer.toString(cardNum); return result; } ///// 블랙잭 승리 판단 public boolean chekBJ(String CardSet[]) { boolean check[] = new boolean[2]; for (int i = 0; i < CardSet.length; i++) { if (CardSet[i].equals("A")) { check[0] = true; } } for (int i = 0; i < CardSet.length; i++) { if (CardSet[i].equals("K")) { check[1] = true; } } if (check[0] && check[1]) { return true; } else { return false; } } ///// 카드 1장 뽑기 public void drawCardOne(int comCardSet[], String cardSet[]) { int drawLoop = 0; int cardSetIdx = 0; int drawCard = 0; String drawCardStr = ""; while (drawLoop < 1) { cardSetIdx = (int)(Math.random() * 52); drawCard = comCardSet[cardSetIdx]; if (drawCard != 0) { // 테스트: 공용 카드set에서 뽑은 카드의 위치 확인 // System.out.println("뽑은 카드의 배열 인덱스 = " + cardSetPos); drawCardStr = checkNum(drawCard); for (int i = 0; i < cardSet.length; i++) { if (cardSet[i] == "0") { cardSet[i] = drawCardStr; comCardSet[cardSetIdx] = 0; drawLoop++; break; } } } } } /* * [배분된 카드를 출력] * - 'index' 값이 1이면 카드set 공개 * - 'index' 값이 2면 카드set에서 카드 1개 숨김 */ public void cardSetNum(String cardSet[], int index) { if (index == 1) { for (int i = 0; i < cardSet.length; i++) { if (cardSet[i] == "0") { System.out.print(" "); } else { System.out.print(cardSet[i] + " "); } } System.out.println(); } else if (index == 2) { for (int i = 0; i < cardSet.length; i++) { if (i == 0) { // 첫 번째 자리의 카드 숨김 System.out.print("? "); } else { if (cardSet[i] == "0") { System.out.print(" "); } else { System.out.print(cardSet[i] + " "); } } } System.out.println(); } else { // 예외 처리 System.out.println("디버그. 인덱스 값이 잘못되었습니다."); } } ///// 카드set이 꽉 찬 상태인지 체크 public boolean cardFull(String cardSet[]) { boolean cardSetFull = false; int count = 0; for (int i = 0; i < cardSet.length; i++) { if (cardSet[i] == "0") { count++; } } if (count == 0) { cardSetFull = true; } return cardSetFull; } /* * [점수 구하기] * - 1차 점수 합산: 알파벳 카드는 종류에 따라 점수를 다르게 합산 * - 2차 점수 합산: 1차 점수 합산이 끝난 뒤 카드set에 'A'가 존재할 경우, * 10점을 추가한 점수가 '21점 이하'면 10점 추가(= 'A'는 '11점'과 같은 의미) */ public int pointResult(String cardSet[]) { int point = 0; for (int i = 0; i < cardSet.length; i++) { if (cardSet[i] == "A") { point += 1; } else if (cardSet[i] == "J") { point += 10; } else if (cardSet[i] == "Q") { point += 10; } else if (cardSet[i] == "K") { point += 10; } else if (Integer.parseInt(cardSet[i]) > 1 && Integer.parseInt(cardSet[i]) <= 10) { point += Integer.parseInt(cardSet[i]); } else { point += 0; } } for (int i = 0; i < cardSet.length; i++) { if (cardSet[i] == "A" && point + 10 <= 21) { point += 10; } } return point; } /* * 승패 * 1.유저 승리 * - 유저의 기본 카드 2장이 블랙잭(A, K)이고, 딜러는 해당되지 않을 경우 * - 각자 점수가 '21점 이하'이고, 유저의 점수가 더 높을 경우 * - 유저의 점수가 '21점 이하'이고, 딜러의 점수는 '21점을 초과'할 경우 * * 2.유저 패배 * - 딜러의 기본 카드 2장이 블랙잭(A, K)이고, 유저는 해당되지 않을 경우 * - 각자 점수가 '21점 이하'이고, 딜러의 점수가 더 높을 경우 * - 유저의 점수가 '21점을 초과'할 경우 * * 3.무승부 * - 각자 기본 카드 2장이 블랙잭(A, K)일 경우 * - 각자 점수가 동일한 경우 */ ///// 결과 출력 public void gameResult(String uCardSet[], String dCardSet[], boolean uBJWin, boolean dBJWin, boolean gameWin, ArrayList<memDTO> arrlist, String playID[], int betChip) { System.out.println("카드를 오픈합니다."); System.out.println(); System.out.println("유저에게 배분된 카드"); cardSetNum(uCardSet, 1); System.out.println("유저의 점수 = " + pointResult(uCardSet)); System.out.println(); System.out.println("딜러에게 배분된 카드"); cardSetNum(dCardSet, 1); System.out.println("딜러의 점수 = " + pointResult(dCardSet)); System.out.println(); int resultNum = 0; // 결과 메시지 - 블랙잭 유무 if (uBJWin && !dBJWin) { System.out.println("대박! ★ 축하합니다 ★ '블랙잭'으로 승리!!"); resultNum = 1; } else if (!uBJWin && dBJWin) { System.out.println("헐... '블랙잭'으로 패배!"); resultNum = 2; } else if (uBJWin && dBJWin) { System.out.println("이럴수가!! '블랙잭'으로 무승부!!!"); } // 결과 메시지 - 점수 비교 else { if (gameWin && pointResult(uCardSet) > pointResult(dCardSet) && pointResult(uCardSet) <= 21 || gameWin && pointResult(uCardSet) < pointResult(dCardSet) && pointResult(dCardSet) > 21) { System.out.println("★ 축하합니다 ★ 승리하셨습니다!!"); resultNum = 3; } else if (gameWin && pointResult(uCardSet) == pointResult(dCardSet) && pointResult(uCardSet) <= 21) { System.out.println("이럴수가... 무승부입니다!"); } else { System.out.println("패배!"); resultNum = 4; } } System.out.println(); // 칩 개수 갱신 chipRec(resultNum, arrlist, playID, betChip); } ///// 칩 개수 갱신 public void chipRec(int resultNum, ArrayList<memDTO> arrlist, String playID[], int betChip) { memDTO loginID = loginIDInfo(arrlist, playID); int idIdx = loginidIdx(arrlist, playID); int myChip = loginID.getChip(); switch (resultNum) { case 1: // 승리: 블랙잭 myChip += betChip * 1.5; break; case 2: // 패배: 블랙잭 myChip -= betChip; break; case 3: // 승리: 점수 비교 myChip += betChip * 2; break; case 4: // 패배: 점수 비교 myChip -= betChip; if (myChip < 0) { // 칩 개수가 0점 이하가 되면 0점으로 고정 myChip = 0; } break; default: System.out.println("무승부는 점수 변화가 없습니다."); break; } /* * [기록 갱신] * - 배열 리스트에 기존 정보를 지우고 지운 위치에 변경된 정보를 다시 저장 */ arrlist.remove(idIdx); arrlist.add(idIdx, loginID); loginID.setChip(myChip); } ///// 게임 재시작 유무 public boolean reGame() { Scanner sc = new Scanner(System.in); System.out.println("[게임 종료]"); while (true) { System.out.println("무엇을 하시겠습니까?"); System.out.print("재시작(1), 종료(2): "); int input = sc.nextInt(); switch (input) { case 1: System.out.println(); return true; case 2: System.out.println("게임을 종료합니다."); return false; default: System.out.println("잘못 입력하셨습니다."); } } } ///////////// TODO 테스트용 메소드 // 공용 카드set을 출력 public void comCardSetPrint(int cardSet[]) { for(int i=0; i < cardSet.length; i++) { if (i % 3 == 0) { System.out.println(); } System.out.print("cardSet[" + i + "] = " + cardSet[i] + " "); } System.out.println("\n"); } } | cs |
■ memDAO.java
package blackjackGame; import java.util.ArrayList; import java.util.Scanner; public class memDAO { public ArrayList<memDTO> arrlist; private memDTO mdto; public String playID[]; public boolean newID[]; private final int startChip = 100; // 신규 계정에 지급되는 칩 개수 memDAO() { arrlist = new ArrayList<memDTO>(); mdto = new memDTO(); playID = new String[1]; newID = new boolean[1]; } ///// 로그인 메뉴 public boolean loginMenu() { Scanner sc = new Scanner(System.in); // nullpointerEx 예외 방지 boolean loop = true; while (loop) { System.out.println("기존 ID 로그인(1), 신규 ID 생성(2), ID 리스트(3)"); System.out.print("입력: "); int inputNum = sc.nextInt(); switch (inputNum) { case 1: loop = login(playID); break; case 2: loop = insert(select(newID)); break; case 3: memberPrint(); break; default: System.out.println("잘못 입력하셨습니다."); } } gamePlay gPlay = new gamePlay(); memDTO loginID = gPlay.loginIDInfo(arrlist, playID); if (loginID.getChip() < 10) { System.out.println("칩을 10개 이상 갖고있어야 게임 이용이 가능합니다."); System.out.println(loginID.getId() + "님의 칩 개수는 " + loginID.getChip()); System.out.println(); return false; } return true; } ///// 로그인 public boolean login(String playID[]) { Scanner sc = new Scanner(System.in); String selID = select(newID); if (newID[0]) { System.out.println("입력하신 ID를 찾을 수 없습니다."); System.out.print("새로 등록하시겠습니까? 예(1), 아니오(2): "); int num = sc.nextInt(); sc.nextLine(); boolean loop = true; while (loop) { switch (num) { case 1: loop = insert(selID); playID[0] = selID; break; case 2: return true; default: System.out.println("잘못 입력하셨습니다."); } } } playID[0] = selID; return false; } ///// 신규 계정 등록 public boolean insert(String selID) { mdto = new memDTO(); if (newID[0]) { mdto.setId(selID); mdto.setChip(startChip); arrlist.add(mdto); System.out.println("닉네임 " + selID + "(을)를 새로 등록했습니다."); playID[0] = selID; return false; } System.out.println("오류: 동일한 ID가 존재합니다."); return true; } ///// ID 검색 public String select(boolean newID[]) { Scanner sc = new Scanner(System.in); System.out.print("닉네임 입력: "); String nickName = sc.next(); String nameChek; for (int i = 0; i < arrlist.size(); i++) { nameChek = arrlist.get(i).getId(); if (nameChek.equals(nickName)) { // System.out.println("찾았습니다."); newID[0] = false; return nickName; } } newID[0] = true; return nickName; } ///// DB 파일에서 회원 정보를 불러오기 public void memberInit() { FileDao fdao = new FileDao(); fdao.fileCreate(); arrlist = fdao.fileRead(); } ///// 게임에 저장된 회원 정보를 DB 파일에 저장하기 public void memberRec() { FileDao fdao = new FileDao(); fdao.fileWrite(arrlist); } ///// 모든 회원 정보를 출력하기 public void memberPrint() { mdto = new memDTO(); System.out.println(); System.out.println("[ID List]"); for (int i = 0; i < arrlist.size(); i++) { mdto = arrlist.get(i); System.out.println("ID: " + mdto.getId() + ", point: " + mdto.getChip()); } System.out.println(); } } | cs |
■ memDTO.java
package blackjackGame; public class memDTO { private String id; private int chip; public memDTO() {} public String getId() { return id; } public void setId(String id) { this.id = id; } public int getChip() { return chip; } public void setChip(int chip) { this.chip = chip; } } | cs |
■ FileDAO.java
package blackjackGame; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.util.ArrayList; public class FileDao { ArrayList<memDTO> flistLoad = new ArrayList<memDTO>(); FileDao() {} File dbFolder = new File("C:/Blackjack_GameDB"); File dbFile = new File("C:/Blackjack_GameDB/member_DB.txt"); public void fileCreate() { try { if (!dbFolder.exists()) { dbFolder.mkdir(); } if (!dbFile.exists()) { dbFile.canWrite(); } } catch (Exception e) { System.out.println("생성 오류 발생"); // e.printStackTrace(); } } public ArrayList<memDTO> fileRead() { try { BufferedReader br = new BufferedReader(new FileReader(dbFile)); if (dbFile.exists()) { String memRec; while ((memRec = br.readLine()) != null) { String memInfo[] = memRec.split(":"); memDTO mdto = new memDTO(); mdto.setId(memInfo[0]); mdto.setChip((Integer.parseInt(memInfo[1]))); flistLoad.add(mdto); } br.close(); } else { System.out.println("파일 없음"); } } catch (Exception e) { // System.out.println("오류: 파일이 존재하지 않습니다"); // e.printStackTrace(); } return flistLoad; } public void fileWrite(ArrayList<memDTO> arrlist) { try { FileWriter fwrite = new FileWriter(dbFile); // 'ID:Point' 형식으로 파일에 입력 for (int i = 0; i < arrlist.size(); i++) { fwrite.write(arrlist.get(i).getId() + ":" + arrlist.get(i).getChip() + "\r\n"); } // scanWrite.close(); fwrite.close(); } catch (Exception e) { System.out.println("쓰기 오류 발생"); e.printStackTrace(); } } } | cs |
■ mainClass.java
/* * [게임 규칙] * ※ 실제 블랙잭 게임 규칙과 일부 다름 * * 공통 * - 유저와 딜러의 1:1 대결 * - 52장의 트럼프 카드를 사용(13장(A~K)씩 4묶음 * ※ 문양(스페이드, 다이아몬드, 하트, 클로버)의 의미는 없음 * - 최초 기본 카드는 각각 2장을 배분 * - 'J, Q, K'는 10점으로 계산 * - 'A'는 '1점' 또는 '11점'으로 계산되는데, * '점수 > 21점 == 1점'으로 계산, '점수 <= 21점 == 11점'으로 계산 * * 베팅 * - 로그인한 ID의 칩 개수가 '10개 미만'이면 게임 진행불가 * - 게임이 시작되면 최소 10개, 최대 100개까지 자신의 칩 개수 범위 내에서 베팅가능 * * 유저 * - 기본 카드를 받고 난 후 유저는 승패가 결정되기 전까지, 'Hit'or'Stay'를 결정해야 함 * - 'Hit'결정 시 유저는 카드 1장을 뽑음 * 'Hit'는 4번만 가능. 총 6개의 카드를 가질 수 있음 * - 'Stay'결정 시 각자의 카들를 모두 공개하고, 점수를 비교하여 승패를 결정 * * 딜러 * - 딜러의 첫 번째 카드는 유저에게 보여주지 않음 * ※ '?'로 표시 * - 유저가 'Hit'or'Stay'를 결정하면, 각 점수를 비교함 * 딜러의 점수가 '21점 이하'이고, 유저의 점수보다 낮을 경우 카드 1장을 뽑음 * ※ 게임 진행 중 1회만 뽑을 수 있음 * * 승패 * 1.유저 승리 * - 유저의 기본 카드 2장이 블랙잭(A, K)이고, 딜러는 해당되지 않을 경우 * - 각자 점수가 '21점 이하'이고, 유저의 점수가 더 높을 경우 * - 유저의 점수가 '21점 이하'이고, 딜러의 점수는 '21점을 초과'할 경우 * * 2.유저 패배 * - 딜러의 기본 카드 2장이 블랙잭(A, K)이고, 유저는 해당되지 않을 경우 * - 각자 점수가 '21점 이하'이고, 딜러의 점수가 더 높을 경우 * - 유저의 점수가 '21점을 초과'할 경우 * * 3.무승부 * - 각자 기본 카드 2장이 블랙잭(A, K)일 경우 * - 각자 점수가 동일한 경우 */ package blackjackGame; class blackjackGame { public static void main(String[] args) { memDAO mdao = new memDAO(); ///// 로그인 System.out.println("--- 블랙잭 게임 ---"); System.out.println(); boolean playLoop = true; while (playLoop) { System.out.println("[로그인]"); mdao.memberInit(); while (true) { if (mdao.loginMenu()) { break; } } System.out.println(mdao.playID[0] + "(으)로 로그인 되었습니다."); System.out.println(); ///// 게임 플레이 gamePlay gplay = new gamePlay(mdao.arrlist, mdao.playID); mdao.memberRec(); playLoop = gplay.reGame(); } } } | cs |
[첨부 파일]
'프로그래밍 언어 > Java(연습)' 카테고리의 다른 글
해시맵 (0) | 2016.05.12 |
---|---|
배열 리스트, 연결 리스트 (0) | 2016.05.11 |
추상 클래스, 인터페이스 (0) | 2016.05.09 |
클래스(상속), Over Ride (0) | 2016.05.09 |
선수 관리 프로그램(스택 구조, 클래스 연습) (0) | 2016.05.05 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Reference
- 여행영어 100일의 기적
- RA
- System
- java
- Pte
- SysUtils
- 왕초보 영어회화 100일의 기적
- 응용
- 독해
- 스택
- 말하기
- 알고리즘
- 자료구조
- 설명
- 정렬
- 일기
- Delphi
- 상황
- ADODB
- VCL
- SWT
- 교육센터
- 계산기
- 대상
- tdataset
- 작문
- 문법
- 영어
- wfd
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함