A Monopoly-style business simulation game built in Java, featuring real-time stock price fluctuations, property trading across 26 world cities, and multi-player account management β all played through an interactive console.
- Features
- Project Structure
- Architecture Overview
- Getting Started
- How to Play
- Class Reference
- Known Bugs Fixed
- Future Improvements
| Feature | Description |
|---|---|
| Multi-player accounts | Up to 100 player accounts with PIN authentication |
| Live stock market | Background thread fluctuates the share price Β±$10 every 10 seconds |
| ASCII stock chart | Price history visualised in the terminal |
| Property trading | Buy/sell city properties across 26 world cities |
| Round inflation | Type 11 to end a round and apply 5 % price inflation to all properties |
| Fund transfers | Securely move money between accounts |
| Save to file | Persist account balances to accounts.txt |
BusinessGame/
βββ pom.xml β Maven build file
βββ README.md
βββ src/
βββ main/
βββ java/
βββ com/businessgame/
βββ Main.java β Entry point & dependency wiring
β
βββ model/ β Pure domain objects (no I/O)
β βββ Account.java β Player account: balance, shares, properties
β βββ Property.java β City/country: name, price, index
β
βββ service/ β Business logic layer
β βββ AccountRegistry.java β In-memory account store
β βββ PropertyMarket.java β Property catalogue & round inflation
β βββ StockMarket.java β Thread-safe share price + fluctuator
β βββ StockChart.java β ASCII chart renderer
β βββ SaveService.java β Persist accounts to file
β
βββ ui/ β Console I/O handlers
β βββ GameMenu.java β Main game loop & top-level menu
β βββ AccountUI.java β Account commands (create, balance, β¦)
β βββ PropertyUI.java β Property sub-menu
β βββ MarketUI.java β Stock market sub-menu
β
βββ util/
βββ InputHelper.java β Safe Scanner wrapper with retry logic
βββββββββββββββββββββββββββββββββββββββββββββββ
β Main.java β
β Wires services β GameMenu β runs game loop β
βββββββββββββββββββββ¬ββββββββββββββββββββββββββ
β
βββββββββββββΌββββββββββββ
β GameMenu β
β (top-level commands) β
ββββ¬βββββββ¬βββββββ¬βββββββ
β β β
AccountUI PropertyUI MarketUI
β β β
ββββββββ΄βββ¬ββββ
β delegates to
ββββββββββββΌβββββββββββ
β Services β
β AccountRegistry β
β PropertyMarket β
β StockMarket β
β SaveService β
ββββββββββββ¬βββββββββββ
β owns
ββββββββββββΌβββββββββββ
β Models β
β Account β
β Property β
βββββββββββββββββββββββ
All I/O is confined to the ui package. Services and models have zero System.out dependencies β they throw typed exceptions that the UI layer catches and presents as friendly messages.
- Java 17 or later
- Maven 3.8+ (or use the included wrapper if present)
mvn clean packageThis produces a runnable fat-jar at target/business-game-1.0.0.jar.
java -jar target/business-game-1.0.0.jarOr run directly from source:
mvn exec:java -Dexec.mainClass=com.businessgame.MainOn launch you will see the main menu. Type the number for the action you want and press Enter.
ββββββββββββββββββββββββββββββββββββββββ
β BUSINESS GAME v1.0 β
β βββββββββββββββββββββββββββββββββββββββ£
β 0 Check balance β
β 1 Add balance β
β 2 Withdraw funds β
β 3 Property dealing β
β 4 Transfer funds β
β 5 Stock market β
β 7 Save game to file β
β 9 New account β
β 11 End of round β
β 99 Quit β
ββββββββββββββββββββββββββββββββββββββββ
- Create accounts β each player types
9to register with a unique account number and PIN. - Add starting money β the banker types
1and deposits the agreed starting amount (a 10 % bonus is added automatically). - Take turns β players buy/sell properties (
3) and trade on the stock market (5). - End each round β type
11to advance the round; all property prices rise by 5 %. - Save progress β type
7to write balances toaccounts.txt. - Quit β type
99when the game ends.
| Code | City | Start Price |
|---|---|---|
| new | New York | $8,500 |
| rom | Rome | $3,000 |
| hon | Hong Kong | $2,500 |
| syd | Sydney | $4,500 |
| dub | Dubai | $5,000 |
| kua | Kuala Lumpur | $3,500 |
| deh | Delhi | $4,500 |
| ber | Berlin | $5,000 |
| rai | Riyadh | $9,500 |
| zur | Zurich | $5,500 |
| tok | Tokyo | $3,500 |
| lon | London | $4,500 |
| air | (top city) | $10,500 |
| mos | Moscow | $5,000 |
| β¦ | β¦ | β¦ |
Encapsulates all per-player state: balance, share count, property holdings, and PIN. Throws IllegalArgumentException / IllegalStateException on invalid operations β callers never check raw array bounds.
Immutable city descriptor with a mutable price. applyRoundInflation() applies the 5 % round increase.
HashMap-backed store replacing the original parallel arrays. Provides find(accountNumber) and authenticate(accountNumber, password) returning Optional<Account>.
Holds the catalogue of 26 Property objects. findByName() is case-insensitive. applyRoundInflation() delegates to each property.
Maintains an AtomicInteger share price, safe for concurrent access. Starts a daemon thread that fluctuates the price Β±$10 every 10 seconds and prints an updated chart.
Static utility β renders an ASCII bar chart of a price-history array. Separated from StockMarket so it can be tested independently.
Writes all account balances to accounts.txt using a BufferedWriter inside a proper try-with-resources block.
Main loop. Maps integer commands to handler calls. All sub-menus loop internally and return control here when the user exits.
Thin console-interaction layers. Each reads input via InputHelper, calls service/model methods, and prints results or exception messages.
Wraps Scanner. readInt(), readLong(), and readWord() retry indefinitely on bad input instead of crashing with InputMismatchException.
| # | Original issue | Fix |
|---|---|---|
| 1 | Data race on static int stockprice mutated from two threads |
Replaced with AtomicInteger in StockMarket |
| 2 | InputMismatchException crash on non-integer input |
InputHelper retries with a clear error message |
| 3 | Fernflower decompiler garbage (var0, var10000, nested Throwable catch) in saveToFile |
Rewritten with proper try-with-resources |
| 4 | static int o counter in main() breaks if account creation fails (counter still incremented) |
AccountRegistry uses a HashMap; no index needed |
| 5 | checkPrice() had a pointless try/catch(Exception) around System.out.println |
Removed |
| 6 | propertyDealing() used while(as == 0) flag instead of a boolean |
Replaced with clean boolean active loop |
| 7 | No validation β negative amounts, zero-division, array out-of-bounds all possible | Every model method validates input and throws typed exceptions |
| 8 | Stock price could go to 0 or negative with repeated bad ticks | Math.max(MIN_PRICE, ...) guard in fluctuator |
| 9 | createAccount used a separate o index that was never bounds-checked |
Registry enforces MAX_ACCOUNTS with a clear error |
| 10 | No way to exit the game cleanly | Added command 99 and a JVM shutdown hook |
- Persistence β load
accounts.txton startup to resume a saved game - Password hashing β use BCrypt instead of storing plain-text PINs
- GUI β Swing or JavaFX board view
- Network play β expose services over sockets or REST for remote players
- Unit tests β JUnit 5 tests for model layer (no I/O required)
- Event system β Chance/Community Chest cards that trigger random events