Java小游戏——五子棋


内容简介

本文介绍了一个修改自某位大佬的五子棋小游戏qwq
目前可以实现简单的双人对战~

原文传送门
GitHub传送门


以下是本篇文章正文内容

一、规则

本程序作为基础的五子棋,连成五个即可获胜,没有设置禁手。

注:五子棋RIF规则中黑棋只能以“四、三”取胜

二、具体代码实现

1.调试环境

开发环境为Eclipse

2.代码实现

大致结构
GoBang1

具体代码如下:

1.GoBangframe类

package GoBang1;

// 构建五子棋界面GoBangframe类

import javax.swing.JFrame; 
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import java.awt.Dimension;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import java.util.ArrayList;

public class GoBangframe extends JPanel implements GoBangconfig{
	public Graphics g;// 定义一支画笔
	public int[][] isAvail=new int [15][15];// 定义一个二维数组来储存棋盘的落子情况
	public ArrayList<ChessPosition>ChessPositonList=new ArrayList<ChessPosition>();// 保存每一步的落子情况
	public int turn=1;
	
	// 主函数入口
	public static void main(String args[]) {
		GoBangframe gf=new GoBangframe();// 初始化一个五子棋界面的对象
		gf.initUI();// 调用方法进行界面的初始化
	}
	
	public void initUI() {
		// 初始化一个界面,并设置标题大小等属性
		JFrame jf=new JFrame();
		jf.setTitle("五子棋");
		jf.setSize(800,650); // 800,650
		jf.setLocationRelativeTo(null);
		jf.setDefaultCloseOperation(3);
		
		jf.setLayout(new BorderLayout());//设置顶级容器JFrame为框架布局
		
		Dimension dim1=new Dimension(150,0); // 设置右半部分的大小 // 150 0
		Dimension dim3=new Dimension(550,0); // 设置左半部分的大小 // 550 0
		Dimension dim2=new Dimension(140,40); // 设置右边按钮组件的大小 // 140,40
		
		// 实现左边的界面,把GoBangframe的对象添加到框架布局的中间部分
		// 已经有一个GoBangframe对象了,表示当前类的对象是this
		this.setPreferredSize(dim3);// 设置下棋界面的大小
		this.setBackground(new Color(220,200,150));// 设置下棋界面的颜色(棕色)
		
		// this.setBackground(Color.orange); // new Color(255,200,0)
		// this.setBackground(Color.LIGHT_GRAY); // new Color(192,192,192)
		
		
		// 这里的话直接把左边的画板添加上去,指明是在框架布局的中间版块
		// 若放在其他版块会有一些小问题
		jf.add(this,BorderLayout.CENTER);// 添加到框架布局的中间部分
		
		//实现右边的JPanel容器界面
		JPanel jp=new JPanel();
		jp.setPreferredSize(dim1);// 设置JPanel的大小
		jp.setBackground(Color.white);// 设置右边的界面颜色为白色
	
		jf.add(jp,BorderLayout.EAST);// 添加到框架布局的东边部分
		jp.setLayout(new FlowLayout());// 设置JPanel为流式布局
		
		// 接下来我们需要把按钮等组件依次加到那个JPanel上面
		// 设置按钮数组
		String[] butname= {"开始新游戏^▽^","悔棋[○・`Д´・ ○]","认输o(╥﹏╥)o"};
		// String[] butname= {"开始新游戏","悔棋","认输"}; 
		
		JButton[] button=new JButton[3];
		
		
		// 依次把三个按钮组件加上去
		for(int i=0;i<butname.length;i++) {
			button[i]=new JButton(butname[i]);
			button[i].setPreferredSize(dim2);
			jp.add(button[i]);
		}
		
		// 按钮监控类
		ButtonListener butListen=new ButtonListener(this);
		// 对每一个按钮都添加状态事件的监听处理机制
		for(int i=0;i<butname.length;i++) {
			button[i].addActionListener(butListen);// 添加发生操作的监听方法
		}
		
		// 设置选项按钮
		String[] boxname= {"人人对战","人机对战"};
		JComboBox box=new JComboBox(boxname);
		jp.add(box);
				
		jf.setVisible(true);
	}
	
	
	// 重写重绘方法,这里重写的是第一个大的JPanel的方法
	public void paint(Graphics g) {
		super.paint(g);// 画出棕色背景
		
		// 重绘出棋盘
		
		// System.out.println(size); // size==40
		// System.out.println(row+" "+column);
		g.setColor(Color.black);
		for(int i=0;i<row;i++) { // row==15
			g.drawLine(x, y+size*i, x+size*(column-1), y+size*i); // column==15
		}
		for(int j=0;j<column;j++) {
			g.drawLine(x+size*j, y, x+size*j, y+size*(row-1));
		}
		
		
		// 重绘出棋子
		for(int i=0;i<row;i++) {
			for(int j=0;j<column;j++) {
				if(isAvail[i][j]==1) { // 黑子
					int countx=size*i+20;
					int county=size*j+20;
					g.setColor(Color.black);
					g.fillOval(countx-size/2, county-size/2, size, size);
				}
				else if(isAvail[i][j]==2) { // 白子
					int countx=size*i+20;
					int county=size*j+20;
					g.setColor(Color.white);
					g.fillOval(countx-size/2, county-size/2, size, size);
				}
			}
		}	
	}
}

2.ButtonListener类

package GoBang1;
// 设置按钮监听方法ButttonLitener类
import java.awt.event.ActionListener;
import java.awt.Color;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
 
// 实现对JPanel的监听接口处理
public class ButtonListener implements GoBangconfig,ActionListener{
	public GoBangframe gf;
	
	public ButtonListener(GoBangframe gf) {
		this.gf=gf;// 获取左半部分的画板
	}
	
	// 当界面发生操作时进行处理
	public void actionPerformed(ActionEvent e) {
		// 获取当前被点击按钮的内容,判断是不是"开始新游戏"这个按钮
		if(e.getActionCommand().equals("开始新游戏^▽^")) { // 
			// 如果是开始新游戏的按钮,再为左半部分设置监听方法
			frameListener fl=new frameListener();
			fl.setGraphics(gf);// 获取画笔对象
			gf.addMouseListener(fl);
		}
		// 判断当前点击的按钮是不是悔棋
		else if(e.getActionCommand().equals("悔棋[○・`Д´・ ○]")) { //
			if(gf.ChessPositonList.size()>=1) { //
				// 把棋子数组相应的位置置为0;
				ChessPosition l=new ChessPosition();
				// 获取最后一个棋子的对象信息
				l=gf.ChessPositonList.remove(gf.ChessPositonList.size()-1);
				// 把相应的数组位置置为0
				gf.isAvail[l.Listi][l.Listj]=0;
				// 把玩家还原为上一步的玩家
				if(gf.turn==1) gf.turn++;
				else gf.turn--;
				
				// 直接调用gf的重绘方法,重绘方法的画笔应该是在棋盘页面还没生成的时候就要获取
				// 调用repaint会自动调用paint方法,而且不用给参数
				gf.repaint();
				// gf.paint(gf.getGraphics());
 
			}
			else {
				System.out.println("不能悔棋!");
			}
		}
		else if(e.getActionCommand().equals("认输o(╥﹏╥)o")) { //
			if(gf.turn==1) { 
				System.out.println("白方赢");
			    // Alert alert1=Alert(Alert.AlertType.INFORMATION);
			    // alert1.showAndWait();
			}
			else {
				System.out.println("黑方赢");
			
			}
		}
	}
	
}

3.ChessPosition类

package GoBang1;

//新建一个棋子类ChessPosition保存每一步棋子所在的位置
public class ChessPosition {
	public int Listi,Listj;
	
	public ChessPosition() {}
	
	public ChessPosition(int Listi,int Listj) {
		this.Listi=Listi;
		this.Listj=Listj;
	}
}

