黑马程序员_历经两天半研究的成果:联网版五子棋

来源:互联网 发布:做海报的软件 编辑:程序博客网 时间:2024/05/16 08:13


----------android培训java培训、期待与您交流! ----------

 从十月份学习java到今天,已经两月有余,看完毕姥爷和张孝祥老师的视频,又不系统的看了一些网上关于java的书籍,比如java疯狂讲义,java开发宝典。总想着自己写一些应用,小游戏什么的,娱乐自己,解决遇到的一些小问题。

本来想练练手,写一个五子棋,也就玩玩而已。后来想博客才写了两篇,何不认认真真的做好这个小游戏,将它包装成一篇博客呢?

这就有了下文。

程序中的图片,都是自己ps的,还臭美的贴上了自己的网名。

程序逻辑肯定不是最完美的,比如判定5颗棋是否呈一条直线,应该还有更快捷简便的方法,但是时间有限,就没有再去优化,以后会重新设计逻辑的吧。

下面是程序运行时的界面

 

 

 

 点击建立游戏时,会开启一个线程,线程中开启一个serversocket 服务,监听本地10086端口,当有其他应用访问本地10086端口时,将开启游戏主界面。

 

点击加入游戏后 弹出一个对话框。

 

输入开启10086端口的机器的ip时,将进入到游戏主界面

 

游戏主界面如图

 

 以下是游戏源码,主要是server.java和frame.java

frame.java

