实践周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 }?
轉載于:https://www.cnblogs.com/0405mxh/p/10173137.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的实践周java基础软件开发app之五子棋的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [认证授权] 5.OIDC(OpenId
- 下一篇: js函数的默认参数