实践周java基础软件开发app之五子棋

五子棋人机对战实践项目

总的任务和目标

完成一个人机对战的五子棋项目,基本效果如下:

   

第一部分 Java绘图原理

1.   基本概念

像素,坐标

第二部分 绘制棋盘

1.   基本思路

在一个JPanel上绘制一个背景,然后绘制水平和垂直的若干条线,使其构成等距离的格子,通常是15*15(条线)。

2.   代码实现

第三部分 绘制棋子

1.   基本思路

使用drawOval()可以绘制空心的圆,使用fillOval()可以填充实心的圆。

2.   坐标计算

由于格子是水平和垂直的有下标的,而绘制时需要使用实际的像素坐标,所以,需要进行行列下标到像素坐标的转换:

int x = col * GRID_WIDTH;

int y = row * GRID_WIDTH;

3.   代码实现

(1)     ChessPanel代码:

 

第四部分 鼠标下棋

1.   基本思路

需要处理鼠标单点事件,获取鼠标所在的位置,然后计算出应该绘制棋子的行列下标,并使用一个二维数组来全局存储棋子的位置。

2.   鼠标位置与行列下标计算

        int x = e.getX();

        int y = e.getY();

        int row = y / GRID_WIDTH;

     int col = x / GRID_WIDTH;

3.   代码实现

(1)      ChessPanel属性和构造方法代码:

 

(2)监听器类(内部类)代码:

 

(3)绘图代码:

 

第五部分 判断胜负

1.   基本思路

判断胜负是因为在当前位置(row, col)落子导致了胜负,所以,判断胜负其实是在当前落子位置为中心,横向搜索左边第4个位置开始到右边第4个位置(其余位置不需要考虑),或者从上到下,或者正向45度,或者反向45度位置。

2.   处理方法

处理方法有很多,可以采用计数的方式,也可以采用字符串连接的方式,此处采用了将从左边第4颗开始,到右边第4颗结束,将每颗的颜色表示成字符1(黑色)或者2(白色),只需要判断其中是否有连续的5个1或5个2,即“11111”或“22222”即可知道胜负。

3.   代码实现

(1)     监听器类(内部类)代码:

 

(2)checkWin判断胜负的代码:

/** 判断胜负

        * @param row      落子的行下标

        * @param col       落子的列下标

        * @return 是否获胜,true-是,false-否

        */

public boolean checkWin(int row, int col) {}

 

(3)重置游戏状态

 

