Java实现四连环棋游戏

Java实现四连环棋游戏

游戏规则
(1)双人游戏,有黑红两色棋子,双方各执一色棋子。
(2)空棋局开盘,黑棋先发,从最上面一行开始下,棋子会落到最下行。
(3)黑、红交替下子,每次只能下一子,从最上行开始下。
(4)棋子下在任何位置,都会掉落至该列的最下方的空格处,只有该列已有棋子时,该棋子才落在该列最上面棋子的上一格(就是往上摞棋子),以此类推。
(5)棋子下定后便不可以移动。
(6)不许悔棋,下定即确定。
(7)允许中途认输,则对方获胜。
(8)哪一方最先出现横或竖或斜向四颗同色已落子,则该方获胜。
(9)若棋子填满双方仍未分出胜负则平局
游戏原型在这里插入图片描述
功能实现
定义一个居中窗口,用画板画出6x7的格子。添加鼠标监听器,鼠标点击时获取坐标,用数组存储黑红双方棋子位置。给下黑棋赋一个布尔值,黑子下完后改变布尔值,改为下红棋的布尔值,实现黑红棋交替下在棋盘上。通过查找空格的方法,使棋子下在任何位置,都会落在该列格子中最下面的空格子里,如果该列已有棋子,则该棋子落在该列最上面的棋子的上一格空格处。每下一个棋子时就依次横向和纵向做出判断是否连成四子,以四子棋的颜色为判断基础 ,如果横向和纵向都不符合要求,开始进行斜着判断,直到发现四子相同为止,如果都不成立就代表没有连成四子,如果棋盘下满了仍未有任意一方连成同色四子,则为双方平局。设置重新开始、游戏规则、退出游戏、认输选项,用获取到的坐标确定选择的是哪个功能,点击后会弹出居中的消息框,判断是否确定选择。

代码部分如下

