日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

五子棋java判断平局_2020-10-03 Java初级项目——从零开始制作一个简易五子棋游戏...

發布時間:2025/5/22 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 五子棋java判断平局_2020-10-03 Java初级项目——从零开始制作一个简易五子棋游戏... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、棋盤的繪制

使用JFrame容器制作五子棋的窗體

創建一個類——UI,如下:

public class UI {

private JFrame frame = new JFrame();

public void init() {

frame.setTitle("五子棋");

frame.setSize(518, 540);

frame.setLocationRelativeTo(null); //居中

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setVisible(true); //讓窗體顯示

}

public static void main(String[] args) {

new UI().init();

}

}

使用JPanel和Graphics畫出大小為15X15的棋盤

再創建一個新的類——Chessboard,繼承JPanel:

public class Chessboard extends JPanel {

//規定由15條橫豎線組成

private static final int CHESSBOARD_SIZE = 15;

//外邊距

private int margin = 20;

/**

* 繪圖工具

*

* @param g 畫筆工具

*/

@Override

public void paint(Graphics g) {

super.paint(g);

drawChessBoard(g);

drawPieces(g);

}

/**

* 畫棋盤

*

* @param g 畫筆工具

*/

private void drawChessBoard(Graphics g) {

int cellSize = (getWidth() - 2 * margin) / (CHESSBOARD_SIZE - 1);

for (int i = 0; i < CHESSBOARD_SIZE; i++) {

//畫橫線

g.drawLine(margin, margin + cellSize * i, getWidth() - margin, margin + cellSize * i);

//畫豎線

g.drawLine(margin + cellSize * i, margin, margin + cellSize * i, getHeight() - margin);

}

}

}

實現點擊鼠標落子的功能

在UI類中添加以下代碼:

public class UI {

private JFrame frame = new JFrame();

private Chessboard chessboard = new Chessboard();

public void init() {

frame.setTitle("五子棋");

frame.setSize(518, 540);

frame.setLocationRelativeTo(null); //居中

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setVisible(true); //讓窗體顯示

//給棋盤添加鼠標監聽事件,具體來說就是鼠標點擊事件

chessboard.addMouseListener(new MouseAdapter() { //匿名內部類

@Override

public void mouseClicked(MouseEvent e) {

super.mouseClicked(e);

//調用畫棋子的方法

play(e);

}

});

}

/**

* 處理鼠標點擊事件的方法

*/

private void play(MouseEvent e) {

int cellSize = chessboard.getCellSize();

int x = (e.getX() - 5) / cellSize;

int y = (e.getY() - 5) / cellSize;

chessboard.move(new Pieces(x, y, 1));

}

public static void main(String[] args) {

new UI().init();

}

}

再在Chessboard類中添加drawPieces、move、getCellSize方法,如下:

public class Chessboard extends JPanel {

private List piecesList = new ArrayList<>();

/**

* 繪圖工具

*

* @param g 畫筆工具

*/

@Override

public void paint(Graphics g) {

super.paint(g);

drawChessBoard(g);

drawPieces(g);

}

public int getCellSize() {

return (getWidth() - 2 * margin) / (CHESSBOARD_SIZE - 1);

}

public void drawPieces(Graphics g) {

for (Pieces piece : piecesList) {

if (piece.getPlayer() == 1) {

//默認值為1代表人類,棋子顏色為黑色

g.setColor(Color.black);

} else {

g.setColor(Color.white);

}

int cellSize = (getWidth() - 2 * margin) / (CHESSBOARD_SIZE - 1);

g.fillOval(piece.getX() * cellSize + margin - cellSize / 2, piece.getY() * cellSize + margin - cellSize / 2, cellSize, cellSize);

}

}

/**

* 落子的方法

*/

public void move(Pieces piece) {

piecesList.add(piece);

repaint();

}

}

然后創建一個新的類——Pieces,如下:

/***

* 棋子對象

*/

