📄 client.java
字号:
import java.awt.*;
import java.net.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.geom.*;
class OmokBoard extends JPanel
{
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];
setSize(size*(cell+1)+size, size*(cell+1)+size);
/*在棋盘中放下棋子,并向服务器发送信息
*当鼠标按下时响应的动作。记下当前鼠标点击的位置,即当前落子的位置。
*/
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent me){
if(!enable)return;//是否轮到下棋
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=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="开始游戏... 请等待.";
}
}
////游戏停止,向服务器发送[STOPGAME]
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;
}
public void update(Graphics g)
{
paint(g);
}
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);
}
}
//填充颜色
private void drawBlack(int x, int y)
{
Graphics2D gbuff=(Graphics2D)this.gbuff;
gbuff.setColor(Color.black);
gbuff.fillOval(x*cell-cell/2, y*cell-cell/2, cell, cell);
gbuff.setColor(Color.white);
gbuff.drawOval(x*cell-cell/2, y*cell-cell/2, cell, cell);
}
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);
}
//画棋子
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);
}
//调用count方法检查是否为五子相连
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;
}
//count()方法用来查找并计算连在一起的棋子的个数
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 Client extends JFrame implements Runnable, ActionListener//提供一个适当的run()方法实现Runnable接口
{
//五子棋客户端框架的构造函数。用来初始化一些对象、布局和为按钮添加监听器
private Sound music;//播放音乐
private JMenuBar jmb = new JMenuBar();
private JMenu game = new JMenu("游戏");
private JMenu sound = new JMenu("音乐");
private JMenu help = new JMenu("帮助");
JMenuItem start = new JMenuItem("游戏开始",'N');
JMenuItem out = new JMenuItem("游戏退出");
JMenuItem helpp = new JMenuItem("使用说明");
JMenuItem about = new JMenuItem("关于");
JMenuItem quit = new JMenuItem("退出程序");
JMenuItem play = new JMenuItem("播放");
JMenuItem stop = new JMenuItem("停止");
private TextArea msgView=new TextArea("", 1,1,1);
private JTextField sendBox=new JTextField("若群发则在消息前加'a'");
private JTextField nameBox=new JTextField();
private JTextArea showhelp;
JScrollPane scrollHelp;
JPanel panel;
private JTextField roomBox=new JTextField("0");
private JLabel pInfo=new JLabel("游戏大厅: 玩家");
private java.awt.List pList=new java.awt.List();
private JButton stopButton=new JButton("弃权",new ImageIcon(getClass().getResource("img/lose.jpg")));
private JButton startButton=new JButton("游戏开始",new ImageIcon(getClass().getResource("img/start.jpg")));
private JButton enterButton=new JButton("选择房间号");
private JButton exitButton=new JButton("进入游戏室");
private Label infoView=new Label("java五子棋网络版", 1);
private Label timeField=new Label(" ");
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 Client(String title)
{
//窗体布局
super(title);
setLayout(null);
jmb.add(game);
jmb.add(sound);
jmb.add(help);
game.add(start);
game.add(out);
game.addSeparator();
game.add(quit);
help.add(helpp);
help.add(about);
sound.add(play);
sound.add(stop);
this.setJMenuBar(jmb);
showhelp=new JTextArea(8, 30);
scrollHelp = new JScrollPane(showhelp);
showhelp.setEditable(false);
showhelp.append("网络五子棋玩法\n");
showhelp.append("1.输入姓名,点击进入游戏厅\n");
showhelp.append("2.输入房间号,进入房间,一个房间最多可有两个人\n");
showhelp.append("3.点击开始游戏,如果另一个人也开始游戏,则游戏开始,否则等待\n");
showhelp.append("4.可以聊天,最底部文本框中输入内容,按回车发送(群发在前面加'a')\n");
showhelp.append("***************************************\n");
showhelp.append("五子棋规则\n");
showhelp.append("黑棋先下,五子同色相连为胜,如果放弃,则失败\n");
msgView.setEditable(false);
JPanel px=new JPanel();//创建绘图面板
px.setBounds(10,10,480,30);
px.setBackground(new Color(200,200,100));
px.add(infoView);
board.setLocation(10,40);
setBackground(new Color(200,200,100));
add(board);
JPanel p=new JPanel();
p.setBackground(new Color(200,200,100));
p.setLayout(new GridLayout(3,3));
p.add(new JLabel("名字:", 2));
p.add(nameBox);
p.add(new JLabel("对战桌号:", 2));
p.add(roomBox);
p.add(enterButton);
p.add(exitButton);
enterButton.setEnabled(false);
p.setBounds(500,10, 250,70);
JPanel p2=new JPanel();
p2.setBackground(new Color(200,200,100));
p2.setLayout(new BorderLayout());
JPanel p2_1=new JPanel();
p2_1.add(startButton); p2_1.add(stopButton);
p2_1.setBackground(new Color(200,200,100));
p2.add(pInfo,"North"); p2.add(pList,"Center"); p2.add(p2_1,"South");
startButton.setEnabled(false); stopButton.setEnabled(false);
p2.setBounds(500,80,250,210);
JPanel p3=new JPanel();
p3.setLayout(new BorderLayout());
p3.add(msgView,"Center");
p3.add(sendBox, "South");//发送聊天信息
sendBox.setToolTipText("若群发则在消息前加'a'");//浮动提示
p3.setBounds(500, 290, 250,230);
add(px);add(p); add(p2); add(p3);
sendBox.addActionListener(this);
enterButton.addActionListener(this);
exitButton.addActionListener(this);
startButton.addActionListener(this);
stopButton.addActionListener(this);
about.addActionListener(this);
play.addActionListener(this);
stop.addActionListener(this);
quit.addActionListener(this);
start.addActionListener(this);
out.addActionListener(this);
helpp.addActionListener(this);
//添加窗口监听器,当窗口关闭时,关闭用于通讯Socket。
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we)
{
System.exit(0);
}
});
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -