package tictactoe2;
import java.awt.BorderLayout;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.util.Formatter;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TicTacToeServer extends JFrame
{
private String[] board = new String[ 225 ]; //字符串数组用来记录棋盘里下棋的位置
private JTextArea outputArea; // 游戏提示的JTextArea
private Player[] players; // 玩家数组
private ServerSocket server; // server socket 与客户端相连接
private int currentPlayer; // 当前行动的玩家
private final static int PLAYER_BLACK = 0; // 黑棋玩家
private final static int PLAYER_WHITE = 1; // 白棋玩家
private final static String[] MARKS = { "BLACK", "WHITE" }; // marks数组
private ExecutorService runGame; // 使游戏运行
private Lock gameLock; // 把游戏锁起来用于同步
private Condition otherPlayerConnected; // 等待对方连接的情况
private Condition otherPlayerTurn; //等待对方下棋的情况
// 建立五子棋服务器端和显示信息的图形界面
public TicTacToeServer()
{
super( "五子棋服务器端" ); // 建立window标题
// 对每一个玩家线程创建ExecutorService
runGame = Executors.newFixedThreadPool( 2 );//线程池
gameLock = new ReentrantLock(); // 创建锁
otherPlayerConnected = gameLock.newCondition();//创建玩家连接的connection
otherPlayerTurn = gameLock.newCondition(); //创建玩家玩的connection
for ( int i = 0; i < 225; i++ )
board[ i ] = new String( "" ); // 初始化board[ i ]数组
players = new Player[ 2 ]; // 创建玩家数组
currentPlayer = PLAYER_BLACK; // 设置第一个玩家为黑棋玩家
try
{
server = new ServerSocket( 12345, 2 ); //创建 ServerSocket
} // end try
catch ( IOException ioException ) //异常判断
{
ioException.printStackTrace();
System.exit( 1 );
} // end catch
outputArea = new JTextArea(); // 创建JTextArea
add( outputArea, BorderLayout.CENTER );//将outputArea添加到布局中心
outputArea.setText( "服务器正在等待连接,请稍侯!\n" );//提示正在等待连接
setSize( 300, 300 ); // 设置window的大小
setVisible( true ); // 设置可见性
} //结束构造函数
public void execute()
{
//等待每一个客户端连接
for ( int i = 0; i < players.length; i++ )
{
try // 等待连接, 创建玩家, 开始运行
{
players[ i ] = new Player( server.accept(), i );
runGame.execute( players[ i ] ); // 使玩家可运行
}
catch ( IOException ioException )
{
ioException.printStackTrace();
System.exit( 1 );
}
}
gameLock.lock(); // 游戏加锁唤醒 黑棋玩家线程
try
{
players[ PLAYER_BLACK ].setSuspended( false );
otherPlayerConnected.signal(); // 唤醒另一个玩家线程
}
finally
{
gameLock.unlock(); // 解锁
}
}
// 在outputArea显示信息
private void displayMessage( final String messageToDisplay )
{
// display message from event-dispatch thread of execution
SwingUtilities.invokeLater(
new Runnable()
{
public void run() //更新outputArea
{
outputArea.append( messageToDisplay ); // 添加信息
}
}
);
}
// 判断下棋是否有效
public boolean validateAndMove( int location, int player )
{
// 如果不是当前玩家,必须等待
while ( player != currentPlayer )
{
gameLock.lock(); // 将游戏锁上等待另一个玩家落棋
try
{
otherPlayerTurn.await(); // 等待另一个玩家
}
catch ( InterruptedException exception )
{
exception.printStackTrace();
}
finally
{
gameLock.unlock(); // 等待后解锁
}
}
// 如果鼠标点击位置没有被占据,则有效
if ( !isOccupied( location ) )
{
board[ location ] = MARKS[ currentPlayer ]; // board记录该位置的下棋结果
currentPlayer = ( currentPlayer + 1 ) % 2; // 换玩家
// 让另一个玩家知道上一个玩家下在哪了
players[ currentPlayer ].otherPlayerMoved( location );
gameLock.lock(); // 游戏加锁提示玩家下棋
try
{
otherPlayerTurn.signal(); // 唤醒其他玩家继续游戏
}
finally
{
gameLock.unlock(); // 唤醒后解锁游戏
}
return true; // 返回下棋有效布尔值
}
else
return false; // 返回下棋无效布尔值
}
// 判断位置是否被占据
public boolean isOccupied( int location )
{
if ( board[ location ].equals( MARKS[ PLAYER_BLACK ] ) ||
board [ location ].equals( MARKS[ PLAYER_WHITE ] ) )
return true; // 返回位置被占据布尔值
else
return false; // 返回位置未被占据布尔值
}
// 判断游戏是否结束的函数
public int isGameOver()
{
int black_count = 0;
int white_count = 0;
int i = 0;
for(i = 0;i < 15;i++)//横向判断
{
for(int j = 0;j < 15;j++)
{
if(board[i*15+j].equals("BLACK") )
{
black_count++;
if(black_count == 5)
{
JOptionPane.showMessageDialog(this, "黑棋胜利");
return 1;
}
}
else
{
black_count = 0;
}
if(board[i*15+j].equals("WHITE"))
{
white_count++;
if(white_count == 5)
{
JOptionPane.showMessageDialog(this, "白棋胜利");
return 2;
}
}
else
{
white_count = 0;
}
}
}
for(i = 0;i < 15;i++)//竖向判断
{
for(int j = 0;j < 15;j++)
{
if(board[j*15+i].equals("BLACK"))
{
black_count++;
if(black_count == 5)
{
JOptionPane.showMessageDialog(this, "黑棋胜利");
return 1;
}
}
else
{
black_count = 0;
}
if(board[j*15+i].equals("WHITE"))
{
white_count++;
if(white_count == 5)
{
JOpt