complete lab09
This commit is contained in:
8 files changed
+628
No files matched your search
@@ -0,0 +1,107 @@
|
||||
package ca.bcit.comp2522.lab09;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Handles loading, tracking, and saving the player's best score.
|
||||
*
|
||||
* @author Nico Agostini
|
||||
* @author Braeden Sowinski
|
||||
* @author Trishaan Shetty
|
||||
* @author Calvin Arifianto
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public class HighScoreService
|
||||
{
|
||||
private static final String FILE_PATH = "./data/highscore.txt";
|
||||
private static final String PREFIX = "COUNTRY=";
|
||||
|
||||
private final BufferedWriter writer;
|
||||
private final int highScore;
|
||||
|
||||
/**
|
||||
* Creates a HighScoreService and loads the stored high score.
|
||||
*
|
||||
* @throws IOException if the high score file cannot be read or created.
|
||||
*/
|
||||
public HighScoreService()
|
||||
throws IOException
|
||||
{
|
||||
final File scoreFile;
|
||||
final BufferedReader reader;
|
||||
final String line;
|
||||
|
||||
scoreFile = new File(FILE_PATH);
|
||||
scoreFile.createNewFile();
|
||||
|
||||
reader = new BufferedReader(new FileReader(FILE_PATH));
|
||||
line = reader.readLine();
|
||||
|
||||
if (line == null)
|
||||
{
|
||||
this.highScore = Integer.MAX_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.highScore = Integer.parseInt(line.replaceAll(PREFIX, ""));
|
||||
}
|
||||
|
||||
reader.close();
|
||||
|
||||
this.writer = new BufferedWriter(new FileWriter(FILE_PATH));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current high score.
|
||||
*
|
||||
* @return the saved high score.
|
||||
*/
|
||||
public int getHighScore()
|
||||
{
|
||||
return this.highScore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the high score if the new score is better.
|
||||
*
|
||||
* @param newScore the new score to compare.
|
||||
*/
|
||||
public void updateCurrentScore(final int newScore)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (newScore < this.highScore)
|
||||
{
|
||||
this.writer.write(PREFIX + newScore);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.writer.write(PREFIX + this.highScore);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.printf("Failed to update high score: %s\n", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the high score file.
|
||||
*/
|
||||
public void saveHighScore()
|
||||
{
|
||||
try
|
||||
{
|
||||
writer.close();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
System.err.println("Error closing the writer: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package ca.bcit.comp2522.lab09;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* Creates and writes game logs for each play session.
|
||||
* Each guess and outcome is recorded with a timestamp.
|
||||
*
|
||||
* @author Nico Agostini
|
||||
* @author Braeden Sowinski
|
||||
* @author Trishaan Shetty
|
||||
* @author Calvin Arifianto
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public class LoggerService
|
||||
{
|
||||
private static final Path BASE_PATH = Paths.get("data", "logs");
|
||||
private static final String DATE_PATTERN = "YYYY-MM-dd_HH-mm-ss";
|
||||
|
||||
private final BufferedWriter writer;
|
||||
|
||||
/**
|
||||
* getDateTime returns a string of the
|
||||
* date and time for the logs
|
||||
* @return date time string formatted as the pattern
|
||||
*/
|
||||
private static String getDateTime()
|
||||
{
|
||||
final LocalDateTime now;
|
||||
final DateTimeFormatter formatter;
|
||||
|
||||
now = LocalDateTime.now();
|
||||
formatter = DateTimeFormatter.ofPattern(DATE_PATTERN);
|
||||
|
||||
return now.format(formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new log file for a game session.
|
||||
*
|
||||
* @param country the correct word used in the round.
|
||||
* @throws IOException if the log directory or file cannot be created.
|
||||
*/
|
||||
public LoggerService(final String country)
|
||||
throws IOException
|
||||
{
|
||||
Files.createDirectories(BASE_PATH);
|
||||
|
||||
final String logFilename = BASE_PATH + "/" + getDateTime() + "_" + country + ".txt";
|
||||
|
||||
this.writer = new BufferedWriter(new FileWriter(logFilename));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a log entry.
|
||||
*
|
||||
* @param guess the player's guess.
|
||||
* @param outcome the result of the guess.
|
||||
*/
|
||||
public void log(final String guess, final String outcome)
|
||||
{
|
||||
final StringBuilder log = new StringBuilder();
|
||||
|
||||
log.append(getDateTime());
|
||||
log.append(" Guess: ");
|
||||
log.append(guess);
|
||||
log.append(" Outcome: ");
|
||||
log.append(outcome);
|
||||
|
||||
try {
|
||||
this.writer.write(log.toString());
|
||||
this.writer.newLine();
|
||||
}
|
||||
catch (final IOException e)
|
||||
{
|
||||
System.err.printf("Failed to write to log: %s\n", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves and closes the log file.
|
||||
*/
|
||||
public void saveLog()
|
||||
{
|
||||
try
|
||||
{
|
||||
writer.close();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
System.err.println("Error closing the writer: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package ca.bcit.comp2522.lab09;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Scanner;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
/**
|
||||
* Game controller for Lucky Vault. Generates a random word and manages gameplay.
|
||||
* Tracks user guesses, logging, and high score updates.
|
||||
*
|
||||
* @author Nico Agostini
|
||||
* @author Braeden Sowinski
|
||||
* @author Trishaan Shetty
|
||||
* @author Calvin Arifianto
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public class LuckyVault
|
||||
{
|
||||
private static final int STARTING_VALUE = 0;
|
||||
private static final int INVALID_MATCH = -1;
|
||||
|
||||
private final String country;
|
||||
private final LoggerService logger;
|
||||
private final HighScoreService highScore;
|
||||
|
||||
/*
|
||||
* matchingChars checks how many characters match two
|
||||
* given strings
|
||||
* @param s1 string one to match
|
||||
* @param s2 string two to match
|
||||
* @return number of characters matching (same position)
|
||||
*/
|
||||
private static int matchingChars(
|
||||
final String s1,
|
||||
final String s2
|
||||
) {
|
||||
if (s1.length() != s2.length())
|
||||
{
|
||||
return INVALID_MATCH;
|
||||
}
|
||||
|
||||
int matched = STARTING_VALUE;
|
||||
|
||||
for (int i = 0; i < s1.length(); i++)
|
||||
{
|
||||
if (s1.charAt(i) == s2.charAt(i))
|
||||
{
|
||||
matched++;
|
||||
}
|
||||
}
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a LuckyVault game with a random word.
|
||||
*
|
||||
* @throws IOException if files are missing or unreadable.
|
||||
*/
|
||||
public LuckyVault()
|
||||
throws IOException, FileNotFoundException
|
||||
{
|
||||
final WordList countries = new WordList("./data/countries.txt");
|
||||
|
||||
this.country = countries.getRandomWord();
|
||||
this.logger = new LoggerService(this.country);
|
||||
this.highScore = new HighScoreService();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the game session.
|
||||
*/
|
||||
public void run()
|
||||
{
|
||||
final Scanner inputScanner = new Scanner(System.in);
|
||||
String input;
|
||||
int attempts = STARTING_VALUE;
|
||||
|
||||
System.out.println("Lucky Vault — COUNTRY MODE. Type QUIT to exit.");
|
||||
System.out.printf("Secret Word Length: %d\n", country.length());
|
||||
System.out.println("Current Best: " + (this.highScore.getHighScore() == Integer.MAX_VALUE ?
|
||||
"-" : this.highScore.getHighScore()));
|
||||
|
||||
while(true)
|
||||
{
|
||||
System.out.print("Your guess: ");
|
||||
input = inputScanner.nextLine();
|
||||
|
||||
if (input.isEmpty())
|
||||
{
|
||||
System.out.println("Empty guess. Try again.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(input.equalsIgnoreCase("QUIT"))
|
||||
{
|
||||
System.out.println("Bye!");
|
||||
break;
|
||||
}
|
||||
|
||||
attempts++;
|
||||
|
||||
if (input.length() != this.country.length())
|
||||
{
|
||||
System.out.printf("Wrong length (%d). Need %d\n", input.length(), this.country.length());
|
||||
this.logger.log(input, "wrong_length");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!input.equalsIgnoreCase(this.country))
|
||||
{
|
||||
final int matching = matchingChars(input, this.country);
|
||||
|
||||
System.out.printf("Not it. %d letter(s) correct (correct position).\n", matching);
|
||||
this.logger.log(input, "matches=" + matching);
|
||||
continue;
|
||||
}
|
||||
|
||||
System.out.printf("Correct in %d attempts! Word was: %s\n", attempts, this.country);
|
||||
|
||||
this.logger.log(input, "CORRECT_in=" + attempts);
|
||||
this.highScore.updateCurrentScore(attempts);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
inputScanner.close();
|
||||
this.logger.saveLog();
|
||||
this.highScore.saveHighScore();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package ca.bcit.comp2522.lab09;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Entry point for the Lucky Vault game.
|
||||
*
|
||||
* @author Nico Agostini
|
||||
* @author Braeden Sowinski
|
||||
* @author Trishaan Shetty
|
||||
* @author Calvin Arifianto
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public class Main
|
||||
{
|
||||
/**
|
||||
* Starts the Lucky Vault application.
|
||||
*
|
||||
* @param args command line arguments (unused).
|
||||
*/
|
||||
public static void main(final String[] args)
|
||||
{
|
||||
final LuckyVault vault;
|
||||
|
||||
try {
|
||||
vault = new LuckyVault();
|
||||
}
|
||||
catch (final IOException e)
|
||||
{
|
||||
System.err.printf("An error occurred during an IO operation: %s\n", e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
vault.run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package ca.bcit.comp2522.lab09;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Loads a list of words from a text file and provides random selection.
|
||||
* @author Nico Agostini
|
||||
* @author Braeden Sowinski
|
||||
* @author Trishaan Shetty
|
||||
* @author Calvin Arifianto
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public class WordList
|
||||
{
|
||||
private final List<String> wordList;
|
||||
|
||||
/**
|
||||
* Creates a word list by reading each line of the given file.
|
||||
*
|
||||
* @param filePath the file containing words.
|
||||
* @throws FileNotFoundException if the file cannot be opened.
|
||||
*/
|
||||
public WordList(final String filePath)
|
||||
throws FileNotFoundException
|
||||
{
|
||||
this.wordList = new ArrayList<>();
|
||||
|
||||
final Scanner fileScanner;
|
||||
final File file = new File(filePath);
|
||||
|
||||
fileScanner = new Scanner(file);
|
||||
|
||||
while (fileScanner.hasNextLine())
|
||||
{
|
||||
this.wordList.add(fileScanner.nextLine());
|
||||
}
|
||||
|
||||
fileScanner.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random word from the list.
|
||||
*
|
||||
* @return a randomly selected word.
|
||||
*/
|
||||
public String getRandomWord()
|
||||
{
|
||||
final Random rand = new Random();
|
||||
|
||||
return this.wordList.get(rand.nextInt(this.wordList.size()));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user