Online-TicTacToe

Log | Files | Refs | README | LICENSE

commit c0b1dcc45a9ad28297172fdacac8b0a8035de713
parent c8cf3c064984f3cfcf378082f0332c4c41019778
Author: lukeeeeeee334 <lukeosullivan123@gmail.com>
Date:   Tue, 19 Nov 2024 10:57:43 +0000

score.java, allscore.java and mainpanel.java

added some functionality to the main panel board, got the personal score and the leader board working.

Diffstat:
MTicTacToeClient/src/main/java/com/groupproject/tictactoeclient/ContentPanes/MainContentPanel.java | 202++++++++++++++++++++++++++++++++++++-------------------------------------------
ATicTacToeClient/src/main/java/com/groupproject/tictactoeclient/ContentPanes/allscore.java | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MTicTacToeClient/src/main/java/com/groupproject/tictactoeclient/ContentPanes/score.java | 57++++++++++++++++++++++++++++++++-------------------------
3 files changed, 245 insertions(+), 136 deletions(-)

diff --git a/TicTacToeClient/src/main/java/com/groupproject/tictactoeclient/ContentPanes/MainContentPanel.java b/TicTacToeClient/src/main/java/com/groupproject/tictactoeclient/ContentPanes/MainContentPanel.java @@ -1,64 +1,47 @@ -/* - * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license - * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template - */ package com.groupproject.tictactoeclient.ContentPanes; import com.groupproject.tictactoeclient.TicTacToeClient; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.SpringLayout; -import javax.swing.Timer; +import javax.swing.*; /** - * - * @author William and Adam - * Contains the content visible in the main program. + * MainContentPanel contains the content visible in the main program. */ - - public class MainContentPanel extends CustomPanel { - - + TicTacToeClient client; JList<String> openGamesList; - + private JLabel gameTimerLabel; private Timer timer; private int remainingTime; - public MainContentPanel(TicTacToeClient client) { - this.client = client; - - // Set panel layout to spring layout + + // Set panel layout to SpringLayout SpringLayout layout = new SpringLayout(); setLayout(layout); - + // Create panel components JButton createGameButton = new JButton("New Game"); - JButton scoreBoardButton = new JButton("Scoreboard"); + JButton allscoreButton = new JButton("Scoreboard"); JButton joinGameButton = new JButton("Join Game"); openGamesList = new JList<>(); JScrollPane openGamesScrollPane = new JScrollPane(openGamesList); - TicTacToeGrid grid = new TicTacToeGrid(); + TicTacToeGrid grid = new TicTacToeGrid(3, 3); // A 3x3 TicTacToe grid JLabel gameStatusLabel = new JLabel(); gameTimerLabel = new JLabel(); JButton scoreButton = new JButton("View Personal Score"); - - // set mock data for labels: - gameStatusLabel.setText("Opponents turn"); + + // Set mock data for labels + gameStatusLabel.setText("Opponent's turn"); gameTimerLabel.setText("15m 0s"); - // Add buttons to panel - add(scoreBoardButton); + add(allscoreButton); add(createGameButton); add(openGamesScrollPane); add(joinGameButton); @@ -66,71 +49,57 @@ public class MainContentPanel extends CustomPanel { add(gameStatusLabel); add(gameTimerLabel); add(scoreButton); - - // Add sprint layout constraints - // create game button constraints + + // SpringLayout constraints layout.putConstraint(SpringLayout.WEST, createGameButton, 20, SpringLayout.WEST, this); layout.putConstraint(SpringLayout.NORTH, createGameButton, 10, SpringLayout.NORTH, this); - - // scoreboard button constraints - layout.putConstraint(SpringLayout.WEST, scoreBoardButton, 20, SpringLayout.EAST, createGameButton); - layout.putConstraint(SpringLayout.NORTH, scoreBoardButton, 0, SpringLayout.NORTH, createGameButton); - - // Games list constraints + + layout.putConstraint(SpringLayout.WEST, allscoreButton, 20, SpringLayout.EAST, createGameButton); + layout.putConstraint(SpringLayout.NORTH, allscoreButton, 0, SpringLayout.NORTH, createGameButton); + layout.putConstraint(SpringLayout.WEST, openGamesScrollPane, 0, SpringLayout.WEST, createGameButton); - layout.putConstraint(SpringLayout.EAST, openGamesScrollPane, 0, SpringLayout.EAST, scoreBoardButton); + layout.putConstraint(SpringLayout.EAST, openGamesScrollPane, 0, SpringLayout.EAST, allscoreButton); layout.putConstraint(SpringLayout.NORTH, openGamesScrollPane, 10, SpringLayout.SOUTH, createGameButton); layout.putConstraint(SpringLayout.SOUTH, openGamesScrollPane, -10, SpringLayout.NORTH, joinGameButton); - - // join button constraints + layout.putConstraint(SpringLayout.WEST, joinGameButton, 20, SpringLayout.WEST, this); layout.putConstraint(SpringLayout.SOUTH, joinGameButton, -20, SpringLayout.SOUTH, this); - layout.putConstraint(SpringLayout.EAST, joinGameButton, 0, SpringLayout.EAST, scoreBoardButton); - - // Add label constraints + layout.putConstraint(SpringLayout.EAST, joinGameButton, 0, SpringLayout.EAST, allscoreButton); + layout.putConstraint(SpringLayout.WEST, gameStatusLabel, 0, SpringLayout.WEST, grid); layout.putConstraint(SpringLayout.NORTH, gameStatusLabel, -20, SpringLayout.NORTH, grid); layout.putConstraint(SpringLayout.EAST, gameTimerLabel, 0, SpringLayout.EAST, grid); layout.putConstraint(SpringLayout.NORTH, gameTimerLabel, -20, SpringLayout.NORTH, grid); - - // grid constraints - layout.putConstraint(SpringLayout.WEST, grid, 40, SpringLayout.EAST, scoreBoardButton); + + layout.putConstraint(SpringLayout.WEST, grid, 40, SpringLayout.EAST, allscoreButton); layout.putConstraint(SpringLayout.NORTH, grid, 40, SpringLayout.NORTH, this); layout.putConstraint(SpringLayout.SOUTH, grid, 240, SpringLayout.NORTH, this); layout.putConstraint(SpringLayout.EAST, grid, -20, SpringLayout.EAST, this); - - // View score button constraints + layout.putConstraint(SpringLayout.SOUTH, scoreButton, -20, SpringLayout.SOUTH, this); layout.putConstraint(SpringLayout.EAST, scoreButton, -20, SpringLayout.EAST, this); - - - //Create game button action listener - createGameButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - client.proxy.newGame(Integer.parseInt(client.UID)); - - //start countdown when create game - startTimer(); - } + + // Button action listeners + createGameButton.addActionListener(e -> { + client.proxy.newGame(Integer.parseInt(client.UID)); + startTimer(); }); - - - scoreButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - client.showPanel(new score(client)); - - //start countdown when create game - startTimer(); - } + + joinGameButton.addActionListener(e -> { + //client.proxy.joinGame(Integer.parseInt(client.UID), Integer.parseInt(client.GID)); + //startTimer(); + }); + + scoreButton.addActionListener(e -> { + client.showPanel(new score(client)); + startTimer(); + }); + + allscoreButton.addActionListener(e -> { + client.showPanel(new allscore(client)); + startTimer(); }); } - - - - - @Override public void refresh() { @@ -141,40 +110,52 @@ public class MainContentPanel extends CustomPanel { this.revalidate(); this.repaint(); } - - - private void startTimer() - { - //remaining time is 15 minutes + + private void startTimer() { + // Remaining time is 15 minutes remainingTime = 15 * 60; - - //create timer that updates every 1 seconds i.e countdown clock - timer = new Timer(1000, new ActionListener(){ - @Override - public void actionPerformed(ActionEvent e) { - - //countdown time - remainingTime--; - - int minutes = remainingTime / 60; - int seconds = remainingTime % 60; - - String time = String.format("%02d:%02d", minutes, seconds); - - gameTimerLabel.setText(time); - - //need to implement when no one else joins the game - //and the countdown is finished that the game is then deleted - //at the moment it just prints game finished - if(remainingTime <= 0) { - timer.stop(); - gameTimerLabel.setText("Finished"); - } + + // Create a timer that updates every second + timer = new Timer(1000, e -> { + // Countdown time + remainingTime--; + + int minutes = remainingTime / 60; + int seconds = remainingTime % 60; + + String time = String.format("%02d:%02d", minutes, seconds); + + gameTimerLabel.setText(time); + + if (remainingTime <= 0) { + timer.stop(); + gameTimerLabel.setText("Finished"); } }); - timer.start(); + timer.start(); + } + + /** + * A custom class for the TicTacToe grid. + */ + class TicTacToeGrid extends JPanel { + public TicTacToeGrid(int rows, int cols) { + setLayout(new GridLayout(rows, cols, 5, 5)); // Grid with 5px gaps + + for (int i = 0; i < rows * cols; i++) { + JButton button = new JButton(); + button.setFont(new Font("Arial", Font.BOLD, 32)); // Large text for "X" + add(button); + + // Add ActionListener for button clicks + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + button.setText("X"); + button.setEnabled(false); // Disable the button after it's clicked + } + }); + } + } } - - - -} -\ No newline at end of file +} diff --git a/TicTacToeClient/src/main/java/com/groupproject/tictactoeclient/ContentPanes/allscore.java b/TicTacToeClient/src/main/java/com/groupproject/tictactoeclient/ContentPanes/allscore.java @@ -0,0 +1,122 @@ +package com.groupproject.tictactoeclient.ContentPanes; + +import com.groupproject.tictactoeclient.TicTacToeClient; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.HashMap; +import java.util.Map; + +/** + * Class to display the scores of all users. + */ +public class allscore extends CustomPanel { + public allscore(TicTacToeClient client) { + // Set SpringLayout + SpringLayout layout = new SpringLayout(); + setLayout(layout); + + // Text Area for displaying scores + JTextArea statsArea = new JTextArea(); + statsArea.setEditable(false); + statsArea.setFont(new Font("Monospaced", Font.PLAIN, 14)); + + // Add Text Area inside a Scroll Pane + JScrollPane scrollPane = new JScrollPane(statsArea); + add(scrollPane); + + // Back Button + JButton backButton = new JButton("Back"); + add(backButton); + + // Set constraints for Scroll Pane + layout.putConstraint(SpringLayout.NORTH, scrollPane, 10, SpringLayout.NORTH, this); + layout.putConstraint(SpringLayout.WEST, scrollPane, 10, SpringLayout.WEST, this); + layout.putConstraint(SpringLayout.EAST, scrollPane, -10, SpringLayout.EAST, this); + layout.putConstraint(SpringLayout.SOUTH, scrollPane, -50, SpringLayout.SOUTH, this); + + // Set constraints for Back Button + layout.putConstraint(SpringLayout.SOUTH, backButton, -10, SpringLayout.SOUTH, this); // 10px above bottom + layout.putConstraint(SpringLayout.WEST, backButton, 10, SpringLayout.WEST, this); + + // Populate stats area + try { + String leagueData = client.proxy.leagueTable(); + if (leagueData.equals("ERROR-NOGAMES")) { + statsArea.setText("No games found."); + return; + } else if (leagueData.equals("ERROR-DB")) { + statsArea.setText("Database error occurred."); + return; + } + + // Split the result into rows + String[] games = leagueData.split("\n"); + Map<String, int[]> playerStats = new HashMap<>(); + + // Parse each game's data + for (String game : games) { + try { + String[] columns = game.split(","); // Assuming data is comma-separated + if (columns.length < 4) { + throw new IllegalArgumentException("Malformed row: " + game); + } + + String player1UID = columns[1].trim(); // Player 1 UID + String player2UID = columns[2].trim(); // Player 2 UID + String gameState = columns[3].trim(); // Game state as a string + + int gameStateInt = Integer.parseInt(gameState); + + // Update stats for Player 1 + playerStats.putIfAbsent(player1UID, new int[2]); + playerStats.putIfAbsent(player2UID, new int[2]); + + if (gameStateInt == 1) { // Player 1 wins + playerStats.get(player1UID)[0]++; // Increment wins for Player 1 + playerStats.get(player2UID)[1]++; // Increment losses for Player 2 + } else if (gameStateInt == 2) { // Player 2 wins + playerStats.get(player2UID)[0]++; // Increment wins for Player 2 + playerStats.get(player1UID)[1]++; // Increment losses for Player 1 + } + + } catch (Exception rowException) { + System.err.println("Error processing row: " + game); + rowException.printStackTrace(); + } + } + + // Build the display string + StringBuilder statsBuilder = new StringBuilder(); + statsBuilder.append(String.format("%-20s %-10s %-10s\n", "Username", "Wins", "Losses")); + statsBuilder.append("-".repeat(40)).append("\n"); + + for (Map.Entry<String, int[]> entry : playerStats.entrySet()) { + String username = entry.getKey(); + int wins = entry.getValue()[0]; + int losses = entry.getValue()[1]; + statsBuilder.append(String.format("%-20s %-10d %-10d\n", username, wins, losses)); + } + + statsArea.setText(statsBuilder.toString()); + + } catch (Exception e) { + statsArea.setText("An error occurred while calculating player stats."); + e.printStackTrace(); + } + + // Back Button Listener + backButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + client.showPanel(new MainContentPanel(client)); + } + }); + } + + @Override + public void refresh() { + throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/TicTacToeClient/src/main/java/com/groupproject/tictactoeclient/ContentPanes/score.java b/TicTacToeClient/src/main/java/com/groupproject/tictactoeclient/ContentPanes/score.java @@ -3,26 +3,35 @@ package com.groupproject.tictactoeclient.ContentPanes; import com.groupproject.tictactoeclient.TicTacToeClient; import javax.swing.*; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; /** * Class to display the score panel with player stats. */ public class score extends CustomPanel { public score(TicTacToeClient client) { -//super(); // Call the parent constructor + SpringLayout layout = new SpringLayout(); + setLayout(layout); - // Get the logged-in UID from the client - String loggedInUID = client.UID; - String loggedInUsername = client.username; - System.out.println("Logged-in UID: " + loggedInUID); - - // Panel to display the stats - setLayout(new BorderLayout()); + // Label to display stats JLabel statsLabel = new JLabel(); statsLabel.setHorizontalAlignment(SwingConstants.CENTER); statsLabel.setFont(new Font("Arial", Font.BOLD, 16)); statsLabel.setForeground(Color.BLACK); - add(statsLabel, BorderLayout.CENTER); + add(statsLabel); + + // Back Button + JButton backButton = new JButton("Back"); + add(backButton); + + // Position the statsLabel (centered horizontally, at the top) + layout.putConstraint(SpringLayout.HORIZONTAL_CENTER, statsLabel, 0, SpringLayout.HORIZONTAL_CENTER, this); + layout.putConstraint(SpringLayout.NORTH, statsLabel, 20, SpringLayout.NORTH, this); + + // Position the backButton (bottom-left corner) + layout.putConstraint(SpringLayout.SOUTH, backButton, -10, SpringLayout.SOUTH, this); + layout.putConstraint(SpringLayout.WEST, backButton, 10, SpringLayout.WEST, this); try { // Call the leagueTable method to get all games @@ -53,33 +62,24 @@ public class score extends CustomPanel { String player1UID = columns[1].trim(); // Player 1 UID String player2UID = columns[2].trim(); // Player 2 UID - String gameState = columns[3].trim(); // Game state as a string + String gameState = columns[3].trim(); // Game state as a string - // Convert game state to an integer int gameStateInt = Integer.parseInt(gameState); - // Determine results for the logged-in player - - // Logged-in player is Player 1 - - if (player1UID.equals(loggedInUsername)) { - // Logged-in player is Player 1 + if (player1UID.equals(client.username)) { if (gameStateInt == 1) { // Player 1 wins wins++; } else if (gameStateInt == 2) { // Player 2 wins losses++; } - } else if (player2UID.equals(loggedInUsername)) { - // Logged-in player is Player 2 + } else if (player2UID.equals(client.username)) { if (gameStateInt == 2) { // Player 2 wins wins++; } else if (gameStateInt == 1) { // Player 1 wins losses++; } } - - - + } catch (Exception rowException) { System.err.println("Error processing row: " + game); rowException.printStackTrace(); @@ -87,12 +87,19 @@ public class score extends CustomPanel { } // Display the result as a summary - statsLabel.setText(String.format("Player %s: Wins = %d, Losses = %d", loggedInUsername, wins, losses)); + statsLabel.setText(String.format("Player %s: Wins = %d, Losses = %d", client.username, wins, losses)); } catch (Exception e) { - // Catch any unexpected errors statsLabel.setText("An error occurred while calculating player stats."); - e.printStackTrace(); // Log the exception for debugging + e.printStackTrace(); } + + // Back Button Action + backButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + client.showPanel(new MainContentPanel(client)); + } + }); } @Override