前言
刚开始学java时接触到GUI,一时兴起写了个五子棋,五子棋的关键点在于判断输赢,其他的都没什么,现在翻出来整理并记录下来,不足之处还望各位路过的大佬多多指教。
代码实现
代码不多,四百多行,全都在这个类里面,直接运行main函数就可以看到效果,JDK用的是1.7
1@SuppressWarnings("ALL") 2public class MyFrame extends Frame { 3 private static int y;// 鼠标点击的X轴 4 private static int x;// 鼠标点击的Y轴 5 private int[][] xY = new int[400][2];// 定义二维数组x_y来保存每一个棋子的坐标,用于界面的展示 6 private int a = 0;//定义一个变量表示已经保存了的坐标数 7 private static String[][] str = new String[20][20];// 定义一个二维数组str来保存每一个棋子的位置和颜色,用于判断输赢 8 private boolean isWhite = true;// 棋子的颜色是否为白色 9 static boolean flagWin = false;// 是否分出输赢 10 private boolean isClick = false;// 是否点击了鼠标 11 private int win;// 判断是白棋赢还是黑棋赢,返回0,还没有人赢,返回1,白棋赢,返回2,黑棋赢 12 private String whoWin = "";//谁赢了 13 14 /** 15 * 初始化str,二维数组str来保存每一个棋子的位置和颜色,用于判断输赢 16 */ 17 private static void initStr() { 18 19 // 初始化str 20 for (int i = 0; i < str.length; i++) { 21 for (int j = 0; j < str[0].length; j++) { 22 str[i][j] = "*"; 23 } 24 } 25 } 26 27 /** 28 * 判断输赢,返回0,还没有人赢,返回1,白棋赢,返回2,黑棋赢 29 */ 30 private static int win(String s) { 31 final int b = 1; 32 final int h = 2; 33 int win = 0; 34 35 for (int i = 0; i < str.length; i++) { 36 for (int j = 0; j < str[0].length; j++) { 37 // 横向的判断 38 if (j < str[0].length - 4) { 39 if (s.equals(str[i][j]) && s.equals(str[i][j + 1]) 40 && s.equals(str[i][j + 2]) 41 && s.equals(str[i][j + 3]) 42 && s.equals(str[i][j + 4])) { 43 // 返回0,还没有人赢,返回1,白棋赢,返回2,黑棋赢 44 if ("O".equals(s)) { 45 win = b; 46 } 47 if ("@".equals(s)) { 48 win = h; 49 } 50 return win; 51 } 52 } 53 // 横向的判断 54 if (j > 4) { 55 if (s.equals(str[i][j - 4]) 56 && s.equals(str[i][j - 3]) 57 && s.equals(str[i][j - 2]) 58 && s.equals(str[i][j - 1]) 59 && s.equals(str[i][j])) { 60 // 返回0,还没有人赢,返回1,白棋赢,返回2,黑棋赢 61 if ("O".equals(s)) { 62 win = b; 63 } 64 if ("@".equals(s)) { 65 win = h; 66 } 67 return win; 68 } 69 } 70 // 纵向的判断 71 if (i < str.length - 4) { 72 if (s.equals(str[i][j]) 73 && s.equals(str[i + 1][j]) 74 && s.equals(str[i + 2][j]) 75 && s.equals(str[i + 3][j]) 76 && s.equals(str[i + 4][j])) { 77 // 返回0,还没有人赢,返回1,白棋赢,返回2,黑棋赢 78 if ("O".equals(s)) { 79 win = b; 80 } 81 if ("@".equals(s)) { 82 win = h; 83 } 84 return win; 85 } 86 } 87 // 纵向的判断 88 if (i > 4) { 89 if (s.equals(str[i - 4][j]) 90 && s.equals(str[i - 3][j]) 91 && s.equals(str[i - 2][j]) 92 && s.equals(str[i - 1][j]) 93 && s.equals(str[i][j])) { 94 // 返回0,还没有人赢,返回1,白棋赢,返回2,黑棋赢 95 if ("O".equals(s)) { 96 win = b; 97 } 98 if ("@".equals(s)) { 99 win = h; 100 } 101 return win; 102 } 103 } 104 // 捺方向的判断 105 if (i < str.length - 4 && j < str[0].length - 4) { 106 if (s.equals(str[i][j]) 107 && s.equals(str[i + 1][j + 1]) 108 && s.equals(str[i + 2][j + 2]) 109 && s.equals(str[i + 3][j + 3]) 110 && s.equals(str[i + 4][j + 4])) { 111 // 返回0,还没有人赢,返回1,白棋赢,返回2,黑棋赢 112 if ("O".equals(s)) { 113 win = b; 114 } 115 if ("@".equals(s)) { 116 win = h; 117 } 118 return win; 119 } 120 } 121 // 捺方向的判断 122 if (i > 4 && j > 4) { 123 if (s.equals(str[i - 4][j - 4]) 124 && s.equals(str[i - 3][j - 3]) 125 && s.equals(str[i - 2][j - 2]) 126 && s.equals(str[i - 1][j - 1]) 127 && s.equals(str[i][j])) { 128 // 返回0,还没有人赢,返回1,白棋赢,返回2,黑棋赢 129 if ("O".equals(s)) { 130 win = b; 131 } 132 if ("@".equals(s)) { 133 win = h; 134 } 135 return win; 136 } 137 } 138 // 撇丿方向的判断 139 if (j >= 4 && i < str.length - 4) { 140 if (s.equals(str[i][j]) 141 && s.equals(str[i + 1][j - 1]) 142 && s.equals(str[i + 2][j - 2]) 143 && s.equals(str[i + 3][j - 3]) 144 && s.equals(str[i + 4][j - 4])) { 145 // 返回0,还没有人赢,返回1,白棋赢,返回2,黑棋赢 146 if ("O".equals(s)) { 147 win = b; 148 } 149 if ("@".equals(s)) { 150 win = h; 151 } 152 return win; 153 } 154 } 155 // 撇丿方向的判断 156 if (i >= 4 && j < str[0].length - 4) { 157 if (s.equals(str[i - 4][j + 4]) 158 && s.equals(str[i - 3][j + 3]) 159 && s.equals(str[i - 2][j + 2]) 160 && s.equals(str[i - 1][j + 1]) 161 && s.equals(str[i][j])) { 162 // 返回0,还没有人赢,返回1,白棋赢,返回2,黑棋赢 163 if ("O".equals(s)) { 164 win = b; 165 } 166 if ("@".equals(s)) { 167 win = h; 168 } 169 return win; 170 } 171 } 172 } 173 } 174 // 返回0,还没有人赢,返回1,白棋赢,返回2,黑棋赢 175 return win; 176 } 177 178 /** 179 * 判断是否和棋 返回true则棋盘上已经放满了 返回false则表示还没有放满 180 */ 181 private static boolean isDraw() { 182 for (String[] aStr : str) { 183 for (int j = 0; j < str[0].length; j++) { 184 if ("*".equals(aStr[j])) { 185 return false; 186 } 187 } 188 } 189 return true; 190 } 191 192 /** 193 * 对落子位置的逻辑判断 194 */ 195 private void ifPrint(Graphics g) { 196 197 // 如果已经分出胜负 198 if (!flagWin) { 199 // 是否为和棋 200 if (!isDraw()) { 201 //判断画笔颜色 202 if (isWhite) { 203 g.setColor(Color.WHITE);//定义画笔颜色 204 g.drawString("白棋走棋", 660, 100); 205 } else { 206 g.setColor(Color.BLACK);//定义画笔颜色 207 g.drawString("黑棋走棋", 660, 100); 208 } 209 // 往空格添加棋子 210 if (isClick) {// 是否点击了鼠标 211 if (x > 50 && x < 650 && y > 50 && y < 650) {// 是否在正确的位置下子 212 for (int i = 50; i < 650; i += 30) { 213 for (int j = 50; j < 650; j += 30) { 214 if (x > i && x < i + 30 && y > j && y < j + 30) {// 判断是在哪一个空格下子 215 if ("*".equals(str[(j - 50) / 30][(i - 50) / 30])) {// 判断该空格是否已经有子 216 217 if (isWhite) {// 判断下的棋子的颜色 218 g.setColor(Color.WHITE);//定义画笔颜色 219 str[(j - 50) / 30][(i - 50) / 30] = "O";// 保存棋子的位置和颜色 220 } else { 221 g.setColor(Color.BLACK);//定义画笔颜色 222 str[(j - 50) / 30][(i - 50) / 30] = "@"; 223 } 224 g.fillOval(i, j, 30, 30);// //画棋子,实心圆 225 // 保存棋子的坐标 226 xY[a][0] = i; 227 xY[a][1] = j; 228 229 System.out.println("x:" + x + " y:" + y 230 + "a:" + a + " teyp" + isWhite); 231 a++; 232 // 重置坐标 233 x = 0; 234 y = 0; 235 isWhite = !isWhite; 236 237 for (int i1 = 0; i1 < str.length; i1++) { 238 for (int j1 = 0; j1 < str[0].length; j1++) { 239 System.out.print(str[i1][j1] + " "); 240 241 } 242 } 243 } else { 244 g.setColor(Color.RED);//定义画笔颜色 245 g.drawString("该位置已经有子,请从新下!", 660, 120); 246 System.out.println("该位置已经有子,请从新下!"); 247 } 248 } 249 } 250 } 251 } else { 252 g.setColor(Color.RED);//定义画笔颜色 253 g.drawString("请在正确的位置放子!", 660, 120); 254 System.out.println("请在正确的位置放子!"); 255 } 256 isClick = false; 257 } 258 259 if (!isWhite) {// 因为前面下完子之后已经取反了,所以这里取非 260 win = win("O");// 判断白棋是否赢 261 } else { 262 win = win("@");// 判断黑棋是否赢 263 } 264 switch (win) { 265 case 1: 266 System.out.println("白棋赢了"); 267 flagWin = true; 268 whoWin = "白棋赢了"; 269 break; 270 case 2: 271 System.out.println("黑棋赢了"); 272 flagWin = true; 273 whoWin = "黑棋赢了"; 274 break; 275 default: 276 277 } 278 } else { 279 g.setColor(Color.RED);//定义画笔颜色 280 g.drawString("和棋!!!", 660, 100); 281 g.drawString("你们打成了平手!", 660, 120); 282 } 283 } else { 284 g.setColor(Color.RED);//定义画笔颜色 285 g.drawString(whoWin, 660, 100); 286 g.drawString("已经分出了胜负啦!", 660, 120); 287 } 288 289 } 290 291 /** 292 * 初始化窗口 293 */ 294 private void launchFrame() { 295 296 // 设置窗口大小 297 setSize(800, 700); 298 // 设置窗口位置 299 setLocation(50, 50); 300 // 设置背景颜色 301 setBackground(Color.PINK); 302 // 设置窗口可见 303 setVisible(true); 304 // 设置标题 305 setTitle("欢子出品,必属精品"); 306 // 设置窗口大小不可变 307 setResizable(false); 308 // 启用线程 309 new PaintThread().start(); 310 311 // 添加窗口监听,实现窗口关闭 312 addWindowListener(new MyWindow()); 313 // 添加鼠标监听 314 addMouseListener(new MyMouse()); 315 316 } 317 318 /** 319 * 画窗体里的内容 320 */ 321 @Override 322 public void paint(Graphics g) { 323 //初始化画笔的颜色 324 g.setColor(Color.BLACK); 325 326 // 画线,画方格 327 // X轴方向 328 for (int i = 0, j = 50; i <= 20; i++) { 329 g.drawLine(50, j, 650, j); 330 j += 30; 331 } 332 333 // Y轴方向 334 for (int i = 0, j = 50; i <= 20; i++) { 335 g.drawLine(j, 50, j, 650); 336 j += 30; 337 } 338 339 // 画棋子 340 for (int i = 0; i < a; i++) { 341 if ("O".equals(str[(xY[i][1] - 50) / 30][(xY[i][0] - 50) / 30])) { 342 g.setColor(Color.WHITE);//定义画笔颜色 343 } else if ("@" 344 .equals(str[(xY[i][1] - 50) / 30][(xY[i][0] - 50) / 30])) { 345 g.setColor(Color.BLACK);//定义画笔颜色 346 } 347 g.fillOval(xY[i][0], xY[i][1], 30, 30);//画棋子,实心圆 348 } 349 350 //对落子位置的逻辑判断 351 ifPrint(g); 352 353 //恢复画笔的颜色 354 g.setColor(Color.BLACK); 355 356 } 357 358 /** 359 * 退出 360 */ 361 class MyWindow extends WindowAdapter { 362 @Override 363 public void windowClosing(WindowEvent e) { 364 System.exit(0); 365 } 366 } 367 368 /** 369 * 定义一个鼠标监听事件类 370 */ 371 class MyMouse implements MouseListener { 372 373 /** 374 * 鼠标释放 375 */ 376 @Override 377 public void mouseReleased(MouseEvent arg0) { 378 // System.out.println("鼠标释放"+arg0); 379 380 } 381 382 /** 383 * 鼠标按下 384 */ 385 @Override 386 public void mousePressed(MouseEvent arg0) { 387 // System.out.println("鼠标按下"+arg0); 388 389 } 390 391 /** 392 * 鼠标离开 393 */ 394 @Override 395 public void mouseExited(MouseEvent arg0) { 396 // System.out.println("鼠标离开)"+arg0); 397 } 398 399 /** 400 * 鼠标进入 401 */ 402 @Override 403 public void mouseEntered(MouseEvent arg0) { 404 // System.out.println("鼠标进入)"+arg0); 405 } 406 407 /** 408 * 鼠标点击 409 */ 410 @Override 411 public void mouseClicked(MouseEvent arg0) { 412 x = arg0.getX(); 413 y = arg0.getY(); 414 isClick = true; 415 } 416 } 417 418 /** 419 * 定义一个线程重画窗口,是一个内部类 420 */ 421 class PaintThread extends Thread { 422 @Override 423 public void run() { 424 while (true) { 425 repaint(); 426 try { 427 Thread.sleep(40); 428 } catch (InterruptedException e) { 429 e.printStackTrace(); 430 } 431 } 432 } 433 } 434 435 /** 436 * main函数 437 */ 438 public static void main(String[] args) { 439 440 new MyFrame().launchFrame(); 441 initStr(); 442 443 } 444}
效果
功能有些简陋,提示语不够友好,悔棋、再开一局等功能也都还没有做...。输赢算法分为横、竖、撇、捺四个方向判断
横

竖

撇

捺

总结
五子棋的重点在于判断输赢,其他的一些“小功能”都只是锦上添花,有时间可以用socket搞个多人在线对弈版本,不过这些东西也只有在学校的时候骗骗学弟学妹装装逼,同时可以巩固自己、其他的感觉没什么用,各位大佬觉得呢?