public class Pieces {

private int x;

private int y;

private int player; //表示黑棋還是白棋,1代表黑棋,-1代表白棋

public Pieces(int x, int y, int player) {

this.x = x; //非實際坐標,而是格子數,第x格

this.y = y; //同上,第y格

this.player = player;

}

public int getX() {

return x;

}

public int getY() {

return y;

}

public int getPlayer() {

return player;

}

}

二、判斷勝負

實現五子棋勝負判斷的思路是:

判斷勝負就看哪個顏色的棋子首先達到五子相連。若黑棋先達到五子相連,則黑棋勝,否則,白棋勝;

也就是下在每個棋子時都要判斷它的八個方向的棋子相連個數,如果判斷某一方向與其相鄰點的顏色相同,將循環計數;

還需要注意邊界點的范圍,在循環的時候應注意設置邊界條件;

可以建一個類,在類中寫判斷輸贏的方法;

在Chessboard類中添加如下代碼:

public class Chessboard extends JPanel {

private static final int CHESSBOARD_SIZE = 15;

private int margin = 20;

private List piecesList = new ArrayList<>();

//創建一個數組,用來表示棋盤上被占用的位置

private int[][] location = new int[CHESSBOARD_SIZE][CHESSBOARD_SIZE];

}

但是,落子的位置是有限制的,具體來說就是:

落子的位置不能有其它棋子;

不能超過棋盤的邊界;

所以要在UI類中的play()方法里添加一個落子合法性的判定:

private void play(MouseEvent e) {

int cellSize = chessboard.getCellSize();

int x = (e.getX() - 5) / cellSize;

int y = (e.getY() - 5) / cellSize;

if (chessboard.isLegal(x, y)) {

//添加棋子

chessboard.move(new Pieces(x, y, 1));

//記錄人類落子的位置

chessboard.setLocation(x, y, 1);

//判斷輸贏

if (chessboard.checkWinner(x, y, 1)) {

JOptionPane.showMessageDialog(frame, "人類獲勝", "您贏了!", JOptionPane.PLAIN_MESSAGE);

return;

}

}

}

而對應Chessboard類中新增的isLegal方法、setLocation方法以及checkWinner方法就是:

/**

* 判斷是否重復落子以及落子位置是否合法

*/

public boolean isLegal(int x, int y) {

return x >= 0 && x <= CHESSBOARD_SIZE && y >= 0 && y <= CHESSBOARD_SIZE && location[x][y] == 0;

}

/**

* 記錄落子后,棋子占用棋盤的位置

*/

public void setLocation(int x, int y, int player) {

location[x][y] = player;

}

/**

* 判斷勝負

*/

public boolean checkWinner(int x, int y, int player) {

int sum = 0;

//判斷水平方向,水平左側

for (int i = x - 1; i >= 0; i--) {

if (location[i][y] == player) {

sum++;

} else {

break;

}

}

//水平右側

for (int i = x + 1; i <= CHESSBOARD_SIZE; i++) {

if (location[i][y] == player) {

sum++;

} else {

break;

}

}

if (sum >= 4) {

return true;

}

//判斷垂直方向

sum = 0;

for (int i = y - 1; i >= 0; i--) {

if (location[x][i] == player) {

sum++;

} else {

break;

}

}

for (int i = y + 1; i <= CHESSBOARD_SIZE; i++) {

if (location[x][i] == player) {

sum++;

} else {

break;

}

}

if (sum >= 4) {

return true;

}

//判斷左上到右下這個對角線方向

sum = 0;

for (int i = x - 1, j = y - 1; i >= 0 && j >= 0; i--, j--) {

if (location[i][j] == player) {

sum++;

} else {

break;

}

}

for (int i = x + 1, j = y + 1; i <= CHESSBOARD_SIZE && j <= CHESSBOARD_SIZE; i++, j++) {

if (location[i][j] == player) {

sum++;

} else {

break;

}

}

if (sum >= 4) {

return true;

}

//判斷右上到左下這個對角線方向

sum = 0;

for (int i = x + 1, j = y - 1; i <= CHESSBOARD_SIZE && j >= 0; i++, j--) {

if (location[i][j] == player) {

sum++;

} else {

break;

}

}

for (int i = x - 1, j = y + 1; i >= 0 && j <= CHESSBOARD_SIZE; i--, j++) {

if (location[i][j] == player) {

sum++;

} else {

break;

}

}

if (sum >= 4) {

return true;

}

sum = 0;

return false;

}