package com.itheima;import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.awt.event.MouseMotionListener;import java.awt.image.BufferedImage;import java.io.File;import java.io.IOException;import java.io.OutputStream;import java.net.URL;import javax.imageio.ImageIO;import javax.swing.Icon;import javax.swing.ImageIcon;import javax.swing.JDialog;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JPanel;public class frame extends JFrame {private int Model;private JLabel target;private JPanel chess;private BufferedImage hqimg, bqimg;private JLabel black, white;private int wScorte = 0, bScorte = 0;private int CAMP;private OutputStream os;private Timermsg Jtime;private timer time;//棋子对应的二维数组,当数组中的某一元素的值为1时,添加一颗黑棋,当数组中某一元素值为2,则添加白棋int[][] chessArray = {                                { 0, 0, 0, 0, 0, 0, 0, 0, 0 },       { 0, 0, 0, 0, 0, 0, 0, 0, 0 },                                { 0, 0, 0, 0, 0, 0, 0, 0, 0 },       { 0, 0, 0, 0, 0, 0, 0, 0, 0 },                                { 0, 0, 0, 0, 0, 0, 0, 0, 0 },       { 0, 0, 0, 0, 0, 0, 0, 0, 0 },                                { 0, 0, 0, 0, 0, 0, 0, 0, 0 },       { 0, 0, 0, 0, 0, 0, 0, 0, 0 },                               { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, };//构造函数frame(int CAMP, int Model,OutputStream os) {this.CAMP = CAMP;this.os = os;this.Model=Model;window();}// 将接收到的字符串转化为二维数组public void setChessArray(String str) {for (int x = 0; x < chessArray.length; x++) {for (int y = 0; y < chessArray[x].length; y++) {chessArray[x][y] = str.charAt((x * chessArray[0].length + y)) - 48;}}victoryDecide();chess.repaint();target.setVisible(false);target.setVisible(true);}// 将本地二维数组转换为字符串用于发送public String getChessArray() {StringBuilder sb = new StringBuilder();for (int x = 0; x < chessArray.length; x++) {for (int y = 0; y < chessArray[x].length; y++) {sb.append(chessArray[x][y]);}}return sb.toString();}//改变目标public void changeModel(){Jtime.changeTimermsg();time.changeTimer();}// 主窗口相关设置private void window() {this.setTitle("欢乐五子棋  www.itheima.com 几番意难相付");this.setBounds(100, 100, 505, 600);this.setLayout(null);this.setResizable(false);this.setVisible(true);try {URL hq=this.getClass().getResource("hq.png");URL bq=this.getClass().getResource("bq.png");hqimg = ImageIO.read(hq);bqimg = ImageIO.read(bq);} catch (IOException e) {e.printStackTrace();}msg();choose();addqz();addJtime();bgimg();this.addWindowListener(new close());}// 显示相关信息窗口private void msg() {JLabel jl = new JLabel("黑方得分:");jl.setBounds(0, 5, 100, 20);this.add(jl);JLabel jl2 = new JLabel("白方得分:");jl2.setBounds(0, 35, 100, 20);this.add(jl2);black = new JLabel("0");black.setBounds(80, 5, 100, 20);this.add(black);white = new JLabel("0");white.setBounds(80, 35, 100, 20);this.add(white);}// 设置当前得分private void setScores(int ds, String str) {if (ds == 1) {black.setText(str);} else {white.setText(str);}}// 获取当前得分private String getScores(int x) {if (x == 1) {bScorte = bScorte + 10;} else {wScorte = wScorte + 10;}if (x == 1)return bScorte + "";elsereturn wScorte + "";}// 背景图片:棋盘private void bgimg() {URL img=this.getClass().getResource("qipan.png");Icon ic = new ImageIcon(img);JLabel jl = new JLabel(ic);jl.setBounds(0, 60, 500, 500);add(jl);jl.repaint();}// 鼠标移动时跟随的选择框private void choose() {URL img=this.getClass().getResource("mb.png");Icon icc = new ImageIcon(img);target = new JLabel(icc);target.setSize(50, 50);add(target);}// 将棋子容器添加进主窗体的方法private void addqz() {chess = new jpnel();chess.setBounds(0, 60, 500, 500);add(chess);chess.repaint();chess.addMouseMotionListener(new move());}//添加计时器private void addJtime(){Jtime=new Timermsg(Model);time=new timer(Model);time.setBounds(300, 10, 80, 40);Jtime.setBounds(200, 20, 80, 20);this.add(Jtime);this.add(time);}//计时器前的提示文字class Timermsg extends JLabel{private int model;Timermsg(int model){this.model=model;setOwn();}private void setOwn(){if(model==0){this.setText("等待已方落子");}else{this.setText("等待对方落子");}}public void changeTimermsg(){model=(model+1)%2;setOwn();}}//计时器class timer extends JLabel{private int model;private Thread th;private MouseListener m;timer(int model){this.model=model;setOwn();}private void setOwn(){this.setFont(new Font("",10,40));m=new move();if(model==0){this.setForeground(Color.green);chess.addMouseListener(m);}else{this.setForeground(Color.red);}this.setText("0");th=new Thread(new countdown(this));th.start();}public void changeTimer(){chess.removeMouseListener(m);th.interrupt();model=(model+1)%2;setOwn();}}//计时器计时方法(多线程)class countdown implements Runnable{JLabel jl=null;countdown(JLabel jl){this.jl=jl;}public void run(){int x=30;try{for(int y=x;y>0;y--){Thread.sleep(1000);jl.setText(y+"");}changeModel();sendArray();}catch(Exception e){}finally{jl.setText("");}}}// 棋子的容器 继承了JPanel并复写了其中的paint方法class jpnel extends JPanel {public void paint(Graphics g) {for (int x = 0; x < chessArray.length; x++) {for (int y = 0; y < chessArray[x].length; y++) {if (chessArray[x][y] == 1) {g.drawImage(hqimg, y * 50 + 25, x * 50 + 25, 50, 50,null);} else if (chessArray[x][y] == 2) {g.drawImage(bqimg, y * 50 + 25, x * 50 + 25, 50, 50,null);}}}}}// 鼠标移动监听事件class move extends MouseAdapter implements MouseMotionListener {public void mouseMoved(MouseEvent el) {int mx = (int) el.getPoint().getX();int my = (int) el.getPoint().getY();for (int x = 0; x < chessArray.length; x++) {for (int y = 0; y < chessArray.length; y++) {if (mx > x * 50 + 25 && mx < (x + 1) * 50 + 25&& my > y * 50 + 25 && my < (y + 1) * 50 + 25) {target.setLocation(x * 50 + 25, y * 50 + 85);}}}}// 鼠标点击监听事件public void mouseClicked(MouseEvent e) {int mx = (int) (target.getLocation().getX() - 25) / 50;int my = (int) (target.getLocation().getY() - 60) / 50;if (chessArray[my][mx] == 0) {if (CAMP == 1)chessArray[my][mx] = 1;else {chessArray[my][mx] = 2;}changeModel();sendArray();victoryDecide();}}}// 服务器与客户端间的通信事件private void sendArray() {String str=getChessArray();try {os.write(str.getBytes());os.flush();} catch (IOException e) {e.printStackTrace();}}// 胜利判断private void victoryDecide() {setl2r();setu2d();setu2r();setu2l();chess.repaint();target.setVisible(false);target.setVisible(true);new Thread(new victory()).start();}// 胜利后显示的消息框class dialog {final static int VICTORY_MODEL=1;final static int LOSE_MODEL=2;dialog(int x) {if(x==VICTORY_MODEL)open(VICTORY_MODEL);elseopen(LOSE_MODEL);}public void open(int model) {JDialog jd=null;JLabel jl=null;if(model==VICTORY_MODEL){jd= new JDialog(frame.this, "获胜!",true);jl= new JLabel("哇哦,你真厉害!");}else{jd=new JDialog(frame.this, "失败!",true);jl= new JLabel("失败是成功他妈妈");}jd.setSize(200, 100);jd.setLocationRelativeTo(frame.this);jd.add(jl);jd.setVisible(true);setqz();setScores(1, "0");setScores(2, "0");}}// 判断规则 从左到右public void setl2r() {for (int x = 0; x < chessArray.length; x++) {for (int y = 0; y < chessArray[x].length; y++) {if (chessArray[x][y] != 0 && y < 5) {int con = chessArray[x][y];for (int z = 1; z < 5; z++) {if (chessArray[x][y + z] != con) {break;}if (z == 4) {for (int aa = 0; aa < 5; aa++) {chessArray[x][y + aa] = 0;}setScores(con, getScores(con));}}}}}}// 从上到下public void setu2d() {for (int x = 0; x < chessArray.length; x++) {for (int y = 0; y < chessArray[x].length; y++) {if (chessArray[x][y] != 0 && x < 5) {int con = chessArray[x][y];for (int z = 1; z < 5; z++) {if (chessArray[x + z][y] != con) {break;}if (z == 4) {for (int aa = 0; aa < 5; aa++) {chessArray[x + aa][y] = 0;}setScores(con, getScores(con));}}}}}}// 左上右下public void setu2r() {for (int x = 0; x < chessArray.length; x++) {for (int y = 0; y < chessArray[x].length; y++) {if (chessArray[x][y] != 0 && y < 5 && x < 5) {int con = chessArray[x][y];for (int z = 1; z < 5; z++) {if (chessArray[x + z][y + z] != con) {break;}if (z == 4) {for (int aa = 0; aa < 5; aa++) {chessArray[x + aa][y + aa] = 0;}setScores(con, getScores(con));}}}}}}// 右上左下public void setu2l() {for (int x = 0; x < chessArray.length; x++) {for (int y = 0; y < chessArray[x].length; y++) {if (chessArray[x][y] != 0 && y < 5 && x > 3) {int con = chessArray[x][y];for (int z = 1; z < 5; z++) {if (chessArray[x - z][y + z] != con) {break;}if (z == 4) {for (int aa = 0; aa < 5; aa++) {chessArray[x - aa][y + aa] = 0;}setScores(con, getScores(con));}}}}}}// 胜利后分别给不同的阵营显示不同的消息框class victory implements Runnable {public void run() {if (wScorte == 100&&CAMP==2  || bScorte == 100 && CAMP==1) {new dialog(dialog.VICTORY_MODEL);} else if(wScorte==100 || bScorte ==100){new dialog(dialog.LOSE_MODEL);}}private void loop(){for(int x=0;x<chessArray.length;x++){for(int y=0;y<chessArray[x].length;y++){if(chessArray[x][y]!=0){break;}}}if(wScorte>bScorte&&CAMP==2 || bScorte>wScorte&&CAMP==1){new dialog(dialog.VICTORY_MODEL);}else{new dialog(dialog.LOSE_MODEL);}if(wScorte==bScorte){JOptionPane.showConfirmDialog(frame.this, "和棋","和棋",JOptionPane.OK_OPTION);}}}// 当一方胜利后执行的操作private void setqz() {for (int x = 0; x < chessArray.length; x++) {for (int y = 0; y < chessArray[x].length; y++) {chessArray[x][y] = 0;}}wScorte = bScorte = 0;chess.repaint();target.setVisible(false);target.setVisible(true);}}

 

server.java


package com.itheima;import java.awt.GridLayout;import java.awt.Toolkit;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.BufferedInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import java.net.SocketException;import java.net.UnknownHostException;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JOptionPane;public class server {server(){window();}JFrame jf=null;//游戏模式选择窗体private void window(){jf=new JFrame();jf.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){System.exit(0);}});Toolkit tk=Toolkit.getDefaultToolkit();jf.setSize(150,200);int x=((int)tk.getScreenSize().getWidth()-(int)jf.getSize().getWidth())/2;int y=((int)tk.getScreenSize().getHeight()-(int)jf.getSize().getHeight())/2;jf.setLocation(x, y);jf.setLayout(new GridLayout(2,1,30,30));jf.setResizable(false);choose();jf.setVisible(true);}//选择建立服务端 还是做为客户端连接服务端private void choose(){final JButton create=new JButton("建立游戏");create.addMouseListener(new MouseAdapter() {public void mouseClicked(MouseEvent e){new Thread(new createServer()).start();creatDialog();}});JButton add=new JButton("加入游戏");add.addMouseListener(new MouseAdapter() {public void mouseClicked(MouseEvent e){addClient();}});jf.add(create);jf.add(add);}//选择“建立游戏”后的操作class createServer implements Runnable{public void run(){frame fr=null;try {ServerSocket ss=new ServerSocket(10086);Socket s=ss.accept();OutputStream os=s.getOutputStream();jf.setVisible(false);fr=new frame(1,0,os);InputStream is=s.getInputStream();while(true){BufferedInputStream bis=new BufferedInputStream(s.getInputStream());byte[] by=new byte[1024];int x=0;String str=null;while((x=bis.read(by))!=-1){str=new String(by,0,x);fr.setChessArray(str);fr.changeModel();}}}catch (SocketException e){JOptionPane.showConfirmDialog(fr, "对方已逃跑!点击\"确定\"退出","即将退出",JOptionPane.CLOSED_OPTION);System.exit(0);}  catch (IOException e) {e.printStackTrace();}}}//选择“建立游戏”后 弹出一个对话框  告知玩家private void creatDialog(){JOptionPane.showConfirmDialog(jf,"等待主机连接中...","等待连接",JOptionPane.OK_OPTION);}//选择"加入游戏"后的操作class createCliect implements Runnable{String str;createCliect(String str){this.str=str;}public void run(){frame fr = null;try {Socket s=new Socket(str,10086);OutputStream os=s.getOutputStream();jf.setVisible(false);fr=new frame(2,1,os);while(true){BufferedInputStream bis=new BufferedInputStream(s.getInputStream());byte[] by=new byte[1024];int x=0;String array=null;while((x=bis.read(by))!=-1){array=new String(by,0,x);fr.setChessArray(array);fr.changeModel();}}}catch (SocketException e){JOptionPane.showConfirmDialog(fr, "对方已逃跑!点击\"确定\"退出","即将退出",JOptionPane.CLOSED_OPTION);System.exit(0);} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} }}//选择“加入游戏”后,弹出一个对话框 接收用户输入的ip地址private void addClient(){String str=JOptionPane.showInputDialog("请输入目标主机地址:","192.168.1.103");new Thread(new createCliect(str.trim())).start();}}


main.java

package com.itheima;public class main {public static void main(String[] args) {new server();}}

 

close.java

 

package com.itheima;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;public class close extends WindowAdapter {public void windowClosing(WindowEvent e){System.exit(0);}}

 


总结:关于游戏

游戏有4个类,4张图片

图片:hq.png 黑色棋子的图片

           bq.png 白色棋子的图片

           qipan.png 背景棋盘图片

           mb.png 选择框的图片

类 :close.java  游戏关闭时调用的窗口事件

         frame.java  游戏主界面

         server.java 联网时依赖的逻辑

         main.java 调用该类运行游戏

 

打开游戏后,首先弹出选择框,选择框包含“建立游戏”和“加入游戏”

点击“建立游戏” 弹出一个提示窗口,并开启一个新的线程,线程中开启一个serversocket服务,监听10086端口;

点击“加入游戏” 弹出一个输入窗口,并开启一个新的线程,线程中开启一个socket服务,连接输入窗口中输入的ip地址;

当服务端和客户端成功连接后 弹出游戏主窗体

主窗体中加载背景棋盘图片 加载一个棋子的容器 加载一个计时器 创建一个二维数组 根据本地的状态(是服务端还是客户端)来确定本地的阵营(黑方白方)

给双方添加一个计时器,如果轮到当前玩家下棋,则给当前玩家添加一个鼠标点击事件,计时器开始倒计时。

如果倒计时变为0,或者玩家下完了棋后,移除当前玩家的鼠标点击事件,并将当前的二维数组,发送给对方

如果二位数组中的元素有连续的5个相同的值,就将这5个值都设置为0。如果值为1,则黑方总分加10分,如果为2,则白方加10分

当一方的总分达到100分时,该方胜出。

或者当棋盘不再有剩余空间时,根据当前双方分数的高低来判定胜负。

当一方关闭游戏窗口,退出游戏时。

另一方显示对方逃跑,并关闭本地窗口。

 

 

0 0
原创粉丝点击