├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── jarRepositories.xml ├── libraries │ └── javafx_sdk_23.xml ├── misc.xml ├── uiDesigner.xml └── vcs.xml ├── HOME.md ├── README.md ├── TeachMeJava.iml ├── snake-game-js ├── game.js ├── index.html └── styles.css ├── src └── main │ └── java │ ├── com │ └── github │ │ └── karabosithole │ │ ├── Board.java │ │ ├── Question.java │ │ ├── QuestionManager.java │ │ └── Snake.java │ └── resources │ ├── apple.png │ ├── dot.png │ ├── head.png │ └── questions.txt └── target └── classes └── com └── github └── karabosithole ├── Board$1.class ├── Board$TAdapter.class ├── Board.class ├── Question.class ├── QuestionManager.class └── Snake.class /.gitignore: -------------------------------------------------------------------------------- 1 | ### IntelliJ IDEA ### 2 | out/ 3 | !**/src/main/**/out/ 4 | !**/src/test/**/out/ 5 | 6 | ### Eclipse ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | .sts4-cache 14 | bin/ 15 | !**/src/main/**/bin/ 16 | !**/src/test/**/bin/ 17 | 18 | ### NetBeans ### 19 | /nbproject/private/ 20 | /nbbuild/ 21 | /dist/ 22 | /nbdist/ 23 | /.nb-gradle/ 24 | 25 | ### VS Code ### 26 | .vscode/ 27 | 28 | ### Mac OS ### 29 | .DS_Store -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/libraries/javafx_sdk_23.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 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 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HOME.md: -------------------------------------------------------------------------------- 1 | # Snake Game Project Wiki 2 | 3 | ## Overview 4 | The Snake Game is a fun and interactive project developed in Java, where players control a snake to eat apples and answer trivia questions after each successful catch. This project was designed to reinforce my Java skills through hands-on practice while creating an engaging and educational game. 5 | 6 | For more details, you can also check out the project’s [README file](https://github.com/Karabosithole/LearnJavaSnakeGame). 7 | --- 8 | 9 | ## Project Motivation 10 | 11 | ### Why I Did the Project 12 | I created the Snake Game primarily to learn Java by practicing through an actual project. I find that hands-on, interactive learning works best for me, so developing a game allowed me to make the learning process fun and effective. My goal was to deepen my understanding of Java concepts while simultaneously creating an enjoyable experience. 13 | 14 | ### Target Audience 15 | This game is aimed at casual gamers and trivia enthusiasts who enjoy quick, fun games that also challenge their knowledge. It could also be useful for educators seeking innovative ways to engage students with learning through gamification. 16 | 17 | --- 18 | ### Realization: Running Java on the Web 19 | 20 | Initially, I designed the Snake Game in **Java** using the Swing framework. However, I soon realized that Java applications, especially ones built with Swing for a graphical user interface, cannot be run directly on a website due to browser limitations. Modern browsers do not support running Java applets or Swing-based applications natively, meaning users would have to download the game to run it locally. 21 | 22 | #### Pivot to JavaScript 23 | 24 | To offer a more seamless user experience where visitors could play the Snake Game directly on my portfolio site, I decided to recreate the game using **JavaScript**, **HTML**, and **CSS**. By doing this, users can play the game directly in their browser without needing to download anything. 25 | 26 | This transition involved learning how to recreate the core mechanics of the game in a web-friendly format while maintaining the same interactive gameplay. The new browser-based version of the Snake Game ensures ease of access for users and allows it to be embedded directly on my portfolio site. 27 | 28 | --- 29 | 30 | ### Technologies Used 31 | 32 | - **Java**: Original implementation of the Snake Game (downloadable version). 33 | - **JavaScript/HTML/CSS**: Rewritten version for browser playability. 34 | 35 | --- 36 | 37 | ### Future Plans 38 | 39 | - Continue supporting both versions of the Snake Game: one for download (Java) and one for browser play (JavaScript). 40 | - Explore other technologies to potentially expand the game's accessibility to more platforms. 41 | 42 | ## Learning Objectives 43 | In this project, I focused on achieving several learning goals: 44 | - **Object-Oriented Programming (OOP)**: Understanding and applying OOP principles in Java, including classes, inheritance, and polymorphism. 45 | - **GUI Development**: Designing a graphical user interface using Java's Swing library to create an interactive gaming experience. 46 | - **Event Handling**: Managing real-time player input and game events like key presses and game over states. 47 | - **Game Logic**: Implementing the core game mechanics such as movement, apple consumption, score calculation, and trivia integration. 48 | 49 | --- 50 | 51 | ## Development Process 52 | 53 | ### Tools and Technologies 54 | - **Java (JDK 17)**: The main programming language used to develop the Snake Game. 55 | - **Swing**: Java’s built-in GUI toolkit for building the graphical interface. 56 | - **Git**: For version control and collaboration. 57 | - **IDE**: Used IntelliJ IDEA for development. 58 | 59 | ### Key Design Decisions 60 | - **Modular Code Structure**: To make the code more readable and maintainable, I broke down the project into separate classes such as `Snake`, `Apple`, `GameBoard`, and `TriviaQuestion`. 61 | - **Trivia Integration**: After each apple consumption, the player is presented with a trivia question to enhance the gameplay and make it both fun and educational. 62 | 63 | --- 64 | 65 | ## Challenges and Solutions 66 | 67 | ### Challenge: Real-Time Event Handling 68 | One of the challenges I faced was managing the game loop while simultaneously handling real-time player input without slowing down the game. 69 | 70 | **Solution**: I solved this by using `KeyListener` and an efficient game loop structure that checks for input asynchronously, ensuring smooth gameplay. 71 | 72 | ### Challenge: Collision Detection 73 | Detecting when the snake collided with itself or the game boundaries posed a problem due to the continuous movement logic. 74 | 75 | **Solution**: I implemented precise boundary checks and a method that checks for collisions with the snake's own body, ensuring the game ends correctly when necessary. 76 | 77 | ### Challenge: Trivia Question Timing 78 | Integrating trivia questions after the snake eats an apple was tricky in terms of pausing the game and resuming after the answer. 79 | 80 | **Solution**: I added a trivia screen that pops up when the snake eats an apple, which halts the game temporarily and resumes only when the player answers the question. 81 | 82 | --- 83 | 84 | ## Reflections 85 | 86 | This project reaffirmed my love for learning through practice and play. As someone with ADHD, I often find traditional learning methods challenging, but creating something interactive and engaging made the entire process enjoyable. Through this project, I not only strengthened my Java programming skills but also learned how to work on a project that requires real-time interaction and user input. 87 | 88 | This experience reinforced my belief that gamification can be a powerful tool for learning. It also taught me the value of persistence—when facing challenges like handling event-driven programming and implementing complex game logic, I learned how to break problems down and solve them step by step. 89 | 90 | --- 91 | 92 | ## Future Improvements 93 | 94 | While the Snake Game is fully functional, I see a few areas for potential enhancement: 95 | - **Mobile Compatibility**: I plan to adapt the game to work on mobile devices, using frameworks like LibGDX for Java-based game development on Android. 96 | - **Multiplayer Mode**: Adding a multiplayer mode where two players can control different snakes, competing to collect the most apples while answering trivia questions. 97 | - **Question Bank Expansion**: I aim to expand the trivia question bank to cover more categories and difficulty levels, making the game even more educational. 98 | 99 | --- 100 | 101 | ## How to Play 102 | 103 | 1. **Movement**: Use the arrow keys to control the direction of the snake. 104 | 2. **Objective**: Eat apples to score points. 105 | 3. **Trivia**: After each apple is eaten, answer a trivia question to continue the game. 106 | 4. **Game Over**: The game ends if the snake collides with itself or the game boundary. 107 | 108 | --- 109 | 110 | ## Installation 111 | 112 | 1. Clone the repository: 113 | ```bash 114 | git clone https://github.com/karabosithole/snake-game.git 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Java Multiple-Choice Quiz Game & Snake Game (Java and JavaScript) 2 | 3 | ## Overview 4 | 5 | This repository contains two projects: 6 | - A **Multiple-Choice Quiz Game** built in Java using the Swing framework. 7 | - A **Snake Game**, originally developed in Java, with a new version that can be played directly in the browser using JavaScript. 8 | 9 | Both projects aim to provide fun and educational experiences for users while showcasing Java programming concepts. 10 | 11 | For detailed documentation and project motivation, visit the [Wiki Home](https://github.com/Karabosithole/LearnJavaSnakeGame). 12 | 13 | --- 14 | 15 | ## Projects in This Repository 16 | 17 | ### 1. Multiple-Choice Quiz Game (Java) 18 | 19 | **Overview**: 20 | This is a simple multiple-choice quiz game built in Java using the Swing framework. The game randomly selects a Java-related question and presents it to the user along with four possible answers. 21 | 22 | - **Features**: Random question selection, immediate feedback, easy to extend with new questions. 23 | - **Technologies Used**: Java, Swing (for GUI). 24 | 25 | **Installation**: 26 | 1. Prerequisites: Java 8+ and a Java IDE or command-line tools. 27 | 2. Clone the repository and compile the code: 28 | ```bash 29 | git clone https://github.com/your-username/java-multiple-choice-quiz.git 30 | javac com/github/karabosithole/Main.java 31 | java com.github.karabosithole.Main 32 | 33 | 34 | # Java Multiple-Choice Quiz Game (Java) 35 | 36 | ## Overview 37 | This is a simple multiple-choice quiz game built in Java using the Swing framework. The game randomly selects a question from a pool of Java-related questions and presents it to the user along with four possible answers. The user must choose the correct answer from the options presented. Immediate feedback is given on whether the answer is correct or incorrect. 38 | 39 | For detailed documentation and project motivation, visit the [Wiki Home](https://github.com/Karabosithole/LearnJavaSnakeGame). 40 | 41 | ## Features 42 | - Multiple-choice questions related to Java programming. 43 | - Random question selection from a pool of predefined questions. 44 | - Interactive GUI using Java Swing for question display and user input. 45 | - Immediate feedback after each answer. 46 | - Easy to extend with additional questions and answers. 47 | 48 | ## Installation 49 | 50 | ### Prerequisites 51 | - Java 8 or higher 52 | - A Java IDE (e.g., IntelliJ IDEA, Eclipse) or simply `javac` for command-line compilation 53 | 54 | ### Steps 55 | 1. Clone this repository or download the source code: 56 | ```bash 57 | git clone https://github.com/your-username/java-multiple-choice-quiz.git 58 | ``` 59 | 2. Open the project in your preferred Java IDE or navigate to the folder in the terminal. 60 | 3. Compile and run the `Main` class to start the quiz game. 61 | 62 | Using the terminal: 63 | ```bash 64 | javac com/github/karabosithole/Main.java 65 | java com.github.karabosithole.Main 66 | ``` 67 | 68 | ## How to Play 69 | 1. When the game starts, a question will be displayed with four answer choices (A, B, C, D). 70 | 2. Select one of the answers from the dialog box. 71 | 3. You will receive immediate feedback on whether your answer was correct or incorrect. 72 | 4. The game will then ask the next question after a short delay. 73 | 74 | ### Example Flow 75 | 1. **Question**: What does JVM stand for? 76 | - A) Java Virtual Machine 77 | - B) Java Visual Model 78 | - C) Java Version Manager 79 | - D) Java Variable Model 80 | 81 | **Answer**: If the user selects "A) Java Virtual Machine," they receive a message indicating whether they were correct. 82 | 83 | ## Adding More Questions 84 | To add more questions to the game, follow these steps: 85 | 1. Open the `QuestionManager` class. 86 | 2. In the `initQuestions()` method, add a new `Question` object with your custom question, answer choices, and the index of the correct answer. 87 | 88 | ```bash 89 | Questions.add(new Question("Your custom question?", 90 | new String[] {"A) Option1", "B) Option2", "C) Option3", "D) Option4"}, 91 | 2)); // Correct answer is the 3rd option (index 2) 92 | ``` 93 | 94 | ## Technologies Used 95 | - **Java**: Programming language used to develop the game. 96 | - **Swing**: Java's GUI framework to display dialogs and capture user input. 97 | 98 | ## Credits 99 | Created by Karabo Sithole. 100 | -------------------------------------------------------------------------------- /TeachMeJava.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /snake-game-js/game.js: -------------------------------------------------------------------------------- 1 | const questions = [ 2 | { 3 | question: "What does JVM stand for?", 4 | answers: ["A) Java Virtual Machine", "B) Java Visual Model", "C) Java Version Manager", "D) Java Variable Model"], 5 | correct: 0 6 | }, 7 | { 8 | question: "Which of these is not a Java keyword?", 9 | answers: ["A) public", "B) static", "C) void", "D) main"], 10 | correct: 3 11 | }, 12 | { 13 | question: "What is the extension of Java files?", 14 | answers: ["A) .jav", "B) .java", "C) .class", "D) .js"], 15 | correct: 1 16 | }, 17 | // Add more questions here 18 | ]; 19 | 20 | let currentQuestionIndex = 0; 21 | let score = 0; 22 | let snake = [{ x: 10, y: 10 }]; 23 | let apple = { x: 15, y: 15 }; 24 | let gameCanvas = document.getElementById("gameCanvas"); 25 | let ctx = gameCanvas.getContext("2d"); 26 | let box = 20; 27 | let d; 28 | let gameSpeed = 200; // Adjust the speed of the game (lower is faster) 29 | let game; 30 | 31 | // Control whether the game is paused 32 | let isPaused = false; 33 | 34 | document.addEventListener("keydown", direction); 35 | 36 | function direction(event) { 37 | if (event.keyCode == 37 && d != "RIGHT") { 38 | d = "LEFT"; 39 | } else if (event.keyCode == 38 && d != "DOWN") { 40 | d = "UP"; 41 | } else if (event.keyCode == 39 && d != "LEFT") { 42 | d = "RIGHT"; 43 | } else if (event.keyCode == 40 && d != "UP") { 44 | d = "DOWN"; 45 | } 46 | } 47 | 48 | function draw() { 49 | if (isPaused) return; // Pause the game if isPaused is true 50 | 51 | ctx.clearRect(0, 0, gameCanvas.width, gameCanvas.height); 52 | for (let i = 0; i < snake.length; i++) { 53 | ctx.fillStyle = (i === 0) ? "green" : "white"; 54 | ctx.fillRect(snake[i].x * box, snake[i].y * box, box, box); 55 | ctx.strokeStyle = "black"; 56 | ctx.strokeRect(snake[i].x * box, snake[i].y * box, box, box); 57 | } 58 | 59 | ctx.fillStyle = "red"; 60 | ctx.fillRect(apple.x * box, apple.y * box, box, box); 61 | 62 | let snakeX = snake[0].x; 63 | let snakeY = snake[0].y; 64 | 65 | if (d === "LEFT") snakeX--; 66 | if (d === "UP") snakeY--; 67 | if (d === "RIGHT") snakeX++; 68 | if (d === "DOWN") snakeY++; 69 | 70 | if (snakeX === apple.x && snakeY === apple.y) { 71 | score++; 72 | apple = { 73 | x: Math.floor(Math.random() * (gameCanvas.width / box)), 74 | y: Math.floor(Math.random() * (gameCanvas.height / box)) 75 | }; 76 | displayQuestion(); 77 | } else { 78 | snake.pop(); 79 | } 80 | 81 | // Check collision with itself or walls 82 | if (snakeX < 0 || snakeX >= gameCanvas.width / box || snakeY < 0 || snakeY >= gameCanvas.height / box || collision(snakeX, snakeY, snake)) { 83 | clearInterval(game); 84 | alert("Game Over! Score: " + score); 85 | } 86 | 87 | let newHead = { x: snakeX, y: snakeY }; 88 | snake.unshift(newHead); 89 | } 90 | 91 | function collision(x, y, snake) { 92 | for (let i = 1; i < snake.length; i++) { 93 | if (snake[i].x === x && snake[i].y === y) { 94 | return true; 95 | } 96 | } 97 | return false; 98 | } 99 | 100 | // Display question when snake eats apple 101 | function displayQuestion() { 102 | isPaused = true; // Pause the game 103 | const questionElement = document.getElementById('question'); 104 | const answersElement = document.getElementById('answers'); 105 | const feedbackElement = document.getElementById('feedback'); 106 | const nextButton = document.getElementById('next'); 107 | 108 | feedbackElement.textContent = ''; // Clear feedback 109 | nextButton.style.display = 'none'; // Hide next button 110 | 111 | if (currentQuestionIndex < questions.length) { 112 | questionElement.textContent = questions[currentQuestionIndex].question; 113 | questionElement.style.display = 'block'; 114 | answersElement.innerHTML = ''; // Clear previous answers 115 | 116 | questions[currentQuestionIndex].answers.forEach((answer, index) => { 117 | const button = document.createElement('button'); 118 | button.textContent = answer; 119 | button.onclick = () => checkAnswer(index); 120 | answersElement.appendChild(button); 121 | }); 122 | answersElement.style.display = 'block'; // Show answers 123 | } else { 124 | questionElement.textContent = 'Quiz Completed!'; 125 | answersElement.innerHTML = ''; 126 | nextButton.style.display = 'none'; 127 | } 128 | } 129 | 130 | function checkAnswer(selectedIndex) { 131 | const feedbackElement = document.getElementById('feedback'); 132 | const nextButton = document.getElementById('next'); 133 | const currentQuestion = questions[currentQuestionIndex]; 134 | 135 | if (selectedIndex === currentQuestion.correct) { 136 | feedbackElement.textContent = 'Correct!'; 137 | } else { 138 | feedbackElement.textContent = 'Incorrect! The correct answer is: ' + currentQuestion.answers[currentQuestion.correct]; 139 | } 140 | 141 | currentQuestionIndex++; 142 | nextButton.style.display = 'block'; // Show next button 143 | } 144 | 145 | document.getElementById('next').onclick = () => { 146 | const questionElement = document.getElementById('question'); 147 | const answersElement = document.getElementById('answers'); 148 | 149 | questionElement.style.display = 'none'; 150 | answersElement.style.display = 'none'; 151 | document.getElementById('feedback').textContent = ''; // Clear feedback 152 | 153 | isPaused = false; // Resume the game 154 | }; 155 | 156 | // Start the game 157 | game = setInterval(draw, gameSpeed); 158 | -------------------------------------------------------------------------------- /snake-game-js/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Snake Game with Quiz 7 | 8 | 9 | 10 |
11 |

