Javaによる簡易電卓と貪欲蛇ゲームの実装

簡易電卓の実装

以下は、標準入力から2つの整数と演算子を受け取り、四則演算を行うJavaプログラムです。

import java.util.Scanner;

public class SimpleCalculator {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        while (true) {
            System.out.println("2つの整数と演算子をスペース区切りで入力してください:");
            int num1 = input.nextInt();
            String op = input.next();
            int num2 = input.nextInt();

            switch (op) {
                case "+":
                    System.out.printf("%d + %d = %d%n", num1, num2, add(num1, num2));
                    break;
                case "-":
                    System.out.printf("%d - %d = %d%n", num1, num2, subtract(num1, num2));
                    break;
                case "*":
                    System.out.printf("%d * %d = %d%n", num1, num2, multiply(num1, num2));
                    break;
                case "/":
                    System.out.printf("%d / %d = %d%n", num1, num2, divide(num1, num2));
                    break;
            }
        }
    }

    private static int add(int a, int b) { return a + b; }
    private static int subtract(int a, int b) { return a - b; }
    private static int multiply(int a, int b) { return a * b; }
    private static int divide(int a, int b) { return a / b; }
}

貪欲蛇(スネーク)ゲームの実装

リソースパスの確認

画像リソースの相対パスを確認するためのテストコードです。

import java.net.URL;

public class ResourcePathTest {
    public static void main(String[] args) {
        URL url = ResourcePathTest.class.getResource("/assets/body.png");
        System.out.println("Body image path: " + url);
    }
}

画像リソースの管理

ゲームで使用する画像を一元管理するクラスです。

import javax.swing.ImageIcon;
import java.net.URL;

public class GameImages {
    public static final ImageIcon HEAD_UP    = loadImage("/assets/head_up.png");
    public static final ImageIcon HEAD_DOWN  = loadImage("/assets/head_down.png");
    public static final ImageIcon HEAD_LEFT  = loadImage("/assets/head_left.png");
    public static final ImageIcon HEAD_RIGHT = loadImage("/assets/head_right.png");
    public static final ImageIcon BODY       = loadImage("/assets/body.png");
    public static final ImageIcon FOOD       = loadImage("/assets/food.png");

    private static ImageIcon loadImage(String path) {
        URL url = GameImages.class.getResource(path);
        return new ImageIcon(url);
    }
}

メインウィンドウの作成

ゲームのメインフレームを初期化します。

import javax.swing.JFrame;
import java.awt.Toolkit;

public class SnakeGameLauncher {
    public static void main(String[] args) {
        JFrame window = new JFrame("貪欲蛇ゲーム");
        int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
        int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
        
        window.setBounds((screenWidth - 800) / 2, (screenHeight - 800) / 2, 800, 800);
        window.setResizable(false);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.add(new GameBoard());
        window.setVisible(true);
    }
}

ゲームボードの描画

ゲームの描画ロジックを含むパネルクラスです。

import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;

public class GameBoard extends JPanel {
    private static final int MAX_SNAKE_LENGTH = 300;
    private static final int CELL_SIZE = 25;
    private static final int BOARD_WIDTH = 770;
    private static final int BOARD_HEIGHT = 685;
    private static final int BOARD_X = 10;
    private static final int BOARD_Y = 70;

    private int[] snakeX = new int[MAX_SNAKE_LENGTH];
    private int[] snakeY = new int[MAX_SNAKE_LENGTH];
    private int snakeLength = 3;
    private String direction = "RIGHT";
    private boolean gameRunning = false;
    private boolean gameOver = false;
    private int foodX, foodY;
    private int score = 0;
    private Timer gameTimer;

    public GameBoard() {
        initializeGame();
        setFocusable(true);
        setupKeyControls();
        startGameLoop();
    }

    private void initializeGame() {
        snakeLength = 3;
        snakeX[0] = 175; snakeY[0] = 275;
        snakeX[1] = 150; snakeY[1] = 275;
        snakeX[2] = 125; snakeY[2] = 275;
        direction = "RIGHT";
        generateFood();
        score = 0;
        gameOver = false;
    }

