자바(JAVA)/미니 프로젝트 & 기초 공부

Java 기초 다시 공부하기 4주차 - 달력 출력 프로그램, 가상 대선 당선 시뮬레이션 프로그램

개발학생 2024. 6. 30. 23:52
반응형

1. 달력 출력 프로그램 

1) 조건

  • 입력받은 년도와 월을 통해 달력 출력 - 입력한 달 기준으로 이전달/입력달/다음달 출력(3달 출력)
  • 날짜는 LocalDate 클래스 이용(Calendar와 Date 클래스도 이용 가능)
  • 이미지와 같은 형식으로 출력

2) 코드

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.Scanner;

public class MiniTask5 {
    public static String[] makeCalendar(int year, int month) {
        // 월이 12월을 넘어가거나 1월 이전으로 가는 경우 조정
        if (month > 12) {
            year += (month - 1) / 12;
            month = (month - 1) % 12 + 1;
        } else if (month < 1) {
            year += (month - 1) / 12;
            month = 12 + month % 12;
        }

        LocalDate firstDayOfMonth = LocalDate.of(year, month, 1);
        int daysInMonth = firstDayOfMonth.lengthOfMonth();
        DayOfWeek firstDayOfWeek = firstDayOfMonth.getDayOfWeek();

        String[] calendar = new String[6]; // 6 weeks maximum

        int dow = firstDayOfWeek.getValue();
        // 일요일이 첫 번째 열에 오도록 조정
        if (dow == 7) {
            dow = 0;
        }

        StringBuilder weekBuilder = new StringBuilder();
        for (int i = 0; i < dow; i++) {
            weekBuilder.append("    ");
        }

        int lineIndex = 0;
        for (int day = 1; day <= daysInMonth; day++) {
            weekBuilder.append(String.format("%2d  ", day)); // 날짜 포맷 수정
            if ((day + dow) % 7 == 0 || day == daysInMonth) {
                while (weekBuilder.length() < 32) { // 너비를 32칸으로 수정
                    weekBuilder.append("    ");
                }
                calendar[lineIndex] = weekBuilder.toString();
                weekBuilder.setLength(0);
                lineIndex++;
            }
        }

        while (lineIndex < 6) {
            calendar[lineIndex++] = "                                "; // 각 달력의 넓이(32칸, 공백 포함)
        }

        return calendar;
    }

    public static void printCalendar(int year, int month) {
        String[][] calendars = new String[3][];

        // 각 월의 달력을 문자열 배열에 저장
        for (int i = -1; i <= 1; i++) {
            calendars[i + 1] = makeCalendar(year, month + i);
        }

        // 각 달의 연도와 월 출력
        for (int i = -1; i <= 1; i++) {
            int currentMonth = month + i;
            int currentYear = year;

            // 월이 1월 이전이나 12월을 넘어가는 경우 조정
            if (currentMonth > 12) {
                currentYear += (currentMonth - 1) / 12;
                currentMonth = (currentMonth - 1) % 12 + 1;
            } else if (currentMonth < 1) {
                currentYear += (currentMonth - 1) / 12;
                currentMonth = 12 + currentMonth % 12;
            }

            System.out.printf("[%4d년 %02d월]                      ", currentYear, currentMonth);
        }
        System.out.println();

        // 요일 이름 출력
        for (int i = 0; i < 3; i++) {
            System.out.print("일  월  화  수  목  금  토           ");
        }
        System.out.println();

        // 3개의 달력을 나란히 출력
        for (int line = 0; line < 6; line++) {
            for (int m = 0; m < 3; m++) {
                if (line < calendars[m].length && calendars[m][line] != null) {
                    System.out.print(calendars[m][line]);
                } else {
                    System.out.print("                                "); // 각 달력의 넓이(32칸)
                }
                System.out.print("  "); // 달력 사이의 간격
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("달력의 년도를 입력해 주세요.(yyyy): ");
        int year = sc.nextInt();
        System.out.print("달력의 월을 입력해 주세요.(mm): ");
        int month = sc.nextInt();

        // 3개의 달력을 출력
        printCalendar(year, month);
    }
}

3) 출력 결과

2. 가상 대선 당선 시뮬레이션 프로그램

1) 조건

  • 조건문 및 반복문과 배열(or 컬렉션) 사용
  • 전체 투표수와 후보자를 입력받아 그 결과를 미리 확인(각 후보자에게는 순서대로 기호1, 기호2, 기호3 형식으로 번호 부여)
    -> 투표수는 1~10000 사이 값을 입력하며, 그외 값 입력에 대한 예외는 없다고 가정
    -> 후보자 인원은 2~10 사이의 값을 입력받으며, 그외 값 입력에 대한 예외는 없다고 가정
    -> 후보자 인원은 한글 10자 미만으로 입력받으며, 그외 값 입력에 대한 예외는 없다고 가정
  • 각 투표수의 결과는 선거를 진행할 후보자를 동일한 비율로 랜덤하게 발생(단, 당선자는 동률이 안됨) 
    -> Random함수의 nextInt() 함수로 생성
  • 1표를 투표했을 때의 결과에 대해, 투표자와 이에 대한 결과를 화면 출력해야 함 
  • 이미지와 같은 형식으로 출력 