三、簡易的AI算法

思路:

五元組:棋盤中橫豎斜四個方向的所有相鄰五個可連成一條線的格子

五元組的表示:用某格子的橫縱坐標以及+1/-1來表示相鄰四個格子的坐標,從而計算五元組坐標

五子棋棋盤大小是15X15,橫豎斜四個方向共有572個五元組,給每個五元組一個評分

這個五元組將為它的每個位置貢獻的分數就是這個五元組自身的得分

對整個棋盤來說,每個位置的得分就是該位置所在的橫豎斜四個方向所有五元組的得分之和

然后從所有空位置中選得分最高的位置即為機器落子的位置

首先,添加機器落子的代碼,完善UI類中play方法:

private void play(MouseEvent e) {

int cellSize = chessboard.getCellSize();

int x = (e.getX() - 5) / cellSize;

int y = (e.getY() - 5) / cellSize;

if (chessboard.isLegal(x, y)) {

//添加棋子

chessboard.move(new Pieces(x, y, 1));

//記錄人類落子的位置

chessboard.setLocation(x, y, 1);

//判斷輸贏

if (chessboard.checkWinner(x, y, 1)) {

JOptionPane.showMessageDialog(frame, "人類獲勝", "您贏了!", JOptionPane.PLAIN_MESSAGE);

return;

}

//機器落子

Pieces piece = chessboard.searchLocation();

chessboard.move(piece);

chessboard.setLocation(piece.getX(),piece.getY(),piece.getPlayer());

//判斷勝負

if (chessboard.checkWinner(piece.getX(),piece.getY(),piece.getPlayer())){

JOptionPane.showMessageDialog(frame, "電腦獲勝", "您輸了!", JOptionPane.PLAIN_MESSAGE);

}

}

}

其次,還需要一個評估函數(評分表),來對整個棋局中有效位置進行評價,但評分表很難確定,沒有所謂最好的,只能根據經驗和測試來選擇,我選擇的評分表如下:

既有人類落子,又有機器落子,判分為0;

全部為空,沒有落子,判分為7;

機器落1子,判分為35

機器落2子,判分為800

機器落3子,判分為15000

機器落4子,評分為800000

人類落1子,評分為15

人類落2子,評分為400

人類落3子,評分為1800

人類落4子,評分為100000

在Chessboard類中添加tupleScore方法:

private int tupleScore(int humanChessmanNum, int machineChessmanNum) {

if (humanChessmanNum > 0 && machineChessmanNum > 0) {

return 0;

}

if (humanChessmanNum == 0 && machineChessmanNum == 0) {

return 7;

}

if (machineChessmanNum == 1) {

return 35;

}

if (machineChessmanNum == 2) {

return 800;

}

if (machineChessmanNum == 3) {

return 15000;

}

if (machineChessmanNum == 4) {

return 800000;

}

if (humanChessmanNum == 1) {

return 15;

}

if (humanChessmanNum == 2) {

return 400;

}

if (humanChessmanNum == 3) {

return 1800;

}

if (humanChessmanNum == 4) {

return 100000;

}

return -1;

}

在Chessboard類中添加searchLocation方法:

/**

* 計算機器落子的最佳位置

*/

