五子棋基础

五子棋课程设计基础

我们小组三人(小白)的成果,参考b站MLDN的五子棋教程

代码如下:

package wuziqi;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
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;
//00点31 57 间隔40
public class FiveChessFrame extends JFrame implements MouseListener, Runnable {
	
	BufferedImage bgImage = null;
	
	int x = 0;
	int y = 0;
	int[][] allChess = new int[15][15];
	boolean isBlack = true;
	//表示当前游戏是否继续
	boolean canPlay = true;
	//保存显示的提示信息
	String message="黑方先行";
	//保存最多拥有的时间
	int maxTime = 0;
	//做倒计时的线程类
	Thread t = new Thread (this);
	//保存黑方与白方的剩余时间
	int blackTime = 0;
	int whiteTime = 0;
	//保存上方剩余时间的显示信息
	String blackMessage = "无限制";
	String whiteMessage = "无限制";
	
	public FiveChessFrame(){
		this.setTitle("五子棋");
		this.setSize(900,700);
		this.setResizable(false);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.addMouseListener(this);
		int width = Toolkit.getDefaultToolkit().getScreenSize().width;
		int height = Toolkit.getDefaultToolkit().getScreenSize().height;
		this.setLocation((width-900)/2, (height-700)/2);
		try {
			bgImage = ImageIO.read(new File("D:/Pic/background.jpg"));
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		this.setVisible(true);
		
		t.start();
		t.suspend();
		//刷新屏幕
		
	
	}
	public void paint(Graphics g) {
		//双缓冲技术防止屏幕闪烁
		//BufferedImage bi = new BufferedImage(900, 700, BufferedImage.TYPE_INT_ARGB);
		//Graphics g2 = bi.createGraphics();
		g.drawImage(bgImage, 0, 30, this);
		g.setFont(new Font("宋体",Font.BOLD,20));
		g.drawString("游戏信息:"+message, 50, 50);
		g.setFont(new Font("宋体",Font.BOLD,16));
		g.drawString("黑方时间:"+blackMessage, 50, 680);
		g.drawString("白方时间:"+whiteMessage, 450, 680);
		g.setFont(new Font("宋体",Font.BOLD,16));
		g.drawString("开始游戏", 722, 88);
		g.drawString("游戏设置", 722, 167);
		g.drawString("认输", 738, 249);
		//棋盘
		for(int i=0;i<15;i++) {
			g.drawLine(31, 57+40*i, 591, 57+40*i);
			g.drawLine(31+40*i, 57, 31+40*i, 617);
		}
		//棋子
		for(int i=0;i<15;i++)
			for(int j=0;j<15;j++) {
				if(allChess[i][j]==1) {
					int tempX=i*40+31;
					int tempY=j*40+57;
					g.fillOval(tempX-15, tempY-15, 30, 30);
				}
				if(allChess[i][j]==2) {
					int tempX=i*40+31;
					int tempY=j*40+57;
					g.setColor(Color.WHITE);
					g.fillOval(tempX-15, tempY-15, 30, 30);
					g.setColor(Color.BLACK);
					g.drawOval(tempX-15, tempY-15, 30, 30);
				}
			}
		//g.drawImage(bi, 0, 0, this);
	}
	
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO 自动生成的方法存根
 
	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO 自动生成的方法存根
		if(canPlay==true) {
		x = e.getX();
		y = e.getY();
		if(x>=31 && x<=591 && y>=57 && y<=617) {
			if((x-31)%40>20) {
				x=(x-31)/40+1;
			}
			else {
				x=(x-31)/40;
			}
			if((y-57)%40>20) {
				y=(y-57)/40+1;
			}
			else {
				y=(y-57)/40;
			}
			
			if(allChess[x][y]==0) {
				if(isBlack==true) {
					allChess[x][y]=1;
					isBlack=false;
					message = "轮到白方";
				}
				else {
					allChess[x][y]=2;
					isBlack=true;
					message="轮到黑方";
				}
				//判断输赢,看周围相连是否有五个
				boolean winFlag = this.checkWin();
				if(winFlag==true) {
					JOptionPane.showMessageDialog(this, "Game Over,"+(allChess[x][y]==1?"黑方":"白方")+"获胜!");
					canPlay=false;
				}
			}
			//判断输赢,看周围相连是否有五个
			this.repaint();
		}
	 }
	 System.out.println(e.getX()+"--"+e.getY());
	 if(e.getX() >=678 && e.getX() <=838 && e.getY() >=50 && e.getY() <=115){
		 int result = JOptionPane.showConfirmDialog(this, "是否重新开始游戏?");
		 if(result == 0) {
			 allChess = new int [19][19];
			 isBlack = true;
			 canPlay = 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);
			 }else {
				 blackMessage = "无限制";
			     whiteMessage = "无限制";
			 }
			 t.resume();
			 this.repaint();
		 }
	 }
	 if(e.getX() >=678 && e.getX() <=838 && e.getY() >=134 && e.getY() <=194){
		 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) {
				 allChess = new int [19][19];
				 isBlack = true;
				 canPlay = true;
				 blackTime = maxTime;
				 whiteTime = maxTime;
				 blackMessage = "无限制";
			     whiteMessage = "无限制";
				 this.repaint();
			 }
		 }
		 if(maxTime > 0) {
			 int result = JOptionPane.showConfirmDialog(this, "设置完成,是否重新开始游戏?");
			 if(result == 0) {
				 allChess = new int [19][19];
				 isBlack = true;
				 canPlay = 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 el) {
			 JOptionPane.showMessageDialog(this, "请输入正确信息!");
		 }
	 }
		 
	 if(e.getX() >=678 && e.getX() <=838 && e.getY() >=215 && e.getY() <=274){
		 int result = JOptionPane.showConfirmDialog(this,"是否确认 认输?" );
		 	if(result == 0) {
		 		if(isBlack) {
		 			JOptionPane.showMessageDialog(this, "黑方已经认输,游戏结束!");
		 			canPlay = false;
		 		}
		 		else{
		 			JOptionPane.showMessageDialog(this, "白方已经认输,游戏结束!");
		 			canPlay = false;
		 		}
		 		
		 	
		 	}				 
	 }
	}
	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO 自动生成的方法存根

	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO 自动生成的方法存根

	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO 自动生成的方法存根

	}
	public boolean checkWin() {
		boolean flag=false;
		// 保存共有相同颜色多少棋子相连
		int count = 1;
		int color = allChess[x][y];
		count = this.checkCount(1, 0, color);
		if (count>=5) {
			flag=true;
		} else {
			count=this.checkCount(0, 1, color);
			if(count>=5) {
				flag=true;
			} else {
				count=this.checkCount(1, -1, color);
				if(count>=5) {
					flag=true;
				} else {
					count=this.checkCount(1, 1, color);
					if(count>=5) {
						flag=true;
					}
				}
			}
		}
		return flag;
		
	}
	private int checkCount(int xChange, int yChange, int color) {
		int count = 1;
		int tempX = xChange;
		int tempY = yChange;
		while (x + xChange >= 0 && x + xChange <= 14 && y + yChange >= 0
				&& y + yChange <= 14
				&& color == allChess[x + xChange][y + yChange]) {
			count++;
			if (xChange != 0)
				xChange++;
			if (yChange != 0) {
				if (yChange > 0)
					yChange++;
				else {
					yChange--;
				}
			}
		}
		xChange = tempX;
		yChange = tempY;
		while (x - xChange >= 0 && x - xChange <= 14 && y - yChange >= 0
				&& y - yChange <= 14
				&& color == allChess[x - xChange][y - yChange]) {
			count++;
			if (xChange != 0)
				xChange++;
			if (yChange != 0) {
				if (yChange > 0)
					yChange++;
				else {
					yChange--;
				}
			}
		}
		return count;
	}
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		//判断是否有时间限制
		if(maxTime > 0) {
			while(true) {
				if(isBlack) {
					blackTime-- ;
					if(blackTime == 0) {
						JOptionPane.showMessageDialog(this, "黑方超时,游戏结束");
						
						canPlay = false;
						t.stop();
					}
				}else {
					whiteTime-- ;
					if(whiteTime == 0) {
						JOptionPane.showMessageDialog(this, "白方超时,游戏结束");
						
						canPlay = false;
						t.stop();
					}
				}
				try {
					Thread.sleep(1000);
				}catch (InterruptedException e) {
					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);
			}
			
		}
		
	}
}

我负责的主要部分为各个按钮的实现与控制以及倒计时的设置。

(1)各个按钮的实现与控制

其中的难点在于每个按钮的使用过程中都是有一些联系的,不然会出现意想不到的bug。例如“认输”按钮后面canPlay = false;会影响接下来的使用,会使认输之后再重新开始后不能落子,所以必须在每一个有重新开始功能的按钮下加入canPlay = true;

allChess = new int【19】【19】作用就是清空棋盘。注:【19】【19】应该为【15】【15】否则会出现bug。

 if(e.getX() >=678 && e.getX() <=838 && e.getY() >=50 && e.getY() <=115){
		 int result = JOptionPane.showConfirmDialog(this, "是否重新开始游戏?");
		 if(result == 0) {
			 allChess = new int [19][19];
			 isBlack = true;
			 canPlay = 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);
			 }else {
				 blackMessage = "无限制";
			     whiteMessage = "无限制";
			 }
			 t.resume();
			 this.repaint();
		 }
	 }
	 if(e.getX() >=678 && e.getX() <=838 && e.getY() >=134 && e.getY() <=194){
		 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) {
				 allChess = new int [19][19];
				 isBlack = true;
				 canPlay = true;
				 blackTime = maxTime;
				 whiteTime = maxTime;
				 blackMessage = "无限制";
			     whiteMessage = "无限制";
				 this.repaint();
			 }
		 }
		 if(maxTime > 0) {
			 int result = JOptionPane.showConfirmDialog(this, "设置完成,是否重新开始游戏?");
			 if(result == 0) {
				 allChess = new int [19][19];
				 isBlack = true;
				 canPlay = 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 el) {
			 JOptionPane.showMessageDialog(this, "请输入正确信息!");
		 }
	 }
		 
	 if(e.getX() >=678 && e.getX() <=838 && e.getY() >=215 && e.getY() <=274){
		 int result = JOptionPane.showConfirmDialog(this,"是否确认 认输?" );
		 	if(result == 0) {
		 		if(isBlack) {
		 			JOptionPane.showMessageDialog(this, "黑方已经认输,游戏结束!");
		 			canPlay = false;
		 		}
		 		else{
		 			JOptionPane.showMessageDialog(this, "白方已经认输,游戏结束!");
		 			canPlay = false;
		 		}
		 		
		 	
		 	}				 
	 }

(2)倒计时的设置

前面的声明定义就不展示了,设计倒计时的重点之一就是,要让倒计时结束时停止计时,要用到t.stop() (当然这类方法已经过时了但是其他的不会用) 并且要在此之前加入canPlay = false;否则计时结束分出胜负后依然能下棋。

if(maxTime > 0) {
			while(true) {
				if(isBlack) {
					blackTime-- ;
					if(blackTime == 0) {
						JOptionPane.showMessageDialog(this, "黑方超时,游戏结束");
						
						canPlay = false;
						t.stop();
					}
				}else {
					whiteTime-- ;
					if(whiteTime == 0) {
						JOptionPane.showMessageDialog(this, "白方超时,游戏结束");
						
						canPlay = false;
						t.stop();
					}
				}
				try {
					Thread.sleep(1000);
				}catch (InterruptedException e) {
					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);
			}
			
		}

其他的bug暂时没发现,第一次写程序练手多多包涵! 

 

效果如下:

背景图片为江流儿(网图),各位可以自行设计背景图片。这个程序会出现屏闪问题,目前也不会修复,还请各位大佬指点。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值