五子棋游戏制作的详细思路及原理

五子棋设计思路文档

一、程序设计原理、目的以及算法

运用java swing和awt框架实现五子棋的绘图,按钮的事件响应等功能。主要分为三个类:主要UI类、棋子类、以及棋盘类。在原有的五子棋的基础上增加了四子棋和六子棋的扩展玩法,对于六子棋来说,玩家需要每人一次下两颗棋子,四子棋和五子棋的判定依据相同,增加娱乐性。

在算法方面主要有两个难点,第一,需要将棋谱的绘制坐标转化为基本的数据结构,例如棋子和网格交点的坐标均采用邻接矩阵的表示方式来存储。第二,五子棋的判定输赢的算法,即,横向扫描,竖向扫描,斜向扫描,其中,斜向扫描最为困难,需要将棋盘分为两个部分依次进行。具体的伪码描述如下:

           输赢判断伪码描述:

                     for everychesses{

                                chessesare not null && chesses have played;                               

                                count++;

                                ifcount is 5, winner

}

                                棋子坐标转化为邻接矩阵的伪码描述:

                                          forevery chesses{

chess[][].X ← X

                                                     chess[][].y ← Y

                                          }

二、         程序的流程框图,以及UML图

五子棋游戏制作的详细思路及原理_第1张图片


主要UI的逻辑框图

五子棋游戏制作的详细思路及原理_第2张图片

后端算法实现的主要框图

五子棋游戏制作的详细思路及原理_第3张图片

这个设计采用了单一职责原则,将前端与后端的业务逻辑进行了分离,降低整个程序的耦合度,我们可以在以上的UML图中看到这个彼此的依赖关系。

 

 

三、算法的重难点

整个五子棋游戏在开发过程中遇到最为困难的是搭建基本数据结构的算法,判定输赢的算法,用户点击非网格处时,棋子自动修正至正确的位置上,涉及到对矩阵坐标的转换,以及对矩阵的遍历,尤其是矩阵的斜向遍历,以下就会通过源码分析的方式来进行解读。

1、 关于坐标转换矩阵的算法

我们知道,五子棋的棋盘是由若干的直线通过交错来进行绘制的,那么,每条直线的交点坐标之间应该具有一定的规律,这个交点的坐标可以用矩阵来保存,那么我们就能定义一个五子棋棋谱的行数、列数和行列之间的间隔差。

publicstaticfinalintMARGIN = 30; // 边距

        publicstaticfinalintGRID_SPAN = 35; // 网络距离

        publicstaticfinalintROW = 15;     // 行数

publicstaticfinalintCOW = 15;     // 列数

这我们能看到,我们定义了行数和列数,并且网络(格)距离我们也定义了,网络距离的数值是相对于容器的坐标,边距就是我们所谓的容器边缘的距离。

 

画出棋谱

//画出棋盘的横向线条

for(inti = 0 ;i <= ROW ;i++) {

g.drawLine(MARGIN,MARGIN +i * GRID_SPAN,MARGIN +COW *GRID_SPAN,MARGIN +i * GRID_SPAN);

             }

             //画出棋盘的纵向线条

for(inti = 0;i <= COW ;i++) {

             g.drawLine(MARGIN +i * GRID_SPAN,MARGIN,MARGIN +i * GRID_SPAN,MARGIN +ROW *GRID_SPAN);

        }

五子棋游戏制作的详细思路及原理_第4张图片

这里我们进行了两次遍历分别画横向线和纵向线,drawLine中的前两个参数表示起始位置的坐标,后面两个参数表示终止位置的坐标,那么起始位置应该是一个间隔进行数的i倍,因此可以进行遍历画图,同时每个网格交点的坐标可以存储到棋子对象中。

2、用户点击非网格位置,棋子自动修正落子点的算法

//通过鼠标的坐标换算成索引下标

     xIndex = (e.getX() -MARGIN +GRID_SPAN/2)/GRID_SPAN ;

     yIndex = (e.getY() -MARGIN +GRID_SPAN/2)/GRID_SPAN ;       

