本文主要是介绍java 三子棋案例添加人机对战,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
实验目的:
为基础案例添加人机对战,我给这份源代码做了一个函数的思维导图,让我看的时候对每个函数清楚一点。其中我也总结了一些运行时发现的规律。
源码server:
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** A server for a multi-player tic tac toe game. Loosely based on an example in* Deitel and Deitel��s ��Java How to Program�� book. For this project I created a* new application-level protocol called TTTP (for Tic Tac Toe Protocol), which* is entirely plain text. The messages of TTTP are:** Client -> Server MOVE <n> QUIT** Server -> Client WELCOME <char> VALID_MOVE OTHER_PLAYER_MOVED <n>* OTHER_PLAYER_LEFT VICTORY DEFEAT TIE MESSAGE <text>*/
public class TicTacToeServer {public static void main(String[] args) throws Exception {try (ServerSocket listener = new ServerSocket(58901)) {System.out.println("Tic Tac Toe Server is Running...");ExecutorService pool = Executors.newFixedThreadPool(200);while (true) {Game game = new Game();pool.execute(game.new Player(listener.accept(), 'X'));pool.execute(game.new Player(listener.accept(), 'O'));}}}
}class Game {// Board cells numbered 0-8, top to bottom, left to right; null if emptyprivate Player[] board = new Player[9];Player currentPlayer;public boolean hasWinner() {return (board[0] != null && board[0] == board[1] && board[0] == board[2])|| (board[3] != null && board[3] == board[4] && board[3] == board[5])|| (board[6] != null && board[6] == board[7] && board[6] == board[8])|| (board[0] != null && board[0] == board[3] && board[0] == board[6])|| (board[1] != null && board[1] == board[4] && board[1] == board[7])|| (board[2] != null && board[2] == board[5] && board[2] == board[8])|| (board[0] != null && board[0] == board[4] && board[0] == board[8])|| (board[2] != null && board[2] == board[4] && board[2] == board[6]);}public boolean boardFilledUp() {for(int i=0;i<9;i++){if(board[i]==null) return false;}return true;}public synchronized void move(int location, Player player) {if (player != currentPlayer) {throw new IllegalStateException("Not your turn");} else if (player.opponent == null) {throw new IllegalStateException("You don't have an opponent yet");} else if (board[location] != null) {throw new IllegalStateException("Cell already occupied");}board[location] = currentPlayer;currentPlayer = currentPlayer.opponent;}/*** A Player is identified by a character mark which is either 'X' or 'O'. For* communication with the client the player has a socket and associated Scanner* and PrintWriter.*/class Player implements Runnable {char mark;Player opponent;Socket socket;Scanner input;PrintWriter output;public Player(Socket socket, char mark) {this.socket = socket;this.mark = mark;}public void run() {try {setup();processCommands();} catch (Exception e) {e.printStackTrace();} finally {if (opponent != null && opponent.output != null) {opponent.output.println("OTHER_PLAYER_LEFT");}try {socket.close();} catch (IOException e) {}}}private void setup() throws IOException {input = new Scanner(socket.getInputStream());output = new PrintWriter(socket.getOutputStream(), true);output.println("WELCOME " + mark);//char mark = response.charAt(8);�ͻ��˴���if (mark == 'X') {currentPlayer = this;output.println("MESSAGE Waiting for opponent to connect");} else {opponent = currentPlayer;opponent.opponent = this;opponent.output.println("MESSAGE Your move");}}private void processCommands() {String command="";while (input.hasNextLine()) {command = input.nextLine();if (command.startsWith("QUIT")) {return;} else if (command.startsWith("MOVE")) {//out.println("MOVE " + j);�ͻ��˴���processMoveCommand(Integer.parseInt(command.substring(5)));}}}private void processMoveCommand(int location) {try {move(location, this);output.println("VALID_MOVE");opponent.output.println("OPPONENT_MOVED " + location);if (hasWinner()) {output.println("VICTORY");opponent.output.println("DEFEAT");} else if (boardFilledUp()) {output.println("TIE");opponent.output.println("TIE");}} catch (IllegalStateException e) {output.println("MESSAGE " + e.getMessage());}}}
}
源码client:
import java.awt.Font;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.GridBagLayout;
import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Scanner;
import java.io.PrintWriter;
import java.net.Socket;import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;/*** A client for a multi-player tic tac toe game. Loosely based on an example in* Deitel and Deitel��s ��Java How to Program�� book. For this project I created a* new application-level protocol called TTTP (for Tic Tac Toe Protocol), which* is entirely plain text. The messages of TTTP are:** Client -> Server MOVE <n> QUIT** Server -> Client WELCOME <char> VALID_MOVE OTHER_PLAYER_MOVED <n>* OTHER_PLAYER_LEFT VICTORY DEFEAT TIE MESSAGE <text>*/
public class TicTacToeClient {private JFrame frame = new JFrame("Tic Tac Toe");private JLabel messageLabel = new JLabel("...");private Square[] board = new Square[9];private Square currentSquare;private Socket socket;private Scanner in;private PrintWriter out;public TicTacToeClient(String serverAddress) throws Exception {socket = new Socket(serverAddress, 58901);in = new Scanner(socket.getInputStream());out = new PrintWriter(socket.getOutputStream(), true);messageLabel.setBackground(Color.lightGray);frame.getContentPane().add(messageLabel, BorderLayout.SOUTH);JPanel boardPanel = new JPanel();boardPanel.setBackground(Color.black);boardPanel.setLayout(new GridLayout(3, 3, 2, 2));for (int i = 0; i < board.length; i++) {final int j = i;board[i] = new Square();board[i].addMouseListener(new MouseAdapter() {public void mousePressed(MouseEvent e) {currentSquare = board[j];out.println("MOVE " + j);}});boardPanel.add(board[i]);}frame.getContentPane().add(boardPanel, BorderLayout.CENTER);}/*** The main thread of the client will listen for messages from the server. The* first message will be a "WELCOME" message in which we receive our mark. Then* we go into a loop listening for any of the other messages, and handling each* message appropriately. The "VICTORY", "DEFEAT", "TIE", and* "OTHER_PLAYER_LEFT" messages will ask the user whether or not to play another* game. If the answer is no, the loop is exited and the server is sent a "QUIT"* message.*/public void play() throws Exception {try {String response = in.nextLine();char mark = response.charAt(8);char opponentMark = mark == 'X' ? 'O' : 'X';frame.setTitle("Tic Tac Toe: Player " + mark);while (in.hasNextLine()) {response = in.nextLine();if (response.startsWith("VALID_MOVE")) {messageLabel.setText("Valid move, please wait");currentSquare.setText(mark);currentSquare.repaint();} else if (response.startsWith("OPPONENT_MOVED")) {int loc = Integer.parseInt(response.substring(15));board[loc].setText(opponentMark);board[loc].repaint();messageLabel.setText("Opponent moved, your turn");} else if (response.startsWith("MESSAGE")) {messageLabel.setText(response.substring(8));} else if (response.startsWith("VICTORY")) {JOptionPane.showMessageDialog(frame, "Winner Winner");break;} else if (response.startsWith("DEFEAT")) {JOptionPane.showMessageDialog(frame, "Sorry you lost");break;} else if (response.startsWith("TIE")) {JOptionPane.showMessageDialog(frame, "Tie");break;} else if (response.startsWith("OTHER_PLAYER_LEFT")) {JOptionPane.showMessageDialog(frame, "Other player left");break;}}out.println("QUIT");} catch (Exception e) {e.printStackTrace();} finally {socket.close();frame.dispose();}}static class Square extends JPanel {/*** */private static final long serialVersionUID = 1L;JLabel label = new JLabel();public Square() {setBackground(Color.white);setLayout(new GridBagLayout());label.setFont(new Font("Arial", Font.BOLD, 40));add(label);}public void setText(char text) {label.setForeground(text == 'X' ? Color.BLUE : Color.RED);label.setText(text + "");}}public static void main(String[] args) throws Exception {if (args.length != 1) {System.err.println("Pass the server IP as the sole command line argument");return;}TicTacToeClient client = new TicTacToeClient(args[0]);client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);client.frame.setSize(320, 320);client.frame.setVisible(true);client.frame.setResizable(false);client.play();}
}
实验步骤:
1.client端中添加消息响应框,并且提前建立数据流,根据数据流的返回值判别是否人机对战
2.在server端直接新建一个socket,再通过accept接收,这样做的目的就可以将原本一号玩家走完棋子后发送给人机的消息接收并在server端做出反应。其中我重构了player类的构造函数,加上了服务端的socket和bool类型的人机辨别flag。然后在后面的run函数中根据flag来执行不同的操作,使得无需太多的改动完成应有的效果。
3.接受到信号后,我采用alpha-beta剪枝来使人机做出决策,效果是可以的,虽然原理大概懂,但是代码还是不太会写,参考了一位大哥的python代码,我认为应该是比dfs要好。具体参考链接都放在最后了
做的过程中遇到的问题(其实多半是因为没有搞清楚原理,稍微看看运行结果就以为是那样):
1.server端中,因为player会在run函数中的processcommands通过input.HasNextLine()阻塞,想通过更改此判断实现人机对战,但是每次有信息传入时,getInputStream()只能读取一次信息,电脑读取时会产生缓存溢出的错误,也就是没东西给他读。于是我想的有两种方式:
a.不使用该函数阻塞,而使用输入流读取后的信息存储到某个变量里,然后再进行判断
感觉这个方法一般般,效率不高,逻辑较为复杂,只是稍微试了一下可行性
我的方法就是将command变为一个player的属性,然后传给computer试一试
b.将输入流实现两次(没实现),只是觉得可以
c.使用本来应该在client端的socket
尝试实现人机交互的过程:
其实不懂原理做尝试是挺痛苦的,因为我连scanner一开始都不知道怎么用。。
一开始直接使用对方的输入流
然后发现输入流一条信息只能读取一次,想了想,直接构造一个使用对方的socket的getinputstream(),结果什么都读取不到,调试了确实是用了对方的socket获得的输入流,不知道为什么得不到消息。
当时我猜测原因应该是即使都是相同的socket,但是输入流只有一个,被一个player读取了之后流就消失了。(但是其实是因为没搞懂socket的原理)
其实搞懂原理再做尝试就非常的简单了,因为new一个socket,与server端accept接受到的socket是不同(serversocket会接受socket并且虚拟化一个新的socket与其对接),但是互相联系的,我只需要在完成移动操作后,本来要给client端的消息发送给电脑类即可。(哎,还是搞懂原理好改,就稍微改动一点就好了,还不会报错)
实现效果:
1.如果我下了边角,人机会自动的下中间,如果我下中间也会找机会拉平。根据reference中果壳这篇文章的原理来说,如果我下了边角,人机不下中间他就必输。
最后也给大家看看我的源码吧
server:
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** A server for a multi-player tic tac toe game. Loosely based on an example in* Deitel and Deitel’s “Java How to Program” book. For this project I created a* new application-level protocol called TTTP (for Tic Tac Toe Protocol), which* is entirely plain text. The messages of TTTP are:* 发送的都是纯文本* Client -> Server MOVE <n> QUIT** Server -> Client WELCOME <char> VALID_MOVE OTHER_PLAYER_MOVED <n>* OTHER_PLAYER_LEFT VICTORY DEFEAT TIE MESSAGE <text>*/
public class TicTacToeServer {public static void main(String[] args) throws Exception {// create a listener 来监听这个端口的所有东西try (ServerSocket listener = new ServerSocket(58901)) {System.out.println("Tic Tac Toe Server is Running...");// 维护一个线程池ExecutorService pool = Executors.newFixedThreadPool(200);while (true) {// 一直循环构造新的game类Game game = new Game();Socket socket_x = listener.accept();//构造一个scanner,来监听是否需要人机对战Scanner mode_listen = new Scanner(socket_x.getInputStream());// 在得到socket的时间点处理一个线程,在new一个player后结束这个语句,也就是等待一个新的playerpool.execute(game.new Player(socket_x, 'X',false));System.out.println("处理完 X player");String mode = mode_listen.nextLine();if(mode.startsWith("0")) {//人人对战pool.execute(game.new Player(listener.accept(), 'O',false));//当有人时,就get他System.out.println("处理完 O player");} else if (mode.startsWith("1")) {//人机对战Socket socket_O_client = new Socket("127.0.0.1", 58901);Socket socket_O = listener.accept();pool.execute(game.new Player(socket_O, socket_O_client ,'O',true));//当有人时,就get他System.out.println("处理完 O player");}}}}
}class Game {// Board cells numbered 0-8, top to bottom, left to right; null if empty编号为0-8的板单元格,从上到下,从左到右;null如果空private Player[] board = new Player[9];Player currentPlayer;public boolean hasWinner() {// 判断是否有winner,一共八个条件return (board[0] != null && board[0] == board[1] && board[0] == board[2])|| (board[3] != null && board[3] == board[4] && board[3] == board[5])|| (board[6] != null && board[6] == board[7] && board[6] == board[8])|| (board[0] != null && board[0] == board[3] && board[0] == board[6])|| (board[1] != null && board[1] == board[4] && board[1] == board[7])|| (board[2] != null && board[2] == board[5] && board[2] == board[8])|| (board[0] != null && board[0] == board[4] && board[0] == board[8])|| (board[2] != null && board[2] == board[4] && board[2] == board[6]);}public int hasWinner(Player currentPlayer) {// 判断是否有winner,一共八个条件boolean computerwin = (board[0] != null && board[0] == board[1] && board[0] == board[2] && board[0] == currentPlayer )|| (board[3] != null && board[3] == board[4] && board[3] == board[5] && board[3] == currentPlayer)|| (board[6] != null && board[6] == board[7] && board[6] == board[8] && board[6] == currentPlayer)|| (board[0] != null && board[0] == board[3] && board[0] == board[6] && board[0] == currentPlayer)|| (board[1] != null && board[1] == board[4] && board[1] == board[7] && board[1] == currentPlayer)|| (board[2] != null && board[2] == board[5] && board[2] == board[8] && board[2] == currentPlayer)|| (board[0] != null && board[0] == board[4] && board[0] == board[8] && board[0] == currentPlayer)|| (board[2] != null && board[2] == board[4] && board[2] == board[6] && board[2] == currentPlayer);boolean peoplewin = (board[0] != null && board[0] == board[1] && board[0] == board[2] && board[0] == currentPlayer.opponent )|| (board[3] != null && board[3] == board[4] && board[3] == board[5] && board[3] == currentPlayer.opponent)|| (board[6] != null && board[6] == board[7] && board[6] == board[8] && board[6] == currentPlayer.opponent)|| (board[0] != null && board[0] == board[3] && board[0] == board[6] && board[0] == currentPlayer.opponent)|| (board[1] != null && board[1] == board[4] && board[1] == board[7] && board[1] == currentPlayer.opponent)|| (board[2] != null && board[2] == board[5] && board[2] == board[8] && board[2] == currentPlayer.opponent)|| (board[0] != null && board[0] == board[4] && board[0] == board[8] && board[0] == currentPlayer.opponent)|| (board[2] != null && board[2] == board[4] && board[2] == board[6] && board[2] == currentPlayer.opponent);if(computerwin){return 1;}if(peoplewin){return -1;}return 0;}public boolean boardFilledUp() {// 判断是否全都填充满for(int i=0;i<9;i++){if(board[i]==null) return false;}return true;}public synchronized void move(int location, Player player) {// synchronized使得方法只能有一个线程访问if (player != currentPlayer) {throw new IllegalStateException("Not your turn");} else if (player.opponent == null) {throw new IllegalStateException("You don't have an opponent yet");} else if (board[location] != null) {throw new IllegalStateException("Cell already occupied");}board[location] = currentPlayer;currentPlayer = currentPlayer.opponent;}public int alpha_beta(Player now_player,Player next_player,int alpha,int beta){if(hasWinner(currentPlayer)!=0){return hasWinner(currentPlayer);}else if (boardFilledUp()) {return 0;}for(int i=0;i<9;i++){if(board[i]==null){board[i] = now_player;int test = alpha_beta(next_player,now_player,alpha,beta);board[i] = null;if (now_player == currentPlayer){if (test>alpha){alpha = test;}if (alpha>=beta){return alpha;}}else {if (test<beta){beta = test;}if (alpha>=beta){return beta;}}}}if (now_player == currentPlayer){return alpha;}else {return beta;}}public int compute_move() {// 判断是否全都填充满,val到底是什么先?应该是随便取得一个值,保证后面的值完整int val = -2;if(hasWinner()){return -1;}String move_ = "";Random rand = new Random();for(int i=0;i<9;i++){if(board[i]==null){board[i] = currentPlayer;// computer moveif(hasWinner()){board[i] =null;return i;}int test = alpha_beta(currentPlayer.opponent,currentPlayer,-2,2);board[i] = null;if (test>val){val = test;move_= String.valueOf((char)(i + '0'));} else if (test==val) {move_+=(char)(i + '0');}}}//字符串存储一个position数组,随机抽取其中一个作为值System.out.println(move_.length());int position =(int) (move_.charAt(rand.nextInt(move_.length()))-'0');return position;}/*** A Player is identified by a character mark which is either 'X' or 'O'. For* communication with the client the player has a socket and associated Scanner* and PrintWriter.*/class Player implements Runnable {// 每个playchar mark;Player opponent;Socket socket;Scanner input;PrintWriter output;boolean computer;Socket socket_client;Scanner input_client;PrintWriter output_client;public Player(Socket socket, char mark, boolean computer) {// 每个player由mark和socket初始化System.out.println("构造player");this.socket = socket;this.mark = mark;this.computer = computer;}public Player(Socket socket, Socket socket_client ,char mark, boolean computer) {// 每个player由mark和socket初始化System.out.println("构造player");this.socket = socket;this.socket_client = socket_client;this.mark = mark;this.computer = computer;}public void run() {try {setup();processCommands();} catch (Exception e) {e.printStackTrace();} finally {if (opponent != null && opponent.output != null) {opponent.output.println("OTHER_PLAYER_LEFT");}try {socket.close();} catch (IOException e) {}}}private void setup() throws IOException {//每次创建一个player类时都会运行下面的结果input = new Scanner(socket.getInputStream());output = new PrintWriter(socket.getOutputStream(), true);if (computer){input_client = new Scanner(socket_client.getInputStream());output_client = new PrintWriter(socket_client.getOutputStream(), true);}output.println("WELCOME " + mark);//char mark = response.charAt(8);客户端代码if (mark == 'X') {//强制对手为O,并且如果还没有创建下一个对手,那么就会发送此消息,如果有下一个对手,那就发送 你的回合currentPlayer = this;output.println("MESSAGE Waiting for opponent to connect");} else {opponent = currentPlayer;opponent.opponent = this;opponent.output.println("MESSAGE Your move");}}private void processCommands() {System.out.println("processCommands");String command="";if (computer){while (input_client.hasNextLine()) {command = input_client.nextLine();if (command.startsWith("QUIT")) {return;} else if (command.startsWith("OPPONENT_MOVED")) {//out.println("MOVE " + j);客户端代码// 判断对面走了哪一步,然后下没走的地方,这里只需要返回一个坐标就够了int space = compute_move();if(space!=-1){System.out.println(space);processMoveCommand(space);}}}} else {while (input.hasNextLine()) {command = input.nextLine();if (command.startsWith("QUIT")) {return;} else if (command.startsWith("MOVE")) {//out.println("MOVE " + j);客户端代码opponent.output.println("MOVE");processMoveCommand(Integer.parseInt(command.substring(5)));}}System.out.println("结束while,也就是一个player线程的生命周期");}}private void processMoveCommand(int location) {try {move(location, this);// 全局变量来定义player和对手,移动后显示多个结果output.println("VALID_MOVE");opponent.output.println("OPPONENT_MOVED " + location);if (hasWinner()) {output.println("VICTORY");opponent.output.println("DEFEAT");} else if (boardFilledUp()) {output.println("TIE");opponent.output.println("TIE");}} catch (IllegalStateException e) {output.println("MESSAGE " + e.getMessage());}}}
}
client:
import java.awt.Font;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.GridBagLayout;
import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Scanner;
import java.io.PrintWriter;
import java.net.Socket;import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;/*** A client for a multi-player tic tac toe game. Loosely based on an example in* Deitel and Deitel’s “Java How to Program” book. For this project I created a* new application-level protocol called TTTP (for Tic Tac Toe Protocol), which* is entirely plain text. The messages of TTTP are:** Client -> Server MOVE <n> QUIT** Server -> Client WELCOME <char> VALID_MOVE OTHER_PLAYER_MOVED <n>* OTHER_PLAYER_LEFT VICTORY DEFEAT TIE MESSAGE <text>*/
public class TicTacToeClient {//bool 标志是否人机对战public int flag;private JFrame frame = new JFrame("Tic Tac Toe");private JLabel messageLabel = new JLabel("...");private Square[] board = new Square[9];//private Square currentSquare;private Socket socket;private Scanner in;private PrintWriter out;public int GetFlag() {Object[] flags = {"人人对战","人机对战"};Object choose ;choose = JOptionPane.showInputDialog(frame, "Choose a way:", "对战方式",JOptionPane.QUESTION_MESSAGE,null,flags,flags[0]);if (choose == flags[0]) {return 0;} else if (choose == flags[1]) {return 1;}return 0;}public TicTacToeClient(String serverAddress) throws Exception {//初始化时连接对应接口socket = new Socket(serverAddress, 58901);in = new Scanner(socket.getInputStream());out = new PrintWriter(socket.getOutputStream(), true);// 设置消息框messageLabel.setBackground(Color.lightGray);frame.getContentPane().add(messageLabel, BorderLayout.SOUTH);// 面板JPanel boardPanel = new JPanel();boardPanel.setBackground(Color.black);boardPanel.setLayout(new GridLayout(3, 3, 2, 2));// 这里的board就是9个方块for (int i = 0; i < board.length; i++) {final int j = i;board[i] = new Square();// 设置鼠标点击事件,如果点击了,就将全局变量currentSquare改变board[i].addMouseListener(new MouseAdapter() {public void mousePressed(MouseEvent e) {currentSquare = board[j];out.println("MOVE " + j);}});boardPanel.add(board[i]);}//加入boardframe.getContentPane().add(boardPanel, BorderLayout.CENTER);flag = GetFlag();out.println(flag);}/*** The main thread of the client will listen for messages from the server. The* first message will be a "WELCOME" message in which we receive our mark. Then* we go into a loop listening for any of the other messages, and handling each* message appropriately. The "VICTORY", "DEFEAT", "TIE", and* "OTHER_PLAYER_LEFT" messages will ask the user whether or not to play another* game. If the answer is no, the loop is exited and the server is sent a "QUIT"* message.*/public void play() throws Exception {try {// 将response 设置为 in里面的输入流,然后等待返回结果:WELCOME OString response = in.nextLine();char mark = response.charAt(8); //这里只取其中最后一个字符char opponentMark = mark == 'X' ? 'O' : 'X';frame.setTitle("Tic Tac Toe: Player " + mark);//设置标题while (in.hasNextLine()) { //当有新的信息传入时,反正每个窗口就是一直等待response = in.nextLine();if (response.startsWith("VALID_MOVE")) {// 当对手下棋时,return OPPONENT_MOVED 0messageLabel.setText("Valid move, please wait");currentSquare.setText(mark);currentSquare.repaint();} else if (response.startsWith("OPPONENT_MOVED")) {//System.out.println("opponent moved");int loc = Integer.parseInt(response.substring(15));board[loc].setText(opponentMark);board[loc].repaint(); //当对方下棋后,就将这些显示到自己的上面,并且显示文字messageLabel.setText("Opponent moved, your turn");} else if (response.startsWith("MESSAGE")) {messageLabel.setText(response.substring(8));} else if (response.startsWith("VICTORY")) {JOptionPane.showMessageDialog(frame, "Winner Winner");break;} else if (response.startsWith("DEFEAT")) {JOptionPane.showMessageDialog(frame, "Sorry you lost");break;} else if (response.startsWith("TIE")) {JOptionPane.showMessageDialog(frame, "Tie");break;} else if (response.startsWith("OTHER_PLAYER_LEFT")) {JOptionPane.showMessageDialog(frame, "Other player left");break;}}out.println("QUIT");} catch (Exception e) {e.printStackTrace();} finally {socket.close();frame.dispose();}}static class Square extends JPanel {/*** */private static final long serialVersionUID = 1L;JLabel label = new JLabel();public Square() {setBackground(Color.white);setLayout(new GridBagLayout());label.setFont(new Font("Arial", Font.BOLD, 40));add(label);}public void setText(char text) {label.setForeground(text == 'X' ? Color.BLUE : Color.RED);label.setText(text + "");}}public static void main(String[] args) throws Exception {if (args.length != 1) {System.err.println("Pass the server IP as the sole command line argument");return;}// 创建一个客户类,初始化时TicTacToeClient client = new TicTacToeClient(args[0]);client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);client.frame.setSize(320, 320);client.frame.setVisible(true);client.frame.setResizable(false);//play就是展示五子棋client.play();}
}
reference:
井字棋的最优策略竟是先占角!| 果壳 科技有意思 (guokr.com)
查阅java scanner类Java Scanner 类 | 菜鸟教程 (runoob.com)
查阅java getinputstreamJava.lang.Process.getInputStream() 方法 (w3schools.cn)
查阅网络编程动物书
查阅博客园关于Socket和ServerSocket类详解 - 一天一夜 - 博客园
查询alpha-beta剪枝【AI】对抗搜索:Alpha-Beta剪枝搜索图解及井字棋应用的python实现_风巽·剑染春水的博客-CSDN博客_alpha剪枝图解
这篇关于java 三子棋案例添加人机对战的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!