package chess;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public  class 四连环棋  extends JFrame implements MouseListener{
	/**
	 * 为了在反序列化时,确保类版本的兼容性,最好在每个要序列化的类中加入private static final long serialVersionUID这个属性,具体数值自己定义.
	 */
	private static final long serialVersionUID = 7715397504806319506L;
	
	int[][] allChess = new int[7][6];   // 用数组来保存棋子,0表示无子,1表示黑子,2表示红子
	int[] chessX = new int[42];//保存棋谱,记录双方每一步落子的位置
	int[] chessY = new int[42];
	int x;  // 定义鼠标的坐标
	int y;
	boolean isblack = true;   //用来表示黑子还是红子, true表示黑子   false表示红子
	boolean canPlay = true;   // 用来表示当前游戏是否结束
	 BufferedImage background;
	 
	四连环棋() {
		 setBounds(600, 270, 580, 450);//设置窗口的位置 坐标,距左上角的,窗口的大小
			setVisible(true);//显示窗口
			setTitle("四连环棋");
			setBackground(Color.yellow);
			addMouseListener(this);
			setDefaultCloseOperation(EXIT_ON_CLOSE);
			setResizable(false);//不可改变大小
			
	}
	
	//画棋盘界面
	 public void paint(Graphics g) {
		//异常处理,找不到背景图片
		 try {
			
			background=ImageIO.read(getClass().getResource("5.png"));
			
			}catch(IOException m) {
				m.printStackTrace();
			}
		 g.drawImage(background,0,0,null);
		
			  for(int i=0; i<7; i++){
				for (int j = 0; j < 6; j++) {
					//画实心黑子
					if(allChess[i][j] == 1){    
						int weizhiX = i*53+50;
						int weizhiY = j*53+68;
						g.setColor(Color.BLACK);
						g.fillOval(weizhiX, weizhiY, 40, 40);
						g.drawOval(weizhiX, weizhiY, 40, 40);
					}
					
					//画实心白子
					if(allChess[i][j] == 2){
						int weizhiX = i*53+50;
						int weizhiY = j*53+68;
						g.setColor(Color.red);
						g.fillOval(weizhiX, weizhiY, 40, 40);
						g.drawOval(weizhiX, weizhiY, 40, 40);
					}
				}
			}	
			
	}
	
	 public void mousePressed(MouseEvent e) {
			
				x=e.getX();
				y=e.getY();  // 用来获取鼠标坐标
				//异常处理
				 if(e.getX()<=30 || e.getX()>= 460+43 || e.getY()<=50 ||e.getY()>=329+60) {
			          try {
						throw new BeyondBoardException("您所点击位置超出棋盘");
					} catch (BeyondBoardException k) {
						// TODO 自动生成的 catch 块
						System.out.println(k);
					}
				 }
				 
				if(x>43 && x<= 414  && y>=60 && y<=378){
					//让鼠标在棋盘范围内
					if((x-69)%53>26){
						x=(x-69)/53 + 1;
						y=findEmptyPosition(x);
					}else {
						x = (x-69)/53;
						y=findEmptyPosition(x);
					}
				
					//落子
					if(allChess[x][y] == 0){
						
						if(isblack){
							allChess[x][y] = 1;
							isblack = false;
						
						}else {
							allChess[x][y] = 2;
							isblack = true;
							
						}
						this.repaint();
						if(this.Win()){
							if(allChess[x][y] == 1){
								JOptionPane.showMessageDialog(this, "游戏结束,黑方胜利");
							}else {
								JOptionPane.showMessageDialog(this, "游戏结束,红方胜利");
							}
							this.canPlay = false;  //表示游戏结束
						}
						
						//判断平局
						int sum=0;
						for(int i=0;i<7;i++) {
							for(int j=0;j<6;j++) {
								if(allChess[i][j]!=0) {
									sum++;
									if(sum==42)
									JOptionPane.showMessageDialog(this, "游戏结束,双方平局");
								}
							}
						}			
				}
			}
			
			//重新开始游戏
			if(e.getX() >=430 && e.getX() <= (428+55)  && e.getY() >= 66
				&&	e.getY() <= (66+20) ){
				int result = JOptionPane.showConfirmDialog(this, "是否重新开始游戏?"); 
				if(result == 0){
					restarGame();
				}
			}
			
			//游戏规则
			if(e.getX() >= 430 && e.getX() <= (430+55)  && e.getY() >=106
				&&	e.getY() <= (106+20) ){
				JOptionPane.showMessageDialog(this, "规则:(1)双人游戏,有黑红两色棋子,双方各执一色棋子。\r\n" + 
						"      (2)空棋局开盘,黑棋先发,从最上面一行开始下,棋子会落到最下行。\r\n" + 
						"      (3)黑、红交替下子,每次只能下一子,从最上行开始下。\r\n" + 
						"      (4)棋子下在任何位置,都会掉落至该列的最下方的空格处,只有该列已有棋子时,该棋子才落在该列最上面棋子的上一格(就是往上摞棋子),以此类推。\r\n" + 
						"      (5)棋子下定后便不可以移动。\r\n" + 
						"      (6)不许悔棋,下定即确定。\r\n" + 
						"      (7)允许中途认输,则对方获胜。\r\n" + 
						"      (8)哪一方最先出现横或竖或斜向四颗同色已落子,则该方获胜。\r\n"+
						"      (9)若棋盘填满棋子双方仍未分出胜负则平局。");
			}
			
			//退出游戏
			if(e.getX() >=430 && e.getX() <= (430+55)  && e.getY() >=146 
					&&  e.getY() <= (146+20)){
				int result = JOptionPane.showConfirmDialog(this, "是否退出游戏?");
				if(result == 0){
					System.exit(0);
				}
			}
			
			 //认输
	        if(e.getX()>=430 && e.getX()<=(428+55) && e.getY()>=186 
	        		&& e.getY()<=(186+20)){
	            int result=JOptionPane.showConfirmDialog(this, "是否认输?");
	            if(result==0){
	                JOptionPane.showMessageDialog(this,
	                	"游戏结束,"+(isblack==true ? "黑方认输,红方获胜!" : "红方认输,黑方获胜!"));
	            }
	        }
	
		}
	 
		
			public void restarGame(){
				for (int i = 0; i < 7; i++) {
					for (int j = 0; j < 6; j++) {
						allChess[i][j] = 0;  //清空棋盘的棋子
					}
					
				}
				
				//清空下棋棋子坐标的记录
				for (int i = 0; i < 7; i++) {
					chessX[i] = 0;
				for (int j = 0; j < 6; j++) {
						chessY[j] = 0;
					}
					
				}
				
				isblack = true;
				canPlay = true;
				this.repaint();
				
			}
	
		// 判断输赢规则
		
		public boolean Win(){
			boolean flag = false;
			int count = 1;  //用来保存共有相同颜色多少棋子相连,初始值为1
			int color = allChess[x][y];  //color = 1 (黑子) color = 2(白子)
			
			//判断横向是否有4个棋子相连,特点:纵坐标是相同,即allChess[x][y] 中y值是相同
			count = this.checkCount(1,0,color);
			if(count >= 4){
				flag = true;
			}else {
				//判断纵向
				count = this.checkCount(0,1,color);
				if(count >= 4){
					flag = true;
				}else {
					 //判断右上,左下
					count = this.checkCount(1,-1,color);
					if(count >= 4){
						flag = true;
					}else {
						//判断右下,左上
						count = this.checkCount(1,1,color);
						if(count >= 4){
							flag =  true;
						}
					}
				}
			}
			
			return flag;
		}
		
		// 检查棋盘中的棋是否连成四子
		 
		public int checkCount(int heng , int zong ,int color){
			int count = 1;
			int weizhiX = heng;
			int weizhiY = zong;  //保存初始值
			
			//寻找相同颜色的棋子
			while(x + heng >=0 && x+heng <7  && y+zong >=0 && 
					y+zong < 6 && color == allChess[x+heng][y+zong]){
		
				count++;
				if(heng != 0)  heng++;    
				if(zong != 0 ){      
					if(zong != 0){
						if(zong > 0) {   
							zong++;		
						}else {
							zong--;		
						}
					}
				}
				
			}
			
			heng = weizhiX;
			zong = weizhiY;   // 恢复初始值
			
			while(x-heng >=0 && x-heng <7 && y-zong >=0 &&
					y-zong <6 && color == allChess[x-heng][y-zong]){		
				count++;
				if(heng != 0){
					heng++;
				}
				if(zong != 0){
					if (zong > 0) {
						zong++;			
					}else {
						zong--;			
					}
				}
			}
			
			return count;
		}
	
		  public int  findEmptyPosition(int i)
		    {    int j;
		        //找到空的位置
		        for (j = 5; j >= 0; j--)
		        {
		            if (allChess[i][j]==0)
		            {
		            	return j;
		            }
		        }
				return j;
		    }
		
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
	 
		public void mouseReleased(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
	 
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
	 
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
		
		public static void main(String[] args)throws BeyondBoardException {
			new 四连环棋();
			
		}
	 
	}
//点击位置超出棋盘的异常
	class BeyondBoardException extends Exception{
		private static final long serialVersionUID = 1L;
			
			BeyondBoardException(String ErrorMessage){
				super(ErrorMessage);

		}
		
	}


背景选用图片名:5.png,与四连环棋.java同在chess包目录下。
图片如下:
在这里插入图片描述

运行结果如下在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值