drawX = (int)((e.getX() - MARGIN +GRID_SPAN/2)/GRID_SPAN)*GRID_SPAN + MARGIN ;

drawY = (int)((e.getY() -MARGIN +GRID_SPAN/2)/GRID_SPAN)*GRID_SPAN + MARGIN ;

前两行表示的是鼠标点击的位置转化为五子棋棋子的下标索引,后两行是五子棋棋子绘制的绝对坐标,由于变量名全部采用的是int类型,所以很容易就能取到整数。这个算法的核心思路是:当用户鼠标点击网格交点以外,但是我们可以通过计算(鼠标坐标加上半个网格长度,除以网格数量后取余数),找到距离鼠标点击位置最近的那个网格点,那么就能将棋子画在网格的交点上了。

3、判断输赢的算法描述

判断输赢的算法在横向和竖向方向比较简单,但是斜向判断有一定难度。判断输赢的思路就是通过用户每次下一步棋子,进行横向纵向斜向扫描,累计到5颗子即可判断输赢。下面就是一些算法实现:

五子棋游戏制作的详细思路及原理_第5张图片

斜向扫描判定

五子棋游戏制作的详细思路及原理_第6张图片

就用类似的思路进行遍历即可(以下是图解)

五子棋游戏制作的详细思路及原理_第7张图片

这部分功能的实现在现阶段没有寻找到一个更加好的算法,因此只能重复代码段来进行黑白棋子的交替判断,后续代码的重构过程中在加以改进。

以下贴出的源码有详细注释

package 五子棋对战版;

import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;

import javax.sound.sampled.AudioInputStream;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

//主要UI类
public class mainUI extends JFrame {
	//实例化棋谱
	 chessMap Board ;
	 
	 
	JButton StartorRestart  ;  //开始和重新开始循环按钮
	JButton FourPoint;			//四子琪按钮			增加娱乐性
	JButton SixPoint;			//六子棋子按钮			哈哈好玩
	JButton FivePoint;			//五子棋按钮
	
	//胜利者输出信息
	JLabel WinerInfor ;
	JLabel Info;			//面板信息,提示玩家现在玩的是几子棋
	JLabel Who;			//输出那个玩家下棋
	
	//图片加载
	ImageIcon Black = new ImageIcon("黑子.png");
	ImageIcon White = new ImageIcon("白子.png");
	ImageIcon SixPointPNG = new ImageIcon("sixBTN.png");
	ImageIcon FourPointPNG = new ImageIcon("fourBTN.png");	//导入图片
	ImageIcon FivePointPNG = new ImageIcon("fiveBTN.png");
	ImageIcon StartGame = new ImageIcon("StartGame.png");
	ImageIcon ReStartGame = new ImageIcon("ReStartGame.png");
	
	boolean flag = true ;			//这个标签用来控制按钮,当开始按钮开启时,其他的按钮不能响应
	
