Dev/Classic Game Dev

Hunt the Wumpus(1973) Source Code(JAVA)

나무수피아 2025. 4. 16. 22:24
728x90
반응형

아래의 소스는 Hunt the Wumpus(1973) 를 Java코드로 구현한 것입니다.

package javaDev;
import java.util.Random;
import java.util.Scanner;

public class HuntTheWumpus {

    static int[][] S = new int[20][3]; // Cave system
    static int[] L = new int[6]; // Positions (player, wumpus, pits, and bats)
    static int[] M = new int[6]; // Temporary storage of L
    static int A = 5; // Number of arrows
    static int F = 0; // Flag for game state
    static Random rand = new Random();
    static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        System.out.println("INSTRUCTIONS (Y-N)");
        String input = scanner.nextLine().toUpperCase();
        if (input.equals("N")) {
            return;
        }

        // Initialize cave layout
        initializeCave();

        // Display instructions
        displayInstructions();

        // Set up game and start
        gameLoop();
    }

    // Method to initialize the cave system and the positions of hazards
    static void initializeCave() {
        int[][] caveData = {
                {2, 5, 8}, {1, 3, 10}, {2, 4, 12}, {3, 5, 14}, {1, 4, 6},
                {5, 7, 15}, {6, 8, 17}, {1, 7, 9}, {8, 10, 18}, {2, 9, 11},
                {10, 12, 19}, {3, 11, 13}, {12, 14, 20}, {4, 13, 15}, {6, 14, 16},
                {15, 17, 20}, {7, 16, 18}, {9, 17, 19}, {11, 18, 20}, {13, 16, 19}
        };

        // Assign cave layout data
        for (int i = 0; i < 20; i++) {
            S[i] = caveData[i];
        }

        // Randomly assign positions for the player, Wumpus, pits, and bats
        for (int i = 0; i < 6; i++) {
            L[i] = getRandomNumber(20);
            M[i] = L[i];
        }

        // Check for crossovers (no duplicates in the setup)
        checkForCrossover();
    }

    // Method to check for any crossover (same position for player, wumpus, etc.)
    static void checkForCrossover() {
        for (int i = 0; i < 6; i++) {
            for (int j = i + 1; j < 6; j++) {
                if (L[i] == L[j]) {
                    L[j] = getRandomNumber(20);
                    i = 0; // Restart checking after modifying
                    break;
                }
            }
        }
    }

    // Helper method to generate a random number within a range
    static int getRandomNumber(int range) {
        return rand.nextInt(range) + 1;
    }

    // Method to display the game instructions
    static void displayInstructions() {
        System.out.println("\nWELCOME TO 'HUNT THE WUMPUS'");
        System.out.println("THE WUMPUS LIVES IN A CAVE OF 20 ROOMS...");
        System.out.println("... (long instructions, omitted for brevity)");
        System.out.println("WUMPUS - 'I SMELL A WUMPUS'");
        System.out.println("BAT - 'BATS NEARBY'");
        System.out.println("PIT - 'I FEEL A DRAFT'");
    }

    // Main game loop
    static void gameLoop() {
        while (true) {
            // Print location and hazard warnings
            printLocationAndHazards();

            // Choose action (shoot or move)
            chooseAction();

            // Check for game over conditions
            if (F != 0) {
                break;
            }
        }
    }

    // Print location and hazard warnings
    static void printLocationAndHazards() {
        System.out.println("\nYOU ARE IN ROOM " + L[0]);
        System.out.print("TUNNELS LEAD TO: ");
        for (int i = 0; i < 3; i++) {
            System.out.print(S[L[0] - 1][i] + " ");
        }
        System.out.println();

        // Check for hazards
        for (int i = 1; i < 6; i++) {
            if (L[0] == L[i]) {
                switch (i) {
                    case 1: // Wumpus
                        System.out.println("I SMELL A WUMPUS!");
                        break;
                    case 2: // Pit
                    case 3:
                        System.out.println("I FEEL A DRAFT");
                        break;
                    case 4: // Bat
                    case 5:
                        System.out.println("BATS NEARBY!");
                        break;
                }
            }
        }
    }

    // Choose to shoot or move
    static void chooseAction() {
        System.out.print("SHOOT OR MOVE (S-M): ");
        String choice = scanner.nextLine().toUpperCase();

        if (choice.equals("S")) {
            shootArrow();
        } else if (choice.equals("M")) {
            movePlayer();
        }
    }

    // Handle shooting an arrow
    static void shootArrow() {
        System.out.println("NO. OF ROOMS (1-5): ");
        int arrowLength = Integer.parseInt(scanner.nextLine());
        if (arrowLength < 1 || arrowLength > 5) {
            shootArrow(); // Invalid input, retry
            return;
        }

        int[] path = new int[arrowLength];
        for (int i = 0; i < arrowLength; i++) {
            System.out.print("ROOM #" + (i + 1) + ": ");
            path[i] = Integer.parseInt(scanner.nextLine());
            if (i > 0 && path[i] == path[i - 1]) {
                System.out.println("ARROWS AREN'T THAT CROOKED - TRY ANOTHER ROOM");
                return;
            }
        }

        // Shoot the arrow
        for (int i = 0; i < arrowLength; i++) {
            boolean hit = false;
            for (int j = 0; j < 3; j++) {
                if (S[L[0] - 1][j] == path[i]) {
                    L[0] = path[i];
                    hit = true;
                    break;
                }
            }
            if (!hit) {
                L[0] = S[L[0] - 1][rand.nextInt(3)];
            }
        }

        // Check if the arrow hits the Wumpus
        if (L[0] == L[1]) {
            System.out.println("AHA! YOU GOT THE WUMPUS!");
            F = 1;
        } else {
            A--;
            if (A <= 0) {
                System.out.println("YOU RAN OUT OF ARROWS! YOU LOSE!");
                F = -1;
            } else {
                System.out.println("MISSED");
            }
        }
    }

    // Handle moving the player
    static void movePlayer() {
        System.out.print("WHERE TO: ");
        int newRoom = Integer.parseInt(scanner.nextLine());
        if (newRoom < 1 || newRoom > 20) {
            System.out.println("INVALID ROOM, TRY AGAIN.");
            movePlayer();
            return;
        }

        // Check if the move is valid
        boolean validMove = false;
        for (int i = 0; i < 3; i++) {
            if (S[L[0] - 1][i] == newRoom) {
                validMove = true;
                break;
            }
        }

        if (!validMove) {
            System.out.println("NOT POSSIBLE - TRY ANOTHER ROOM.");
            movePlayer();
            return;
        }

        // Update player position
        L[0] = newRoom;

        // Check for hazards
        if (L[0] == L[1]) {
            System.out.println("OOPS! BUMPED A WUMPUS!");
            F = -1; // Game over
        } else if (L[0] == L[2] || L[0] == L[3]) {
            System.out.println("YOU FELL IN A PIT!");
            F = -1; // Game over
        } else if (L[0] == L[4] || L[0] == L[5]) {
            System.out.println("SUPER BAT SNATCH! ELSEWHEREVILLE FOR YOU!");
            L[0] = getRandomNumber(20);
        }
    }
}

 