4.frameListener类

package GoBang1;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import java.awt.event.ActionEvent;
import java.awt.Graphics;
import java.awt.Color;
import java.util.ArrayList;
 
// 实现对GoBangframe下棋界面的监听接口处理
public class frameListener implements GoBangconfig,MouseListener{
	public GoBangframe gf;
	
	public void setGraphics(GoBangframe gf) {
		this.gf=gf;
	}
	
	
	  public void mouseClicked(java.awt.event.MouseEvent e) {
		  int x=e.getX();
		  int y=e.getY();
		  // 计算棋子要落在棋盘的哪个交叉点上
		  int countx=(x/40)*40+20;
		  int county=(y/40)*40+20;
		  Graphics g=gf.getGraphics();
		  
		  if(gf.isAvail[(countx-20)/40][(county-20)/40]!=0) {
			  System.out.println("此处已经有棋子了,请下在其它地方");
		  }
		  else {
			  // 计算棋盘上棋子在数组中相应的位置
			  int colu=(countx-20)/40;
			  int ro=(county-20)/40;
			  
			  if(gf.turn==1) { // 黑子
				  // 先获取要落的地方
				  g.setColor(Color.black);
				  // 落子
				  g.fillOval(countx-size/2, county-size/2, size, size);
				  // 设置当前位置已经有棋子了,棋子为黑子
				  gf.isAvail[colu][ro]=1;
				  // 把当前所下的棋子位置保存在动态数组中
				  gf.ChessPositonList.add(new ChessPosition(colu,ro));
				  gf.turn++;
				  
				  // 判断是否已经出现五科棋子了
				  // 列判断
				  // 首先界定数组范围,防止越界
				  int imin=colu-4,imax=colu+4;
				  if(imin<0) imin=0;
				  if(imax>14) imax=14;
				  int count1=0;// 判断相连的棋子数
				  for(int i=imin;i<=imax;i++) {
					  if(gf.isAvail[i][ro]==1) count1++;
					  // 如果出现了其他棋子,或者是没有棋子时,就重新开始计数
					  else count1=0;
					  if(count1==5) { 
						  System.out.println("黑方赢");
						  return;
					  }
				  }
				  // 行判断
				  // 首先界定数组范围,防止越界
				  int jmin=ro-4,jmax=ro+4;
				  if(jmin<0) jmin=0;
				  if(jmax>14) jmax=14;
				  int count2=0;// 判断相连的棋子数
				  for(int j=jmin;j<=jmax;j++) {
					  if(gf.isAvail[colu][j]==1) count2++;
					  else count2=0;
					  if(count2==5) {
						  System.out.println("黑方赢");
						  return;
					  }
					// 如果出现了其他棋子,或者是没有棋子时,就重新开始计数
					  
				  }
				  // 135度判断
				  // 首先界定数组范围,防止越界
				  int count3=0;//判断相连的棋子数
				  for(int i=-4;i<=4;i++) {
					  if((colu+i>=0)&&(ro+i>=0)&&(colu+i<=14)&&(ro+i<=14)) {
						  if(gf.isAvail[colu+i][ro+i]==1) count3++;
							// 如果出现了其他棋子,或者是没有棋子时,就重新开始计数
						  else count3=0;
						  if(count3==5) {
							  System.out.println("黑方赢");
							  return;
						  }
					  }
				  }
				  int count4=0;// 判断相连的棋子数
				  for(int i=-4;i<=4;i++) {
					  if((colu+i>=0)&&(ro-i>=0)&&(colu+i<=14)&&(ro-i<=14)) {
						  
						  // debug
						  // System.out.print("count4:"+count4+" "); 
						  
						  if(gf.isAvail[colu+i][ro-i]==1) count4++;
							//如果出现了其他棋子,或者是没有棋子时,就重新开始计数
						  else count4=0;
						  if(count4==5) {
							  System.out.println("黑方赢");
							  return;
						  }
					  }
				  }
				  // debug
				  // System.out.println(); 
			  }
			  else { // 白子
				  g.setColor(Color.white);
				  g.fillOval(countx-size/2, county-size/2, size, size);
				  // 设置当前位置已经有棋子了,棋子为白子
				  gf.ChessPositonList.add(new ChessPosition(colu,ro));
				  gf.isAvail[colu][ro]=2;
				  gf.turn--;
				 
				  // 列判断
				  // 首先界定数组范围,防止越界
				  int imin=colu-4,imax=colu+4;
				  if(imin<0) imin=0;
				  if(imax>14) imax=14;
				  int count1=0;// 判断相连的棋子数
				  for(int i=imin;i<=imax;i++) {
					  if(gf.isAvail[i][ro]==2) count1++;
 
					// 如果出现了其他棋子,或者是没有棋子时,就重新开始计数
					  else count1=0;
					  if(count1==5) {
						  System.out.println("白方赢");
						  return;
					  }
				  }
				  // 行判断
				  // 首先界定数组范围,防止越界
				  int jmin=ro-4,jmax=ro+4;
				  if(jmin<0) jmin=0;
				  if(jmax>14) jmax=14;
				  int count2=0;// 判断相连的棋子数
				  for(int j=jmin;j<=jmax;j++) {
					  if(gf.isAvail[colu][j]==2) count2++;
					  // 如果出现了其他棋子,或者是没有棋子时,就重新开始计数
					  else count2=0;
					  if(count2==5) {
						  System.out.println("白方赢");
						  return;
					  }
					  
				  }
				  // 135度判断
				  // 首先界定数组范围,防止越界
				  int count3=0;// 判断相连的棋子数
				  for(int i=-4;i<=4;i++) {
					  if((colu+i>=0)&&(ro+i>=0)&&(colu+i<=14)&&(ro+i<=14)) {
						  if(gf.isAvail[colu+i][ro+i]==2) count3++;
						  // 如果出现了其他棋子,或者是没有棋子时,就重新开始计数
						  else count3=0;
						  if(count3==5) {
							  System.out.println("白方赢");
							  return;
						  }
					  }
				  }
				  int count4=0;// 判断相连的棋子数
				  for(int i=-4;i<=4;i++) {
					  if((colu+i>=0)&&(ro-i>=0)&&(colu+i<=14)&&(ro-i<=14)) {
						  if(gf.isAvail[colu+i][ro-i]==2) count4++;
						  // 如果出现了其他棋子,或者是没有棋子时,就重新开始计数
						  else count4=0;
						  if(count4==5) {
							  System.out.println("白方赢");
							  return;
						  }
					  }
				  }
			  }
		  }
	  }
	  
	  
	  // Method descriptor (方法描述符) 
	  public void mousePressed(java.awt.event.MouseEvent e) {}
	  public void mouseReleased(java.awt.event.MouseEvent e) {}
	  public void mouseEntered(java.awt.event.MouseEvent e) {}
	  public void mouseExited(java.awt.event.MouseEvent e) {}
}

5.GoBangconfig接口

package GoBang1;

// 定义GoBangconfig接口
// 定义与棋盘数据相关的接口,保存棋盘的起点,格子大小,行数列数等信息
public interface GoBangconfig {
	int x=20,y=20,size=40,row=15,column=15;
}


3.运行演示

开始界面

开始界面


游戏进行界面1

游戏进行界面


在这里插入图片描述

胜利!


小结

以上就是今天带来的全部正篇内容啦,看到这里不点个赞或者一键三连支持一下这个刚刚开始写博客的萌新博主嘛qwq 你的关注和支持就是我进步的动力呐~

后续我会继续分享一些有趣的小游戏给大家哦~~
c++/Java小游戏专栏保持不定期更新~~qwq

好啦,朋友们下期再见啦!!!


彩蛋

五子棋先手必胜策略传送门 :)

  • 7
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值