J'ai un jeu de tic-tac-toe de serveur client qui essaye d'exécuter un fil différent (dans différents terminaux) pour chaque joueur, que j'ai construit dans l'éclipse.Pourquoi mon fil d'attente ne se réveille-t-il pas même s'il est notifié?
Mon but est de faire bouger chaque joueur, .notifier() l'autre joueur et ensuite .wait() pour que l'autre joueur fasse son mouvement, et alterner ce processus jusqu'à ce que la partie soit terminée.
toSync est l'objet utilisé pour la synchronisation
public static final Object toSync = new Object()
et il se trouve dans la classe de lecteur (qui se prolonge par deux XPlayer et OPlayer).
Les lignes qui semblent être à l'origine du problème sont commentés dans XPlayer et oPlayer:
Les deux Xplayer et OPlayer ont des méthodes principales, afin qu'elles puissent être exécutées simultanément. X fait le premier mouvement puis utilise un socket pour communiquer ce mouvement au serveur.
Le serveur passe ce déplacement à O, qui effectue ensuite son propre déplacement et le renvoie au serveur. Cela alterne jusqu'à ce que le jeu soit terminé. Faire le premier coup lorsque le joueur x fonctionne bien, mais une fois le mouvement initial effectué, o est supposé afficher le tableau, puis inviter l'utilisateur à se déplacer. Cela ne se produit cependant pas: x fait son mouvement, et o est censé être notifié, mais en réalité ne se réveille jamais. L'accolade qui termine la boucle while qui est commentée dans OPlayer n'est jamais atteinte (ce que je sais être vrai par le débogage que j'ai fait jusqu'ici).
Classe XPlayer:
import java.io.*;
public class XPlayer
extends Player
implements Runnable
{
public static volatile boolean xTurn = true;
public XPlayer() throws IOException
{
super();
mark = LETTER_X;
}
public void run()
{
try
{
System.out.println("Okay " + name + ", You will be the X-Player");
synchronized(toSync)
{
Cell move = makeMove();
out.println(move.toString());
board.addMark
(move.row(),move.col(),move.mark());
board.display();
xTurn = false;
toSync.notifyAll(); //THIS IS THE LINE THAT ISNT WORKING!!
System.out.println(WAITING);
}
synchronized(toSync)
{
while (!xTurn)
{toSync.wait();}
}
while (!board.isOver())
{
synchronized(toSync)
{
String line;
do {line = in.readLine();}
while (line == null);
Cell opponentMove = Cell.split(line);
board.addMark
(opponentMove.row(),opponentMove.col(), opponentMove.mark());
String move = makeMove().toString();
out.println(move);
xTurn = false;
toSync.notifyAll();
while (!xTurn)
{toSync.wait();}
}
}
endGame();
sock.close();
in.close();
stdin.close();
out.close();
} catch (InterruptedException ie)
{
System.out.println("IE IN XPLAYER! " + ie.getMessage());
System.exit(1);
} catch (IOException ioe)
{
System.out.println("IOE IN XPLAYER! " + ioe.getMessage());
System.exit(1);
}
}
public static void main(String[] args)
{
try
{
XPlayer x = new XPlayer();
Thread t = new Thread(x);
t.start();
} catch(IOException ioe)
{
System.err.println
("IOE IN XPLAYER MAIN " + ioe.getMessage());
System.exit(1);
}
}
Classe OPlayer:
import java.io.*;
public class OPlayer
extends Player
implements Runnable
{
public OPlayer() throws IOException
{
super();
mark = LETTER_O;
}
public void run()
{
try
{
synchronized(toSync)
{
System.out.println("Okay " + name + ", You will be the O-Player");
System.out.println(WAITING);
while(!XPlayer.xTurn)
{toSync.wait();} // THIS IS THE LINE THAT ISN'T WAKING UP
while (!board.isOver())
{
String line;
do {line = in.readLine();}
while (line == null);
Cell opponentMove = Cell.split(line);
board.addMark
(opponentMove.row(),opponentMove.col(),opponentMove.mark());
Cell move = makeMove();
out.println(move.toString());
board.addMark(move.row(),move.col(),move.mark());
board.display();
XPlayer.xTurn = true;
toSync.notifyAll();
System.out.println(WAITING);
while (XPlayer.xTurn)
{toSync.wait();}
}
}
endGame();
sock.close();
in.close();
stdin.close();
out.close();
} catch (InterruptedException ie)
{
System.out.println("IE IN OPLAYER " + ie.getMessage());
System.exit(1);
} catch (IOException ioe)
{
System.err.println("IOE IN OPLAYER " + ioe.getMessage());
System.exit(1);
}
}
public static void main(String[] args)
{
try
{
OPlayer o = new OPlayer();
Thread t = new Thread(o);
t.start();
} catch(IOException ioe)
{
System.err.println("IOE IN OPLAYER MAIN" + ioe.getMessage());
System.exit(1);
}
}
}
Comme indiqué par le code, l'appel toSync.notifyAll() dans XPlayer ne se réveille pas le fil OPlayer, et je suis coincé dans une impasse une fois le premier mouvement a été fait par le XPlayer
Je crois que seulement ces 2 classes sont nécessaires pour résoudre le problème, mais juste au cas où, voici les classes Player Boar d et TTTServer: Classe du joueur:
import java.net.*;
import java.io.*;
public class Player
implements Constants
{
protected static final Object toSync = new Object();
protected Socket sock;
protected BufferedReader stdin;
protected BufferedReader in;
protected PrintWriter out;
protected String name;
protected char mark;
protected Board board;
public Player() throws IOException
{
sock = new Socket("localhost",1298);
stdin = new BufferedReader(new InputStreamReader(System.in));
in = new BufferedReader(new
InputStreamReader(sock.getInputStream()));
out = new PrintWriter(sock.getOutputStream(),true);
System.out.println(WELCOME);
System.out.println("Please Enter your name:");
name = stdin.readLine();
board = new Board();
}
public Cell makeMove() throws IOException
{
board.display();
int row = -1;
int col = -1;
do
{
while (row < 0 || row > 2)
{
System.out.println
(name + ", what row would you like your next move to be in?");
row = Integer.parseInt(stdin.readLine());
if (row < 0 || row > 2)
{System.out.println("Invalid entry! Try again...");}
}
while (col < 0 || col > 2)
{
System.out.println
(name + ", what column would you like your next move to be in?");
col = Integer.parseInt(stdin.readLine());
if (col < 0 || col > 2)
{System.out.println("Invalid entry! Try again...");}
}
if (board.getMark(row, col) != SPACE_CHAR)
{System.out.println("That spot is already taken Try again...");}
} while (board.getMark(row,col) != SPACE_CHAR);
return new Cell(row,col,mark);
}
public void endGame()
{
if (board.xWins() == 1) {System.out.println(END + XWIN);}
if (board.oWins() == 1) {System.out.println(END + OWIN);}
else {System.out.println(END + " It was a tie!!");}
}
}
Classe TTTServer:
import java.net.*;
import java.io.*;
public class TTTServer
implements Constants
{
public static void main(String[] args)
{
try
{
ServerSocket ss = new ServerSocket(1298,2);
System.out.println("The Server is running...");
Socket sock;
Board board = new Board();
sock = ss.accept();
sock = ss.accept();
BufferedReader in = new BufferedReader(new
InputStreamReader(sock.getInputStream()));
PrintWriter out = new PrintWriter(sock.getOutputStream(),true);
do
{
String moveString;
do {moveString = in.readLine();}
while (moveString == null);
Cell move = Cell.split(moveString);
board.addMark(move.row(), move.col(), move.mark());
out.println(moveString);
} while(!board.isOver());
in.close();
out.close();
ss.close();
sock.close();
} catch(IOException ioe)
{
System.out.println("IOE IN TTTSERVER " + ioe.getMessage());
System.exit(1);
}
}
}
Conseil Classe:
public class Board
implements Constants
{
/**
* A 2D char array stores the game board and
* the total number of marks
*/
private char theBoard[][];
private int markCount;
/**
* Default constructor initializes the array and fills it with
* SPACE_CHARs from the Constants interface
*/
public Board()
{
markCount = 0;
theBoard = new char[3][];
for (int i = 0; i < 3; i++) {
theBoard[i] = new char[3];
for (int j = 0; j < 3; j++)
theBoard[i][j] = SPACE_CHAR;
}
}
/**
* Getter for the mark at the location specified by the arguments
*
* @param row
* @param column
*
* @return mark
*/
public char getMark(int row, int col)
{return theBoard[row][col];}
/**
* Getter for the number of moves which have been made thus far
*
* @return markCount
*/
public int getMarkCount() {return markCount;}
/**
* @return true if the game is over, otherwise false
*/
public boolean isOver()
{
if (xWins() == 1 || oWins() == 1 || isFull())
{return true;}
return false;
}
/**
* @return true if the board has been completely filled with
* X_CHARs and O_CHARs from Constants interface, else false
*/
public boolean isFull()
{return markCount == 9;}
/**
* Runs checkWinner on LETTER_X from Constants interface
*
* @return true if X has won, else false
*/
public int xWins()
{return checkWinner(LETTER_X);}
/**
* Runs checkWinner on LETTER_O from Constants interface
*
* @return true if O has won, else false
*/
public int oWins()
{return checkWinner(LETTER_O);}
/**
* Uses the formatting helper methods to display the board
* in the console
*/
public void display()
{
displayColumnHeaders();
addHyphens();
for (int row = 0; row < 3; row++) {
addSpaces();
System.out.print(" row " + row + ' ');
for (int col = 0; col < 3; col++)
System.out.print("| " + getMark(row, col) + " ");
System.out.println("|");
addSpaces();
addHyphens();
}
}
/**
* Add the mark in the last argument to the location specified by the
* first two arguments
*
* @param row
* @param column
* @param mark
*/
public void addMark(int row, int col, char mark)
{
theBoard[row][col] = mark;
markCount++;
}
/**
* Clears the board by replacing all marks with
* SPACE_CHARs from the Constants interface
*/
public void clear()
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
theBoard[i][j] = SPACE_CHAR;
markCount = 0;
}
/**
* Checks if the player with the argument mark has won the game
*
* @param mark
*
* @return true if the game was won, else false
*/
int checkWinner(char mark) {
int row, col;
int result = 0;
for (row = 0; result == 0 && row < 3; row++) {
int row_result = 1;
for (col = 0; row_result == 1 && col < 3; col++)
if (theBoard[row][col] != mark)
row_result = 0;
if (row_result != 0)
result = 1;
}
for (col = 0; result == 0 && col < 3; col++) {
int col_result = 1;
for (row = 0; col_result != 0 && row < 3; row++)
if (theBoard[row][col] != mark)
col_result = 0;
if (col_result != 0)
result = 1;
}
if (result == 0) {
int diag1Result = 1;
for (row = 0; diag1Result != 0 && row < 3; row++)
if (theBoard[row][row] != mark)
diag1Result = 0;
if (diag1Result != 0)
result = 1;
}
if (result == 0) {
int diag2Result = 1;
for (row = 0; diag2Result != 0 && row < 3; row++)
if (theBoard[row][3 - 1 - row] != mark)
diag2Result = 0;
if (diag2Result != 0)
result = 1;
}
return result;
}
/**
* The final three helper methods are called by display
* to format the board properly in the console
*/
void displayColumnHeaders() {
System.out.print(" ");
for (int j = 0; j < 3; j++)
System.out.print("|col " + j);
System.out.println();
}
void addHyphens() {
System.out.print(" ");
for (int j = 0; j < 3; j++)
System.out.print("+-----");
System.out.println("+");
}
void addSpaces() {
System.out.print(" ");
for (int j = 0; j < 3; j++)
System.out.print("| ");
System.out.println("|");
}
}
Beaucoup trop de code pour que quelqu'un veuille lire et résoudre (gratuitement :)) – pczeus