Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.{java,xml,yml,yaml,md}]
indent_style = space
indent_size = 4

[*.md]
trim_trailing_whitespace = false
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: maven
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 10

- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: CI

on:
push:
branches: [master]
pull_request:
branches: [master]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: "21"
distribution: temurin
cache: maven

- name: Format check (Spotless)
run: mvn -B spotless:check

- name: Compile
run: mvn -B -DskipTests compile

- name: Test
run: mvn -B test
21 changes: 15 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
# Ignore the .idea folder
# IDE
.idea/
*.iml
.vscode/
*.swp
*~

# Ignore the out folder
# Build
target/
out/
build/
bin/
obj/

# IML files
*.iml
# OS
.DS_Store
Thumbs.db

# yml files
*.yml
# Logs
*.log
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Joel Shearon

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
89 changes: 72 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,73 @@
# randobotjava
A (now less) buggy JavaFx robot game I made to play with JavaFx concepts

Options include:
Setting the grid size for the game
Autoplay for when you are lazy
Manual play either with direction keys or have the game decide a move for you
Ability to exit or restart the game


# Future features
* Making it an actual game where the treasure is hidden and you have to find it like a pirate or whatever (Robot Pirates are
a thing, right? Right?)
* Gonna make this bot real smart so it can find the treasure quicker and in a future release it will probably steal your
girl
* A scoreboard for when you want to feel proud about things that don't matter (I know I do since I am making this project and
feeling good about it, right? Raight? Guise?)
* Online multiplayer so you can race your friends at pressing buttons quickly so its basically Rocket League at that point. Lit.

