编写一个五子棋代码量不会很大,但这好歹也算是个项目,所以还是需要花点时间的。看别人的代码需要耐心,要看懂别人的代码就更需要耐心了,作为一个程序员也就是需要这样的耐心。当然,在代码里我会尽量的多加一些注释来提高代码的可读性,唯一的要求就是要读者们一步一步的跟着我来,顺着我的思路一步一步的深入,这样才能最终达到我写这篇博客和你看这篇博客的目的。
那下面呢,我就具体介绍一下人人五子棋是如何实现的。
1)首先我们要有一个五子棋界面,就是画出许多行横线和许多行竖线
private void DrawCheesTable(Graphics g) { // TODO Auto-generated method stub //画出指定的行数 for( int i = 0; i < Config.ROWS; i++) g.drawLine(Config.X0, Config.Y0 + Config.SIZE * i, Config.X0 + Config.SIZE *( Config.COLUMNS - 1), Config.Y0 +Config.SIZE * i); //画出指定的列数 for( int i = 0; i < Config.COLUMNS; i++) g.drawLine(Config.X0 + Config.SIZE * i,Config.Y0, Config.X0 + Config.SIZE * i,Config.Y0 +( Config.ROWS - 1) * Config.SIZE); }
看到上面的代码里面有一些奇怪的符号吧,不急,那是我事先定义好的保存常量数据的类。另外,for语句中画线所用到的数据是如何给定的,留给读者自己分析了。
2)创建一个保存常量的类,为了方便我们改变棋子大小,棋盘大小
棋盘画好了,现在就来实现释放鼠标时画填充圆。鼠标释放,就用到 public void mouseReleased(MouseEvent e) {}函数,于是就要监听器类extends java.awt.event.MouseAdapter了。
public interface Config { //棋盘的初始点坐标 public static final int X0 = 50; public static final int Y0 = 50; //多少列多少行 public static final int ROWS = 11; public static final int COLUMNS = 14; //棋子的大小 //格子的大小 public static final int CHESS_SIZE = 40; public static final int SIZE = 40; }
3)鼠标释放方法
public void mouseReleased(MouseEvent e) { //得到鼠标释放时的点的坐标 int x1 = e.getX(); int y1 = e.getY(); //按下点后我们就去找 它在拿个交点附近 for(int i = 0; i < Config.ROWS; i++){ for(int j = 0; j < Config.COLUMNS; j++){ //得到每一个交点的值 xx = Config.X0 + Config.SIZE * j; yy = Config.Y0 + Config.SIZE * i; //如果这个交点可以放棋子 if(FiveChress_array[i][j] == 0) //判断离谁更近 if(x1 > xx - Config.SIZE/3 && x1 < xx + Config.SIZE/ 3 && y1 > yy - Config.SIZE /3 && y1 < yy + Config.SIZE /3 ) //花黑棋 if(count){ System.out.println("再黑棋中xx的值是 " +xx +"\t" + "在黑棋中yy的值是 " + yy); //画出来的是黑棋 g.setColor(java.awt.Color.BLACK); g.fillOval(xx - Config.CHESS_SIZE/2, yy - Config.CHESS_SIZE/2, Config.CHESS_SIZE, Config.CHESS_SIZE); //下一次是画白棋 count = false; //用数组记录每个交点的属性 1黑棋 0空白 -1白棋 FiveChress_array[i][j] = 1; x = j; y = i; //画出了点酒结束 不再循环 break; }else{ //画白棋 System.out.println("再白棋中xx的值是 " +xx +"\t" + "在白棋中yy的值是 " + yy); g.setColor(java.awt.Color.WHITE); g.fillOval(xx - Config.CHESS_SIZE/2, yy - Config.CHESS_SIZE/2, Config.CHESS_SIZE, Config.CHESS_SIZE); count = true; FiveChress_array[i][j] = -1 ; x = j; y = i; //画出了点酒结束 不再循环 break; } } } //调用判断是否赢棋函数 win_or_not(x,y); }
这其中包含了一个判断鼠标按下点离哪个棋盘交点最近的算法,留给读者自己分析了。里面同时有使用很多的变量它们的声明如下
//定义画板对象 private java.awt.Graphics g; //每个棋子的基本属性 true表示要放黑棋 false表示要放白棋 private boolean count = true; //再创建两个数来表示交点坐标 使得画出来的圈圆心会在交点 private int xx,yy; //创建(x,y)来表示按下的那个点所放在的焦点坐标 比如(1,3) 表示第一行第三个交点 private int x,y; //创建一个数组记录每个可以放棋子的点的状态 0表示空 1表示黑棋 -1表示白棋 private int [][] FiveChress_array = new int[Config.ROWS][Config.COLUMNS];
4)鼠标监听器类的构造函数
//构造函数 public ChessListener(java.awt.Graphics g1 , int [][] FiveChress_array){ //地址传递 this.g = g1; this.FiveChress_array = FiveChress_array; }
现在我们的棋子可以下了,而且可以下在正确的位置上,下面要做的是实现win_or_not()函数了,该函数里我们要实现行列左倾斜,右倾斜的判断。
5)实现win_or_not()函数
private void win_or_not(int x, int y) { //如果在行列左斜右斜的方向上有了五个连续的同色棋子 就可以判断出输赢了 System.out.println("进入win_or_not函数"); if(check_row(x,y) || check_columns(x,y) || check_left(x,y) || check_right(x,y) ){ if(!count){ //黑棋赢了 JOptionPane.showMessageDialog(null,"我靠 黑棋赢了"); System.out.println("我靠 黑棋赢了"); }else{ //白棋赢了 JOptionPane.showMessageDialog(null,"我靠 白棋赢了"); System.out.println("我靠 白棋赢了"); } } }
在if判断里调用了判断行、列、左斜、右斜的函数。其中JOptionPane.showMessageDialog(null,"");是用来弹出一个对话框突出显示输赢。
6)check_row函数的实现
private boolean check_row(int x, int y) { int num = 0; //表示相同颜色的棋子个数 //开始向右找相邻的相同颜色的 for(int i = x ; i < Config.COLUMNS ; i++){ if(FiveChress_array[y][x] == FiveChress_array[y][i]){ //找到了 就加一 num ++; }else{ //找到了有一个不是 就跳出 break; } } //开始向左找相邻的相同颜色的 for(int i = x ; i > 0 ; i--){ if(FiveChress_array[y][x] == FiveChress_array[y][i-1]){ //找到了 就加一 num ++; }else{ //找到了有一个不是 就跳出 break; } } System.out.println("在check_row函数里num = " + num); //如果有了五个或五个以上的连续相同颜色就给出判断 true if(num >= 5) return true; else return false; }
7)check_columns函数的实现
private boolean check_columns(int x, int y) { int num = 0; //表示相同颜色的棋子个数 //开始向右找相邻的相同颜色的 for(int i = y ; i < Config.ROWS ; i++){ if(FiveChress_array[y][x] == FiveChress_array[i][x]){ //找到了 就加一 num ++; }else{ //找到了有一个不是 就跳出 break; } } //开始向左找相邻的相同颜色的 for(int i = y ; i > 0 ; i--){ if(FiveChress_array[y][x] == FiveChress_array[i-1][x]){ //找到了 就加一 num ++; }else{ //找到了有一个不是 就跳出 break; } } System.out.println("在check_columns函数中num = " + num); //如果有了五个或五个以上的连续相同颜色就给出判断 true if(num >= 5) return true; else return false; }
8)check_left函数的实现
private boolean check_left(int x, int y) { int num = 0; //表示相同颜色的棋子个数 //定义ix,jy记录下(y,x); int ix = x; int jy = y; //开始向右上找相邻的相同颜色的 for(int i = x, j = y;(Config.COLUMNS - i) < j ? (i < Config.COLUMNS) : j >= 0 ; i++,j--){ if(FiveChress_array[y][x] == FiveChress_array[j][i]){ //找到了 就加一 num ++; }else{ //找到了有一个不是 就跳出 break; } } //开始向左下角找相邻的相同颜色的 for(int i = ix, j = jy ; i <(Config.ROWS - j) ? i>=0 : (j < Config.ROWS) ; i--,j++){ if(FiveChress_array[jy][ix] == FiveChress_array[j][i]){ //找到了 就加一 num ++; }else{ //找到了有一个不是 就跳出 break; } } //在两个for循环里有两次和自己比较颜色 num--; System.out.println("在check_left函数里num = " + num); //如果有了五个或五个以上的连续相同颜色就给出判断 true if(num >= 5) return true; else return false; }
9)check_right函数的实现
private boolean check_right(int x, int y) { int num = 0; //表示相同颜色的棋子个数 //定义i,j记录下(y,x); int ix = x; int jy = y; //开始向右下角找相邻的相同颜色的 for(int i = x, j = y;(Config.COLUMNS - i) < (Config.ROWS - j) ? (i < Config.COLUMNS) : (j < Config.ROWS) ; i++,j++){ if(FiveChress_array[jy][ix] == FiveChress_array[j][i]){ //找到了 就加一 num ++; }else{ //找到了有一个不是 就跳出 break; } } //开始向左上角找相邻的相同颜色的 for(int i = ix, j = jy ; i < j ? i >= 0 : j >= 0 ; i--,j--){ if(FiveChress_array[y][x] == FiveChress_array[j][i]){ //找到了 就加一 num ++; }else{ //找到了有一个不是 就跳出 break; } } //在两个for循环里有两次和自己比较颜色 num--; System.out.println("在check_right函数里num = " + num); //如果有了五个或五个以上的连续相同颜色就给出判断 true if(num >= 5) return true; else return false; }
这些个方法都大同小异,主要注意它们的坐标,和递增递减关系,行和列一定不能表示错。x的改变就是列数的改变,y的改变就是行数的改变。
写到这里基本上人人五子棋就完成了,下面要做的就是重绘,因为之前我们已经有用一个二维数组及路线每一个交点的属性,现在这个也就比较好实现了。
10)paint函数的重写
public void paint(Graphics g1){ //先绘出各个组件 super.paint(g1); //绘出棋盘 DrawCheesTable(g1); //重绘棋子 DrawChees(g1); }
11)重绘棋子函数的实现
private void DrawChees(Graphics g1) { // TODO Auto-generated method stub for(int i = 0; i < Config.ROWS; i++){ for(int j = 0; j < Config.COLUMNS; j++){ //得到每一个交点的值 xx = Config.X0 + Config.SIZE * j; yy = Config.Y0 + Config.SIZE * i; if(FiveChress_array[i][j] == 1){ g.setColor(Color.BLACK); g.fillOval(xx - Config.CHESS_SIZE/2, yy - Config.CHESS_SIZE/2, Config.CHESS_SIZE, Config.CHESS_SIZE); }else if(FiveChress_array[i][j] == -1){ g.setColor(Color.WHITE); g.fillOval(xx - Config.CHESS_SIZE/2, yy - Config.CHESS_SIZE/2, Config.CHESS_SIZE, Config.CHESS_SIZE); } } } }
现在人人五子棋就完成了。
但,这还是无比不够的。首先非常重要的界面不够美观,悔棋,重新开始,判断输赢后就不可以再下棋等等都还没有实现,留给读者们自己扩展了。
相关推荐
java五子棋人机人人
简易版的五子棋,运用view来进行布局和代码的编写
Python小游戏源码-五子棋之人人对战项目源码
五子棋是世界智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏,是世界智力运动会竞技项目之一,通常双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成5子连线者获胜。 棋具与围棋通用,...
VC++五子棋程序集合(内含有控制台下、窗体界面、人机对战、人人对战和五子棋算法精析等多个经典之作源代码)全部亲自测试后,都能在VC6.0环境下直接编译成功!
五子棋人机对战,人人对战,局域网对战,注释清楚,另加了一些小功能,联系qq:1345136805
五子棋包括悔棋功能。人人对战判断输赢。赢棋之后清空界面。传参问题。
NULL 博文链接:https://1075345532.iteye.com/blog/1882153
基于MFC的五子棋程序,里面有人人和人机对弈模式,AI水平还不错,可以下载参考啦,里面是一个完整的工程,代码后面有足够详细的注释
简易五子棋,通俗易懂型。能实现人与人的对战,棋盘,棋子均是用GDI绘的。
可以轻松调试,就是程序有些简陋 不够美观
一个五子棋 图形界面 人机或人人对战 VC++ MFC 对于一个想学习游戏编程来说的学者,值得一看喔
人人版五子棋源代码,鼠标控制,左击下棋,右击可悔棋,计算双方赢的局数,悔棋数量,显示所下棋子的四个方向相同棋子数量
五子棋,人人对战,可重置游戏, 代码是相当的简单,适合初学者阅读吧
实现安卓端人人对战,采用自定义View方便二次开发使用
鼠标指针可变,左下角状态栏提示,最小化后保存棋盘,悔棋还没有做好。
用VC++ 编写五子棋游戏,目前只是想了人人对战,谢谢大家支持,写出人机的继续上传
用java开发的五子棋,使用了java的awt和swing,其中没有AI,粗略的看了网上的AI算法,看的头都大了。
五子棋代码,人人对战,绿色背景
人人对战的五子棋,比较简单的程序。希望大家看看