public Pieces searchLocation() {

//每次都初始化一下score的評分數組

for (int i = 0; i < CHESSBOARD_SIZE; i++) {

for (int j = 0; j < CHESSBOARD_SIZE; j++) {

score[i][j] = 0;

}

}

//每次機器尋找了落子位置,評分都重新計算一遍

int humanChessmanNum = 0;

int machineChessmanNum = 0;

int tupleScoreTmp = 0;

int goalX = -1;

int goalY = -1;

int maxScore = -1;

//縱向掃描棋盤

for (int i = 0; i < 15; i++) {

for (int j = 0; j < 11; j++) {

int k = j;

while (k < j + 5) {

if (location[j][k] == -1) machineChessmanNum++;

else if (location[i][k] == 1) humanChessmanNum++;

k++;

}

// 將每一個五元組中的黑棋個數與白棋個數傳入評分表中

tupleScoreTmp = tupleScore(humanChessmanNum, machineChessmanNum);

//為該五元組的每一個位置添加分數

for (k = j; k < j + 5; k++) {

score[i][k] += tupleScoreTmp;

}

//歸零

humanChessmanNum = 0;

machineChessmanNum = 0;

tupleScoreTmp = 0;

}

}

//橫向掃描棋盤

for (int i = 0; i < 15; i++) {

for (int j = 0; j < 11; j++) {

int k = j;

while (k < j + 5) {

if (location[k][i] == -1) machineChessmanNum++;

else if (location[k][i] == 1) humanChessmanNum++;

k++;

}

// 將每一個五元組中的黑棋個數與白棋個數傳入評分表中

tupleScoreTmp = tupleScore(humanChessmanNum, machineChessmanNum);

//為該五元組的每一個位置添加分數

for (k = j; k < j + 5; k++) {

score[k][i] += tupleScoreTmp;

}

//歸零

humanChessmanNum = 0;

machineChessmanNum = 0;

tupleScoreTmp = 0;

}

}

//3.掃描右對角線 上側部分

for (int i = 14; i >= 4; i--) {

for (int k = i, j = 0; j < 15 && k >= 0; j++, k--) {

int m = k; //x軸

int n = j; //y軸

while (m > k - 5 && k - 5 >= -1) {

if (location[m][n] == -1) machineChessmanNum++;

else if (location[m][n] == 1) humanChessmanNum++;

m--;

n++;

}

//注意斜向判斷時,可能不構成五元組(靠近四個角落),遇到這種情況要忽略掉

if (m == k - 5) {

tupleScoreTmp = tupleScore(machineChessmanNum, humanChessmanNum);

for (m = k, n = j; m > k - 5; m--, n++) {

score[m][n] += tupleScoreTmp;

}

}

//歸零

humanChessmanNum = 0;

machineChessmanNum = 0;

tupleScoreTmp = 0;

}

}

//4.掃描右對角線 下側部分

for (int i = 1; i < 15; i++) {

for (int k = i, j = 14; j >= 0 && k < 15; j--, k++) {

int m = k;

int n = j;

while (m < k + 5 && k + 5 <= 15) {

if (location[n][m] == -1) machineChessmanNum++;

else if (location[n][m] == 1) humanChessmanNum++;

m++;

n--;

}

if (m == k + 5) {

tupleScoreTmp = tupleScore(machineChessmanNum, humanChessmanNum);

for (m = k, n = j; m < k + 5; m++, n--) {

score[n][m] += tupleScoreTmp;

}

}

//歸零

humanChessmanNum = 0;

machineChessmanNum = 0;

tupleScoreTmp = 0;

}

}

//5.掃描左對角線上側部分

for (int i = 0; i < 11; i++) {

for (int k = i, j = 0; j < 15 && k < 15; j++, k++) {

int m = k;

int n = j;

while (m < k + 5 && k + 5 <= 15) {

if (location[m][n] == -1) machineChessmanNum++;

else if (location[m][n] == 1) humanChessmanNum++;

m++;

n++;

}

if (m == k + 5) {

tupleScoreTmp = tupleScore(machineChessmanNum, humanChessmanNum);

for (m = k, n = j; m < k + 5; m++, n++) {

score[m][n] += tupleScoreTmp;

}

}

//歸零

humanChessmanNum = 0;

machineChessmanNum = 0;

tupleScoreTmp = 0;

}

}

//6.掃描左對角線下側部分

for (int i = 1; i < 11; i++) {

for (int k = i, j = 0; j < 15 && k < 15; j++, k++) {

int m = k;

int n = j;

while (m < k + 5 && k + 5 <= 15) {

if (location[n][m] == -1) machineChessmanNum++;

else if (location[n][m] == 1) humanChessmanNum++;

m++;

n++;

}

if (m == k + 5) {

tupleScoreTmp = tupleScore(machineChessmanNum, humanChessmanNum);

for (m = k, n = j; m < k + 5; m++, n++) {

score[n][m] += tupleScoreTmp;

}

}

//歸零

humanChessmanNum = 0;

machineChessmanNum = 0;

tupleScoreTmp = 0;

}

}

//從空位置中找到最大的位置

for (int i = 0; i < 15; i++) {

for (int j = 0; j < 15; j++) {

if (location[i][j] == 0 && score[i][j] > maxScore) {

goalX = i;

goalY = j;

maxScore = score[i][j];

}

}

}

if (goalX != -1) {

return new Pieces(goalX, goalY, -1);

}

//沒找到坐標說明平局,暫不處理

return new Pieces(-1, -1, -1);

}

