1. 程式人生 > >Java GUI 單機版五子棋

Java GUI 單機版五子棋

  前言

  剛開始學java時接觸到GUI,一時興起寫了個五子棋,五子棋的關鍵點在於判斷輸贏,其他的都沒什麼,現在翻出來整理並記錄下來,不足之處還望各位路過的大佬多多指教。

  程式碼實現

  程式碼不多,四百多行,全都在這個類裡面,直接執行main函式就可以看到效果,JDK用的是1.7

@SuppressWarnings("ALL")
public class MyFrame extends Frame {
    private static int y;// 滑鼠點選的X軸
    private static int x;// 滑鼠點選的Y軸
    private int
[][] xY = new int[400][2];// 定義二維陣列x_y來儲存每一個棋子的座標,用於介面的展示 private int a = 0;//定義一個變量表示已經儲存了的座標數 private static String[][] str = new String[20][20];// 定義一個二維陣列str來儲存每一個棋子的位置和顏色,用於判斷輸贏 private boolean isWhite = true;// 棋子的顏色是否為白色 static boolean flagWin = false;// 是否分出輸贏 private boolean isClick = false
;// 是否點選了滑鼠 private int win;// 判斷是白棋贏還是黑棋贏,返回0,還沒有人贏,返回1,白棋贏,返回2,黑棋贏 private String whoWin = "";//誰贏了 /** * 初始化str,二維陣列str來儲存每一個棋子的位置和顏色,用於判斷輸贏 */ private static void initStr() { // 初始化str for (int i = 0; i < str.length; i++) { for (int j = 0; j < str[0].length; j++) { str[i][j]
= "*"; } } } /** * 判斷輸贏,返回0,還沒有人贏,返回1,白棋贏,返回2,黑棋贏 */ private static int win(String s) { final int b = 1; final int h = 2; int win = 0; for (int i = 0; i < str.length; i++) { for (int j = 0; j < str[0].length; j++) { // 橫向的判斷 if (j < str[0].length - 4) { if (s.equals(str[i][j]) && s.equals(str[i][j + 1]) && s.equals(str[i][j + 2]) && s.equals(str[i][j + 3]) && s.equals(str[i][j + 4])) { // 返回0,還沒有人贏,返回1,白棋贏,返回2,黑棋贏 if ("O".equals(s)) { win = b; } if ("@".equals(s)) { win = h; } return win; } } // 橫向的判斷 if (j > 4) { if (s.equals(str[i][j - 4]) && s.equals(str[i][j - 3]) && s.equals(str[i][j - 2]) && s.equals(str[i][j - 1]) && s.equals(str[i][j])) { // 返回0,還沒有人贏,返回1,白棋贏,返回2,黑棋贏 if ("O".equals(s)) { win = b; } if ("@".equals(s)) { win = h; } return win; } } // 縱向的判斷 if (i < str.length - 4) { if (s.equals(str[i][j]) && s.equals(str[i + 1][j]) && s.equals(str[i + 2][j]) && s.equals(str[i + 3][j]) && s.equals(str[i + 4][j])) { // 返回0,還沒有人贏,返回1,白棋贏,返回2,黑棋贏 if ("O".equals(s)) { win = b; } if ("@".equals(s)) { win = h; } return win; } } // 縱向的判斷 if (i > 4) { if (s.equals(str[i - 4][j]) && s.equals(str[i - 3][j]) && s.equals(str[i - 2][j]) && s.equals(str[i - 1][j]) && s.equals(str[i][j])) { // 返回0,還沒有人贏,返回1,白棋贏,返回2,黑棋贏 if ("O".equals(s)) { win = b; } if ("@".equals(s)) { win = h; } return win; } } // 捺方向的判斷 if (i < str.length - 4 && j < str[0].length - 4) { if (s.equals(str[i][j]) && s.equals(str[i + 1][j + 1]) && s.equals(str[i + 2][j + 2]) && s.equals(str[i + 3][j + 3]) && s.equals(str[i + 4][j + 4])) { // 返回0,還沒有人贏,返回1,白棋贏,返回2,黑棋贏 if ("O".equals(s)) { win = b; } if ("@".equals(s)) { win = h; } return win; } } // 捺方向的判斷 if (i > 4 && j > 4) { if (s.equals(str[i - 4][j - 4]) && s.equals(str[i - 3][j - 3]) && s.equals(str[i - 2][j - 2]) && s.equals(str[i - 1][j - 1]) && s.equals(str[i][j])) { // 返回0,還沒有人贏,返回1,白棋贏,返回2,黑棋贏 if ("O".equals(s)) { win = b; } if ("@".equals(s)) { win = h; } return win; } } // 撇丿方向的判斷 if (j >= 4 && i < str.length - 4) { if (s.equals(str[i][j]) && s.equals(str[i + 1][j - 1]) && s.equals(str[i + 2][j - 2]) && s.equals(str[i + 3][j - 3]) && s.equals(str[i + 4][j - 4])) { // 返回0,還沒有人贏,返回1,白棋贏,返回2,黑棋贏 if ("O".equals(s)) { win = b; } if ("@".equals(s)) { win = h; } return win; } } // 撇丿方向的判斷 if (i >= 4 && j < str[0].length - 4) { if (s.equals(str[i - 4][j + 4]) && s.equals(str[i - 3][j + 3]) && s.equals(str[i - 2][j + 2]) && s.equals(str[i - 1][j + 1]) && s.equals(str[i][j])) { // 返回0,還沒有人贏,返回1,白棋贏,返回2,黑棋贏 if ("O".equals(s)) { win = b; } if ("@".equals(s)) { win = h; } return win; } } } } // 返回0,還沒有人贏,返回1,白棋贏,返回2,黑棋贏 return win; } /** * 判斷是否和棋 返回true則棋盤上已經放滿了 返回false則表示還沒有放滿 */ private static boolean isDraw() { for (String[] aStr : str) { for (int j = 0; j < str[0].length; j++) { if ("*".equals(aStr[j])) { return false; } } } return true; } /** * 對落子位置的邏輯判斷 */ private void ifPrint(Graphics g) { // 如果已經分出勝負 if (!flagWin) { // 是否為和棋 if (!isDraw()) { //判斷畫筆顏色 if (isWhite) { g.setColor(Color.WHITE);//定義畫筆顏色 g.drawString("白棋走棋", 660, 100); } else { g.setColor(Color.BLACK);//定義畫筆顏色 g.drawString("黑棋走棋", 660, 100); } // 往空格新增棋子 if (isClick) {// 是否點選了滑鼠 if (x > 50 && x < 650 && y > 50 && y < 650) {// 是否在正確的位置下子 for (int i = 50; i < 650; i += 30) { for (int j = 50; j < 650; j += 30) { if (x > i && x < i + 30 && y > j && y < j + 30) {// 判斷是在哪一個空格下子 if ("*".equals(str[(j - 50) / 30][(i - 50) / 30])) {// 判斷該空格是否已經有子 if (isWhite) {// 判斷下的棋子的顏色 g.setColor(Color.WHITE);//定義畫筆顏色 str[(j - 50) / 30][(i - 50) / 30] = "O";// 儲存棋子的位置和顏色 } else { g.setColor(Color.BLACK);//定義畫筆顏色 str[(j - 50) / 30][(i - 50) / 30] = "@"; } g.fillOval(i, j, 30, 30);// //畫棋子,實心圓 // 儲存棋子的座標 xY[a][0] = i; xY[a][1] = j; System.out.println("x:" + x + " y:" + y + "a:" + a + " teyp" + isWhite); a++; // 重置座標 x = 0; y = 0; isWhite = !isWhite; for (int i1 = 0; i1 < str.length; i1++) { for (int j1 = 0; j1 < str[0].length; j1++) { System.out.print(str[i1][j1] + " "); } } } else { g.setColor(Color.RED);//定義畫筆顏色 g.drawString("該位置已經有子,請從新下!", 660, 120); System.out.println("該位置已經有子,請從新下!"); } } } } } else { g.setColor(Color.RED);//定義畫筆顏色 g.drawString("請在正確的位置放子!", 660, 120); System.out.println("請在正確的位置放子!"); } isClick = false; } if (!isWhite) {// 因為前面下完子之後已經取反了,所以這裡取非 win = win("O");// 判斷白棋是否贏 } else { win = win("@");// 判斷黑棋是否贏 } switch (win) { case 1: System.out.println("白棋贏了"); flagWin = true; whoWin = "白棋贏了"; break; case 2: System.out.println("黑棋贏了"); flagWin = true; whoWin = "黑棋贏了"; break; default: } } else { g.setColor(Color.RED);//定義畫筆顏色 g.drawString("和棋!!!", 660, 100); g.drawString("你們打成了平手!", 660, 120); } } else { g.setColor(Color.RED);//定義畫筆顏色 g.drawString(whoWin, 660, 100); g.drawString("已經分出了勝負啦!", 660, 120); } } /** * 初始化視窗 */ private void launchFrame() { // 設定視窗大小 setSize(800, 700); // 設定視窗位置 setLocation(50, 50); // 設定背景顏色 setBackground(Color.PINK); // 設定視窗可見 setVisible(true); // 設定標題 setTitle("歡子出品,必屬精品"); // 設定視窗大小不可變 setResizable(false); // 啟用執行緒 new PaintThread().start(); // 新增視窗監聽,實現視窗關閉 addWindowListener(new MyWindow()); // 新增滑鼠監聽 addMouseListener(new MyMouse()); } /** * 畫窗體裡的內容 */ @Override public void paint(Graphics g) { //初始化畫筆的顏色 g.setColor(Color.BLACK); // 畫線,畫方格 // X軸方向 for (int i = 0, j = 50; i <= 20; i++) { g.drawLine(50, j, 650, j); j += 30; } // Y軸方向 for (int i = 0, j = 50; i <= 20; i++) { g.drawLine(j, 50, j, 650); j += 30; } // 畫棋子 for (int i = 0; i < a; i++) { if ("O".equals(str[(xY[i][1] - 50) / 30][(xY[i][0] - 50) / 30])) { g.setColor(Color.WHITE);//定義畫筆顏色 } else if ("@" .equals(str[(xY[i][1] - 50) / 30][(xY[i][0] - 50) / 30])) { g.setColor(Color.BLACK);//定義畫筆顏色 } g.fillOval(xY[i][0], xY[i][1], 30, 30);//畫棋子,實心圓 } //對落子位置的邏輯判斷 ifPrint(g); //恢復畫筆的顏色 g.setColor(Color.BLACK); } /** * 退出 */ class MyWindow extends WindowAdapter { @Override public void windowClosing(WindowEvent e) { System.exit(0); } } /** * 定義一個滑鼠監聽事件類 */ class MyMouse implements MouseListener { /** * 滑鼠釋放 */ @Override public void mouseReleased(MouseEvent arg0) { // System.out.println("滑鼠釋放"+arg0); } /** * 滑鼠按下 */ @Override public void mousePressed(MouseEvent arg0) { // System.out.println("滑鼠按下"+arg0); } /** * 滑鼠離開 */ @Override public void mouseExited(MouseEvent arg0) { // System.out.println("滑鼠離開)"+arg0); } /** * 滑鼠進入 */ @Override public void mouseEntered(MouseEvent arg0) { // System.out.println("滑鼠進入)"+arg0); } /** * 滑鼠點選 */ @Override public void mouseClicked(MouseEvent arg0) { x = arg0.getX(); y = arg0.getY(); isClick = true; } } /** * 定義一個執行緒重畫視窗,是一個內部類 */ class PaintThread extends Thread { @Override public void run() { while (true) { repaint(); try { Thread.sleep(40); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * main函式 */ public static void main(String[] args) { new MyFrame().launchFrame(); initStr(); } }

  效果

  功能有些簡陋,提示語不夠友好,悔棋、再開一局等功能也都還沒有做...。輸贏演算法分為橫、豎、撇、捺四個方向判斷

   橫

 

  豎

  撇

  捺

   總結

  五子棋的重點在於判斷輸贏,其他的一些“小功能”都只是錦上添花,有時間可以用socket搞個多人線上對弈版本,不過這些東西也只有在學校的時候騙騙學弟學妹裝裝逼,同時可以鞏固自己、其他的感覺沒什麼用,各位大佬覺得呢?