Snake Game with Quiz

12 | 13 | 14 | 15 |
16 | 17 |
18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /snake-game-js/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, sans-serif; 3 | background-color: #f4f4f4; 4 | display: flex; 5 | justify-content: center; 6 | align-items: center; 7 | height: 100vh; 8 | margin: 0; 9 | } 10 | 11 | .container { 12 | background: white; 13 | padding: 20px; 14 | border-radius: 10px; 15 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); 16 | text-align: center; 17 | } 18 | 19 | canvas { 20 | background: #000; 21 | display: block; 22 | margin: 20px auto; 23 | } 24 | 25 | button { 26 | display: block; 27 | margin: 20px auto; 28 | padding: 10px 20px; 29 | border: none; 30 | background-color: #28a745; 31 | color: white; 32 | border-radius: 5px; 33 | cursor: pointer; 34 | } 35 | 36 | button:hover { 37 | background-color: #218838; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/github/karabosithole/Board.java: -------------------------------------------------------------------------------- 1 | package com.github.karabosithole; 2 | 3 | import java.awt.Color; 4 | import java.awt.Dimension; 5 | import java.awt.Font; 6 | import java.awt.FontMetrics; 7 | import java.awt.Graphics; 8 | import java.awt.Image; 9 | import java.awt.Toolkit; 10 | import java.awt.event.ActionEvent; 11 | import java.awt.event.ActionListener; 12 | import java.awt.event.KeyAdapter; 13 | import java.awt.event.KeyEvent; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import javax.swing.*; 17 | 18 | /** 19 | * The Board class represents the game board for the Snake game. 20 | * It handles the game logic, rendering, and user input. 21 | */ 22 | public class Board extends JPanel implements ActionListener { 23 | 24 | // Dimensions of the game board 25 | private final int B_WIDTH = 300; 26 | private final int B_HEIGHT = 300; 27 | private final int DOT_SIZE = 10; 28 | private final int ALL_DOTS = 900; // Maximum dots on the board 29 | private final int RAND_POS = 29; // Random position for apple 30 | private final int DELAY = 140; // Delay for game speed 31 | 32 | private final int x[] = new int[ALL_DOTS]; // X coordinates of the snake 33 | private final int y[] = new int[ALL_DOTS]; // Y coordinates of the snake 34 | 35 | private int dots; // Current length of the snake 36 | private int apple_x; // X coordinate of the apple 37 | private int apple_y; // Y coordinate of the apple 38 | 39 | // Direction flags for the snake movement 40 | private boolean leftDirection = false; 41 | private boolean rightDirection = true; 42 | private boolean upDirection = false; 43 | private boolean downDirection = false; 44 | private boolean inGame = true; // Game state 45 | 46 | private Timer timer; // Timer to control game speed 47 | private Image ball; // Image for the snake's body 48 | private Image apple; // Image for the apple 49 | private Image head; // Image for the snake's head 50 | 51 | // private List questions; // List of questions to ask 52 | private boolean gamePaused = false; // Pause flag 53 | private QuestionManager questionManager; // Use composition 54 | private Timer delayTimer; 55 | 56 | /** 57 | * Constructor to initialize the Board. 58 | */ 59 | public Board() { 60 | initBoard(); 61 | } 62 | 63 | /** 64 | * Initializes the game board settings and components. 65 | */ 66 | private void initBoard() { 67 | addKeyListener(new TAdapter()); // Add key listener for controls 68 | setBackground(Color.black); // Set background color 69 | setFocusable(true); // Make the panel focusable 70 | 71 | setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT)); // Set preferred size 72 | loadImages(); // Load images for the game 73 | initGame(); // Initialize the game state 74 | 75 | questionManager = new QuestionManager(); 76 | 77 | // Initialize questions 78 | // questions = new ArrayList<>(); 79 | // questions.add("What does JVM stand for?"); 80 | // questions.add("What is the difference between JDK and JRE?"); 81 | // questions.add("What is a constructor in Java?"); 82 | // questions.add("What is polymorphism?"); 83 | // questions.add("What is an interface?"); 84 | } 85 | 86 | /** 87 | * Loads images for the game elements. 88 | */ 89 | private void loadImages() { 90 | ImageIcon iid = new ImageIcon("src/main/java/resources/dot.png"); 91 | ball = iid.getImage(); 92 | 93 | ImageIcon iia = new ImageIcon("src/main/java/resources/apple.png"); 94 | apple = iia.getImage(); 95 | 96 | ImageIcon iih = new ImageIcon("src/main/java/resources/head.png"); 97 | head = iih.getImage(); 98 | } 99 | 100 | /** 101 | * Initializes the game state and positions. 102 | */ 103 | private void initGame() { 104 | dots = 3; // Set initial snake length 105 | 106 | // Initialize snake's starting position 107 | for (int z = 0; z < dots; z++) { 108 | x[z] = 50 - z * 10; 109 | y[z] = 50; 110 | } 111 | 112 | locateApple(); // Locate the first apple 113 | 114 | timer = new Timer(DELAY, this); // Create timer for game updates 115 | timer.start(); // Start the timer 116 | } 117 | 118 | /** 119 | * Paints the game components on the panel. 120 | * 121 | * @param g Graphics object for drawing 122 | */ 123 | @Override 124 | public void paintComponent(Graphics g) { 125 | super.paintComponent(g); // Call parent method 126 | 127 | doDrawing(g); // Custom drawing 128 | } 129 | 130 | /** 131 | * Handles the custom drawing of game elements. 132 | * 133 | * @param g Graphics object for drawing 134 | */ 135 | private void doDrawing(Graphics g) { 136 | if (inGame) { 137 | // Draw apple 138 | g.drawImage(apple, apple_x, apple_y, this); 139 | 140 | // Draw the snake 141 | for (int z = 0; z < dots; z++) { 142 | if (z == 0) { 143 | g.drawImage(head, x[z], y[z], this); // Draw head 144 | } else { 145 | g.drawImage(ball, x[z], y[z], this); // Draw body 146 | } 147 | } 148 | 149 | Toolkit.getDefaultToolkit().sync(); // Sync graphics 150 | 151 | } else { 152 | gameOver(g); // Show game over message 153 | } 154 | } 155 | 156 | /** 157 | * Displays the game over message. 158 | * 159 | * @param g Graphics object for drawing 160 | */ 161 | private void gameOver(Graphics g) { 162 | String msg = "Game Over"; 163 | Font small = new Font("Helvetica", Font.BOLD, 14); 164 | FontMetrics metr = getFontMetrics(small); 165 | 166 | //question box shows 167 | g.setColor(Color.white); // Set color for text 168 | g.setFont(small); // Set font for text 169 | g.drawString(msg, (B_WIDTH - metr.stringWidth(msg)) / 2, B_HEIGHT / 2); // Center the message 170 | } 171 | 172 | /** 173 | * Checks if the snake has eaten an apple and updates the game state. 174 | */ 175 | private void checkApple() { 176 | if ((x[0] == apple_x) && (y[0] == apple_y)) { 177 | dots++; // Increase snake length 178 | locateApple(); // Locate new apple 179 | 180 | // Pause the game before showing the question 181 | pauseGame(); 182 | 183 | questionManager.displayQuestion(); 184 | 185 | // Start a delay before resuming the game 186 | addResumeDelay(); 187 | 188 | // // Show a random question 189 | // int randomIndex = (int) (Math.random() * questions.size()); 190 | // String question = questions.get(randomIndex); 191 | // JOptionPane.showMessageDialog(this, question, "Java Question", JOptionPane.INFORMATION_MESSAGE); 192 | } 193 | } 194 | 195 | // Pause the game by stopping the timer 196 | private void pauseGame() { 197 | gamePaused = true; 198 | timer.stop(); // Stop the timer to pause game updates 199 | } 200 | 201 | // Resume the game by restarting the timer 202 | private void resumeGame() { 203 | gamePaused = false; 204 | timer.start(); // Restart the timer to continue game updates 205 | } 206 | 207 | // Add a delay before resuming the game 208 | private void addResumeDelay() { 209 | // Create a new Timer for a 1 second delay (1000ms) 210 | delayTimer = new Timer(1000, new ActionListener() { 211 | @Override 212 | public void actionPerformed(ActionEvent e) { 213 | // After 1 second, resume the game 214 | resumeGame(); 215 | delayTimer.stop(); // Stop the delay timer 216 | } 217 | }); 218 | 219 | // Start the delay timer 220 | delayTimer.setRepeats(false); // We want this to happen only once 221 | delayTimer.start(); 222 | } 223 | 224 | /** 225 | * Moves the snake in the current direction. 226 | */ 227 | private void move() { 228 | for (int z = dots; z > 0; z--) { 229 | x[z] = x[(z - 1)]; // Move body segments 230 | y[z] = y[(z - 1)]; 231 | } 232 | 233 | // Update head position based on direction 234 | if (leftDirection) { 235 | x[0] -= DOT_SIZE; 236 | } 237 | 238 | if (rightDirection) { 239 | x[0] += DOT_SIZE; 240 | } 241 | 242 | if (upDirection) { 243 | y[0] -= DOT_SIZE; 244 | } 245 | 246 | if (downDirection) { 247 | y[0] += DOT_SIZE; 248 | } 249 | } 250 | 251 | /** 252 | * Checks for collisions with walls or the snake itself. 253 | */ 254 | private void checkCollision() { 255 | // Check for collision with body 256 | for (int z = dots; z > 0; z--) { 257 | if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) { 258 | inGame = false; // Collision detected 259 | } 260 | } 261 | 262 | // Check for collision with walls 263 | if (y[0] >= B_HEIGHT || y[0] < 0 || x[0] >= B_WIDTH || x[0] < 0) { 264 | inGame = false; // Out of bounds 265 | } 266 | 267 | if (!inGame) { 268 | timer.stop(); // Stop the game timer 269 | } 270 | } 271 | 272 | /** 273 | * Locates the apple at a random position on the board. 274 | */ 275 | private void locateApple() { 276 | int r = (int) (Math.random() * RAND_POS); 277 | apple_x = ((r * DOT_SIZE)); // Calculate X position 278 | 279 | r = (int) (Math.random() * RAND_POS); 280 | apple_y = ((r * DOT_SIZE)); // Calculate Y position 281 | } 282 | 283 | /** 284 | * Handles the timer event for updating the game state. 285 | * 286 | * @param e ActionEvent triggered by the timer 287 | */ 288 | @Override 289 | public void actionPerformed(ActionEvent e) { 290 | if (inGame) { 291 | checkApple(); // Check for apple consumption 292 | checkCollision(); // Check for collisions 293 | move(); // Move the snake 294 | } 295 | 296 | repaint(); // Refresh the display 297 | } 298 | 299 | /** 300 | * KeyAdapter for handling user input for snake movement. 301 | */ 302 | private class TAdapter extends KeyAdapter { 303 | @Override 304 | public void keyPressed(KeyEvent e) { 305 | int key = e.getKeyCode(); // Get the key code 306 | 307 | // Change direction based on key press 308 | if ((key == KeyEvent.VK_LEFT) && (!rightDirection)) { 309 | leftDirection = true; 310 | upDirection = false; 311 | downDirection = false; 312 | } 313 | 314 | if ((key == KeyEvent.VK_RIGHT) && (!leftDirection)) { 315 | rightDirection = true; 316 | upDirection = false; 317 | downDirection = false; 318 | } 319 | 320 | if ((key == KeyEvent.VK_UP) && (!downDirection)) { 321 | upDirection = true; 322 | rightDirection = false; 323 | leftDirection = false; 324 | } 325 | 326 | if ((key == KeyEvent.VK_DOWN) && (!upDirection)) { 327 | downDirection = true; 328 | rightDirection = false; 329 | leftDirection = false; 330 | } 331 | } 332 | } 333 | } -------------------------------------------------------------------------------- /src/main/java/com/github/karabosithole/Question.java: -------------------------------------------------------------------------------- 1 | package com.github.karabosithole; 2 | 3 | public class Question { 4 | private String questionText; 5 | private String[] choices; 6 | private int correctAnswerIndex; 7 | 8 | public Question(String questionText, String[] choices, int correctAnswerIndex) { 9 | this.questionText = questionText; 10 | this.choices = choices; 11 | this.correctAnswerIndex = correctAnswerIndex; 12 | } 13 | 14 | public String getQuestionText() { 15 | return questionText; 16 | } 17 | 18 | public String[] getChoices() { 19 | return choices; 20 | } 21 | 22 | public int getCorrectAnswerIndex() { 23 | return correctAnswerIndex; 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/main/java/com/github/karabosithole/QuestionManager.java: -------------------------------------------------------------------------------- 1 | package com.github.karabosithole; 2 | 3 | import javax.swing.*; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | public class QuestionManager { 8 | private List questions; // List of Question objects 9 | 10 | public QuestionManager() { 11 | initQuestions(); 12 | } 13 | 14 | // Initialize questions with multiple choices 15 | public void initQuestions() { 16 | questions = new ArrayList<>(); 17 | 18 | // Add a question with its choices and the correct answer 19 | questions.add(new Question("What does JVM stand for?", 20 | new String[] {"A) Java Virtual Machine", "B) Java Visual Model", "C) Java Version Manager", "D) Java Variable Model"}, 21 | 0)); // Correct answer is index 0 ("Java Virtual Machine") 22 | 23 | questions.add(new Question("What is the difference between JDK and JRE?", 24 | new String[] {"A) JDK is for development; JRE is for running Java", "B) JDK is faster than JRE", "C) JRE is the latest version of JDK", "D) JDK is for UI, JRE for back-end"}, 25 | 0)); 26 | 27 | questions.add(new Question("What is a constructor in Java?", 28 | new String[] {"A) A method to create objects", "B) A special method to initialize objects", "C) A class that builds other classes", "D) A template for creating objects"}, 29 | 1)); 30 | 31 | questions.add(new Question("What is polymorphism?", 32 | new String[] {"A) Ability to take many forms", "B) A type of inheritance", "C) Java method overloading", "D) The ability to create abstract methods"}, 33 | 0)); 34 | 35 | questions.add(new Question("What is an interface?", 36 | new String[] {"A) A class that extends another class", "B) A blueprint for classes", "C) A method signature", "D) A way to inherit multiple classes"}, 37 | 1)); 38 | } 39 | 40 | // Retrieve a random question 41 | public Question getRandomQuestion() { 42 | int randomIndex = (int) (Math.random() * questions.size()); 43 | return questions.get(randomIndex); 44 | } 45 | 46 | // Display the question and handle the user's answer 47 | public void displayQuestion() { 48 | Question question = getRandomQuestion(); 49 | 50 | // Show the question with multiple choices 51 | String selectedAnswer = (String) JOptionPane.showInputDialog( 52 | null, 53 | question.getQuestionText(), 54 | "Multiple Choice Question", 55 | JOptionPane.QUESTION_MESSAGE, 56 | null, 57 | question.getChoices(), // The array of choices (A, B, C, D) 58 | question.getChoices()[0]); // Default selection (optional) 59 | 60 | // Check if the selected answer is correct 61 | int selectedIndex = java.util.Arrays.asList(question.getChoices()).indexOf(selectedAnswer); 62 | if (selectedIndex == question.getCorrectAnswerIndex()) { 63 | JOptionPane.showMessageDialog(null, "Correct!", "Answer", JOptionPane.INFORMATION_MESSAGE); 64 | } else { 65 | JOptionPane.showMessageDialog(null, "Wrong answer. The correct answer is: " + question.getChoices()[question.getCorrectAnswerIndex()], "Answer", JOptionPane.ERROR_MESSAGE); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/github/karabosithole/Snake.java: -------------------------------------------------------------------------------- 1 | package com.github.karabosithole; 2 | 3 | import java.awt.EventQueue; 4 | import javax.swing.JFrame; 5 | 6 | 7 | /** 8 | * The Snake class represents the main window for the Snake game. 9 | * It extends JFrame to create the game UI and manage the game board. 10 | */ 11 | public class Snake extends JFrame { 12 | 13 | /** 14 | * Constructor to initialize the Snake game UI. 15 | */ 16 | 17 | public Snake() { 18 | initUI(); // Initialize the user interface 19 | } 20 | 21 | /** 22 | * Initializes the user interface components for the game. 23 | */ 24 | private void initUI() { 25 | add(new Board()); // Add the game board to the frame 26 | 27 | setResizable(false); // Disable resizing of the window 28 | pack(); // Pack the components within the frame 29 | 30 | setTitle("Snake"); // Set the title of the window 31 | setLocationRelativeTo(null); // Center the window on the screen 32 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Exit the application on close 33 | } 34 | 35 | /** 36 | * The main method to launch the Snake game application. 37 | * 38 | * @param args Command line arguments 39 | */ 40 | public static void main(String[] args) { 41 | // Use EventQueue to ensure that the UI is created on the Event Dispatch Thread 42 | EventQueue.invokeLater(() -> { 43 | JFrame ex = new Snake(); // Create an instance of Snake 44 | ex.setVisible(true); // Make the frame visible 45 | }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/resources/apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karabosithole/LearnJavaSnakeGame/4cfab7f05c48c0abddeefe36259d49f87de24766/src/main/java/resources/apple.png -------------------------------------------------------------------------------- /src/main/java/resources/dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karabosithole/LearnJavaSnakeGame/4cfab7f05c48c0abddeefe36259d49f87de24766/src/main/java/resources/dot.png -------------------------------------------------------------------------------- /src/main/java/resources/head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karabosithole/LearnJavaSnakeGame/4cfab7f05c48c0abddeefe36259d49f87de24766/src/main/java/resources/head.png -------------------------------------------------------------------------------- /src/main/java/resources/questions.txt: -------------------------------------------------------------------------------- 1 | questions: 2 | - id: "start" 3 | text: "What is the keyword to define a class in Java?" 4 | answer: "class" 5 | 6 | - id: "left" 7 | text: "Which method is the entry point of a Java application?" 8 | answer: "main" 9 | 10 | - id: "right" 11 | text: "Which Java keyword is used to create an object?" 12 | answer: "new" 13 | 14 | - id: "swim" 15 | text: "What does 'JVM' stand for?" 16 | answer: "Java Virtual Machine" 17 | 18 | - id: "walk" 19 | text: "What is the parent class of all classes in Java?" 20 | answer: "Object" 21 | 22 | - id: "climb" 23 | text: "What keyword is used to inherit a class in Java?" 24 | answer: "extends" 25 | 26 | - id: "around" 27 | text: "What is the interface keyword used for?" 28 | answer: "interface" 29 | 30 | - id: "left2" 31 | text: "What is polymorphism?" 32 | answer: "The ability of an object to take on many forms" 33 | 34 | - id: "right2" 35 | text: "What is encapsulation?" 36 | answer: "The wrapping of data and methods into a single unit" 37 | 38 | - id: "swim2" 39 | text: "What is inheritance?" 40 | answer: "The mechanism where one class acquires the properties and behaviors of a parent class" 41 | 42 | - id: "walk2" 43 | text: "What is abstraction?" 44 | answer: "The concept of hiding the complex implementation details and showing only the necessary features" 45 | 46 | - id: "climb2" 47 | text: "What is a constructor?" 48 | answer: "A special method used to initialize objects" 49 | 50 | - id: "around2" 51 | text: "What is method overloading?" 52 | answer: "Having multiple methods in the same class with the same name but different parameters" 53 | -------------------------------------------------------------------------------- /target/classes/com/github/karabosithole/Board$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karabosithole/LearnJavaSnakeGame/4cfab7f05c48c0abddeefe36259d49f87de24766/target/classes/com/github/karabosithole/Board$1.class -------------------------------------------------------------------------------- /target/classes/com/github/karabosithole/Board$TAdapter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karabosithole/LearnJavaSnakeGame/4cfab7f05c48c0abddeefe36259d49f87de24766/target/classes/com/github/karabosithole/Board$TAdapter.class -------------------------------------------------------------------------------- /target/classes/com/github/karabosithole/Board.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karabosithole/LearnJavaSnakeGame/4cfab7f05c48c0abddeefe36259d49f87de24766/target/classes/com/github/karabosithole/Board.class -------------------------------------------------------------------------------- /target/classes/com/github/karabosithole/Question.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karabosithole/LearnJavaSnakeGame/4cfab7f05c48c0abddeefe36259d49f87de24766/target/classes/com/github/karabosithole/Question.class -------------------------------------------------------------------------------- /target/classes/com/github/karabosithole/QuestionManager.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karabosithole/LearnJavaSnakeGame/4cfab7f05c48c0abddeefe36259d49f87de24766/target/classes/com/github/karabosithole/QuestionManager.class -------------------------------------------------------------------------------- /target/classes/com/github/karabosithole/Snake.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karabosithole/LearnJavaSnakeGame/4cfab7f05c48c0abddeefe36259d49f87de24766/target/classes/com/github/karabosithole/Snake.class --------------------------------------------------------------------------------