(完)

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的五子棋java判断平局_2020-10-03 Java初级项目——从零开始制作一个简易五子棋游戏...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲欧美日韩精品久久亚洲区 | 国产成人亚洲综合 | 午夜日韩在线观看 | 国产一级二级毛片 | 亚洲日本精品视频 | 亚洲自拍偷拍在线 | 日韩色在线 | 精品人妻人伦一区二区有限公司 | 国产美女久久久久 | 久久久888| 中文字幕亚洲专区 | 水果视频污 | 正在播放国产一区 | 久久香蕉精品 | 久久超碰精品 | 人成在线 | 稀缺呦国内精品呦 | 国产精品久久免费视频 | 中国一区二区三区 | 日韩一区网站 | 无码熟妇αⅴ人妻又粗又大 | 日本精品一二三区 | 2018中文字幕在线观看 | 国产欧美日本在线 | 国产精品久久久影院 | 五月丁香综合激情六月久久 | 黑人无套内谢中国美女 | 久久人妻少妇嫩草av蜜桃 | www激情| 一区二区日韩在线观看 | 日韩激情视频一区二区 | 亚洲国产精品久久久 | 午夜黄色在线观看 | 麻豆乱码国产一区二区三区 | 未满十八18禁止免费无码网站 | 国产一级做a爰片久久毛片男 | 亚洲国产一区二区三区在线观看 | 天天色天天插 | 丝袜国产在线 | 在线国产三级 | 激情的网站| 亚洲毛片大全 | 999久久久免费精品国产 | 精品无码国产一区二区三区51安 | 欧美性天天 | 中文在线a√在线8 | 91丨porny| 午夜影院日本 | 中国老头性行为xxxx | 又黄又爽的网站 | 夜夜爽av | 天天在线免费视频 | 天天色av| 国产一级二级三级在线 | 亚洲国产精品成人综合色在线婷婷 | 国产一区二区在线免费观看 | 欧美在线色视频 | 日本va在线 | 91免费网站在线观看 | 中文字幕第十二页 | 少妇特黄a一区二区三区 | 在线观看日本 | 国产一区二区三区免费观看视频 | 理论片午夜 | 无码人妻一区二区三区在线 | 精品人妻一区二区三 | 国产高清毛片 | 噜噜噜亚洲色成人网站 | 亚洲精品成人无码 | 人人草在线视频 | 丰满少妇高潮一区二区 | 午夜影院网站 | 日韩在线观看不卡 | 国产日韩成人内射视频 | 国产在线观看免费播放 | 91亚洲一线产区二线产区 | 色综合99 | 精品国产鲁一鲁一区二区张丽 | 国产一区二区视频免费在线观看 | 91精品啪在线观看国产线免费 | 国产精品高潮呻吟久久久久久 | 成年午夜视频 | 亚洲黄色网络 | 秋霞在线观看秋 | 麻豆一区二区三区精品视频 | 亚洲一区二区图片 | 色在线视频观看 | 亚洲视频999| 久草免费资源 | 日本xxxx裸体xxxx出水 | 老熟妇一区二区三区 | 快播av在线 | 亚洲av无码一区二区乱孑伦as | 亚洲高清久久久 | 国产精品免费一区 | 自偷自拍亚洲 | 欧美视频成人 | 欧美自拍色图 | 吃奶摸下的激烈视频 |