[![CI](https://github.com/hippi345/randobotjava/actions/workflows/ci.yml/badge.svg)](https://github.com/hippi345/randobotjava/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

A JavaFX desktop game where a robot hunts for treasure on a grid. You can play manually, step move-by-move, or let autoplay run until the bot finds the loot.

## Features

- Configurable grid size (1–15, default 5)
- Manual play: direction buttons or “Next move” (bot chooses intelligently)
- Autoplay until the treasure is found
- Reset and return to the main menu

## Requirements

- **JDK 21** (LTS)
- **Maven 3.9+** (for builds)
- A display for the JavaFX UI (desktop environment)

No API keys, environment variables, or network access are required.

## Setup

```bash
git clone https://github.com/hippi345/randobotjava.git
cd randobotjava
mvn -B package
```

## Run

```bash
mvn javafx:run
```

Or after packaging:

```bash
mvn -B package
java --module-path "$HOME/.m2/repository/org/openjfx/javafx-controls/21.0.6/javafx-controls-21.0.6.jar:$(dirname $(find ~/.m2/repository/org/openjfx -name 'javafx-graphics*.jar' | head -1))" --add-modules javafx.controls,javafx.graphics -cp target/randobotjava-1.0.0-SNAPSHOT.jar sample.Main
```

Using the Maven JavaFX plugin (`mvn javafx:run`) is the simplest option.

## Tests and linting

```bash
# Unit tests (offline, no credentials)
mvn test

# Google Java Format via Spotless
mvn spotless:check
mvn spotless:apply # auto-format
```

## Project structure

```
├── pom.xml # Maven build (Java 21, JavaFX, JUnit 5)
├── src/main/java/sample/
│ ├── Main.java # JavaFX application entry
│ ├── Game.java # Game rules and turns
│ ├── View.java # UI and grid rendering
│ ├── Constants.java # Grid defaults
│ ├── interfaces/ # Game and point contracts
│ └── models/ # Bot, treasure, grid types
└── src/test/java/ # JUnit 5 tests
```

## License

MIT License — see [LICENSE](LICENSE) (Copyright © 2026 Joel Shearon).
15 changes: 15 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Security Policy

## Supported versions

Security fixes are applied on the `master` branch. Use the latest release from that branch.

## Reporting a vulnerability

If you discover a security issue, please open a [private security advisory](https://github.com/hippi345/randobotjava/security/advisories/new) on GitHub or contact the repository owner. Do not open a public issue for sensitive reports.

We will acknowledge reports as quickly as possible and work on a fix or mitigation.

## Secrets and credentials

This project is a local desktop game and does not require API keys or cloud credentials. Do not commit secrets to the repository.
73 changes: 73 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.hippi345</groupId>
<artifactId>randobotjava</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>randobotjava</name>
<description>JavaFX treasure-hunt robot game</description>
<url>https://github.com/hippi345/randobotjava</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
<javafx.version>21.0.6</javafx.version>
<junit.version>5.11.4</junit.version>
</properties>

<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.2</version>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<configuration>
<mainClass>sample.Main</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>2.43.0</version>
<configuration>
<java>
<googleJavaFormat>
<version>1.23.0</version>
<style>AOSP</style>
</googleJavaFormat>
<removeUnusedImports/>
<trimTrailingWhitespace/>
<endWithNewline/>
</java>
</configuration>
</plugin>
</plugins>
</build>
</project>
3 changes: 0 additions & 3 deletions src/META-INF/MANIFEST.MF

This file was deleted.

9 changes: 9 additions & 0 deletions src/main/java/sample/Constants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package sample;

final class Constants {
static final int DEFAULT_GRID_SIZE = 5;
static final int MAX_GRID_SIZE = 15;
static final String LIGHT_BLUE = "-fx-background-color:#00BFFF; -fx-opacity:1;";

private Constants() {}
}
97 changes: 97 additions & 0 deletions src/main/java/sample/Game.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package sample;

import sample.interfaces.IGame;
import sample.interfaces.IMoveablePoint;
import sample.interfaces.IPoint;
import sample.models.Bot;
import sample.models.GameStatusEnum;
import sample.models.MoveEnum;
import sample.models.Point;
import sample.models.Treasure;

class Game implements IGame {
private int turnCount = 0;
private GameStatusEnum status;
private final int gridSize;
private final GameBoardListener boardListener;
IMoveablePoint bot;
Treasure treasure;

Game(int gridSize, GameBoardListener boardListener) {
this.gridSize = gridSize;
this.boardListener = boardListener;
status = GameStatusEnum.NotStarted;
this.bot = new Bot(gridSize);
this.treasure = new Treasure();
initializePositions();
}

@Override
public void makeMove() {
makeMove(this.bot.determineMovement());
}

@Override
public void makeMove(MoveEnum move) {
executeTurn(move);
}

@Override
public GameStatusEnum getStatus() {
return status;
}

@Override
public IPoint getBot() {
return bot;
}

@Override
public IPoint getTreasure() {
return treasure;
}

int getGridSize() {
return gridSize;
}

void initializePositions() {
this.treasure.randomizeLocation(gridSize);
this.bot.randomizeLocation(gridSize);
while (this.bot.equals(this.treasure)) {
this.bot.randomizeLocation(gridSize);
}
boardListener.onPositionsChanged(null, this.bot, this.treasure);
}

private void executeTurn(MoveEnum botMovementDirection) {
if (status == GameStatusEnum.Complete) {
return;
} else if (status == GameStatusEnum.NotStarted) {
status = GameStatusEnum.InProgress;
}

++turnCount;
System.out.println("Current turn: " + turnCount);

IPoint previousBotPoint = new Point(this.bot);
this.bot.move(botMovementDirection);

determineCurrentStatus();
boardListener.onPositionsChanged(previousBotPoint, this.bot, this.treasure);
if (status == GameStatusEnum.Complete) {
System.out.println("You found the treasure!");
boardListener.onGameComplete();
}
}

private boolean treasureIsFound() {
return this.bot.equals(this.treasure);
}

private void determineCurrentStatus() {
if (treasureIsFound()) {
status = GameStatusEnum.Complete;
}
}
}
Loading
Loading