2) 코드

// 가상 대선 당선 시뮬레이션 프로그램
import java.util.*;

class Candidate {
    private String name;
    private int voteCount;
    private int vnum; // 후보자의 기호 번호

    public Candidate(String name) {
        this.name = name;
        this.voteCount = 0;
        this.vnum = -1; // 기본적으로 기호 번호를 -1로 초기화
    }

    public Candidate(String name, int vnum) {
        this.name = name;
        this.voteCount = 0;
        this.vnum = vnum;
    }

    public String getName() {
        return name;
    }

    public int getVoteCount() {
        return voteCount;
    }

    public void incrementVoteCount() {
        voteCount++;
    }

    public int getVnum() {
        return vnum;
    }

    public void setVnum(int vnum) {
        this.vnum = vnum;
    }
}

// 선거 시뮬레이션 클래스
class ElectionSimulation {
    private List<Candidate> candidates;
    private Random random;

    public ElectionSimulation(List<Candidate> candidates) {
        this.candidates = candidates;
        random = new Random();
    }

    public void simulate(int totalVotes) {
        for (int i = 0; i < totalVotes; i++) {

            String totalTurnout = "[투표진행률]: "+ String.format("%1.2f", ((i+1.00)/totalVotes) * 100.00)+"%, ";    // 총 투표진행율 계산-1번당 오름

            int chosenIndex = random.nextInt(candidates.size());
            Candidate ccv = candidates.get(chosenIndex);    // 투표한 후보의 인덱스 가져오기
            ccv.incrementVoteCount();
            System.out.println(totalTurnout + (i+1) + "명 투표 => " + ccv.getName());

            for (Candidate candidate : candidates) {
                int vnum = candidate.getVnum();
                String name = candidate.getName();    // 후보자 이름 가져오기
                int votes = candidate.getVoteCount();    // 후보자 투표 수 가져오기
                double turnoutPercentage = (votes * 100.0) / totalVotes;    // 후보자 투표율 계산

                // 포맷 문자열을 사용하여 좌측 정렬하여 출력
                System.out.printf("[기호:%2d] %-5s: %-5.2f%% (투표수: %d)\n", vnum, name, turnoutPercentage, votes);
            }
        }
        System.out.println();
    }

    //설거 결과 출력
    public void printResults() {
        candidates.sort(Comparator.comparingInt(Candidate::getVoteCount).reversed());

        int maxVotes = candidates.get(0).getVoteCount();
        boolean tie = false;
        for (Candidate candidate : candidates) {
            if (candidate.getVoteCount() == maxVotes) {
                if (!tie) {
                    System.out.println("[투표결과] 당선인 : " + candidate.getName());
                    tie = true;
                }
            }
        }
    }
}

public class MiniTask6 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int numCandidates;

        int totalVotes;
        System.out.print("총 진행할 투표수를 입력해 주세요. (1~10000): ");
        totalVotes = scanner.nextInt();


        System.out.print("가상 선거를 진행할 후보자 인원을 입력해 주세요 (2~10): ");
        numCandidates = scanner.nextInt();

        scanner.nextLine(); // 개행 문자 처리

        List<Candidate> candidates = new ArrayList<>();
        for (int i = 1; i <= numCandidates; i++) {
            System.out.print(i + "번째 후보자 이름을 입력하세요: ");
            String name = scanner.nextLine();
            Candidate candidate = new Candidate(name);
            candidates.add(candidate);
            candidate.setVnum(i); // 후보자 객체에 기호 번호 설정
        }

        ElectionSimulation election = new ElectionSimulation(candidates);

        election.simulate(totalVotes);
        election.printResults();

        scanner.close();
    }
}

3) 출력 결과

3. 회고 

솔직히 챗지피티 없었으면 시작도 못했을 것 같다... 이제 꽤 자바를 하는 건가 생각했는데 이번 문제들을 보자마자 뇌가 정지되는 기분이었다... 두 번째 문제는 시간이 모자라서 당선자 동률 안되게 하는 처리를 못했다.... 

그래도... 챗지피티 코드 그대로 안 쓰고 최대한 수정해서 결과물을 만들었으니 괜찮은 걸까.... 갑자기 자신이 없어졌다....

좋은 곳 취업하려면 코딩테스트는 필수니까 나중에 코드 분석하고 공부 더 해봐야지...

반응형