    private void setupKeyControls() {
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                    if (gameOver) {
                        initializeGame();
                        gameRunning = true;
                    } else {
                        gameRunning = !gameRunning;
                    }
                    repaint();
                } else if (gameRunning && !gameOver) {
                    switch (e.getKeyCode()) {
                        case KeyEvent.VK_UP:    if (!"DOWN".equals(direction)) direction = "UP"; break;
                        case KeyEvent.VK_DOWN:  if (!"UP".equals(direction)) direction = "DOWN"; break;
                        case KeyEvent.VK_LEFT:  if (!"RIGHT".equals(direction)) direction = "LEFT"; break;
                        case KeyEvent.VK_RIGHT: if (!"LEFT".equals(direction)) direction = "RIGHT"; break;
                    }
                }
            }
        });
    }

    private void startGameLoop() {
        gameTimer = new Timer(100, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (gameRunning && !gameOver) {
                    moveSnake();
                    checkBoundaryCollision();
                    checkFoodCollision();
                    checkSelfCollision();
                    repaint();
                }
            }
        });
        gameTimer.start();
    }

    private void moveSnake() {
        for (int i = snakeLength - 1; i > 0; i--) {
            snakeX[i] = snakeX[i - 1];
            snakeY[i] = snakeY[i - 1];
        }

        switch (direction) {
            case "RIGHT": snakeX[0] += CELL_SIZE; break;
            case "LEFT":  snakeX[0] -= CELL_SIZE; break;
            case "UP":    snakeY[0] -= CELL_SIZE; break;
            case "DOWN":  snakeY[0] += CELL_SIZE; break;
        }
    }

    private void checkBoundaryCollision() {
        if (snakeX[0] > BOARD_X + BOARD_WIDTH - CELL_SIZE) snakeX[0] = BOARD_X;
        if (snakeX[0] < BOARD_X) snakeX[0] = BOARD_X + BOARD_WIDTH - CELL_SIZE;
        if (snakeY[0] < BOARD_Y) snakeY[0] = BOARD_Y + BOARD_HEIGHT - CELL_SIZE;
        if (snakeY[0] > BOARD_Y + BOARD_HEIGHT - CELL_SIZE) snakeY[0] = BOARD_Y;
    }

    private void generateFood() {
        Random rand = new Random();
        foodX = (rand.nextInt(30) + 1) * CELL_SIZE;
        foodY = (rand.nextInt(26) + 4) * CELL_SIZE;
    }

    private void checkFoodCollision() {
        if (snakeX[0] == foodX && snakeY[0] == foodY) {
            snakeLength++;
            score += 10;
            generateFood();
        }
    }

    private void checkSelfCollision() {
        for (int i = 1; i < snakeLength; i++) {
            if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
                gameOver = true;
                break;
            }
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        setBackground(new Color(246, 240, 120));
        drawHeader(g);
        drawGameArea(g);
        drawSnake(g);
        drawFood(g);
        drawScore(g);
        drawStatusMessages(g);
    }

    private void drawHeader(Graphics g) {
        GameImages.HEAD_RIGHT.paintIcon(this, g, 10, 10);
    }

    private void drawGameArea(Graphics g) {
        g.setColor(new Color(154, 67, 205));
        g.fillRect(BOARD_X, BOARD_Y, BOARD_WIDTH, BOARD_HEIGHT);
    }

    private void drawSnake(Graphics g) {
        // Draw head
        switch (direction) {
            case "UP":    GameImages.HEAD_UP.paintIcon(this, g, snakeX[0], snakeY[0]); break;
            case "DOWN":  GameImages.HEAD_DOWN.paintIcon(this, g, snakeX[0], snakeY[0]); break;
            case "LEFT":  GameImages.HEAD_LEFT.paintIcon(this, g, snakeX[0], snakeY[0]); break;
            case "RIGHT": GameImages.HEAD_RIGHT.paintIcon(this, g, snakeX[0], snakeY[0]); break;
        }
        // Draw body
        for (int i = 1; i < snakeLength; i++) {
            GameImages.BODY.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
    }

    private void drawFood(Graphics g) {
        GameImages.FOOD.paintIcon(this, g, foodX, foodY);
    }

    private void drawScore(Graphics g) {
        g.setColor(Color.BLACK);
        g.setFont(new Font("Meiryo", Font.BOLD, 20));
        g.drawString("スコア: " + score, 620, 40);
    }

    private void drawStatusMessages(Graphics g) {
        if (!gameRunning && !gameOver) {
            g.setColor(new Color(47, 168, 184));
            g.setFont(new Font("Meiryo", Font.BOLD, 40));
            g.drawString("スペースキーで開始", 230, 330);
        }
        if (gameOver) {
            g.setColor(new Color(193, 26, 26));
            g.setFont(new Font("Meiryo", Font.BOLD, 20));
            g.drawString("ゲームオーバー!スペースで再スタート", 180, 330);
        }
    }
}

タグ: Java Swing GUI ゲーム開発 貪欲蛇

7月29日 06:40 投稿