添加JMenubar以适用于基于服务器客户端的TicTacToe游戏

时间:2016-12-18 13:44:06

标签: java swing

我在网上观看了Tic Tac Toe游戏。游戏运作完美。我需要以这种方式提供 JMenuBar 来即兴创作

JMenuBar > 文件> && 退出

这是完整的代码:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;

public class TicTacToeNewExit implements Runnable, ActionListener{

private String ip = "localhost";
private int port = 22222;
private Scanner scanner = new Scanner(System.in);
private JFrame frame;
private Painter painter;
private Thread thread;
private int WIDTH = 506;
private int HEIGHT = 547;

private JMenuBar jMenuBar;
private JMenu menu;
private JMenuItem newMenuItem, exitMenuItem;

private Socket socket;
private ServerSocket serverSocket;
private DataOutputStream dos;
private DataInputStream dis;

private boolean won = false;
private boolean enemyWon = false;
private boolean tie = false;
private boolean accepted = false;
private boolean circle = true;
private boolean unableToCommunicateWithOpponent = false;
private boolean yourTurn = false;

private BufferedImage board;
private BufferedImage redX;
private BufferedImage redCircle;
private BufferedImage blueX;
private BufferedImage blueCircle;

private String[] spaces = new String[9];

private int lengthOfSpace = 160;
private int errors = 0;
private int firstSpot = -1;
private int secondSpot = -1;

private String wonString = "You Won";
private String enemyWonString = "Opponent Won";
private String unableToCommunicateWithOpponentString = "Cannot connect to opponent";
private String tieString = "It's a tie";
private String waitingString = "Waiting for another player.";

private Font font = new Font("Verdana", Font.BOLD, 30);
private Font smallerFont = new Font("Verdana", Font.BOLD, 20);
private Font largerFont = new Font("Verdana", Font.BOLD, 40);

private int[][] wins = {{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};

public TicTacToeNewExit(){
    System.out.println("Enter IP: ");
    ip = scanner.nextLine();        
    System.out.println("Enter port: ");
    port = scanner.nextInt();
    if(port<1025 || port>65523){
        System.out.println("Port Range Problem. Re-enter: ");
        port = scanner.nextInt();
    }

    loadImages();

    painter = new Painter();

    if(!connect()) initializeServer();

    jMenuBar = new JMenuBar();

    menu = new JMenu("File");

    newMenuItem = new JMenuItem("New");
    newMenuItem.setMnemonic(KeyEvent.VK_N);
    newMenuItem.setActionCommand("New");
    newMenuItem.addActionListener(this);
    exitMenuItem = new JMenuItem("Exit");
    exitMenuItem.setActionCommand("Exit");
    exitMenuItem.addActionListener(this);

    menu.add(newMenuItem);
    menu.add(exitMenuItem);

    jMenuBar.add(menu);

    frame = new JFrame();
    frame.setTitle("TicTacToePractice");
    frame.setContentPane(painter);
    frame.setSize(WIDTH, HEIGHT);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setJMenuBar(jMenuBar);
    frame.setLocationRelativeTo(null);
    frame.setResizable(false);
    frame.setVisible(true);

    thread = new Thread(this, "TicTacToe1");
    thread.start();
}

private void render(Graphics g){
    g.drawImage(board, 0, 0, null);

    if(unableToCommunicateWithOpponent){
        g.setColor(Color.ORANGE);
        g.setFont(smallerFont);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        int stringWidth = g2.getFontMetrics().stringWidth(unableToCommunicateWithOpponentString);
        g.drawString(unableToCommunicateWithOpponentString, WIDTH / 2 - stringWidth / 2, HEIGHT / 2);
        return;
    }

    if(accepted){           
        for (int i = 0; i < spaces.length; i++) {
            if (spaces[i] != null) {                    
                int x = (i % 3) * lengthOfSpace + 10 * (i % 3);
                int y = (int) (i / 3) * lengthOfSpace + 10 * (int) (i / 3);

                if (spaces[i].equals("X")) {
                    if (circle) {
                        g.drawImage(redX, x, y, null);
                    } else {
                        g.drawImage(blueX, x, y, null);
                    }
                } else if (spaces[i].equals("O")) {
                    if (circle) {
                        g.drawImage(blueCircle, x, y, null);
                    } else {
                        g.drawImage(redCircle, x, y, null);
                    }
                }
            }
        }
        if (won || enemyWon) {
            Graphics2D g2 = (Graphics2D) g;
            g2.setStroke(new BasicStroke(10));
            g.setColor(Color.BLACK);
            g.drawLine(firstSpot % 3 * lengthOfSpace + 10 * firstSpot % 3 + lengthOfSpace / 2,
                    (int) (firstSpot / 3) * lengthOfSpace + 10 * (int) (firstSpot / 3) + lengthOfSpace / 2,
                    secondSpot % 3 * lengthOfSpace + 10 * secondSpot % 3 + lengthOfSpace / 2,
                    (int) (secondSpot / 3) * lengthOfSpace + 10 * (int) (secondSpot / 3) + lengthOfSpace / 2); //(x1,y1) && (x2,y2)
            g.setColor(Color.GREEN);
            g.setFont(largerFont);
            if (won) {
                int stringWidth = g2.getFontMetrics().stringWidth(wonString);
                g.drawString(wonString, WIDTH / 2 - stringWidth / 2, HEIGHT / 2);
            } else if (enemyWon) {
                int stringWidth = g2.getFontMetrics().stringWidth(enemyWonString);
                g.drawString(enemyWonString, WIDTH / 2 - stringWidth / 2, HEIGHT / 2);
            }
        }
        if (tie) {
            Graphics2D g2 = (Graphics2D) g;
            g.setColor(Color.BLACK);
            g.setFont(largerFont);
            int stringWidth = g2.getFontMetrics().stringWidth(tieString);
            g.drawString(tieString, WIDTH / 2 - stringWidth / 2, HEIGHT / 2);
        }

    }else{
        g.setColor(Color.YELLOW);
        g.setFont(font);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        int stringWidth = g2.getFontMetrics().stringWidth(waitingString);
        g.drawString(waitingString, WIDTH / 2 - stringWidth / 2, HEIGHT / 2);
        return;
    }
}

private void loadImages() {
    try{
        board = ImageIO.read(getClass().getResourceAsStream("/board.png"));
        redX = ImageIO.read(getClass().getResourceAsStream("/redX.png"));
        redCircle = ImageIO.read(getClass().getResourceAsStream("/redCircle.png"));
        blueX = ImageIO.read(getClass().getResourceAsStream("/blueX.png"));
        blueCircle = ImageIO.read(getClass().getResourceAsStream("/blueCircle.png"));
    }catch(IOException e){
        e.printStackTrace();
    }
}

private boolean connect() {
    try{
        socket = new Socket(ip, port);
        dos = new DataOutputStream(socket.getOutputStream());
        dis = new DataInputStream(socket.getInputStream());
        accepted = true;

    }catch(IOException e){
        System.out.println("Unable to connect to the server. So starting a server on own....Server Started");
        return false;
    }
    System.out.println("Client Connected to Server....");
    return true;
}

private void initializeServer() {
    try{
        serverSocket = new  ServerSocket(port);
    }catch(Exception e){
        e.printStackTrace();
    }
    yourTurn = true;
    circle = false;
}   

@Override
public void run() {
    while(true){
        tick();
        painter.repaint();

        if(!circle && !accepted){
            listenToServerRequest();
        }
    }
}

private void listenToServerRequest() {
    Socket socket = null;
    try{
        socket = serverSocket.accept();
        dos = new DataOutputStream(socket.getOutputStream());
        dis = new DataInputStream(socket.getInputStream());
        accepted = true;
        System.out.println("Client has requested to join. We will accept");
    }catch(IOException e){
        e.printStackTrace();
    }
}

private void tick() {
    if(errors >= 10) System.out.println("Too many errors. Take a step down and get a life");
    if(!yourTurn && !unableToCommunicateWithOpponent){
        try{
            int position = dis.readInt();
            if(circle){
                spaces[position] = "X";
            }
            else{
                spaces[position] = "O";
            }
            checkForEnemyWin();
            checkForTie();
            yourTurn = true;
        }catch(IOException e){
            e.printStackTrace();
            errors++;
        }
    }
}

private void checkForWin(){
    for(int i = 0; i < wins.length; i++){
        if(circle){
            if(spaces[wins[i][0]]=="O" && spaces[wins[i][1]]=="O" && spaces[wins[i][2]]=="O"){
                firstSpot = wins[i][0];
                secondSpot = wins[i][2];
                won = true;
            }
        }else{
            if(spaces[wins[i][0]]=="X" && spaces[wins[i][1]]=="X" && spaces[wins[i][2]]=="X"){
                firstSpot = wins[i][0];
                secondSpot = wins[i][2];
                won = true;
            }
        }
    }
}

private void checkForEnemyWin(){
    for (int i = 0; i < wins.length; i++) {
        if (circle) {
            if (spaces[wins[i][0]] == "X" && spaces[wins[i][1]] == "X" && spaces[wins[i][2]] == "X") {
                firstSpot = wins[i][0];
                secondSpot = wins[i][2];
                enemyWon = true;
            }
        } else {
            if (spaces[wins[i][0]] == "O" && spaces[wins[i][1]] == "O" && spaces[wins[i][2]] == "O") {
                firstSpot = wins[i][0];
                secondSpot = wins[i][2];
                enemyWon = true;
            }
        }
    }
}

private void checkForTie(){
    for(int i = 0; i < spaces.length; i++){
        if(spaces[i] == null){
            return;
        }
    }
    tie = true;
}

@SuppressWarnings("unused")
public static void main(String[] args) {
    TicTacToeNewExit ticTacToe = new TicTacToeNewExit();
}

private class Painter extends JPanel implements MouseListener{
    private static final long serialVersionUID = 1L;

    public Painter(){
        setFocusable(true);
        requestFocus();
        setBackground(Color.WHITE);
        addMouseListener(this);
    }

    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        render(g);
    }

    @Override
    public void mouseClicked(MouseEvent e) {    
        if(accepted){
            if(yourTurn && !unableToCommunicateWithOpponent && !won && !enemyWon){
                int x = e.getX()/lengthOfSpace;
                int y = e.getY()/lengthOfSpace;
                y *= 3;

                int position = x+y;

                if(spaces[position] == null){
                    if(!circle) spaces[position] = "X";
                    else spaces[position] = "O";
                    yourTurn = false;
                    repaint();
                    Toolkit.getDefaultToolkit().sync();

                    try{
                        dos.writeInt(position);
                        dos.flush();
                    }catch(IOException e1){
                        errors++;
                        e1.printStackTrace();
                    }

                    System.out.println("Data was sent");
                    checkForWin();
                    checkForTie();
                }
            }
        }
    }

    @Override
    public void mouseEntered(MouseEvent arg0) {
        // TODO Auto-generated method stub          
    }

    @Override
    public void mouseExited(MouseEvent arg0) {
        // TODO Auto-generated method stub          
    }

    @Override
    public void mousePressed(MouseEvent arg0) {
        // TODO Auto-generated method stub          
    }

    @Override
    public void mouseReleased(MouseEvent arg0) {
        // TODO Auto-generated method stub          
    }

}

@Override
public void actionPerformed(ActionEvent a) {
    if(a.getSource() == this.newMenuItem){
        this.frame.setContentPane(painter);
        errors = 0;
        //new TicTacToeNewExit();
    }
    if(a.getSource() == this.exitMenuItem){
        System.exit(0);
    }
}

}

ActionPerformed位于代码的最底层。

我无法使用new重新绘制()整个服务器端和客户端游戏。相反,GUI关闭并再次询问localhost和端口号。我该怎样进行以下方式:

  1. 如果从任一侧点击“新”,则会在另一侧出现一个对话框,询问用户是否愿意继续新游戏。如果“是”,那么它应该只是刷新“画家”并开始新的游戏,而不是再次编写本地主机和端口。
  2. 如果从任意一侧点击“退出”,则会在另一侧显示一个对话框,显示对手玩家已退出。

0 个答案:

没有答案