	//构造函数
	mainUI() {
		
		
		Board = new chessMap() ;   //实例化棋盘对象
		
		//设置主窗口信息
		setTitle("好玩五子棋游戏");
		setBounds(100, 100, 900, 600);
		setResizable(false);
		setDefaultCloseOperation(3);
		
		//提示玩家信息的标签实例化
		Info = new JLabel() ;
		Info.setLocation(690,50);
		Info.setSize(140, 50);
		Info.setText("
五子棋
"); WinerInfor = new JLabel(); WinerInfor.setLocation(670, 380); WinerInfor.setSize(130, 50); Black.setImage(Black.getImage().getScaledInstance(50, 50, Image.SCALE_DEFAULT)); White.setImage(White.getImage().getScaledInstance(50, 50, Image.SCALE_DEFAULT)); Who = new JLabel(); Who.setLocation(710, 450); Who.setSize(50,50); //实例化按钮对象 //开始重开按钮 StartorRestart = new JButton(); StartGame.setImage(StartGame.getImage().getScaledInstance(130, 50, Image.SCALE_DEFAULT)); ReStartGame.setImage(ReStartGame.getImage().getScaledInstance(130, 50, Image.SCALE_DEFAULT)); StartorRestart.setIcon(StartGame); StartorRestart.setBorderPainted(false); StartorRestart.setBorder(null); StartorRestart.setLocation(670, 100); StartorRestart.setSize(130,50); //四子棋按钮 FourPointPNG.setImage(FourPointPNG.getImage().getScaledInstance(130, 50, Image.SCALE_DEFAULT));//设置大小 FourPoint = new JButton(); FourPoint.setIcon(FourPointPNG); FourPoint.setBorderPainted(false); //不画边框 FourPoint.setBorder(null); //边框为空 FourPoint.setLocation(670, 170); FourPoint.setSize(130, 50); //六子棋按钮 SixPoint = new JButton(); SixPointPNG.setImage(SixPointPNG.getImage().getScaledInstance(130, 50, Image.SCALE_DEFAULT)); SixPoint.setIcon(SixPointPNG); SixPoint.setBorderPainted(false); SixPoint.setBorder(null); SixPoint.setLocation(670, 240); SixPoint.setSize(130, 50); //五子棋按钮 FivePoint = new JButton(); FivePointPNG.setImage(FivePointPNG.getImage().getScaledInstance(130, 50, Image.SCALE_DEFAULT)); FivePoint.setIcon(FivePointPNG); FivePoint.setBorderPainted(false); FivePoint.setBorder(null); FivePoint.setLocation(670, 310); FivePoint.setSize(130, 50); //添加事件监听响应 UIlistener li = new UIlistener(); StartorRestart.addActionListener(li); FourPoint.addActionListener(li); SixPoint.addActionListener(li); FivePoint.addActionListener(li); //容器不知道什么用 Container container = getContentPane(); //容器,好像也没什么用,不知道有啥用 container.add(Board); //棋盘对象的流式布局设置为空,方便在指定位置添加按钮 Board.setLayout(null); Board.add(StartorRestart); Board.add(FourPoint); Board.add(SixPoint) ; Board.add(FivePoint); Board.add(Info); Board.add(WinerInfor); Board.add(Who); //棋盘添加到主窗口 add(Board,BorderLayout.CENTER); //Board.setOpaque(true) ; //设置透明度,然而并没什么卵用 //主窗口可见 setVisible(true); //这里我使用多线程技术,接收从后端传来的输赢消息,从而返回给玩家到底哪方赢了 Thread WinnerPointer = new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub //判断赢家 while(true) { //Who.setText(Board.whoPlay()); if (Board.whoPlay() == "白手") { Who.setIcon(White); } if (Board.whoPlay() == "黑手") { Who.setIcon(Black); } String aString =Board.winner() ; System.out.println("test"); //好像没有这句话线程启动不了了,不知道为啥 if (aString != null) { System.out.println(aString); WinerInfor.setText("
"+Board.winner()+"
"); } } } }) ; WinnerPointer.start(); } private class UIlistener implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub Object object = e.getSource() ; if (object == StartorRestart) { if (StartorRestart.getIcon() == StartGame) { StartorRestart.setIcon(ReStartGame); Board.start(); //Info.setText("五子棋"); System.out.println("开始 游戏按钮响应"); flag = false ; } else if (StartorRestart.getIcon() == ReStartGame) { StartorRestart.setIcon(StartGame); Board.restart(); //Info.setText("五子棋"); System.out.println("重新 游戏按钮响应"); flag = true ; } } if (flag) { if (object == FourPoint) { System.out.println("四子琪好玩哦!!"); Board.fourPoint(); Info.setText("
四子棋
"); } if (object == SixPoint) { System.out.println("六子棋好玩"); Board.sixPoint(); Info.setText("
六子棋
"); } if (object == FivePoint) { Board.fivePoint(); Info.setText("
五子棋
"); } } } } public static void main(String[] args) { // TODO Auto-generated method stub mainUI main = new mainUI(); } }
package 五子棋对战版;
//棋子类

import java.awt.Color;
import java.awt.Image;

public class chessPoint {
	public static final int R = 15 ; //棋子半径
	private  int x ;					//棋子的x坐标
	private  int y ;					//棋子的y坐标
	private Color color ;			//棋子的颜色
	//索引下标
	private int visited = -1 ; 		//表示这个棋子是否被下过,-1代表没有下,1代表下过了
	chessPoint(){
		
	}
	chessPoint(int visited,int X,int Y){
		this.x = X;
		this.y = Y;
		this.visited = visited ;
	}
	//初始化使用
	public void setUnvisited(int Unvisited) {
		this.visited = Unvisited;
	}
	//获取是否访问过
	public int getVisited(){
		return visited ;
	}
	//设置颜色
	public void setColor(Color color){
		this.color = color;
	}
	//获取棋子的颜色
	public Color getColor() {
		return color ;
	}
	
	public int getX() {
		return x;
	}
	public int getY() {
		return y;
	}
	
//	public static void main(String[] args) {
//		
//	}
	
}
package 五子棋对战版;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.RadialGradientPaint;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.text.html.HTMLDocument.HTMLReader.BlockAction;
import 五子棋对战版.chessPoint;

//棋盘类
public class chessMap extends JPanel implements MouseListener{

	
	//确定五子棋棋谱的大小
		public static final int MARGIN = 30; // 边距
		public static final int GRID_SPAN = 35; // 网络距离
		public static final int ROW = 15; 	// 行数
		public static final int COW = 15; 	// 列数
		private int flag;  					//设置标签,用来表示哪一方下棋    0表示白方,1表示黑方 
		private int drawX;					//实际要画的坐标值,这个值就是棋子在panel中的坐标
		private int drawY;
		private int StepOfPlayer = 0;							//玩家的步数记录,应用于六子棋中,记录玩家到底是不是每次走了两步		
		private int xIndex;										//下标索引
		private int yIndex ;
		private int countChess = 5;								//统计棋子数胜利的个数(默认是5),例如五子棋必须5颗子连,那么这个值就是5,如果六子棋六颗连,那么这个值就是6,以此类推
		private boolean gameover = true ;						//游戏结束的标签 
		
		chessPoint[][] chess = new chessPoint[16][16];			//初始化棋子,二维数组实现x轴与y轴坐标
		private String winner;				//记录赢家
		private String blackOrwhite;  		//记录当前在下的棋子是白还是黑,用于输出到前端UI,告诉玩家
		
		private Image image ;									//加载图片的类,表示加载棋谱背景
		
		
		//构造函数
		public chessMap() {
			//背景图片加载
			try {
				image = ImageIO.read(new File("/Users/apple/Desktop/五子棋对战版/background.jpg"));
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			
			//初始化数组,否则会出现空指针错误
			for(int i = 0 ; i<=15 ; i++) {
				for(int j = 0 ; j<=15 ; j++) {
					chess[i][j] = new chessPoint() ;
				}
			}
			
			addMouseListener(this) ;//为当前类添加鼠标监听
			//添加鼠标移动的事件监听
			addMouseMotionListener(new MouseMotionListener() {
				
				@Override
				public void mouseMoved(MouseEvent e) {
					// TODO Auto-generated method stub
					int x1 = (e.getX() - MARGIN + GRID_SPAN/2)/GRID_SPAN ;  //将鼠标的坐标转化为网格坐标      
					int y1 = (e.getY() - MARGIN + GRID_SPAN/2)/GRID_SPAN ;  
					/*这里必须要做一个判断:鼠标不能一移动到棋盘外面去下棋子
					*					游戏结束了也不能下棋
					*					已经有棋子了也不能下棋子
					*/					
					if (x1 < 0 || y1 < 0 || x1 > COW || y1 > ROW) {
						setCursor(new Cursor(Cursor.DEFAULT_CURSOR));  //在棋盘外面,光标默认形态
					}
					else {
						setCursor(new Cursor(Cursor.HAND_CURSOR));//棋盘内,光标手为形态
						//System.out.println(x1+"\t"+y1);
					}
					
				}
				
				@Override
				public void mouseDragged(MouseEvent e) {
					// TODO Auto-generated method stub
					
				}
			});
		}
		
		public void paintComponent(Graphics g) {
			super.paintComponent(g);//将这个graphics,super给它的父类
			
			g.drawImage(image, 0, -100, null);
			//画出棋盘的横向线条
			for(int i = 0 ; i <= ROW ; i++) {
				g.drawLine(MARGIN, MARGIN + i * GRID_SPAN, MARGIN + COW * GRID_SPAN, MARGIN + i * GRID_SPAN);
			}
			//画出棋盘的纵向线条
			for(int i = 0; i <= COW ; i++) {
				g.drawLine(MARGIN + i * GRID_SPAN, MARGIN, MARGIN + i * GRID_SPAN, MARGIN + ROW * GRID_SPAN);
			
			}
			//重画棋子
			for(int i = 0 ; i <= 15;i++) {
				for(int j = 0 ; j <= 15;j++) {
					if (chess[i][j] != null && chess[i][j].getVisited() == 1) {
						g.setColor(chess[i][j].getColor());
						g.fillOval(chess[i][j].getX()-7, chess[i][j].getY()-7, 14, 14);
					}
				}
			}
			if (IsWin()) {
				this.gameover = true ;
		
				return ;
			}
			System.out.println("---------------------------");
			
		}
	//判断是否这个棋子已经下过了,如果没有下过,则返回1,下过了返回0
	private boolean IsVisited(int i,int j) {
		return chess[i][j].getVisited() == -1 ? true:false;
	}
	
	
	//判断输赢
	/*			哎这个算法实在相当复杂,脑细胞已经死亡
	 * 			思路是这样的: 我每次进行横、竖、撇、捺四个方向进行扫描,扫描到连子就判赢了
	 * 						这里的代码重复实在无法避免了,想不出有更好的解决办法,希望大神能指导我一下
	 * 						撇、捺的扫描是最难的,相当于一个矩阵的斜向输出,而且要分成两部分来进行,实在很难,完全是面向试错的程序设计  /(ㄒoㄒ)/~~  算法正确全靠脑补找规律
	 * 						文字实在是说不清楚,本人水平有限,还是看代码吧,不知道能不能看懂额    o(╯□╰)o
	 * */
	private boolean IsWin() {
		
		//黑色棋子竖向查找
		for(int i = 0 ; i<=15;i++) {								//外层循环遍历棋子数组xIndex的X轴的坐标索引	
			int count = 0;										//每次一纵列要是没有连子,那么就必须要将计数器清0了
			for(int j=0;j<=15;j++) {								//内层循环表示遍历棋子数组yIndex的Y轴的坐标索引
				/*这里就是进行连珠计算的逻辑算法
				 * 必须满足三个条件:   1、棋子数组不能为空
				 * 				     2、棋子必须是已经下过了的。即getVisited()这个函数返回一个1值,就表示已经下过了
				 * 					3、判断棋子颜色,这里必须获取到棋子的颜色才行,这样才知道到底是哪一个棋子需要判断连珠
				 * */			
				if (chess[i][j] !=null && chess[i][j].getVisited() == 1 && chess[i][j].getColor() == Color.black) {		
					count++;
					System.out.println(count+"黑  竖向查找");
					if (count == countChess) {											//计数器累计到5,代表5子连在一起
						System.out.println("黑  竖向查找胜!!!");
						winner ="黑棋胜利!";
						return true ;
					}
				}
				else {
					count = 0 ;		//发现不连续的棋子时,我需要将计数器清空为0
				}
			}
		}
		//黑色棋子横向查找       算法思路同理
		for(int i = 0;i<=15;i++) {
			int count = 0 ;
			for(int j=0;j<=15;j++) {
				if (chess[j][i] != null && chess[j][i].getVisited() == 1 && chess[j][i].getColor() == Color.black) {
				count++;
				System.out.println(count+"黑   横向查找");
				if (count == countChess) {
					System.out.println("黑 横向查找胜!!");
					winner ="黑棋胜利!";
					return true ;
					}
				}
				else {
					count = 0 ; 
				}
			}
		}
		//白色棋子竖向查找
		for(int i = 0;i<=15;i++) {
			int count = 0;
			for(int j=0;j<=15;j++) {
				if (chess[i][j] !=null && chess[i][j].getVisited() == 1 && chess[i][j].getColor() == Color.white) {
					count++;
					System.out.println(count+"白  竖向查找");
					if (count == countChess) {
						System.out.println("白  竖向查找胜!!");
						winner ="白棋胜利!";
						return true ;
					}
				}
				else {
					count = 0 ;
				}
			}
		}
		//白色棋子横向查找
		for(int i = 0;i<=15;i++) {
			int count = 0 ;
			for(int j=0;j<=15;j++) {
				if (chess[j][i] !=null && chess[j][i].getVisited() == 1 && chess[j][i].getColor() == Color.white) {
					count++;
					System.out.println(count+"白  竖向查找");
					if (count == countChess) {
						System.out.println("白  竖向查找胜!!");
						winner ="白棋胜利!";
						return true ;
					}
				}
				else {
					count = 0 ;
				}
			}
		}
		
		
		/*	这一层斜向的判断是最难的,主要是把一个棋盘分成两个部分来判断:对角线以上,对角线以下
		 * 	外层循环遍历数组的横坐标索引节点,每次遍历都要重置计数器
		 * 	内层循环的判断很复杂,算法很难,具体就是按照横轴坐标变化的规律,来计算纵轴坐标,只能意会不可言传(实在说不清楚,不过按照这个算法走一遍应该就能理解了)。
		 * */
		//黑色棋子右上至左下查找(前半部分)
	for(int i = 0 ; i <= 15; i++) {
			int count = 0 ;
			for(int j = 0 ;j <= i ; j++) {
				if (chess[j][i-j] != null &&chess[j][i-j].getVisited() == 1 && chess[j][i-j].getColor() == Color.black) {
					count++;
					System.out.println(count+"黑   斜向遍历(前半部分)");
					if (count == countChess) {
						System.out.println("黑   斜向遍历(前半部分)查找胜!!!");
						winner ="黑棋胜利!";
						return true;
					}
				}
				else count = 0;
			}
		}

	//黑色棋子右上至左下查找(后半部分)
	for(int i = 1 ; i <=15 ; i++){
		int count = 0 ;
		for(int j = i ; j<=15; j++) {
			if (chess[j][15 - j + i ] != null &&chess[j][15 - j + i ].getVisited() == 1 && chess[j][15 - j + i ].getColor() == Color.black) {
				count++;
				System.out.println(count +"黑   斜向遍历(后半部分)");
				if (count == countChess) {
					System.out.println("黑   斜向遍历(后半部分)查找胜!!!");
					winner ="黑棋胜利!";
					return true ;
				}
			}
			else count = 0 ;
		}
	}
		
	//白色棋子右上至左下查找(前部分)
	for(int i = 0 ; i <= 15; i++) {
		int count = 0 ;
		for(int j = 0 ;j <= i ; j++) {
			if (chess[j][i-j] != null &&chess[j][i-j].getVisited() == 1 && chess[j][i-j].getColor() == Color.white) {
				count++;
				System.out.println(count+"白   斜向遍历(前半部分)");
				if (count == countChess) {
					System.out.println("白   斜向遍历(前半部分)查找胜!!!");
					winner ="白棋胜利!";
					return true;
				}
			}
			else count = 0;
		}
	}

	//白色棋子右上至左下查找(后半部分)
	for(int i = 1 ; i <=15 ; i++){
		int count = 0 ;
		for(int j = i ; j<=15; j++) {
			if (chess[j][15 - j + i ] != null &&chess[j][15 - j + i ].getVisited() == 1 && chess[j][15 - j + i ].getColor() == Color.white) {
			count++;
			System.out.println(count +"白   斜向遍历(后半部分)");
				if (count == countChess) {
				System.out.println("白   斜向遍历(后半部分)查找胜!!!");
				winner ="白棋胜利!";
				return true ;
				}
			}
			else count = 0 ;
		}
	}
	//黑色棋子左上至右下查找(前部分)
	for(int i = 0 ; i <= 15 ; i++ ) {
		int count = 0 ;
		for(int j = 0 ; j+i<= 15 ; j++ ) {
			if (chess[j + i][ j ] != null &&chess[j+i][j].getVisited() == 1 && chess[j+i][ j ].getColor() == Color.black) {
				count++;
				System.out.println(count+"黑   左上至右下(前半部分)!!!");
				if (count == countChess) {
					System.out.println("黑   左上至右下(前半部分)胜!!!");
					winner ="黑棋胜利!";
					return true ;
				}
			}
			else count = 0 ;
		}
	}
	//黑色棋子左上至右下查找(后部分)
	for(int i = 1 ; i<=15;i++) {
		int count = 0 ;
		for(int j = 0; j+i<=15 ;j++) {
			if (chess[ j ][ j+i ] != null && chess[ j ][ j+i ].getVisited() == 1 && chess[ j ][ j+i ].getColor() == Color.black) {
				count++;
				System.out.println(count+"黑   左上至右下(后半部分)!!!");
				if (count==countChess) {
					System.out.println("黑   左上至右下(后半部分)胜!!!");
					winner ="黑棋胜利!";
					return true ;
				}
			}
			else count = 0 ;
		}
	}
	//白色棋子左上至右下查找(前部分)
	for(int i = 0 ; i <= 15 ; i++ ) {
		int count = 0 ;
		for(int j = 0 ; j+i<= 15 ; j++ ) {
			if (chess[j + i][ j ] != null &&chess[j+i][j].getVisited() == 1 && chess[j+i][ j ].getColor() == Color.white) {
				count++;
				System.out.println(count+"白   左上至右下(前半部分)!!!");
				if (count == countChess) {
					System.out.println("白   左上至右下(前半部分)胜!!!");
					winner ="白棋胜利!";
					return true ;
				}
			}
			else count = 0 ;
		}
	}
	//白色棋子左上至右下查找(后部分)
	for(int i = 1 ; i<=15;i++) {
		int count = 0 ;
		for(int j = 0; j+i<=15 ;j++) {
			if (chess[ j ][ j+i ] != null && chess[ j ][ j+i ].getVisited() == 1 && chess[ j ][ j+i ].getColor() == Color.white) {
				count++;
				System.out.println(count+"白   左上至右下(后半部分)!!!");
				if (count==countChess) {
					System.out.println("白   左上至右下(后半部分)胜!!!");
					winner ="白棋胜利!";
					return true ;
				}
			}
			else count = 0 ;
		}
	}
		return false ;
	}
	
	//重新开始功能
	public void restart() {
		//棋子数组重置清空
		for(int i = 0 ; i <=ROW ; i++) {
			for(int j=0;j<=COW;j++) {
				chess[i][j].setUnvisited(-1); //将所有棋子均标记为没有访问
			}
		}
		//游戏重新开始的判断标签
		this.gameover = true ;
		this.winner = " ";
		//重画棋盘
		repaint();
	} 
	//游戏开始功能
	public void start() {
		this.gameover = false;
	}
	
	//四子棋设定
	public void fourPoint() {
		this.countChess = 4 ;
	}
	//五子棋设定
	public void fivePoint() {
		this.countChess = 5 ;
	}
	//五子棋设定
	public void sixPoint() {
		this.countChess = 6 ;
	}
	
	public String whoPlay() {
		return blackOrwhite;
	}
	public String winner() {
		return winner ;
	}
	
	//六子棋,因为六子棋规则不一样,每个人需要轮流下两颗棋子才行,所以需要一个新的功能,步数判断来实现才行
	private void sixPointGame() {
		if (flag == 0 && IsVisited(xIndex, yIndex)) {
			chess[xIndex][yIndex] = new chessPoint(1,drawX,drawY);
			chess[xIndex][yIndex].setColor(Color.white);						
			repaint();				
			System.out.println("白");	
			this.StepOfPlayer++;
			blackOrwhite = "黑手";
			if (StepOfPlayer == 2) {
				flag = 1;
				StepOfPlayer = 0 ;
			}
		}
		else if ( flag == 1 && IsVisited(xIndex, yIndex) ) {
			chess[xIndex][yIndex] = new chessPoint(1,drawX,drawY);
			chess[xIndex][yIndex].setColor(Color.black);						
			repaint();				
			System.out.println("黑");
			this.StepOfPlayer++;
			blackOrwhite = "白手";
			if (StepOfPlayer == 2) {
				flag = 0 ;
				StepOfPlayer = 0 ;
			}
		}
	}
	//五子棋和四子棋的规则一样,所以不用另外在写一个功能
	private void fiveOrfourPointGame() {
		if (flag == 0 && IsVisited(xIndex, yIndex)) {
			flag = 1 ;
			chess[xIndex][yIndex] = new chessPoint(1,drawX,drawY);
			chess[xIndex][yIndex].setColor(Color.white);						
			repaint();				
			blackOrwhite = "黑手";
			System.out.println("白");
		}
		else if ( flag == 1 && IsVisited(xIndex, yIndex) ) {
			flag = 0 ;
			chess[xIndex][yIndex] = new chessPoint(1,drawX,drawY);
			chess[xIndex][yIndex].setColor(Color.black);						
			repaint();				
			blackOrwhite = "白手";
			System.out.println("黑");
		}

	}
	
	
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		
		//如果游戏结束了,那么就停止鼠标事件响应
		if (gameover == true) {
			return ;
		}
		
		//通过鼠标的坐标换算成索引下标
		 xIndex = (e.getX() - MARGIN + GRID_SPAN/2)/GRID_SPAN ;
		 yIndex = (e.getY() - MARGIN + GRID_SPAN/2)/GRID_SPAN ;
		drawX = (int)((e.getX() - MARGIN + GRID_SPAN/2)/GRID_SPAN)*GRID_SPAN + MARGIN ;
		drawY = (int)((e.getY() - MARGIN + GRID_SPAN/2)/GRID_SPAN)*GRID_SPAN + MARGIN ;
		System.out.println(drawX+"\t"+drawY);
		
		

		if(countChess == 5 || countChess == 4) {
			fiveOrfourPointGame();
		}
		if (countChess == 6) {
			sixPointGame();
		}
		
		//System.out.println(xIndex+"\t"+yIndex);
		//System.out.println(flag);
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
	
	//测试
//	public static void main(String[] args) {
//		// TODO Auto-generated method stub
//		
//		chessMap cMap = new chessMap();
//		JFrame jFrame = new JFrame("test") ;
//		jFrame.add(cMap);
//		jFrame.setBounds(100, 100, 900, 600);
//		jFrame.setDefaultCloseOperation(3);
//		jFrame.setResizable(false);
//		jFrame.setVisible(true);
//	}

}









你可能感兴趣的:(五子棋游戏制作的详细思路及原理)