【目前代码】

 

  1 package wuziqi;
  2 
  3 import java.awt.Color;
  4 import java.awt.Container;
  5 import java.awt.Graphics;
  6 import java.awt.event.MouseAdapter;
  7 import java.awt.event.MouseEvent;
  8 
  9 import javax.swing.JFrame;
 10 import javax.swing.JOptionPane;
 11 import javax.swing.JPanel;
 12 
 13 public class wuziqijiemianDemo {
 14     //创建窗口为主类的类部类并且继承自JFrame
 15     public class Myjframe extends JFrame {
 16         /**
 17          * 用一个构造方法创建窗口
 18          */
 19         public Myjframe() {
 20             this.setTitle("五子棋");
 21             this.setSize(620, 640);
 22             //获取内容面板
 23             Container cp = getContentPane();
 24             //创建一个面板JPanel
 25             JPanel jPanel = new MyJanel();
 26             cp.add(jPanel);
 27             //面板的背景颜色为黄色,便于下白棋与黑棋
 28             jPanel.setBackground(Color.yellow);
 29             this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 30             //窗口默认设置为显示屏的正中间
 31             this.setLocationRelativeTo(null);
 32             //不可改变窗口的大小
 33             this.setResizable(false);
 34         }
 35     }
 36 /**
 37  * 创建一个面板继承自JPanel
 38  * @author Administrator
 39  *
 40  */
 41     public class MyJanel extends JPanel {
 42         //表示每个方格的大小
 43         private static final int GRID_WIDTh = 40;
 44         //棋盘的大小,代表棋盘的线的条数
 45         private static final int LINE_COUNT = 15;
 46         //设置黑棋子为1、白棋子为2、没有棋子为0(默认值)
 47         public static final int BLACK=1;
 48         public static final int WHITE=2;
 49         //定义一个棋盘大小的数组用来存放黑棋和白棋的位置
 50         int[][] chessItems=new int[LINE_COUNT][LINE_COUNT];
 51         //定义一个标志位,代表黑棋先下(黑棋和白棋轮流下棋)
 52         int flag=BLACK;
 53         /**
 54          * 构造方法用来画棋盘的棋子
 55          */
 56         public MyJanel(){
 57             /**
 58              * 为这个面板添加一个鼠标点击事件,鼠标每点击一次,就在棋盘上下一个棋子
 59              *使用适配器的方式添加鼠标点击事件    
 60              */
 61             this.addMouseListener(new MouseAdapter() {
 62                 public void mouseClicked(MouseEvent e){
 63                     /**
 64                      * 获取当前的鼠标点击的位置
 65                      */
 66                     int x=e.getX();
 67                     int y=e.getY();
 68                     /**
 69                      * 因为棋盘是用二维数组的方式表示的,所以最后表示为二维数组的行与列
 70                      */
 71                     int row=y/GRID_WIDTh;
 72                     int col=x/GRID_WIDTh;
 73                     //当前这个位置没有棋子(为零),可以下一个黑棋子
 74                     if(chessItems[row][col]==0){
 75                         if(flag==BLACK){
 76                             chessItems[row][col]=flag;
 77                             //下完黑棋下白棋
 78                             flag=WHITE;
 79                             //必须有,不然后面的白棋会覆盖黑棋
 80                         }
 81                         //当前这个位置没有棋子(为零),可以下一个白棋子
 82                         else{
 83                             chessItems[row][col]=flag;
 84                             //下完白棋下黑棋
 85                             flag=BLACK;
 86                         }
 87                     }
 88                     /**
 89                      * 每当下完一步棋之后便判断是否已经取胜
 90                      */
 91                     if(checkImage(row,col)){
 92                         //显示对话窗口
 93                         JOptionPane.showMessageDialog(null, "your win");
 94                         //清空棋盘
 95                         clear();
 96                     }
 97                     //System.out.println(chessItems[row][col]);
 98                 }
 99             });
100         }
101         /**
102          * 调用public void paintComponent(Graphics arg0){};方法画图
103          */
104         public void paintComponent(Graphics g) {
105             //系统调用
106             super.paintComponent(g);
107 //            g.setColor(Color.yellow);
108 //            g.fillRect(0, 0, jPanel.width(),jPanel.height());
109             /**
110              * 画横线,起始位置在窗口左上定点(GRID_WIDTh/2,GRID_WIDTh/2)
111              */
112             for (int i = 0; i < LINE_COUNT; i++) {
113                 int x1 = GRID_WIDTh / 2;
114                 int y1 = GRID_WIDTh / 2 + i * GRID_WIDTh;
115                 int x2 = x1 + (LINE_COUNT-1)* GRID_WIDTh;
116                 int y2 = y1;
117                 //画线
118                 g.drawLine(x1, y1, x2, y2);
119             }
120             /**
121              * 画竖线
122              */
123             for (int i = 0; i < LINE_COUNT; i++) {
124                 int x1 = GRID_WIDTh / 2 + i * GRID_WIDTh;
125                 int y1 = GRID_WIDTh / 2;
126                 int x2 = x1;
127                 int y2 = y1 + (LINE_COUNT-1) * GRID_WIDTh;
128                 //画线
129                 g.drawLine(x1, y1, x2, y2);
130             }
131             /**
132              * 遍历这个数组
133              */
134             for(int row=0;row<LINE_COUNT;row++){
135                 for(int col=0;col<LINE_COUNT;col++){
136                     //判断数组当前值,来画棋子
137                     switch (chessItems[row][col]) {
138                     case WHITE:chessItem(row, col, Color.WHITE, g);break;
139                     case BLACK:chessItem(row, col, Color.BLACK, g);break;
140                     }
141                     repaint();
142                 }
143             }
144         };
145         /**
146          * 清空数组,便于下次下棋
147          */
148         private void clear() {
149             for(int row=0;row<LINE_COUNT;row++){                    
150                 for(int col=0;col<LINE_COUNT;col++){
151                     //全部置为0
152                     chessItems[row][col]=0;
153                 }
154             }
155             //重画一遍棋盘
156             repaint();
157         }
158         /**
159          * 用于判断是否已经取胜
160          * @param row
161          * @param col
162          * @return
163          */
164         private boolean checkImage(int row, int col) {
165             /**
166              * 判断横行是否win
167              */
168             StringBuilder stringBuilder=new StringBuilder();
169             //记录当前存在字符串中的数据个数
170             int count=0;
171             for(int i=-4;i<=4;i++){
172                 int Newcol=col+i;
173                 if(Newcol>=0&&Newcol<LINE_COUNT){
174                     count++;
175                     stringBuilder.append(chessItems[row][Newcol]);
176                 }
177             }
178             if(stringBuilder.indexOf("11111")>=0||stringBuilder.indexOf("22222")>=0){
179                 return true;
180             }else {
181                 //如果当前不能赢,则清空字符串
182                 stringBuilder.delete(0, count);
183                 count=0;
184             }
185             /**
186              * 判断竖行是否win
187              */
188             for(int i=-4;i<=4;i++){
189                 int Newrow=row+i;
190                 if(Newrow>=0&&Newrow<LINE_COUNT){
191                     count++;
192                     stringBuilder.append(chessItems[Newrow][col]);
193                 }
194             }
195             if(stringBuilder.indexOf("11111")>=0||stringBuilder.indexOf("22222")>=0){
196                 return true;
197             }else {
198                 stringBuilder.delete(0, count);
199                 count=0;
200             }
201             /**
202              * 判断负45°是否win
203              */
204             for(int i=-4;i<=4;i++){
205                 int Newcol=col+i;
206                 int Newrow=row+i;
207                 if(Newcol>=0&&Newcol<LINE_COUNT&&Newrow>=0&&Newrow<LINE_COUNT){
208                     count++;
209                     stringBuilder.append(chessItems[Newrow][Newcol]);
210                 }
211             }
212             if(stringBuilder.indexOf("11111")>=0||stringBuilder.indexOf("22222")>=0){
213                 return true;
214             }else {
215                 stringBuilder.delete(0, count);
216                 count=0;
217             }
218             /**
219              * 判断正45°是否win
220              */
221             for(int i=-4;i<=4;i++){
222                 int Newcol=col+i;
223                 int Newrow=row-i;
224                 if(Newcol>=0&&Newcol<LINE_COUNT&&Newrow>=0&&Newrow<LINE_COUNT){
225                     count++;
226                     stringBuilder.append(chessItems[Newrow][Newcol]);
227                 }
228             }
229             if(stringBuilder.indexOf("11111")>=0||stringBuilder.indexOf("22222")>=0){
230                 return true;
231             }else {
232                 stringBuilder.delete(0, count);
233                 count=0;
234             }
235             return false;
236         }
237         //画棋子
238         public void chessItem(int row,int col,Color color,Graphics graphics){
239             //x与y分别代表在面板上的位置
240             int x=col*GRID_WIDTh;
241             int y=row*GRID_WIDTh;
242             graphics.setColor(color);
243             //画圆
244             graphics.fillOval(x, y, GRID_WIDTh,GRID_WIDTh);
245         }
246     }
247 
248     public static void main(String[] args) {
249         /**
250          * 使用一个java类来创建一个主类为wuziqijiemianDemo,其中的窗口与棋盘为该主类的内部类
251          */
252         //使用类部类的方式创建一个窗口引用对象(方式为 外部类名.内部类名 变量名=new 外部类名().new 内部类名();)
253         wuziqijiemianDemo.Myjframe myjframe = new wuziqijiemianDemo().new Myjframe();
254         //设置窗口可见
255         myjframe.setVisible(true);
256     }
257 
258 }

 

 

 