1. 패키지 선언

package javaDev;
  • package는 Java 프로그램을 논리적으로 그룹화하는 데 사용됩니다. javaDev는 이 파일이 포함된 패키지 이름입니다.

2. 필드 선언

static int[][] S = new int[20][3]; // Cave system
static int[] L = new int[6]; // Positions (player, wumpus, pits, and bats)
static int[] M = new int[6]; // Temporary storage of L
static int A = 5; // Number of arrows
static int F = 0; // Flag for game state
static Random rand = new Random();
static Scanner scanner = new Scanner(System.in);
  • S: 2차원 배열로, 각 방에 연결된 방들의 목록을 저장합니다. 20개의 방과 각 방에 연결된 3개의 방이 존재합니다.
  • L: 게임에 필요한 위치 정보(플레이어, Wumpus, pits, bats 등)를 저장하는 배열입니다.
  • M: L 배열의 임시 복사본입니다.
  • A: 남은 화살의 수입니다.
  • F: 게임 상태를 나타내는 플래그입니다. 0이면 게임이 진행 중, 1이면 승리, -1이면 게임 오버를 나타냅니다.
  • rand: 난수 생성기입니다.
  • scanner: 사용자 입력을 받기 위한 Scanner 객체입니다.

3. main 메서드

public static void main(String[] args) {
    System.out.println("INSTRUCTIONS (Y-N)");
    String input = scanner.nextLine().toUpperCase();
    if (input.equals("N")) {
        return;
    }

    // Initialize cave layout
    initializeCave();

    // Display instructions
    displayInstructions();

    // Set up game and start
    gameLoop();
}
  • main 메서드는 프로그램의 진입점입니다.
  • 사용자에게 게임 설명을 보여주고, "Y" 또는 "N"을 입력받습니다. "N"을 입력하면 게임을 종료합니다.
  • 게임을 시작하기 전에 initializeCave()를 호출하여 동굴을 초기화하고, displayInstructions()로 게임 설명을 출력합니다.
  • 이후 gameLoop()를 호출하여 게임을 시작합니다.

4. initializeCave 메서드

