围棋作为一个棋类竞技运动,在民间十分流行,为了熟悉围棋规则及技巧,以及研究简单的人工智能,决定用Java开发围棋游戏。主要完成了人机对战和玩家之间联网对战2个功能。网络连接部分为Socket编程应用,客户端和服务器端的交互用Class Message定义,有很好的可扩展性,客户端负责界面维护和收集用户输入的信息,及错误处理。服务器维护在线用户的基本信息和任意两个对战用户的棋盘信息,动态维护用户列表。在人机对弈中通过深度搜索和估值模块,来提高电脑棋手的智能。分析估值模块中的影响精准性的几个要素,以及提出若干提高精准性的办法,以及对它们搜索的节点数进行比较,在这些算法的基础上分析一些提高电脑AI方案,如递归算法、电脑学习等。算法的研究有助于理解程序结构,增强逻辑思维能力,在其他人工智能方面也有很大的参考作用。
直接上代码啦,let’s go
/*************************MainWindow**********************/
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Graphics;
//抽象类,不能用于构造方法创建对象
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Label;
import java.awt.Panel;
import java.awt.Point;
import java.awt.TextField;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
//负责创建标签对象,标签用来显示信息,但没有编辑功能
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JTextField; //利用import引用各类包
public class MainWindow extends Frame implements Runnable
{
Go panelGo=new Go(); //用Go类声明并创建一个panelGo对象
Image myImage;
int PORT;
Socket sendSocket; //主动连接Socket
PrintWriter writer; //用来发送message
boolean stopFlag;
boolean isInitiative;
Point messagePoint;
Point goStartPoint=null; //初始化
Point yellowPoint=null;
boolean stepColor=true;
Point LastPoint=null; //移除黄点时,判断位置变动
BorderLayout borderLayout1 = new BorderLayout(); //用BorderLayout布局
Panel panel1 = new Panel(); //创建面板
Panel panel2 = new Panel();
BorderLayout borderLayout2 = new BorderLayout();
Panel panel3 = new Panel();
CheckboxGroup checkboxGroup1 = new CheckboxGroup(); //选项框
Checkbox checkbox1 = new Checkbox(); //声明创建Checkbox类的对象
Checkbox checkbox2 = new Checkbox();
Label label1 = new Label();
TextField textField1 = new TextField();
Button button1 = new Button();
Label label2 = new Label();
Choice choice1 = new Choice();
Button button2 = new Button();
GridLayout gridLayout1 = new GridLayout(); //利用GridLayout布局
BorderLayout borderLayout3 = new BorderLayout();
public MainWindow() //构造MainWindow方法
{
try
{
jbInit(); //可能发生异常的语句
}
catch(Exception e)
{
e.printStackTrace();
} //异常处理
}
private void jbInit() throws Exception //用关键字throws声明抛出异常
{
choice1.setBackground(new Color(236, 190, 120)); //设置棋盘底色
button1.setBackground(new Color(236, 190, 120));
this.setResizable(false);
new Thread(this).start(); //启动监听线程
this.PORT=1976;
this.isInitiative=false; //是否主动连接
this.stopFlag=false; //是否继续监听的标志
this.choice1.addItem("黑");
this.choice1.addItem("白");
LastPoint=new Point();
messagePoint=new Point();
this.setSize(470,450);
this.setTitle("围棋程序 作者:围棋对弈小组"); //设置标题
this.panelGo.setEnabled(false); //开始之前屏蔽掉盘面
checkbox1.addMouseListener(new java.awt.event.MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
checkbox1_mouseClicked(e);
}
}); //获取监听器
this.goStartPoint=this.panelGo.getLocation(); //
this.setLayout(borderLayout1); //设置背景布局
panel1.setLayout(borderLayout2);
checkbox1.setCheckboxGroup(checkboxGroup1);
checkbox1.setLabel("单机");
checkbox2.setCheckboxGroup(checkboxGroup1);
checkbox2.setLabel("联机"); //设置名为联机的复选框
checkbox2.addMouseListener(new java.awt.event.MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
checkbox2_mouseClicked(e);
}
}); //获取监听器
label1.setText("对方地址");//
button1.setLabel("连接"); //设置名为连接的按钮
button1.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
button1_actionPerformed(e);
}
}); //告诉监听器所发生的事件,并执行方法
label2.setText(" ");
button2.setBackground(new Color(236, 190, 120));
button2.setLabel("开始"); //设置名为开始的按钮
button2.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
button2_actionPerformed(e);
}
}); //
panel3.setLayout(gridLayout1); //设置布局
gridLayout1.setRows(8);
gridLayout1.setColumns(1);
gridLayout1.setHgap(100);
gridLayout1.setVgap(10); //
panel2.setLayout(borderLayout3); //
this.panel2.setSize(500,70); //
panelGo.addMouseMotionListener(new java.awt.event.MouseMotionAdapter()
{
public void mouseMoved(MouseEvent e)
{
panelGo_mouseMoved(e);
}
}); //获取监听器
panelGo.addMouseListener(new java.awt.event.MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
panelGo_mouseClicked(e);
}
}); //获取监听器
this.addWindowListener(new java.awt.event.WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
this_windowClosing(e);
}
}); //获取监听器
panel3.setBackground(new Color(236, 190, 120)); //设置背景颜色
//初始化创建的对象
panel3.add(checkbox1, null);
panel3.add(checkbox2, null);
panel3.add(label1, null);
panel3.add(textField1, null);
panel3.add(button1, null);
panel3.add(choice1, null);
panel3.add(button2, null);
panel3.add(label2, null);
this.panel1.add(this.panelGo,BorderLayout.CENTER); //将panelGo添加到BorderLayout布局的中间
this.panel1.add(panel3, BorderLayout.EAST); //将pane13添加到BorderLayout布局的东区域
this.add(panel2, BorderLayout.SOUTH); //将pane12添加到BorderLayout布局的南区域
this.add(panel1, BorderLayout.CENTER); //将pane13添加到BorderLayout布局的中间
this.disableLink(); //废掉控件
this.checkboxGroup1.setSelectedCheckbox(this.checkbox1); //如果复选框处于选中状态该方法返回true,否则返回false
this.yellowPoint=new Point(1000,1000); //初始化一个世纪外的黄点
this.centerWindow();
loginDialog(this); //调用loginDialog方法传进参数this
}
/************用户登录界面************/
private JDialog login; //声明一个私有类变量
private void loginDialog(final Frame frame) {
login = new JDialog();
login.setTitle("登录"); //设置标题
login.setLayout(new FlowLayout()); //利用流布局来设置窗口的布局
login.add(new JLabel("用户名:")); //添加标签为用户名的对象
final JTextField name = new JTextField(10); //设置文本框中字符不得超过10个
login.add(name);
login.add(new JLabel("密 码:"));
final JPasswordField password = new JPasswordField(10); //设置密码框中字符不得多于10个
password.setEchoChar(‘*‘); //设置显示密码对应的字符为*
login.add(password);
JButton confirm = new JButton("登录"); //定义一个登录按钮
confirm.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (compareUserData(name.getText().trim(), new String(password.getPassword()))) {
login.setVisible(false);
frame.show();
myImage=frame.createImage(16,16);//用来纪录有黄点之前的图像
} else {
JOptionPane.showMessageDialog(login, "用户名或密码错误!", "错误提示", JOptionPane.ERROR_MESSAGE);
}
}
}); //获取监听器,并执行事件
login.add(confirm);
final JDialog regDialog = new JDialog(login, "注册", true); //定义一个对象,该对象无法被继承
registerDialog(regDialog);
JButton register = new JButton("注册"); //设置注册的按钮
register.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
regDialog.setVisible(true);
}
}); //获取监听器,执行regDialog为可见
login.add(register);
login.setSize(200, 130);
login.setResizable(false);
login.setLocationRelativeTo(null);
login.setVisible(true); //确保窗体里面的组件可见
}
private boolean compareUserData(String name, String password) {
try {
RandomAccessFile out = new RandomAccessFile("user.dat", "rw");
String fname, fpassword = null;
while (out.getFilePointer() < out.length()) {
fname = out.readUTF();
out.readUTF();
fpassword = out.readUTF();
if (fname.equals(name) && fpassword.equals(password)) return true;
}
out.close(); //可能发生异常的语句
} catch (IOException e) {
e.printStackTrace();
} //异常语句的处理
return false;
}
private void registerDialog(final JDialog regDialog) {
Box box1 = Box.createVerticalBox();
box1.add(new JLabel("用户名:", JLabel.RIGHT)); //添加用户名标签,用户名在标签中靠右对齐
box1.add(Box.createVerticalStrut(10));
box1.add(new JLabel("性别:", JLabel.RIGHT)); //添加性别标签,性别在标签中靠右对齐
box1.add(Box.createVerticalStrut(10));
box1.add(new JLabel("密码:", JLabel.RIGHT), -1); //添加密码标签,密码在标签中靠右对齐
box1.add(Box.createVerticalStrut(10));
box1.add(new JLabel("确认密码:", JLabel.RIGHT)); //添加确认密码标签,确认密码在标签中靠右对齐
Box box2 = Box.createVerticalBox();
final JTextField nameTextField = new JTextField(10); //设置用户名文本框字符不得超过10个,且文本框不能被继承
box2.add(nameTextField);
box2.add(Box.createVerticalStrut(8));
final CheckboxGroup cbg = new CheckboxGroup();
Box box21 = Box.createHorizontalBox();
final Checkbox cb1 = new Checkbox("男", cbg, true); //复选框默认状态选定为男性
box21.add(cb1);
box21.add(new Checkbox("女", cbg, false)); //当鼠标点击女性复选框时,flase自动变为true
box2.add(box21);
box2.add(Box.createVerticalStrut(8));
//定义密码框中的字符长度小于10个
final JPasswordField pass1 = new JPasswordField(10);
box2.add(pass1);
box2.add(Box.createVerticalStrut(8));
final JPasswordField pass2 = new JPasswordField(10);
box2.add(pass2);
Box baseBox = Box.createHorizontalBox();
baseBox.add(box1);
baseBox.add(box2);
regDialog.setLayout(new FlowLayout());
regDialog.add(baseBox);
JButton confirm = new JButton("确定"); //创建并声明确定按钮
JButton cancel = new JButton("取消"); //创建并声明取消按钮
regDialog.add(confirm);
regDialog.add(cancel);
regDialog.setSize(200, 200); //设置大小
regDialog.setResizable(false);
regDialog.setLocationRelativeTo(null);
confirm.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String sex = null;
if (cbg.getSelectedCheckbox() == cb1)
sex = "男";
else
sex = "女";
if (saveUserData(nameTextField.getText().trim(), sex,
new String(pass1.getPassword()), new String(pass2.getPassword())))
regDialog.setVisible(false);
else
JOptionPane.showMessageDialog(regDialog, "输入有误,请检查", "错误提示",
JOptionPane.ERROR_MESSAGE);
}
}); //获取监听器
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
regDialog.setVisible(false);
}
}); //获取监听器
}
private boolean saveUserData(String name, String sex, String password1, String password2) {
if (!password1.equals(password2)) return false;
try {
RandomAccessFile out = new RandomAccessFile("user.dat", "rw");
out.seek(out.length());
out.writeUTF(name);
out.writeUTF(sex);
out.writeUTF(password1);
out.close(); //可能发生异常的语句
} catch (IOException e) {
e.printStackTrace();
return false;
} //异常的处理
return true;
}
void centerWindow()
{
//返回一个Dimension对象的引用,该对象实体中含有名字是width和height的成员变量。
Dimension d=Toolkit.getDefaultToolkit().getScreenSize();
int pX=(d.width-this.getWidth())/2;
int pY=(d.height-this.getHeight())/2;
this.setLocation(pX,pY);
}
/**********主方法*************/
public static void main(String args[])
{
MainWindow main=new MainWindow();
}
//监听线程
public void run()
{
try
{
ServerSocket serverSocket=new ServerSocket(PORT);
Socket receiveSocket=null;
receiveSocket=serverSocket.accept();
if(this.isInitiative) //如果已在进行,则不接受连接
this.stopFlag=true;
this.checkboxGroup1.setSelectedCheckbox(this.checkbox2); //自动选择联机
this.button1.setEnabled(false);
this.choice1.setEnabled(true);
this.textField1.setEnabled(false);
this.checkbox1.setEnabled(false);
this.checkbox2.setEnabled(false);
this.writer=new PrintWriter(receiveSocket.getOutputStream(),true);
BufferedReader reader=new BufferedReader(new InputStreamReader(receiveSocket.getInputStream()));
String message;
while(!this.stopFlag)
{
this.panelGo.showError("接收连接成功");
message=reader.readLine(); //按行读取文件中的内容
this.doMessage(message);
}
reader.close();
receiveSocket.close();
serverSocket.close();
}catch(IOException ioe){this.panelGo.showError("意外中断");}
}
//处理接收到的信息
void doMessage(String message)
{
if(message.startsWith("start"))//判断开始
{
this.panelGo.showError("对方已开始");
if(message.equals("start_black"))
this.choice1.select("白");
else
this.choice1.select("黑");
if(this.choice1.getSelectedItem().equals("黑"))//只要你是黑的,就先走
this.panelGo.setEnabled(true);
this.paintMyColor();//表明颜色
this.disableLink();
}
else//下子的信息
{
int color=Integer.parseInt(message.substring(0,1));
this.messagePoint.x=Integer.parseInt(message.substring(1,3));
this.messagePoint.y=Integer.parseInt(message.substring(3,5));
this.panelGo.setEnabled(true);//解禁
this.panelGo.doStep(this.messagePoint,color);
}
}
//为鼠标定位
void panelGo_mouseMoved(MouseEvent e)
{
Point realPoint=e.getPoint();
Point mousePoint=this.panelGo.getMousePoint(realPoint,this.goStartPoint);
this.removeLastMousePoint(this.LastPoint,mousePoint);
this.LastPoint.x=mousePoint.x;
this.LastPoint.y=mousePoint.y;
if(this.isPlace(mousePoint))
this.showMousePoint(mousePoint);
}
//加黄点的范围
boolean isPlace(Point p)
{
if(p.x>19||p.x<1||p.y<1||p.y>19)
return false;
int color;
One one;
one=(One)(this.panelGo.myHash.get(p));
color=one.color;
if(color!=0)
return false;
return true;
}
void panelGo_mouseClicked(MouseEvent e)
{
if(this.isSingle())
{
this.doSingle();
}
else
{
this.doMultiple();
}
}
//开始
void button2_actionPerformed(ActionEvent e)
{
if(e.getActionCommand().equals("开始"))
{
this.disableLink();
this.checkbox1.setEnabled(false);
this.checkbox2.setEnabled(false);
this.button2.setLabel("退出");
if(this.isSingle())
this.panelGo.setEnabled(true);
else//联机版时
{
if(this.choice1.getSelectedItem().equals("黑"))
{
this.writer.println("start_black");
}
else
this.writer.println("start_white");
}
this.paintMyColor();//表明颜色
}
else if(e.getActionCommand().equals("退出"))
{
this.dispose();
System.exit(0);
}
}
//disable联机时用的控件
void disableLink()
{
this.textField1.setBackground(new Color(236, 190, 120));
this.textField1.setEnabled(false);
this.choice1.setEnabled(false);
this.button1.setEnabled(false);
}
//enable联机时的控件
void enableLink()
{
this.textField1.setBackground(Color.white);
this.textField1.setEnabled(true);
this.choice1.setEnabled(true);
this.button1.setEnabled(true);
}
//判断类型
boolean isSingle()
{
return this.checkbox1.getState();
}
void single()
{
}
void multiple()
{
}
//加小黄点
void showMousePoint(Point mousePoint)
{
Graphics g=this.panelGo.getGraphics();
g.setColor(Color.yellow);
g.fillOval(mousePoint.x*20-6,mousePoint.y*20-6,this.panelGo.INTERVAL-8,this.panelGo.INTERVAL-8);
this.yellowPoint.x=mousePoint.x;//定位黄点
this.yellowPoint.y=mousePoint.y;
Graphics myG=this.myImage.getGraphics();
this.createMyImage(myG,this.yellowPoint,0);
}
//消除前一个黄点
void removeLastMousePoint(Point thatPoint,Point thisPoint)
{
if(thatPoint.x!=thisPoint.x||thatPoint.y!=thisPoint.y)
{
Graphics g=this.panelGo.getGraphics();
if(this.yellowPoint!=null&&this.myImage!=null)
g.drawImage(this.myImage,this.yellowPoint.x*20-8,this.yellowPoint.y*20-8,16,16,null);
this.yellowPoint.x=1000;//不在范围内,就一边去
this.yellowPoint.y=1000;
}
}
//构成所需要的Image
void createMyImage(Graphics g,Point thisPoint,int color)
{
int px=thisPoint.x;
int py=thisPoint.y;
Color myColor=this.panelGo.getBackground(); //设置背景色
//设置棋盘线
if(px==1&&py==1&&color==0)//四个角
{
g.setColor(myColor);
g.fillRect(0,0,16,16);
g.setColor(Color.black);
g.drawLine(8,8,8,16);
g.drawLine(5,5,5,16);
g.drawLine(8,8,16,8);
g.drawLine(5,5,16,5);
}
else if(px==1&&py==19&&color==0)
{
g.setColor(myColor);
g.fillRect(0,0,16,16);
g.setColor(Color.black);
g.drawLine(8,8,8,0);
g.drawLine(8,8,16,8);
g.drawLine(5,11,16,11);
g.drawLine(5,11,5,0);
}
else if(px==19&&py==1&&color==0)
{
g.setColor(myColor);
g.fillRect(0,0,16,16);
g.setColor(Color.black);
g.drawLine(8,8,8,16);
g.drawLine(8,8,0,8);
g.drawLine(11,5,11,16);
g.drawLine(11,5,0,5);
}
else if(px==19&&py==19&&color==0)
{
g.setColor(myColor);
g.fillRect(0,0,16,16);
g.setColor(Color.black);
g.drawLine(8,8,8,0);
g.drawLine(8,8,0,8);
g.drawLine(11,11,11,0);
g.drawLine(11,11,0,11);
}
else if(px==1&&color==0)//四个边
{
g.setColor(myColor);
g.fillRect(0,0,16,16);
g.setColor(Color.black);
g.drawLine(8,8,16,8);
g.drawLine(8,0,8,16);
g.drawLine(5,0,5,16);
}
else if(px==19&&color==0)
{
g.setColor(myColor);
g.fillRect(0,0,16,16);
g.setColor(Color.black);
g.drawLine(8,8,0,8);
g.drawLine(8,0,8,16);
g.drawLine(11,0,11,16);
}
else if(py==1&&color==0)
{
g.setColor(myColor);
g.fillRect(0,0,16,16);
g.setColor(Color.black);
g.drawLine(8,8,8,16);
g.drawLine(0,8,16,8);
g.drawLine(0,5,16,5);
}
else if(py==19&&color==0)
{
g.setColor(myColor);
g.fillRect(0,0,16,16);
g.setColor(Color.black);
g.drawLine(8,8,8,0);
g.drawLine(0,8,16,8);
g.drawLine(0,11,16,11);
}
//八个小黑点
else
if(color==0&&((px==4&&py==4)||(px==4&&py==10)||(px==4&&py==16)||(px==10&&py==4)||(px==10&&py==10)||(px==10&&py==16)||(px==16&&py==4)||(px==16&&py==10)||(px==16&&py==16)))
{
g.setColor(myColor);
g.fillRect(0,0,16,16);
g.setColor(Color.black);
g.drawLine(0,8,16,8);
g.drawLine(8,0,8,16);
g.fillOval(5,5,6,6);
}
else if(color==0)
{
g.setColor(myColor);//
g.fillRect(0,0,16,16);
g.setColor(Color.black);
g.drawLine(0,8,16,8);
g.drawLine(8,0,8,16);
}
}
//单机版走步
void doSingle()
{
if(this.stepColor)
this.panelGo.doStep(this.yellowPoint,1);
else
this.panelGo.doStep(this.yellowPoint,2);
if(!this.panelGo.errorFlag)//如果不违例,则换颜色
{
this.stepColor=!this.stepColor;
this.paintThisColor(this.stepColor);
}
else
this.panelGo.errorFlag=false;
this.yellowPoint.x=1000;//刚走的子不至于删掉
this.yellowPoint.y=1000;
}
//联机版走步
void doMultiple()
{
int color;
if(this.choice1.getSelectedItem().equals("黑"))
color=1;
else
color=2;
this.panelGo.doStep(this.yellowPoint,color);
//如果走法不对,返回
if(this.panelGo.errorFlag)
{
this.panelGo.errorFlag=false;
return;
}
this.panelGo.setEnabled(false);
String message=this.getMessage(color,this.yellowPoint.x,this.yellowPoint.y);
this.writer.println(message);
this.yellowPoint.x=99;//刚走的子不至于删掉,还要可以解析
this.yellowPoint.y=99;
}
//处理发送字符串
String getMessage(int color,int x,int y)
{
String strColor=String.valueOf(color);
String strX;
String strY;
//如果单数的话,就加一位
if(x<10)
strX="0"+String.valueOf(x);
else
strX=String.valueOf(x);
if(y<10)
strY="0"+String.valueOf(y);
else
strY=String.valueOf(y);
return strColor+strX+strY;
}
void this_windowClosing(WindowEvent e)
{
this.dispose();
System.exit(0);
}
void checkbox2_mouseClicked(MouseEvent e)
{
this.enableLink();
}
void checkbox1_mouseClicked(MouseEvent e)
{
this.disableLink();
}
void button1_actionPerformed(ActionEvent e)
{
this.goToLink(this.textField1.getText().trim(),this.PORT);
}
//主动连接serverSocket
void goToLink(String hostName,int port)
{
try
{
this.stopFlag=true;
this.sendSocket=new Socket(hostName,port);
this.panelGo.showError("连接成功!!");
this.choice1.setEnabled(true);
this.button1.setEnabled(false);
this.checkbox1.setEnabled(false);
this.checkbox2.setEnabled(false);
this.textField1.setEnabled(false);
this.writer=new PrintWriter(this.sendSocket.getOutputStream(),true);
new Listen(sendSocket,this).start();
}
catch(IOException ioe){
this.panelGo.showError("意外中断");
}
}
//开始时根据颜色画己方颜色
void paintMyColor()
{
Graphics g=this.label2.getGraphics();
if(this.choice1.getSelectedItem().equals("黑"))
g.fillOval(20,10,30,30);
else
{
g.setColor(Color.white);
g.fillOval(20,10,30,30);
g.setColor(Color.black);
g.drawOval(20,10,30,30);
}
}
//单机版画每步颜色
void paintThisColor(boolean whatColor)
{
Graphics g=this.label2.getGraphics();
if(whatColor)
g.fillOval(20,10,30,30);
else
{
g.setColor(Color.white);
g.fillOval(20,10,30,30);
g.setColor(Color.black);
g.drawOval(20,10,30,30);
}
}
}
/***********************Go*************************************/
import java.awt.*;
import java.util.*;//引入包
public class Go extends Panel
{
int whichStep;
Hashtable myHash;
Point pointNow; //当前的点
Point STARTPOINT; //起始点
int INTERVAL; //等高距
Vector vec; //定义矢量
Point robPoint; //打劫点
Point mousePoint; //鼠标点
boolean errorFlag; //行棋错误标志
//构建器
public Go()
{
super(); //super函数,方便子类调用父类里面的成员变量与构造方法
pointNow=new Point(1000,1000); //把初始红点画在外面
errorFlag=false; //行棋错误标志
whichStep=0;
STARTPOINT=new Point(20,20); //新的点所在的位置
INTERVAL=20; //棋盘的间隔
myHash=new Hashtable(); //创建对象
robPoint=null; //打劫点
mousePoint=new Point(); //开辟鼠标点内存
vec=new Vector(); //存放校验的子
this.initMyHash(STARTPOINT,INTERVAL);
try
{
jbInit();
}
catch(Exception e)
{
e.printStackTrace();
} //异常处理
}
//初始化hashtable
void initMyHash(Point startPoint,int interval)
{
One one;
Point key; //逻辑点标志
int i,j; //定义i,j
for(i=1;i<=19;i++)
for(j=1;j<=19;j++) //循环
{
key=new Point(i,j);
one=new One(); //创建对象
one.posX=startPoint.x+(i-1)*interval;//相邻点处理,获取
one.posY=startPoint.y+(j-1)*interval;//相邻点处理。获取//获取相邻点
one.pointAround[0]=new Point(i,j-1); //上
one.pointAround[1]=new Point(i,j+1); //下
one.pointAround[2]=new Point(i-1,j); //左
one.pointAround[3]=new Point(i+1,j); //右
if(i==1)one.pointAround[2]=one.OUT; //左的周围
if(i==19)one.pointAround[3]=one.OUT; //右的周围
if(j==1)one.pointAround[0]=one.OUT; //上的周围
if(j==19)one.pointAround[1]=one.OUT; //下的周围
myHash.put(key,one); //我的我的哈希表并且在里键入关键字
}
}
//更新盘面
public void paint(Graphics g)
{
Point startPoint=STARTPOINT; //创建对象,开始点
int interval=INTERVAL; //定义成员变量
this.paintChessboard(g,startPoint,interval); //棋盘的操作
this.paintChessman(g,startPoint,interval); //棋子的操作
}
//画棋盘
void paintChessboard(Graphics g,Point startPoint,int interval)
{
int pX=startPoint.x; //定义相邻点X
int pY=startPoint.y; //相邻点Y
int LINELENGTH=interval*18; //定义路线长度
int i;
for(i=0;i<19;i++)
{
g.drawLine(pX+i*interval,pY,pX+i*interval,pY+LINELENGTH);
g.drawLine(pX,pY+i*interval,pX+LINELENGTH,pY+i*interval);
}//for循环,以便构造19*19的棋盘
g.fillOval(pX+interval*3-3,pY+interval*3-3,(int)(interval-14),(int)(interval-14));
g.fillOval(pX+interval*9-3,pY+interval*3-3,(int)(interval-14),(int)(interval-14));
g.fillOval(pX+interval*15-3,pY+interval*3-3,(int)(interval-14),(int)(interval-14));
g.fillOval(pX+interval*3-3,pY+interval*9-3,(int)(interval-14),(int)(interval-14));
g.fillOval(pX+interval*9-3,pY+interval*9-3,(int)(interval-14),(int)(interval-14));
g.fillOval(pX+interval*15-3,pY+interval*9-3,(int)(interval-14),(int)(interval-14));
g.fillOval(pX+interval*3-3,pY+interval*15-3,(int)(interval-14),(int)(interval-14));
g.fillOval(pX+interval*9-3,pY+interval*15-3,(int)(interval-14),(int)(interval-14));
g.fillOval(pX+interval*15-3,pY+interval*15-3,(int)(interval-14),(int)(interval-14));
//路线长度和间隔的确定
g.drawRect(pX-3,pY-3,366,366);//棋盘大小
}
//加棋子
void paintChessman(Graphics g,Point startPoint,int interval)
{//加入棋子,并且是按照一黑一白
int pX=startPoint.x; //相邻点X
int pY=startPoint.y; //相邻点Y
Enumeration enun=myHash.elements(); //创建对象
while(enun.hasMoreElements())
{
One one=(One)enun.nextElement();
if(one.color!=one.BLANK)
{
if(one.color==one.BLACK)
g.setColor(Color.black);
else if(one.color==one.WHITE)
g.setColor(Color.white);
else
break; //如果盘里加满了棋子,则跳出循环
g.fillOval(one.posX-8,one.posY-8,interval-4,interval-4);
//路线长度
g.setColor(Color.black); //获取颜色
g.drawOval(one.posX-8,one.posY-8,interval-4,interval-4);
//画椭圆
}
}
g.setColor(Color.red); //画红点
g.fillOval(this.pointNow.x*20-5,this.pointNow.y*20-5,10,10);
//路线间隔
}
//处理每一步
void doStep(Point whatPoint,int whatColor)
{
//如果点在盘外,返回
if(whatPoint.x<1||whatPoint.x>19||whatPoint.y<1||whatPoint.y>19)
{
this.showError("不能下在此处");
this.errorFlag=true; //在棋盘外,出错
return;
}
//如果点上有子,则返回
if(((One)myHash.get(whatPoint)).color!=0)
{
this.showError("此处已有子");
this.errorFlag=true; //此点已经有棋子了,不能下
return;
}
//如果已经开劫了,则应先应劫,否则返回
if(this.isRob(whatPoint))
{
this.showError("已经开劫,请先应劫");
this.errorFlag=true;
return;
}
this.updateHash(whatPoint,whatColor); //我的棋子所在的地方
this.getRival(whatPoint,whatColor); //对手的棋子所在的地方
//如果没有气也没有己类
if(!this.isLink(whatPoint,whatColor)&&!this.isLink(whatPoint,0))
//0相当于one.BLANK
{
this.showError("此处不可放子");
this.errorFlag=true;
this.singleRemove(whatPoint); //棋子所在的地方
return;//返回
}
this.pointNow.x=whatPoint.x;
this.pointNow.y=whatPoint.y; //得到当前红点
this.repaint(); //返回到当前的点
}
//取异类并判断执行吃子
void getRival(Point whatPoint,int whatColor)
{
boolean removeFlag=false; //判断这一步到底吃没吃子
One one;
one=(One)(this.myHash.get(whatPoint)); //确定该步的位置
Point otherPoint[]=one.pointAround; //该步周围的棋子
int i;
for(i=0;i<4;i++)
{
One otherOne=(One)(this.myHash.get(otherPoint[i]));//举出异类实例
if(!otherPoint[i].equals(one.OUT))
if(otherOne.color!=one.BLANK&&otherOne.color!=whatColor)
{
if(this.isRemove(otherPoint[i])) //如果有气
this.vec.clear(); //不吃子
else
{
this.makeRobber(otherPoint[i]);
this.doRemove(); //进行吃子行为
this.vec.clear(); //改点被清空
removeFlag=true; //返回
}
}
}
if(!removeFlag)
this.robPoint=null; //如果没吃子的话消掉打劫点
}
//判断是否因打劫不能下
boolean isRob(Point p)
{
if(this.robPoint==null) //打劫点不存在
return false; //返回错误
if(this.robPoint.x==p.x&&this.robPoint.y==p.y) //打劫点存在进行判断
return true; //返回正确
return false; //返回错误
}
//建立打劫点
void makeRobber(Point point)
{
if(this.vec.size()==1)
this.robPoint=point; //建立新打劫点
else
this.robPoint=null; //吃多个的话消掉打劫点
}
//判断吃子
boolean isRemove(Point point)
{
if(this.vec.contains(point))
return false;
if(this.isLink(point,0)) //有气的话
return true;
this.vec.add(point); //没有气就加入这个点
One one;
one=(One)(this.myHash.get(point)); //创建新的点
Point otherPoint[]=one.pointAround; //新的点周围的棋子
int i;
for(i=0;i<4;i++)
{
One otherOne=(One)(this.myHash.get(otherPoint[i]));//举出同类实例
if(!otherPoint[i].equals(one.OUT)) //如果周围的点不等同于输入点的颜色
if(otherOne.color==one.color) //如果周围的点是颜色相同
if(this.isRemove(otherPoint[i])) //这里递归,移除
return true;
}
return false;
}
//执行消子
void doRemove() //执行消棋子的步骤
{
Enumeration enun=this.vec.elements(); //列出各种情况
while(enun.hasMoreElements())
{
Point point=(Point)enun.nextElement(); //指向下一个元素
this.singleRemove(point); //单独移除的点
}
}
//消单个子
void singleRemove(Point point)
{
One one=(One)(this.myHash.get(point));
one.isthere=false;
one.color=one.BLANK;
Graphics g=this.getGraphics();
g.clearRect(point.x*20-8,point.y*20-8,20,20); //删除画面上的子
}
//判断有气
boolean isLink(Point point,int color) //进行判断是否有气
{
One one;
one=(One)(this.myHash.get(point)); //新输入的点
Point otherPoint[]=one.pointAround; //周围的点
int i;
for(i=0;i<4;i++)
{
One otherOne=(One)(this.myHash.get(otherPoint[i]));//举出同类实例
if(!otherPoint[i].equals(one.OUT)) //如果周围的点不等同于输入的点的颜色
if(otherOne.color==color) //如果周围的点颜色相同
{
return true; //返回TRUE
}
}
return false; //如果不满足,返回错误
}
//每一步更新myHash
void updateHash(Point whatPoint,int whatColor) //更新操作
{
One one=(One)(this.myHash.get(whatPoint)); //创建myHash
one.isthere=true; //所下的点符合
one.color=whatColor; //确定颜色
this.whichStep=this.whichStep+1; //走步增加1
one.whichStep=this.whichStep; //确定走步
}
Point getMousePoint(Point p1,Point p2) //p1为真实点,p2为相对原点
{
this.mousePoint.x=Math.round((float)(p1.x-p2.x)/this.INTERVAL);
//用四舍五入计算逻辑点位置
this.mousePoint.y=Math.round((float)(p1.y-p2.y)/this.INTERVAL);
//用四舍五入计算逻辑点位置
return this.mousePoint; //返回该位置
}
//显示错误信息
void showError(String errorMessage)
{
Graphics g=this.getGraphics(); //创建图g
g.setColor(new Color(236,190,98)); //定义错误信息的颜色
g.fillRect(20,400,30,200); //路线长度
g.setColor(Color.red); //画红点
g.drawString(errorMessage,60,415); //错误信息
g.fillOval(20,400,20,20); //路线间隔
}
private void jbInit() throws Exception //扔出错误
{
this.setBackground(new Color(236, 190, 120)); //背景色
}
}
/*************************One************************/
import java.awt.*;
public class One
{
int BLACK=1;//定义黑子等于1
int WHITE=2;//定义白子为2
int BLANK=0;
Point OUT=new Point(-1,-1);
int whichStep;
int color=BLANK; //定义颜色
boolean isthere=false;//此处为错误的
Point pointAround[]={OUT,OUT,OUT,OUT};
int posX; //定义相邻点X
int posY; //定义相邻点Y
}
/*******************GoApplet**************************/
import java.applet.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;//引用相应的包
public class GoApplet extends Applet
{
public void init()//创建对象
{
new MainWindow().show();//主窗口
}
}
/***********************Listen******************************/
import java.io.*;
import java.net.*;
public class Listen extends Thread //继承
{
Socket socket;
MainWindow mainWindow; //主窗口
public Listen(Socket socket,MainWindow mainWindow) //监听
{
this.socket=socket; //使用this区分成员变量和局部变量
this.mainWindow=mainWindow; //使用this区分成员变量和局部变量
}
public void run() //运行
{
try
{
this.activeListen(this.socket);
}
catch(IOException ioe){ //异常处理
this.mainWindow.panelGo.showError("意外中断");
}
}
void activeListen(Socket socket) throws IOException //活动监听者
{
BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//缓冲流
String message; //键入通知
while(true)
{
message=reader.readLine(); //读入信息
this.mainWindow.doMessage(message); //在主窗口中执行读取的信息
}
}
}
运行登录后的主界面如下:
时间: 2024-10-06 22:43:57