第六部分 人机对战

1.   基本思路

当人点了鼠标落子以后,轮到电脑下棋,电脑的基本思想就是,在棋盘的空白处的每个位置,进行判断,当前位置的进攻指数和防守指数分别为多少,在进攻指数和防守指数中取一个较大值作为当前位置的评估值,在整个棋盘的所有空白处找到一个最大值,最大值的那个位置即为应该落子的位置。

2.  代码实现

(1)监听器类(内部类)代码:

(2)电脑下棋的代码

(3)     评估关键参数代码:

 

(4) 评估方法代码:

【自己代码】

 

  1 package wuziqi;
  2 
  3 import java.awt.Color;
  4 import java.awt.Container;
  5 import java.awt.Graphics;
  6 import java.awt.Image;
  7 import java.awt.Point;
  8 import java.awt.event.MouseAdapter;
  9 import java.awt.event.MouseEvent;
 10 import java.io.File;
 11 import java.io.IOException;
 12 
 13 import javax.imageio.ImageIO;
 14 import javax.swing.JFrame;
 15 import javax.swing.JOptionPane;
 16 import javax.swing.JPanel;
 17 
 18 public class wuziqijiemianDemo {
 19     // 创建窗口为主类的类部类并且继承自JFrame
 20     public class Myjframe extends JFrame {
 21         /**
 22          * 用一个构造方法创建窗口
 23          */
 24         public Myjframe() {
 25             this.setTitle("五子棋");
 26             this.setSize(620, 640);
 27             // 获取内容面板
 28             Container cp = getContentPane();
 29             // 创建一个面板JPanel
 30             JPanel jPanel = new MyJanel();
 31             cp.add(jPanel);
 32             // 面板的背景颜色为黄色,便于下白棋与黑棋
 33             jPanel.setBackground(Color.yellow);
 34             this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 35             // 窗口默认设置为显示屏的正中间
 36             this.setLocationRelativeTo(null);
 37             // 不可改变窗口的大小
 38             this.setResizable(false);
 39         }
 40     }
 41 
 42     /**
 43      * 创建一个面板继承自JPanel
 44      * 
 45      * @author Administrator
 46      * 
 47      */
 48     public class MyJanel extends JPanel {
 49         // 表示每个方格的大小
 50         private static final int GRID_WIDTh = 40;
 51         // 棋盘的大小,代表棋盘的线的条数
 52         private static final int LINE_COUNT = 15;
 53         // 设置黑棋子为1、白棋子为2、没有棋子为0(默认值)
 54         public static final int BLACK = 1;
 55         public static final int WHITE = 2;
 56         // 定义一个棋盘大小的数组用来存放黑棋和白棋的位置
 57         int[][] chessItems = new int[LINE_COUNT][LINE_COUNT];
 58         // 定义一个标志位,代表黑棋先下(黑棋和白棋轮流下棋)
 59         int flag = BLACK;
 60         //定义一个方框标记计算机下棋的棋子
 61         private Point lastpoint=new Point();
 62         //利用图片代表棋子
 63         Image blackImage=null;
 64         Image whiImage=null;
 65         //定义一个进攻的数组
 66         String[] defendstring={
 67             "11111","011110","11110","01111","11011",
 68             "10111","11101","01110","11100","00111",
 69             "0111","1110","1011","1101","111",
 70             "01100","00110","011","110","11"
 71         };
 72         //定义一个防守的数组
 73         String[] attackstring={
 74             "22222","022220","22220","02222","22022",
 75             "20222","22202","02220","22200","00222",
 76             "0222","2220","2022","2202","222",
 77             "02200","00220","022","220","22"
 78         };
 79         //定义一个防守与进攻对应的得分
 80         int[] score={
 81             100,90,80,80,80,
 82             80,80,70,60,60,
 83             50,50,50,50,40,
 84             30,30,20,20,10,
 85         };
 86         /**
 87          * 构造方法用来画棋盘的棋子
 88          */
 89         public MyJanel() {
 90             /**
 91              * 将棋子改变为图片,将黑子白子图片导入进来
 92              */
 93             try {
 94                 blackImage=ImageIO.read(new File("imgs/black.png"));
 95                 whiImage=ImageIO.read(new File("imgs/WHITE.png"));
 96             } catch (IOException e1) {
 97                 // TODO Auto-generated catch block
 98                 e1.printStackTrace();
 99             }
100             /**
101              * 为这个面板添加一个鼠标点击事件,鼠标每点击一次,就在棋盘上下一个棋子 使用适配器的方式添加鼠标点击事件
102              */
103             this.addMouseListener(new MouseAdapter() {
104                 public void mouseClicked(MouseEvent e) {
105                     /**
106                      * 获取当前的鼠标点击的位置
107                      */
108                     int x = e.getX();
109                     int y = e.getY();
110                     /**
111                      * 因为棋盘是用二维数组的方式表示的,所以最后表示为二维数组的行与列
112                      */
113                     int row = y / GRID_WIDTh;
114                     int col = x / GRID_WIDTh;
115                     // 当前这个位置没有棋子(为零),可以下一个黑棋子
116                     if (chessItems[row][col] == 0) {
117                         //人先下黑棋
118                         chessItems[row][col] = flag;
119                         /**
120                          * 每当下完一步棋之后便判断是否已经取胜
121                          */
122                         if (checkImage(row, col)) {
123                             JOptionPane.showMessageDialog(null, "你赢了");
124                             clear();
125                             return;
126                         }
127                         // 人下完黑棋下白棋,之后再给计算机下黑棋的机会
128                         flag = WHITE;
129                         //计算机下棋
130                         computerPlay();
131                         // 计算机下完摆起之后,给人下黑棋的机会
132                         flag = BLACK;
133                         // 必须有,不然后面的白棋会覆盖黑棋
134                     }        
135                     // System.out.println(chessItems[row][col]);
136                 }
137                 //计算机下棋调用方法
138                 private void computerPlay() {
139                     // 当前初始化找到的位置和期望值
140                     int tempRow = -1, tempCol = -1, maxValue = 0;
141                     // 遍历数组一个位置一个位置的找
142                     for (int i = 0; i < LINE_COUNT; i++) {
143                         for (int j = 0; j < LINE_COUNT; j++) {
144                             // 如果这个位置已经下棋,则跳过
145                             if (chessItems[i][j] > 0) {
146                                 continue;
147                             }
148                             // 表示进攻得分和防守得分
149                             int attack = CheckMax(i, j, WHITE);
150                             int defend= CheckMax(i, j, BLACK);
151                             int max = Math.max(attack, defend);
152                             // 获取最大值,并记录下标
153                             if (max > maxValue) {
154                                 tempRow = i;
155                                 tempCol = j;
156                                 maxValue = max;
157                             }
158                         }
159                     }
160                     //如果当前计算机没有找到下棋的位置,表明为平局
161                     if(tempCol<0||tempRow<0){
162                         JOptionPane.showMessageDialog(null, "平局");
163                         clear();
164                         return;
165                     }else{
166                     // 计算机下白棋,下完之后人下黑棋,画一遍
167                         chessItems[tempRow][tempCol] = WHITE;
168                         lastpoint.x=tempRow;
169                         lastpoint.y=tempCol;
170                         repaint();
171                     }
172                     // 计算机下完棋之后便判断自己是否已经获胜
173                     if (checkImage(tempRow, tempCol)) {
174                         JOptionPane.showMessageDialog(null, "你输了");
175                         clear();
176                         return;
177                     }
178                 }
179                 //计算机查看当前位置(黑棋与白棋)
180                 private int CheckMax(int row, int col, int current_colorpointer) {
181                     //max记录最大的期望,而tempmax记录当前的期望
182                     int max=0,tempmax=0;
183                     //判断当前是进攻还是防守
184                     String[] array=current_colorpointer==WHITE?attackstring:defendstring;
185                     //用一个字符串存放当前的状态
186                     StringBuilder stringBuilder=new StringBuilder();
187                     //水平方向
188                     for (int i = -4; i <= 4; i++) {
189                         int Newcol = col + i;
190                         if (Newcol<0 ||Newcol >= LINE_COUNT) {
191                             continue;
192                         }
193                         //假装先把这个位置下棋,实质上并没有下棋
194                         if(i==0){
195                             stringBuilder.append(current_colorpointer);
196                         }else{
197                             stringBuilder.append(chessItems[row][Newcol]);
198                         }
199                     }
200                     for(int i=0;i<array.length;i++){
201                         String string=array[i];
202                         //查找匹配字符串数组,并计算出期望值,找到即跳出循环
203                         if(stringBuilder.indexOf(string)>=0){
204                             max=score[i];
205                             break;
206                         }
207                     }
208                     //如果当前为最大的期望,即可以获胜,就直接return
209                     if(max==100){
210                         return max;
211                     }
212                     //每次在每个方向判断之后,应该清空当前的stringBuilder字符串
213                     stringBuilder.delete(0, stringBuilder.length());
214                     //垂直方向
215                     for (int i = -4; i <= 4; i++) {
216                         int Newrow = row + i;
217                         if (Newrow<0 ||Newrow >= LINE_COUNT) {
218                             continue;
219                         }
220                         if(i==0){
221                             stringBuilder.append(current_colorpointer);
222                         }else{
223                             stringBuilder.append(chessItems[Newrow][col]);
224                         }
225                     }
226                     tempmax=0;
227                     for(int i=0;i<array.length;i++){
228                         String string=array[i];
229                         if(stringBuilder.indexOf(string)>=0){
230                             tempmax=score[i];
231                             break;
232                         }
233                     }
234                     if(max<tempmax){
235                         max=tempmax;
236                     }
237                     if(max==100){
238                         return max;
239                     }
240                     //每次在每个方向判断之后,应该清空当前的stringBuilder字符串
241                     stringBuilder.delete(0, stringBuilder.length());
242                     //负45°
243                     for (int i = -4; i <= 4; i++) {
244                         int Newrow = row + i;
245                         int Newcol = col + i; 
246                         if ((Newrow<0 ||Newrow >= LINE_COUNT||Newcol<0 ||Newcol >= LINE_COUNT)) {
247                             continue;
248                         }
249                         if(i==0){
250                             stringBuilder.append(current_colorpointer);
251                         }else{
252                             stringBuilder.append(chessItems[Newrow][Newcol]);
253                         }
254                     }
255                     tempmax=0;
256                     for(int i=0;i<array.length;i++){
257                         String string=array[i];
258                         if(stringBuilder.indexOf(string)>=0){
259                             tempmax=score[i];
260                             break;
261                         }
262                     }
263                     if(max<tempmax){
264                         max=tempmax;
265                     }
266                     if(max==100){
267                         return max;
268                     }
269                     //每次在每个方向判断之后,应该清空当前的stringBuilder字符串
270                     stringBuilder.delete(0, stringBuilder.length());
271                     //正45°
272                     for (int i = -4; i <= 4; i++) {
273                         int Newrow = row + i;
274                         int Newcol = col - i; 
275                         if ((Newrow<0 ||Newrow >= LINE_COUNT||Newcol<0 ||Newcol >= LINE_COUNT)) {
276                             continue;
277                         }
278                         if(i==0){
279                             stringBuilder.append(current_colorpointer);
280                         }else{
281                             stringBuilder.append(chessItems[Newrow][Newcol]);
282                         }
283                     }
284                     tempmax=0;
285                     for(int i=0;i<array.length;i++){
286                         String string=array[i];
287                         if(stringBuilder.indexOf(string)>=0){
288                             tempmax=score[i];
289                             break;
290                         }
291                     }
292                     if(max<tempmax){
293                         max=tempmax;
294                     }
295                     if(max==100){
296                         return max;
297                     }
298                     return max;
299                 }
300             });
301         }
302 
303         /**
304          * 调用public void paintComponent(Graphics arg0){};方法画图
305          */
306         public void paintComponent(Graphics g) {
307             // 系统调用
308             super.paintComponent(g);
309             // g.setColor(Color.yellow);
310             // g.fillRect(0, 0, jPanel.width(),jPanel.height());
311             /**
312              * 画横线,起始位置在窗口左上定点(GRID_WIDTh/2,GRID_WIDTh/2)
313              */
314             for (int i = 0; i < LINE_COUNT; i++) {
315                 int x1 = GRID_WIDTh / 2;
316                 int y1 = GRID_WIDTh / 2 + i * GRID_WIDTh;
317                 int x2 = x1 + (LINE_COUNT - 1) * GRID_WIDTh;
318                 int y2 = y1;
319                 // 画线
320                 g.drawLine(x1, y1, x2, y2);
321             }
322             /**
323              * 画竖线
324              */
325             for (int i = 0; i < LINE_COUNT; i++) {
326                 int x1 = GRID_WIDTh / 2 + i * GRID_WIDTh;
327                 int y1 = GRID_WIDTh / 2;
328                 int x2 = x1;
329                 int y2 = y1 + (LINE_COUNT - 1) * GRID_WIDTh;
330                 // 画线
331                 g.drawLine(x1, y1, x2, y2);
332             }
333             /**
334              * 遍历这个数组
335              */
336             for (int row = 0; row < LINE_COUNT; row++) {
337                 for (int col = 0; col < LINE_COUNT; col++) {
338                     // 判断数组当前值,来画棋子
339                     switch (chessItems[row][col]) {
340                     case WHITE:
341                         chessItem(row, col, Color.WHITE, g);
342                         //每次画完计算机下完白棋之后,在白棋上面画一个方框
343                         chessface(lastpoint,Color.RED, g);
344                         break;
345                     case BLACK:
346                         chessItem(row, col, Color.BLACK, g);
347                         break;
348                     }
349                     repaint();
350                 }
351             }
352         };
353 
354         /**
355          * 清空数组,便于下次下棋
356          */
357         private void clear() {
358             for (int row = 0; row < LINE_COUNT; row++) {
359                 for (int col = 0; col < LINE_COUNT; col++) {
360                     // 全部置为0
361                     chessItems[row][col] = 0;
362                 }
363             }
364             // 重画一遍棋盘
365             repaint();
366         }
367 
368         /**
369          * 用于判断是否已经取胜
370          * 
371          * @param row
372          * @param col
373          * @return
374          */
375         private boolean checkImage(int row, int col) {
376             /**
377              * 判断横行是否win
378              */
379             StringBuilder stringBuilder = new StringBuilder();
380             // 记录当前存在字符串中的数据个数
381             int count = 0;
382             for (int i = -4; i <= 4; i++) {
383                 int Newcol = col + i;
384                 if (Newcol >= 0 && Newcol < LINE_COUNT) {
385                     count++;
386                     stringBuilder.append(chessItems[row][Newcol]);
387                 }
388             }
389             if (stringBuilder.indexOf("11111") >= 0
390                     || stringBuilder.indexOf("22222") >= 0) {
391                 return true;
392             } else {
393                 // 如果当前不能赢,则清空字符串
394                 stringBuilder.delete(0, count);
395                 count = 0;
396             }
397             /**
398              * 判断竖行是否win
399              */
400             for (int i = -4; i <= 4; i++) {
401                 int Newrow = row + i;
402                 if (Newrow >= 0 && Newrow < LINE_COUNT) {
403                     count++;
404                     stringBuilder.append(chessItems[Newrow][col]);
405                 }
406             }
407             if (stringBuilder.indexOf("11111") >= 0
408                     || stringBuilder.indexOf("22222") >= 0) {
409                 return true;
410             } else {
411                 stringBuilder.delete(0, count);
412                 count = 0;
413             }
414             /**
415              * 判断负45°是否win
416              */
417             for (int i = -4; i <= 4; i++) {
418                 int Newcol = col + i;
419                 int Newrow = row + i;
420                 if (Newcol >= 0 && Newcol < LINE_COUNT && Newrow >= 0
421                         && Newrow < LINE_COUNT) {
422                     count++;
423                     stringBuilder.append(chessItems[Newrow][Newcol]);
424                 }
425             }
426             if (stringBuilder.indexOf("11111") >= 0
427                     || stringBuilder.indexOf("22222") >= 0) {
428                 return true;
429             } else {
430                 stringBuilder.delete(0, count);
431                 count = 0;
432             }
433             /**
434              * 判断正45°是否win
435              */
436             for (int i = -4; i <= 4; i++) {
437                 int Newcol = col + i;
438                 int Newrow = row - i;
439                 if (Newcol >= 0 && Newcol < LINE_COUNT && Newrow >= 0
440                         && Newrow < LINE_COUNT) {
441                     count++;
442                     stringBuilder.append(chessItems[Newrow][Newcol]);
443                 }
444             }
445             if (stringBuilder.indexOf("11111") >= 0
446                     || stringBuilder.indexOf("22222") >= 0) {
447                 return true;
448             } else {
449                 stringBuilder.delete(0, count);
450                 count = 0;
451             }
452             return false;
453         }
454 
455         // 画棋子
456         public void chessItem(int row, int col, Color color, Graphics graphics) {
457             // x与y分别代表在面板上的位置
458             int x = col * GRID_WIDTh;
459             int y = row * GRID_WIDTh;
460             //判断是白棋还是黑棋
461             Image image=Color.BLACK.equals(color)?blackImage:whiImage;
462             graphics.drawImage(image, x, y, GRID_WIDTh, GRID_WIDTh, this);
463 //            graphics.setColor(color);
464 //            // 画圆
465 //            graphics.fillOval(x, y, GRID_WIDTh, GRID_WIDTh);
466         }
467         /**
468          * 为计算机画白棋定义一个方法,用于在计算机下白棋的棋子上画一个方框,表示是当前的棋子
469          * @param point
470          * @param color
471          * @param graphics
472          */
473         public void chessface(Point point, Color color, Graphics graphics ){
474             int x = point.y * GRID_WIDTh;
475             int y = point.x * GRID_WIDTh;
476             graphics.setColor(color);
477             graphics.drawRect(x+GRID_WIDTh/4, y+GRID_WIDTh/4, GRID_WIDTh/2, GRID_WIDTh/2);
478         }
479     }
480 
481     public static void main(String[] args) {
482         /**
483          * 使用一个java类来创建一个主类为wuziqijiemianDemo,其中的窗口与棋盘为该主类的内部类
484          */
485         // 使用类部类的方式创建一个窗口引用对象(方式为 外部类名.内部类名 变量名=new 外部类名().new 内部类名();)
486         wuziqijiemianDemo.Myjframe myjframe = new wuziqijiemianDemo().new Myjframe();
487         // 设置窗口可见
488         myjframe.setVisible(true);
489     }
490 
491 }

 

posted @ 2018-12-25 12:03  醉画仙  阅读(619)  评论(0编辑  收藏  举报