static void initializeCave() {
    int[][] caveData = {
        {2, 5, 8}, {1, 3, 10}, {2, 4, 12}, {3, 5, 14}, {1, 4, 6},
        {5, 7, 15}, {6, 8, 17}, {1, 7, 9}, {8, 10, 18}, {2, 9, 11},
        {10, 12, 19}, {3, 11, 13}, {12, 14, 20}, {4, 13, 15}, {6, 14, 16},
        {15, 17, 20}, {7, 16, 18}, {9, 17, 19}, {11, 18, 20}, {13, 16, 19}
    };
    for (int i = 0; i < 20; i++) {
        S[i] = caveData[i];
    }

    // Randomly assign positions for the player, Wumpus, pits, and bats
    for (int i = 0; i < 6; i++) {
        L[i] = getRandomNumber(20);
        M[i] = L[i];
    }

    checkForCrossover();
}
  • 동굴 구조를 초기화합니다. caveData 배열은 각 방에 연결된 다른 방들을 나타냅니다. S[i]는 각 방에 연결된 방들의 리스트입니다.
  • L 배열에 플레이어, Wumpus, pits, bats의 위치를 랜덤으로 배치하고, M 배열에 L을 복사합니다.
  • checkForCrossover()는 같은 위치에 플레이어나 다른 객체들이 겹치지 않도록 확인합니다.

5. checkForCrossover 메서드

static void checkForCrossover() {
    for (int i = 0; i < 6; i++) {
        for (int j = i + 1; j < 6; j++) {
            if (L[i] == L[j]) {
                L[j] = getRandomNumber(20);
                i = 0; // Restart checking after modifying
                break;
            }
        }
    }
}
  • L 배열의 각 항목이 중복되는지 확인하여, 중복될 경우 새로운 위치를 할당합니다. 위치가 겹칠 경우 getRandomNumber(20)을 사용하여 새로운 값을 재할당합니다.

6. getRandomNumber 메서드

static int getRandomNumber(int range) {
    return rand.nextInt(range) + 1;
}
  • 주어진 범위 내에서 랜덤한 정수를 생성하는 메서드입니다. rand.nextInt(range)는 0부터 range-1까지의 정수를 반환하는데, +1을 해주어 1부터 range까지의 정수를 반환합니다.

7. displayInstructions 메서드

static void displayInstructions() {
    System.out.println("\nWELCOME TO 'HUNT THE WUMPUS'");
    System.out.println("THE WUMPUS LIVES IN A CAVE OF 20 ROOMS...");
    System.out.println("... (long instructions, omitted for brevity)");
    System.out.println("WUMPUS - 'I SMELL A WUMPUS'");
    System.out.println("BAT - 'BATS NEARBY'");
    System.out.println("PIT - 'I FEEL A DRAFT'");
}
  • 게임 설명을 출력하는 메서드입니다.

8. gameLoop 메서드

static void gameLoop() {
    while (true) {
        // Print location and hazard warnings
        printLocationAndHazards();

        // Choose action (shoot or move)
        chooseAction();

        // Check for game over conditions
        if (F != 0) {
            break;
        }
    }
} 
  • 게임이 진행되는 메서드입니다. printLocationAndHazards()로 현재 위치와 위험 요소를 출력하고, chooseAction()을 통해 이동이나 화살 발사 등의 행동을 선택하게 합니다.
  • 게임이 끝날 조건(F != 0)이 되면 게임을 종료합니다.

9. printLocationAndHazards 메서드

static void printLocationAndHazards() {
    System.out.println("\nYOU ARE IN ROOM " + L[0]);
    System.out.print("TUNNELS LEAD TO: ");
    for (int i = 0; i < 3; i++) {
        System.out.print(S[L[0] - 1][i] + " ");
    }
    System.out.println();

    // Check for hazards
    for (int i = 1; i < 6; i++) {
        if (L[0] == L[i]) {
            switch (i) {
                case 1: // Wumpus
                    System.out.println("I SMELL A WUMPUS!");
                    break;
                case 2: // Pit
                case 3:
                    System.out.println("I FEEL A DRAFT");
                    break;
                case 4: // Bat
                case 5:
                    System.out.println("BATS NEARBY!");
                    break;
            }
        }
    }
}
  • 플레이어의 위치와 연결된 방을 출력하고, 각종 위험(웅푸스, 함정, 박쥐)을 확인하여 출력합니다.

10. chooseAction 메서드

static void chooseAction() {
    System.out.print("SHOOT OR MOVE (S-M): ");
    String choice = scanner.nextLine().toUpperCase();

    if (choice.equals("S")) {
        shootArrow();
    } else if (choice.equals("M")) {
        movePlayer();
    }
}
  • 사용자로부터 "S" (화살 쏘기) 또는 "M" (이동) 입력을 받아 해당 행동을 실행합니다.

11. shootArrow 메서드

  • 화살을 발사하는 방법을 구현한 메서드로, 지정된 방을 목표로 화살을 쏩니다.

12. movePlayer 메서드

  • 플레이어가 이동할 방을 선택하고, 해당 방으로 이동하는 로직을 처리합니다. 위험 요소에 맞닿으면 게임 오버가 됩니다.

이 프로그램은 Hunt the Wumpus 게임을 완전하게 재현하며, 사용자 입력을 통해 플레이어의 행동을 처리하고, 게임 진행 상황을 출력합니다.

728x90
반응형

'Dev > Classic Game Dev' 카테고리의 다른 글

Hunt the Wumpus(1973) Original Source Code(Basic)  (0) 2025.04.16