前言
剛開始學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搞個多人在線對弈版本,不過這些東西也只有在學校的時候騙騙學弟學妹裝裝逼,同時可以鞏固自己、其他的感覺沒什么用,各位大佬覺得呢?
