?? omokclient.java
字號:
package omok;
import java.awt.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.awt.event.*;
//五子棋盤類
class OmokBoard extends Canvas {
public static final int BLACK = 1, WHITE = -1; //黑白子常數
private int[][] map; //map數組
private int size, cell; //棋盤大小,棋盤格大小
private String info = "游戲終止"; //游戲狀態字符串
private int color = BLACK; //用戶的棋子顏色
//是否可以放置棋子
private boolean enable = false;
//顯示游戲是否進行的變量
private boolean running = false;
//向對手傳遞消息的流
private PrintWriter writer;
private Graphics gboard, gbuff;
private Image buff;
OmokBoard(int s, int c) {
this.size = s;
this.cell = c;
map = new int[size + 2][];
for (int i = 0; i < map.length; i++) {
map[i] = new int[size + 2];
}
//設定五子棋盤背景色
setBackground(new Color(200, 200, 100));
//計算棋盤大小
setSize(size * (cell + 1) + size, size * (cell + 1) + size);
addMouseListener(new MouseAdapter() {
//棋盤鼠標事件處理
@Override
public void mousePressed(MouseEvent me) {
if (!enable) {
return;
}
//將鼠標坐標轉換為map坐標
int x = (int) Math.round(me.getX() / (double) cell);
int y = (int) Math.round(me.getY() / (double) cell);
//若不是放置棋子的坐標,則退出
if (x == 0 || y == 0 || x == size + 1 || y == size + 1) {
return;
}
//若棋盤上已經放置了棋子,則退出
if (map[x][y] == BLACK || map[x][y] == WHITE) {
return;
}
//向對手發送棋子坐標
writer.println("[STONE]" + x + " " + y);
map[x][y] = color;
//檢查獲勝與否
if (check(new Point(x, y), color)) {
info = "獲勝";
writer.println("[WIN]");
} else {
info = "等待對方落子";
}
//繪制棋盤
repaint();
//使用戶不可下子
//若對手已經下子,則enable為true,用戶可以落子
enable = false;
}
});
}
//獲取游戲的進行狀態
public boolean isRunning() {
return running;
}
//開始游戲
public void startGame(String col) {
running = true;
//若黑棋被選中
if (col.equals("BLACK")) {
enable = true;
color = BLACK;
info = "開始游戲......請落子";
} //若白棋被選中
else {
enable = false;
color = WHITE;
info = "開始游戲......請等待";
}
}
//停止游戲
public void stopGame() {
//初始化棋盤
reset();
//向對手發送消息
writer.println("[STOPGAME]");
enable = false;
running = false;
}
public void putOpponent(int x, int y) {
map[x][y] = -color;
info = "對手已經落子,請落子";
repaint();
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public void setWriter(PrintWriter writer) {
this.writer = writer;
}
//調用repaint()時自動調用
@Override
public void update(Graphics g) {
paint(g);
}
//繪制畫面
@Override
public void paint(Graphics g) {
if (gbuff == null) {
buff = createImage(getWidth(), getHeight());
gbuff = buff.getGraphics();
}
//繪制棋盤
drawBoard(g);
}
//初始化棋盤
public void reset() {
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
map[i][j] = 0;
}
}
info = "游戲終止";
repaint();
}
//在棋盤上畫線
private void drawLine() {
gbuff.setColor(Color.black);
for (int i = 1; i <= size; i++) {
gbuff.drawLine(cell, i * cell, cell * size, i * cell);
gbuff.drawLine(i * cell, cell, i * cell, cell * size);
}
}
//在(x,y)上繪制黑子
private void drawBlack(int x, int y) {
Graphics2D gbuf = (Graphics2D) this.gbuff;
gbuf.setColor(Color.black);
gbuf.fillOval(x * cell - cell / 2, y * cell - cell / 2, cell, cell);
gbuf.setColor(Color.white);
gbuf.drawOval(x * cell - cell / 2, y * cell - cell / 2, cell, cell);
}
//在(x,y)上繪制白子
private void drawWhite(int x, int y) {
gbuff.setColor(Color.white);
gbuff.fillOval(x * cell - cell / 2, y * cell - cell / 2, cell, cell);
gbuff.setColor(Color.black);
gbuff.drawOval(x * cell - cell / 2, y * cell - cell / 2, cell, cell);
}
//繪制map中的所有棋子
private void drawStones() {
for (int x = 1; x <= size; x++) {
for (int y = 1; y <= size; y++) {
if (map[x][y] == BLACK) {
drawBlack(x, y);
} else if (map[x][y] == WHITE) {
drawWhite(x, y);
}
}
}
}
//繪制棋盤
synchronized private void drawBoard(Graphics g) {
gbuff.clearRect(0, 0, getWidth(), getHeight());
drawLine();
drawStones();
gbuff.setColor(Color.red);
gbuff.drawString(info, 20, 15);
g.drawImage(buff, 0, 0, this);
}
private boolean check(Point p, int col) {
if (count(p, 1, 0, col) + count(p, -1, 0, col) == 4) {
return true;
}
if (count(p, 0, 1, col) + count(p, 0, -1, col) == 4) {
return true;
}
if (count(p, -1, -1, col) + count(p, 1, 1, col) == 4) {
return true;
}
if (count(p, 1, -1, col) + count(p, -1, 1, col) == 4) {
return true;
}
return false;
}
@SuppressWarnings("empty-statement")
private int count(Point p, int dx, int dy, int col) {
int i = 0;
for (; map[p.x + (i + 1) * dx][p.y + (i + 1) * dy] == col; i++);
return i;
}
}
public class OmokClient extends Frame implements Runnable, ActionListener {
//顯示消息的多行文本框
private TextArea msgView = new TextArea("", 1, 1, 1);
//記錄待發消息的對話框
private TextField sendBox = new TextField("");
//用戶名對話框
private TextField nameBox = new TextField();
//房間號對話框
private TextField roomBox = new TextField("0");
//顯示連接人數的標簽
private Label pInfo = new Label("待機室: 名");
//顯示用戶名單的列表
private java.awt.List pList = new java.awt.List();
private Button startButton = new Button("開始對決");
private Button stopButton = new Button("棄權");
private Button enterButton = new Button("入場");
private Button exitButton = new Button("去待機室");
//顯示各種信息的標簽
private Label infoView = new Label("< Thingking Java >", 1);
private OmokBoard board = new OmokBoard(15, 30);//棋盤對象
private BufferedReader reader;//輸入流
private PrintWriter writer;//輸出流
private Socket socket;//套接字
private int roomNumber = -1;//房間號
private String userName = null;//用戶名
public OmokClient(String title) {
super(title);
setLayout(null);//不使用任何布局
msgView.setEditable(false);
//創建并排列各種組件
infoView.setBounds(10, 30, 480, 30);
infoView.setBackground(new Color(200, 200, 255));
board.setLocation(10, 70);
add(infoView);
add(board);
Panel p = new Panel();
p.setBackground(new Color(200, 255, 255));
p.setLayout(new GridLayout(3, 3));
p.add(new Label("名字:", 2));
p.add(nameBox);
p.add(new Label("房間號:", 2));
p.add(roomBox);
p.add(enterButton);
p.add(exitButton);
enterButton.setEnabled(false);
p.setBounds(500, 30, 250, 70);
Panel p2 = new Panel();
p2.setBackground(new Color(255, 255, 100));
p2.setLayout(new BorderLayout());
Panel p2_1 = new Panel();
p2_1.add(startButton);
p2_1.add(stopButton);
p2.add(pInfo, "North");
p2.add(pList, "Center");
p2.add(p2_1, "South");
startButton.setEnabled(false);
stopButton.setEnabled(false);
p2.setBounds(500, 110, 250, 180);
Panel p3 = new Panel();
p3.setLayout(new BorderLayout());
p3.add(msgView, "Center");
p3.add(sendBox, "South");
p3.setBounds(500, 300, 250, 250);
add(p);
add(p2);
add(p3);
//注冊事件監聽器
sendBox.addActionListener(this);
enterButton.addActionListener(this);
exitButton.addActionListener(this);
startButton.addActionListener(this);
stopButton.addActionListener(this);
addWindowListener(new WindowAdapter() {
//關閉窗口
@Override
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
}
//組件動作事件處理
@Override
public void actionPerformed(ActionEvent ae) {
//若為消息輸入對話框
if (ae.getSource() == sendBox) {
String msg = sendBox.getText();
if (msg.length() == 0) {
return;
}
if (msg.length() >= 30) {
msg = msg.substring(0, 30);
}
try {
writer.println("[MSG]" + msg);
sendBox.setText("");
} catch (Exception ie) {
}
}
//若為入場按鈕
else if (ae.getSource() == enterButton) {
try {
if (Integer.parseInt(roomBox.getText()) < 1) {
infoView.setText("房間號錯誤,大于1");
return;
}
writer.println("[ROOM]" + Integer.parseInt(roomBox.getText()));
msgView.setText("");
} catch (Exception ie) {
infoView.setText("輸入的事項發生錯誤");
}
} else if (ae.getSource() == exitButton) {
try {
goToWaitRoom();
startButton.setEnabled(false);
stopButton.setEnabled(false);
} catch (Exception e) {
}
}
//若為對決開始按鈕
else if (ae.getSource() == startButton) {
try {
writer.println("[START]");
infoView.setText("等待對方決定");
startButton.setEnabled(false);
} catch (Exception e) {
}
}
//若為棄權按鈕
else if (ae.getSource() == stopButton) {
try {
writer.println("[DROPGAME]");
endGame("已棄權");
} catch (Exception e) {
}
}
}
//點擊進入待機室按鈕時被調用
void goToWaitRoom() {
if (userName == null) {
String name = nameBox.getText().trim();
if (name.length() <= 2 || name.length() > 10) {
infoView.setText("名字錯誤.3-10個字");
nameBox.requestFocus();
return;
}
userName = name;
writer.println("[NAME]" + userName);
nameBox.setText(userName);
nameBox.setEditable(false);
}
msgView.setText("");
writer.println("[ROOM]0");
infoView.setText("已經進入待機室");
roomBox.setText("0");
enterButton.setEnabled(true);
exitButton.setEnabled(false);
}
@Override
public void run() {
String msg; //來自服務器的消息
try {
while ((msg = reader.readLine()) != null) {
if (msg.startsWith("[STONE]")) {
String temp = msg.substring(7);
int x = Integer.parseInt(temp.substring(0, temp.indexOf(" ")));
int y = Integer.parseInt(temp.substring(temp.indexOf(" ") + 1));
//繪制對方棋子
board.putOpponent(x, y);
board.setEnable(true);
}
//進入房間
else if (msg.startsWith("[ROOM]")) {
//若非待機室
if (!msg.equals("[ROOM]0")) {
enterButton.setEnabled(false);
exitButton.setEnabled(true);
infoView.setText(msg.substring(6) + "號房間已被進入");
} else {
infoView.setText("已進入待機室");
}
//指定房間號
roomNumber = Integer.parseInt(msg.substring(6));
//若游戲進行中
if (board.isRunning()) {
board.stopGame();
}
}
//若房間已滿
else if (msg.startsWith("[FULL]")) {
infoView.setText("房間已滿,禁止入內");
}
//房中用戶名單
else if (msg.startsWith("[PLAYERS]")) {
nameList(msg.substring(9));
} else if (msg.startsWith("[ENTER]")) {
pList.add(msg.substring(7));
playersInfo();
msgView.append("[" + msg.substring(7) + "]入場.\n");
}
//退出
else if (msg.startsWith("[EXIT]")) {
//從列表中刪除
pList.remove(msg.substring(6));
//重新計算并顯示人數
playersInfo();
msgView.append("[" + msg.substring(6) + "]進入其他房間.\n");
if (roomNumber != 0) {
endGame("對方離開.");
}
}
//連接中斷
else if (msg.startsWith("[DISCONNECT]")) {
pList.remove(msg.substring(12));
playersInfo();
msgView.append("[" + msg.substring(12) + "]中斷連接.\n");
if (roomNumber != 0) {
endGame("對方離開.");
}
} else if (msg.startsWith("[COLOR]")) {
String color = msg.substring(7);
board.startGame(color);
if (color.equals("BLACK")) {
infoView.setText("得到黑子.");
} else {
infoView.setText("得到白子.");
}
stopButton.setEnabled(true);
}
//激活棄權按鈕
else if (msg.startsWith("[DROPGAME]")) {
endGame("對方棄權.");
}
//若已獲勝
else if (msg.startsWith("[WIN]")) {
endGame("獲勝.");
}
//若失敗
else if (msg.startsWith("[LOSE]")) {
endGame("失敗.");
} else {
msgView.append(msg + "\n");
}
}
} catch (IOException ie) {
msgView.append(ie + "\n");
}
msgView.append("連接中斷.");
}
//終止游戲
private void endGame(String msg) {
infoView.setText(msg);
startButton.setEnabled(false);
stopButton.setEnabled(false);
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
if (board.isRunning()) {
board.stopGame();
}
if (pList.getItemCount() == 2) {
startButton.setEnabled(true);
}
}
//顯示房間的連接人數
private void playersInfo() {
int count = pList.getItemCount();
if (roomNumber == 0) {
pInfo.setText("待機室: " + count + "名");
} else {
pInfo.setText(roomNumber + " 號房: " + count + "名");
}
if (count == 2 && roomNumber != 0) {
startButton.setEnabled(true);
} else {
startButton.setEnabled(false);
}
}
private void nameList(String msg) {
pList.removeAll();
StringTokenizer st = new StringTokenizer(msg, "\t");
while (st.hasMoreElements()) {
pList.add(st.nextToken());
}
playersInfo();
}
//連接
private void connect() {
try {
msgView.append("請求連接服務器.\n");
socket = new Socket("192.168.1.119", 7777);
msgView.append("-- 連接成功 --.\n");
msgView.append("請輸入大名,然后進入待機室.\n");
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new PrintWriter(socket.getOutputStream(), true);
new Thread(this).start();
board.setWriter(writer);
} catch (Exception e) {
msgView.append(e + "\n\n連接失敗...\n");
}
}
public static void main(String[] args) {
OmokClient client = new OmokClient("網絡五子棋游戲");
client.setSize(760, 560);
client.setVisible(true);
client.connect();
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -