五子棋(java版)

五子棋

  1. 目录结构
    结构如图所示

1. Test.java

package com.fivechess;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class Test {
	public static void main(String[] args) {
		FiveChessFrame fi=new FiveChessFrame();
		
	}

}
class  FiveChessFrame  extends JFrame implements MouseListener,Runnable{
	
//	private static final Image bgImage = null;
	int width = Toolkit.getDefaultToolkit().getScreenSize().width;//获取屏幕宽度
    int height = Toolkit.getDefaultToolkit().getScreenSize().height;//获取屏幕高度
    int x=0;// 鼠标点击的x坐标
    int y=0;// 鼠标点击的y坐标
    int[][] allChess = new int [19][19];	// 保存棋子的状态  0:无棋子  1:黑子  2:白子
    //标识当前是黑棋还是白棋
    boolean isBlack=true;
    boolean canPlay = true;
    String message="黑方先行";//保存要提示的信息;
    boolean flag = false;   //判断谁落子
    
   
/
    class Position {
        int listx;
        int listy;
    }

    class chessUI extends JPanel {
        public Position[] ps = new Position[300];
        int i;
    }

    chessUI ui = new chessUI();
    Position p = new Position();
//
	
    int maxTime = 0;//保存最多拥有多少秒
   
   Thread t = new Thread((Runnable) this);//做倒计时的线程类
   
   保存黑方与白方的剩余时间
       int blackTime=0;
       int whiteTime=0;
    
 
       String blackMessage="无限制";
       String whiteMessage="无限制";
       
	//第一步:窗体设置
	public FiveChessFrame(){
		    this.setTitle("欢乐五子棋"); //标题
	        this.setSize(500, 530); //窗口大小
	        this.setResizable(false); //窗口是否可以改变大小=否
	        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗口关闭方式为关闭窗口同时结束程序
//	        System.out.println("宽度:"+width);//测试
//	        System.out.println("高度:"+height);//测试
	        this.setLocation((width - 500) / 2, (height - 500) / 2); //设置窗口默认位置以屏幕居中
	        this.addMouseListener((MouseListener) this);
	        this.setVisible(true); //窗口是否显示
	        
	       


	      //做倒计时的线程类
	        t.start();
	        t.suspend();  //将线程挂起
	        this.repaint();
	        
	}
	
	///初始化
	public void init() {
	现在重新开始游戏
		   /*
		    * 1.清空棋盘,即将allChess全部数据归零
		    * 2.将游戏信息:的显示改回到开始位置
		    * 3.将下一步下棋的人改为黑方;
		    */
		   for(int i=0;i<19;i++) {  
				for(int j=0;j<19;j++) {
					allChess[i][j]=0;
				}
		   }
		   
		   message ="黑方先行";
		   isBlack=true;
		   blackTime=maxTime;
		   whiteTime=maxTime;
		   if(maxTime>0) {
			   blackMessage = maxTime/3600+ ":" + (maxTime/60-maxTime/3600*60) + ":" + (maxTime-maxTime/60*60);
			   whiteMessage = maxTime/3600+ ":" + (maxTime/60-maxTime/3600*60) + ":" + (maxTime-maxTime/60*60);
			   t.resume();
		   }else {
			   blackMessage="无限制";
		       whiteMessage="无限制";
		       t.suspend();
		   }
	}
/第二步:实现接口///
	
	    //鼠标抬起
	    public void mouseClicked(MouseEvent e) {

	    }
	    //鼠标按下
	    public void mousePressed(MouseEvent e) {
	    	
	第六步:是否开始游戏 ///
	  
	   if(canPlay == true) {
	    	x=e.getX();
	    	y=e.getY();
	    
	    	ui.ps[ui.i]=p;//保存坐标
	    	if(x>=11&&x<=371&&y>=81&&y<=440) {
	    		
	    		
	    		x = Math.round((x-11)/20f);
	    		y=  Math.round((y-80)/20f);
	    		if(allChess[x][y]== 0) {
	    		if(isBlack==true) {
	    			allChess[x][y]=1;
	    			isBlack	=false;	
	    			message="轮到白方";//seven第七步:游戏信息;
	    			
	    		}else {
	    			allChess[x][y]=2;
	    	    	isBlack	=true;	
	    	    	message="轮到黑方";//seven第七步:游戏信息;
	    		}
	    		
	    		ui.ps[ui.i].listx = x;
                ui.ps[ui.i].listy = y;
                ui.i++;

                this.repaint();
	    		第五步:判断这个棋子是否和其他棋子连成五个,判断是否结束;
	    		boolean winFlag = this.checkWin();
	    		
	    		if(winFlag == true) {
	    			t.suspend();
	    			JOptionPane.showMessageDialog(this,"游戏结束!!!"+(allChess[x][y] == 1 ? "黑方" : "白方" )+"获胜!!!");
	    			canPlay=false;
	    		}
	    	}else{
	    			JOptionPane.showMessageDialog(this,"当前已有棋子,请重新落子");
	    		}
	    		
//	    		this.repaint();
	    		
	    	}
	    }
/************************************实现按钮功能***********************************************/	    	
	   ///第八步:右边:点击开始游戏按钮!!!!!!!!!!
	   if(e.getX()>=395&&e.getX()<=467&&e.getY()>=83&&e.getY()<=115) {
		 
		   int result = JOptionPane.showConfirmDialog(this,"是否重新开始游戏");
		   if(result == 0) {			 
			   this.init();
			   this.repaint();
			  canPlay = true;/点击开始游戏可以再开一盘!!! 
		   }
		   
	   }
///第九步:右边:点击游戏设置按钮!!!!!!!!!!
	   if(e.getX()>=395&&e.getX()<=467&&e.getY()>=135&&e.getY()<=162) {
//		   JOptionPane.showMessageDialog(this,"游戏设置");
		   String input =JOptionPane.showInputDialog("游戏设置:请输入游戏的最大时间(单位:分钟),如果输入0,则表示没有时间设置:");
		   try {
			   maxTime = Integer.parseInt(input) * 60;
			   if(maxTime < 0) {
				   JOptionPane.showMessageDialog(this,"请输入正确信息,不允许输入负数!😒");
			   }
			   if(maxTime == 0) {
				   int result =  JOptionPane.showConfirmDialog(this,"设置成功,是否重新开始游戏!😒");
				   if(result == 0) {
					   for(int i=0;i<19;i++) {  
							for(int j=0;j<19;j++) {
								allChess[i][j]=0;
							}
					   }
					   message ="黑方先行";
					   isBlack=true;
					   blackTime=maxTime;
					   whiteTime=maxTime;
					   blackMessage="无限制";
				       whiteMessage="无限制";
					   this.repaint();
				   }
				   
			   }
			   if(maxTime > 0) {
//				   JOptionPane.showMessageDialog(this,"请输入正确信息,不允许输入负数!😒");
				   int result =  JOptionPane.showConfirmDialog(this,"设置成功,是否重新开始游戏!😒");
				   if(result == 0) {
					   for(int i=0;i<19;i++) {  
							for(int j=0;j<19;j++) {
								allChess[i][j]=0;
							}
					   }
					   message ="黑方先行";
					   isBlack=true;
					   blackTime=maxTime;
					   whiteTime=maxTime;
					   blackMessage = maxTime/3600+ ":" + (maxTime/60-maxTime/3600*60) + ":" + (maxTime-maxTime/60*60);
					   whiteMessage = maxTime/3600+ ":" + (maxTime/60-maxTime/3600*60) + ":" + (maxTime-maxTime/60*60);
					   t.resume();
					   this.repaint();
				   }
			   }
		  } catch (NumberFormatException e1) {
			// TODO: handle exception
			  JOptionPane.showMessageDialog(this,"请正确输入信息!😒");
		}
		 
	   }
///第十步:右边:点击游戏说明按钮!!!!!!!!!!  
	   if(e.getX()>=395&&e.getX()<=467&&e.getY()>=183&&e.getY()<=213) {
		   JOptionPane.showMessageDialog(this,"游戏说明:这是一个五子棋游戏程序,黑白双方轮流下棋,当某一方连到五子时,游戏结束。😉");
	   }
///第十一步:右边:点击悔棋按钮!!!!!!!!!!
	   if(e.getX()>=395&&e.getX()<=467&&e.getY()>=233&&e.getY()<=264) {
		   this.remorseful();
	   }
///第十二步:右边:点击认输设置按钮!!!!!!!!!!
	   if(e.getX()>=395&&e.getX()<=467&&e.getY()>=280&&e.getY()<=310) {
		 int result =  JOptionPane.showConfirmDialog(this,"是否确认认输?🤷‍♂️");
		   if(result == 0) {
			   if(isBlack) {
			   JOptionPane.showMessageDialog(this,"黑方已经认输,游戏结束!!!");
			   
			   }else {
			   JOptionPane.showMessageDialog(this,"白方已经认输,游戏结束!!!");
			   
			   }
			   canPlay=false;
		   }
	   }
///第十三步:右边:点击关于设置按钮!!!!!!!!!!
	   if(e.getX()>=395&&e.getX()<=467&&e.getY()>=333&&e.getY()<=363) {
		   JOptionPane.showMessageDialog(this,"关于:本游戏《时光的继承者》制作,有相关问题可以联系QQ582362349😃");
	   }
///第十四步:右边:点击退出设置按钮!!!!!!!!!!
	   if(e.getX()>=395&&e.getX()<=467&&e.getY()>=382&&e.getY()<=411) {
		   JOptionPane.showMessageDialog(this,"退出😜");
		   System.exit(0);
	   }
}	
	    
	
	    //鼠标抬起
	    public void mouseReleased(MouseEvent e) {

	    }

	    //鼠标进入
	    public void mouseEntered(MouseEvent e) {

	    }

	    //鼠标离开
	    public void mouseExited(MouseEvent e) {

	    }
///第三步:插入背景图片
	    public void paint(Graphics g) {
//	    	//双缓冲技术防止屏幕闪烁
//	        BufferedImage bi = new BufferedImage(500, 550, BufferedImage.TYPE_INT_ARGB);
//	        Graphics g2 = bi.createGraphics();
	        //获取图片路径
	        BufferedImage image = null;
	        try {
	            image = ImageIO.read(new File("wuziqi.png"));
	        } catch (IOException e) {
	            e.printStackTrace();
	        }
	        g.drawImage(image, 0, 30, this);//显示图片
	        1.添加文字,绘制标题;
	        g.setFont(new Font("微软雅黑", Font.BOLD, 25));
	        g.setColor(Color.white);
	        g.drawString("游戏信息:"+message, 80, 65);
	        2.输出时间信息
	        g.setFont(new Font("宋体", Font.BOLD, 20));
	        g.setColor(Color.black);
	        g.drawString("黑方时间:"+blackMessage, 45, 480);
	        g.drawString("白方时间:"+whiteMessage, 260, 480);
	        /2.绘制棋盘
			for(int i=0; i<19; i++) {
				// 画横线
				g.drawLine(11, 81+20*i, 371, 81+20*i);
				// 画竖线
				g.drawLine(11+20*i, 81, 11+20*i, 440);
			}
            /3.标注点位;
			g.fillOval(68, 138, 6, 6);
			g.fillOval(188, 138, 6, 6);
			g.fillOval(308, 138, 6, 6);
			g.fillOval(68, 258, 6, 6);
			g.fillOval(68, 378, 6, 6);
			g.fillOval(68, 498, 6, 6);
			g.fillOval(188, 258, 6, 6);
			g.fillOval(308, 258, 6, 6);
			g.fillOval(68, 378, 6, 6);
			g.fillOval(188, 378, 6, 6);
			g.fillOval(308, 378, 6, 6);
//第四步:鼠标按下时,在棋盘绘制棋子,并且落在交叉处;
			for(int i=0;i<19;i++) {  
				for(int j=0;j<19;j++) {
				
						if(allChess[i][j]  ==  1) {
							int tempX=i*20+11;
							int tempY=j*20+81;
							g.setColor(Color.BLACK);
							g.fillOval(tempX-8, tempY-8, 16, 16);
							 
					}
					if(allChess[i][j]  ==  2) {
						int tempX=i*20+11;
						int tempY=j*20+82;
						g.setColor(Color.white);
						g.fillOval(tempX-8, tempY-8, 16, 16);
					}
					
					
				}
			}
			
			
			
	    }//这是paint的

	  ///第四步:判断这个棋子是否和其他棋子连成五个,判断是否结束;
		public boolean checkWin(){
			flag =false;
			int count = 1;  //报存共有多少相同棋子
			//判断这个棋子在横向是否和其他棋子连成五个,特点是y相同;
			int color = allChess[x][y];///判断黑白
//			if(color == allChess[x+1][y]) {
//				count++;
//				if(color == allChess[x+2][y]) {
//					
//				}
//				
//			}
			/横向向右
			int i=1;
			while(color == allChess[x+i][y]&&x+i>=0&&x+i<=18&&y>=0&&y<=18) {
				count++;
				i++;
			}
			/横向向左
			 i=1;
			while(color == allChess[x-i][y]&&x-i>=0&&x-i<=18&&y>=0&&y<=18) {
				count++;
				i++;
			}
			if(count>=5) {
				flag = true;
			}
			///向上
			int i2=1;
			int count2=1;
			while(color == allChess[x][y+i2]&&x>=0&&x<=18&&y+i2>=0&&y+i2<=18) {
				count2++;
				i2++;
			}
			/向下
			 i2=1;
			while(color == allChess[x][y-i2]&&x>=0&&x<=18&&y-i2>=0&&y-i2<=18) {
				count2++;
				i2++;
			}
			if(count2>=5) {
				flag = true;
			}
			/右上,左下;
			int i3=1;
			int count3=1;
			while(color == allChess[x+i3][y-i3]&&x+i3>=0&&x+i3<=18&&y-i3>=0&&y-i3<=18) {
				count3++;
				i3++;
			}
			 i3=1;
			while(color == allChess[x-i3][y+i3]&&x-i3>=0&&x-i3<=18&&y+i3>=0&&y+i3<=18) {
				count3++;
				i3++;
			}
			if(count3>=5) {
				flag = true;
			}
			///左上,右下
			int i4=1;
			int count4=1;
			while(color == allChess[x-i4][y-i4]&&x-i4>=0&&x-i4<=18&&y-i4>=0&&y-i4<=18) {
				count4++;
				i4++;
			}
			 i4=1;
			while(color == allChess[x+i4][y+i4]&&x+i4>=0&&x+i4<=18&&y+i4>=0&&y+i4<=18) {
				count4++;
				i4++;
			}
			if(count4>=5) {
				flag = true;
			}
			return flag;
		}// checkWin()的
/************************************实现多线程接口***********************************************/
		
	    public void run() {
	    	/*
	    	 * 判断是否有时间限制
	    	 */
	    	if(maxTime > 0) {
	    		while(true) {
	    			if(isBlack) {
	    				blackTime--;
	    				if(blackTime==0) {
	    					 JOptionPane.showMessageDialog(this,"黑方超时,游戏结束!😆😅");
	    					 
	    				}
	    			}else {
	    				whiteTime--;
	    				if(whiteTime==0) {
	    					 JOptionPane.showMessageDialog(this,"白方超时,游戏结束!😆😅");
	    					 
	    				}
	    			}
	    			try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO: handle exception
						e.printStackTrace();
					}
	    			   blackMessage = blackTime/3600+ ":" + (blackTime/60-blackTime/3600*60) + ":" + (blackTime-blackTime/60*60);
					   whiteMessage = whiteTime/3600+ ":" + (whiteTime/60-whiteTime/3600*60) + ":" + (whiteTime-whiteTime/60*60);
					   this.repaint();
	    			System.out.println(blackTime+"---"+whiteTime);
	    		}
	    		
	    	}
	    }
		
///第十一步:右边:点击悔棋按钮!!!!!!!!!!
	    public void remorseful() {
	    	 if (canPlay) {
	                //遍历棋盘上是否有棋子
	                int z = 0;
	                for (int i = 0; i < 15; i++) {
	                    for (int j = 0; j < 15; j++) {
	                        if (allChess[i][j] != 0) {
	                            z++;
	                        }
	                    }
	                }
	                //判断是否有棋子
	                if (z != 0) {
	                    int result = JOptionPane.showConfirmDialog(this, "确认要悔棋吗?");
	                    if (result == 0) {
	                        int x = ui.ps[ui.i - 1].listx;
	                        int y = ui.ps[ui.i - 1].listy;

	                        if (allChess[x][y] == 0){
	                            JOptionPane.showMessageDialog(this, "已悔过一次棋了!");
	                        }else{
	                            if (isBlack==true) {
	                            	allChess[x][y] = 1;
	                            	isBlack=false;
	                                message = "轮到白方";
	                            } else if (isBlack==false){
	                            	allChess[x][y] =2;
	                            	isBlack=true;
	                                message = "轮到黑方";
	                            }
	                            allChess[x][y] = 0;
	                            ui.i--;
	                            this.repaint();
	                        }

	                    }
	                } else {
	                    JOptionPane.showMessageDialog(this, "棋盘上已无棋子");
	                }

	            } else {
	                JOptionPane.showMessageDialog(this, "请先开始游戏");
	            }
	        }
	
}

2. WzqGame.java

package flyweight;



import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;


public class WzqGame {
	public static void main(String[] args) {
		new Chessboard();
	}
}

class Chessboard extends MouseAdapter{
	WeiqiFactory wf;
	JFrame f;
	Graphics g;
	JRadioButton wz;
	JRadioButton bz;
	private final int x=50;
	private final int y=50;
	private final int w=40; //小方格宽度与高度
	private final int rw=400;//棋盘高度与宽度
	Chessboard(){
		wf=new WeiqiFactory();
		f=new JFrame("享元模式在五子棋中的应用");
		f.setBounds(100, 100, 500, 550);
		f.setVisible(true);
		f.setResizable(false);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JPanel SouthJP=new JPanel();
		f.add("South",SouthJP);
		wz=new JRadioButton("白子");
		bz=new JRadioButton("黑子",true);
		ButtonGroup group=new ButtonGroup();
		group.add(wz);
		group.add(bz);
		SouthJP.add(wz);
		SouthJP.add(bz);
		JPanel CenterJP=new JPanel();
		CenterJP.setLayout(null);
		CenterJP.setSize(500,500);
		CenterJP.addMouseListener(this);
		f.add("Center",CenterJP);
		try {
			Thread.sleep(500);
		}catch (InterruptedException e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		g=CenterJP.getGraphics();
		g.setColor(Color.BLUE);
		g.drawRect(x, y, rw, rw);
		for(int i=1;i<10;i++) {
			g.drawLine(x+(i*w), y, x+(i*w), y+rw);
			g.drawLine(x, y+(i*w), x+rw, y+(i*w));
		}	
	}
	public void mouseClicked(MouseEvent e) {
		Point pt=new Point(e.getX()-15,e.getY()-15);
		if(wz.isSelected()) {
			ChessPieces c1=wf.getChessPieces("w");
			c1.DownPieces(g,pt);
		}else if(bz.isSelected()) {
			ChessPieces c2=wf.getChessPieces("b");
			c2.DownPieces(g,pt);
		}
	}
	
}

//抽象享元角色:棋子
interface ChessPieces{
	public void DownPieces(Graphics g,Point pt);//落子
}

//具体享元角色:白子
class WhitePieces implements ChessPieces{
	public void DownPieces(Graphics g, Point pt) {
		g.setColor(Color.WHITE);
		g.fillOval(pt.x, pt.y, 30, 30);
	}
	
}

//具体享元角色:黑子
class BlackPieces implements ChessPieces{
	public void DownPieces(Graphics g, Point pt) {
		g.setColor(Color.BLACK);
		g.fillOval(pt.x, pt.y, 30, 30);
	}
	
}

//享元工厂
class WeiqiFactory{
	private ArrayList<ChessPieces> qz;
	public WeiqiFactory() {
		qz=new ArrayList<ChessPieces>();
		ChessPieces w=new WhitePieces();
		qz.add(w);
		ChessPieces b=new BlackPieces();
		qz.add(b);
	}
	public ChessPieces getChessPieces(String type) {
			if(type.equalsIgnoreCase("w")) {
				return (ChessPieces)qz.get(0);
			}else if(type.equalsIgnoreCase("b")) {
				return (ChessPieces)qz.get(1);
			}else {
				return null;
			}
	}
	
	
}

3. 图片资源

在这里插入图片描述

总结

运行Test.java即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值