還在動手畫棋盤 ?20分鐘帶你用Java寫一個井字棋!
文章目錄
- 還在動手畫棋盤 ?20分鐘帶你用Java寫一個井字棋!
- 前言
- 設計程序
- 1.創建表單類MyGameWindow
- 2.創建表單的構造器
- 3.創建棋盤
- 4.撰寫下棋方法
- 5.撰寫尋找下棋位置的方法
- 完善事件監聽器
- 6.增加限制,一個位置只能下一顆棋子
- 7.撰寫勝利方法
- 8.撰寫清楚資料方法
- 最終源代碼
前言
上課無聊的時候,肯定會有很多人拿出一張白紙,老師在上面講的津津有味,我和同桌已經開始下起了井字棋,老師課也講完了,我也畫滿了一張白紙,無聊想要玩井字棋,不僅浪費紙張,還要自己動手畫棋,,今天小編帶著你,用Java撰寫一個井字棋小游戲,
設計程序
1.創建表單類MyGameWindow
創建MyGameWindow類使其繼承JFrame類成為表單類并實作ActionListener介面,并實作ActionListener介面中的actionPerformed(ActionEvent e)方法,
public class MyGameWindow extends JFrame implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
}
}
2.創建表單的構造器
創建表單的構造器,進行一些基礎的設定,并在主方法中進行實體化,
public class MyGameWindow extends JFrame implements ActionListener {
public MyGameWindow(){
//設定視窗的標題
setTitle("井字棋");
//設定表單的位置和大小
setBounds(100,100,600,600);
//設定表單的布局方式
setLayout(new GridLayout(3,3));
//設定表單的關閉方式
setDefaultCloseOperation(EXIT_ON_CLOSE);
//設定表單可見
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
}
public static void main(String[] args) {
new MyGameWindow();
}
}
此時,我們已經造出了一個空的視窗,

3.創建棋盤
創建一個三行三列的按鈕陣串列示棋盤,并將按鈕陣列實體化添加到表單中,并為各按鈕設定事件監聽器,
public class MyGameWindow extends JFrame implements ActionListener {
//以3行3列陣列的形式創建表盤
private JButton[][] boards = new JButton[3][3];
public MyGameWindow(){
//設定視窗的標題
setTitle("井字棋");
//設定表單的位置和大小
setBounds(100,100,600,600);
//設定表單的布局方式
setLayout(new GridLayout(3,3));
//將按鈕陣列添加到表單中去并為按鈕添加事件監聽方法
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//實體化按鈕
boards[i][j] = new JButton();
//將按鈕添加到表單中去
add(boards[i][j]);
//為按鈕添加時間監聽方法
boards[i][j].addActionListener(this);
}
}
//設定表單的關閉方式
setDefaultCloseOperation(EXIT_ON_CLOSE);
//設定表單可見
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
}
public static void main(String[] args) {
new MyGameWindow();
}
}
此時,我們已經可以看到我們造好的棋盤了,

4.撰寫下棋方法
棋盤有了,那該怎么下呢,接下來就需要撰寫下棋的方法,
首先我們需要添加一個標志flag,這個標志將表明此時是誰在下棋,
當flag=0時,表示此時下棋的是執X的玩家,當flag=1時,表示此時下棋的是執O的玩家,我們將標志變數初始化為0,這表明每一局都將是由執X的玩家先手,
接著我們就可以撰寫下棋方法了,當flag=0時,下X,將flag賦值為1,表示此時該執O的玩家下棋了,同理,當flag=1,時,下O,將flag賦值為0,表示此時該執X的玩家下棋了,
//下棋方法
private void play(JButton clickBtn,int i,int j){
if(flag == 0){
clickBtn.setText(“X”);
flag = 1;
}else if(flag == 1){
clickBtn.setText(“O”);
flag = 0;
}
}
public class MyGameWindow extends JFrame implements ActionListener {
//以3行3列陣列的形式創建表盤
private JButton[][] boards = new JButton[3][3];
//X先手
private int flag = 0;//flag = 0 表示落子X flag = 1表示落子O
public MyGameWindow(){
//設定視窗的標題
setTitle("井字棋");
//設定表單的位置和大小
setBounds(100,100,600,600);
//設定表單的布局方式
setLayout(new GridLayout(3,3));
//將按鈕陣列添加到表單中去并為按鈕添加事件監聽方法
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//實體化按鈕
boards[i][j] = new JButton();
//將按鈕添加到表單中去
add(boards[i][j]);
//為按鈕添加時間監聽方法
boards[i][j].addActionListener(this);
}
}
//設定表單的關閉方式
setDefaultCloseOperation(EXIT_ON_CLOSE);
//設定表單可見
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
}
//下棋方法
private void play(JButton clickBtn,int i,int j){
if(flag == 0){
clickBtn.setText("X");
flag = 1;
}else if(flag == 1){
clickBtn.setText("O");
flag = 0;
}
}
public static void main(String[] args) {
new MyGameWindow();
}
}
5.撰寫尋找下棋位置的方法
撰寫完了下棋的方法之后,我們需要準確的知道玩家在棋盤的哪一個位置下了棋,因此需要撰寫一個尋找下棋位置的方法,
這個方法回傳一個長度為2的location陣列,location[0]記錄玩家下棋位置的行數,location[1]記錄玩家下棋位置的列數,
這樣我們就能夠在棋盤中準確的找到玩家下棋的位置了,
//尋找按鈕位置
private int[] location(JButton clickBtn){
int[] location = new int[2];//location[0]表示第i行,location[1]表示第j列
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if(boards[i][j] == clickBtn){
location[0] = i;
location[1] = j;
}
}
}
return location;
}
public class MyGameWindow extends JFrame implements ActionListener {
//以3行3列陣列的形式創建表盤
private JButton[][] boards = new JButton[3][3];
//X先手
private int flag = 0;//flag = 0 表示落子X flag = 1表示落子O
public MyGameWindow(){
//設定視窗的標題
setTitle("井字棋");
//設定表單的位置和大小
setBounds(100,100,600,600);
//設定表單的布局方式
setLayout(new GridLayout(3,3));
//將按鈕陣列添加到表單中去并為按鈕添加事件監聽方法
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//實體化按鈕
boards[i][j] = new JButton();
//將按鈕添加到表單中去
add(boards[i][j]);
//為按鈕添加時間監聽方法
boards[i][j].addActionListener(this);
}
}
//設定表單的關閉方式
setDefaultCloseOperation(EXIT_ON_CLOSE);
//設定表單可見
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
}
//下棋方法
private void play(JButton clickBtn,int i,int j){
if(flag == 0){
clickBtn.setText("X");
flag = 1;
}else if(flag == 1){
clickBtn.setText("O");
flag = 0;
}
}
//尋找按鈕位置
private int[] location(JButton clickBtn){
int[] location = new int[2];//location[0]表示第i行,location[1]表示第j列
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if(boards[i][j] == clickBtn){
location[0] = i;
location[1] = j;
}
}
}
return location;
}
public static void main(String[] args) {
new MyGameWindow();
}
}
完善事件監聽器
前期的準備作業基本上已經完成,想要讓棋子跑到棋盤上去,我們還需要完善按鈕的事件監聽器,
首先我們需要獲取玩家點擊的到底是哪一個按鈕,然后記錄下這個按鈕的行數和列數,然后我們就可以在棋盤上落下棋子啦,
@Override
public void actionPerformed(ActionEvent e) {
//獲取點擊的按鈕
JButton clickBtn = (JButton) e.getSource();
//找到落子的位置
int[] places = location(clickBtn);
int i = places[0];
int j = places[1];
//下棋
play(clickBtn, i, j);
}
public class MyGameWindow extends JFrame implements ActionListener {
//以3行3列陣列的形式創建表盤
private JButton[][] boards = new JButton[3][3];
//X先手
private int flag = 0;//flag = 0 表示落子X flag = 1表示落子O
public MyGameWindow(){
//設定視窗的標題
setTitle("井字棋");
//設定表單的位置和大小
setBounds(100,100,600,600);
//設定表單的布局方式
setLayout(new GridLayout(3,3));
//將按鈕陣列添加到表單中去并為按鈕添加事件監聽方法
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//實體化按鈕
boards[i][j] = new JButton();
//將按鈕添加到表單中去
add(boards[i][j]);
//為按鈕添加時間監聽方法
boards[i][j].addActionListener(this);
}
}
//設定表單的關閉方式
setDefaultCloseOperation(EXIT_ON_CLOSE);
//設定表單可見
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
//獲取點擊的按鈕
JButton clickBtn = (JButton) e.getSource();
//找到落子的位置
int[] places = location(clickBtn);
int i = places[0];
int j = places[1];
//下棋
play(clickBtn, i, j);
}
//下棋方法
private void play(JButton clickBtn,int i,int j){
if(flag == 0){
clickBtn.setText("X");
flag = 1;
}else if(flag == 1){
clickBtn.setText("O");
flag = 0;
}
}
//尋找按鈕位置
private int[] location(JButton clickBtn){
int[] location = new int[2];//location[0]表示第i行,location[1]表示第j列
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if(boards[i][j] == clickBtn){
location[0] = i;
location[1] = j;
}
}
}
return location;
}
public static void main(String[] args) {
new MyGameWindow();
}
}


6.增加限制,一個位置只能下一顆棋子
看看上面的兩張圖片沒有,有沒有發現什么問題,
第一張圖片是正常的,此時棋盤已滿,但是我們仍然可以在棋盤的任意位置下棋,這就導致了第二幅圖的情況,滿屏的O,執X的玩家表示這不公平!

這不合理,那么怎么解決呢?
我們定義一個二維陣列place,存盤棋盤上棋子的情況,
當place[i][j]=1時,表示此位置有棋子X
當place[i][j]=-1時,表示此位置有棋子O
當place[i][j]=0時,表示此位置沒有棋子
當玩家想要在已經有棋子的位置下棋時,我們應該給出提示,提醒他不能下在這里,
既然已經做出了規定,我們就需要在玩家下棋的時候記錄下棋盤的情況,所以我們對下棋的方法稍作更改,讓其及時記錄棋盤的情況,
//下棋方法
private void play(JButton clickBtn,int i,int j){
if(flag == 0){
clickBtn.setText(“X”);
flag = 1;
place[i][j] = 1;
}else if(flag == 1){
clickBtn.setText(“O”);
flag = 0;
place[i][j] = -1;
}
}
//判斷當前位置是否落子
if(place[i][j] == 1 || place[i][j] == -1){
JOptionPane.showMessageDialog(this, “該處已經落子,請選擇其他位置!”);
return ;
}
public class MyGameWindow extends JFrame implements ActionListener {
//以3行3列陣列的形式創建表盤
private JButton[][] boards = new JButton[3][3];
//X先手
private int flag = 0;//flag = 0 表示落子X flag = 1表示落子O
private int[][] place = new int[3][3];//落子X將對應的place設定為1,落子O設定為-1
public MyGameWindow(){
//設定視窗的標題
setTitle("井字棋");
//設定表單的位置和大小
setBounds(100,100,600,600);
//設定表單的布局方式
setLayout(new GridLayout(3,3));
//將按鈕陣列添加到表單中去并為按鈕添加事件監聽方法
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//實體化按鈕
boards[i][j] = new JButton();
//將按鈕添加到表單中去
add(boards[i][j]);
//為按鈕添加時間監聽方法
boards[i][j].addActionListener(this);
}
}
//設定表單的關閉方式
setDefaultCloseOperation(EXIT_ON_CLOSE);
//設定表單可見
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
//獲取點擊的按鈕
JButton clickBtn = (JButton) e.getSource();
//找到落子的位置
int[] places = location(clickBtn);
int i = places[0];
int j = places[1];
//判斷當前位置是否落子
if(place[i][j] == 1 || place[i][j] == -1){
JOptionPane.showMessageDialog(this, "該處已經落子,請選擇其他位置!");
return ;
}
//下棋
play(clickBtn, i, j);
}
//下棋方法
private void play(JButton clickBtn,int i,int j){
if(flag == 0){
clickBtn.setText("X");
flag = 1;
place[i][j] = 1;
}else if(flag == 1){
clickBtn.setText("O");
flag = 0;
place[i][j] = -1;
}
}
//尋找按鈕位置
private int[] location(JButton clickBtn){
int[] location = new int[2];//location[0]表示第i行,location[1]表示第j列
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if(boards[i][j] == clickBtn){
location[0] = i;
location[1] = j;
}
}
}
return location;
}
public static void main(String[] args) {
new MyGameWindow();
}
}

7.撰寫勝利方法
通過上面的運行結果我們又發現了什么問題?對,就是明明X已經贏了,可是游戲仍然在繼續,這就需要我們撰寫勝利方法來判斷誰是贏家,
勝利的方式有幾種?橫著的三種,豎著的三種,斜著的兩種,那么一共就是八種方法,
int first = place[0][0] + place[0][1] + place[0][2];
int second = place[1][0] + place[1][1] + place[1][2];
int third = place[2][0] + place[2][1] + place[2][2];
int forth = place[0][0] + place[1][0] + place[2][0];
int fifth = place[0][1] + place[1][1] + place[2][1];
int sixth = place[0][2] + place[1][2] + place[2][2];
int seventh = place[0][0] + place[1][1] + place[2][2];
int eighth = place[0][2] + place[1][1] + place[2][0];
那么我們怎么判斷是誰贏了呢?前面我們規定,下X的位置places陣列的值被設為1,下O的位置places陣列的值被設為-1,
當此上八種方法中的一種的值為3,則表明執X的玩家勝利,
當此上八種方法中的一種的值為-3,則表明執O的玩家勝利,
if(first == 3 || second == 3 || third == 3 || forth == 3 ||fifth == 3||sixth == 3||seventh == 3||eighth ==3){
return 1;//X勝利
}
else if(first == -3 || second == -3 || third == -3 || forth == -3 ||fifth == -3||sixth == -3||seventh == -3||eighth ==-3){
return -1;//O勝利
}
若棋盤未滿,則繼續游戲,
for (int i = 0; i < 3 ; i++) {
for (int j = 0; j < 3; j++) {
if(place[i][j] == 0)
return -2;//表示繼續進行
}
}
否則,雙方平局,
rerturn 0;
public class MyGameWindow extends JFrame implements ActionListener {
//以3行3列陣列的形式創建表盤
private JButton[][] boards = new JButton[3][3];
//X先手
private int flag = 0;//flag = 0 表示落子X flag = 1表示落子O
private int[][] place = new int[3][3];//落子X將對應的place設定為1,落子O設定為-1
public MyGameWindow(){
//設定視窗的標題
setTitle("井字棋");
//設定表單的位置和大小
setBounds(100,100,600,600);
//設定表單的布局方式
setLayout(new GridLayout(3,3));
//將按鈕陣列添加到表單中去并為按鈕添加事件監聽方法
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//實體化按鈕
boards[i][j] = new JButton();
//將按鈕添加到表單中去
add(boards[i][j]);
//為按鈕添加時間監聽方法
boards[i][j].addActionListener(this);
}
}
//設定表單的關閉方式
setDefaultCloseOperation(EXIT_ON_CLOSE);
//設定表單可見
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
//獲取點擊的按鈕
JButton clickBtn = (JButton) e.getSource();
//找到落子的位置
int[] places = location(clickBtn);
int i = places[0];
int j = places[1];
//判斷當前位置是否落子
if(place[i][j] == 1 || place[i][j] == -1){
JOptionPane.showMessageDialog(this, "該處已經落子,請選擇其他位置!");
return ;
}
//下棋
play(clickBtn, i, j);
//判斷輸贏
int judge = judge();
if(judge == 1){
JOptionPane.showMessageDialog(this, "X勝利!");
}else if(judge == -1){
JOptionPane.showMessageDialog(this, "O勝利!");
}else if(judge == -2){
return;
}else{
JOptionPane.showMessageDialog(this, "平局!");
}
}
//判斷輸贏
private int judge(){
int first = place[0][0] + place[0][1] + place[0][2];
int second = place[1][0] + place[1][1] + place[1][2];
int third = place[2][0] + place[2][1] + place[2][2];
int forth = place[0][0] + place[1][0] + place[2][0];
int fifth = place[0][1] + place[1][1] + place[2][1];
int sixth = place[0][2] + place[1][2] + place[2][2];
int seventh = place[0][0] + place[1][1] + place[2][2];
int eighth = place[0][2] + place[1][1] + place[2][0];
if(first == 3 || second == 3 || third == 3 || forth == 3 ||fifth == 3||sixth == 3||seventh == 3||eighth ==3){
return 1;//X勝利
}
else if(first == -3 || second == -3 || third == -3 || forth == -3 ||fifth == -3||sixth == -3||seventh == -3||eighth ==-3){
return -1;//O勝利
}
for (int i = 0; i < 3 ; i++) {
for (int j = 0; j < 3; j++) {
if(place[i][j] == 0)
return -2;//表示繼續進行
}
}
return 0;//表示平局
}
//下棋方法
private void play(JButton clickBtn,int i,int j){
if(flag == 0){
clickBtn.setText("X");
flag = 1;
place[i][j] = 1;
}else if(flag == 1){
clickBtn.setText("O");
flag = 0;
place[i][j] = -1;
}
}
//尋找按鈕位置
private int[] location(JButton clickBtn){
int[] location = new int[2];//location[0]表示第i行,location[1]表示第j列
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if(boards[i][j] == clickBtn){
location[0] = i;
location[1] = j;
}
}
}
return location;
}
public static void main(String[] args) {
new MyGameWindow();
}
}



8.撰寫清楚資料方法
以上我們已經基本上實作了井字棋游戲了,但是我們每玩一局都需要重新啟動一次程式,這很麻煩,這不是我們想要的,
我們想要每一次游戲結束后,棋盤會自動重繪為最開始的樣子,那么我們就可以隨心所欲的想下幾局就下幾局,不想玩的時候直接關閉程式即可,
我們需要清楚兩個資料,一個棋盤中的棋子,一個是存盤棋子位置的陣列,
將其重新初始化,就可以進行下一局游戲了,
//清屏方法
private void clear(){
flag = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
boards[i][j].setText("");
place[i][j] = 0;
}
}
}
最終源代碼
這樣所有的代碼都寫完了,是不是很簡單,

代碼整理如下:
package com.zhang.game;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* @author nanqi-code
* @create 2021/9/1-23:11
*/
public class MyGameWindow extends JFrame implements ActionListener {
//以3行3列陣列的形式創建表盤
private JButton[][] boards = new JButton[3][3];
//X先手
private int flag = 0;//flag = 0 表示落子X flag = 1表示落子O
private int[][] place = new int[3][3];//落子X將對應的place設定為1,落子O設定為-1
public MyGameWindow(){
//設定視窗的標題
setTitle("井字棋");
//設定表單的位置和大小
setBounds(100,100,600,600);
//設定表單的布局方式
setLayout(new GridLayout(3,3));
//將按鈕陣列添加到表單中去并為按鈕添加事件監聽方法
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//實體化按鈕
boards[i][j] = new JButton();
//將按鈕添加到表單中去
add(boards[i][j]);
//為按鈕添加時間監聽方法
boards[i][j].addActionListener(this);
}
}
//設定表單的關閉方式
setDefaultCloseOperation(EXIT_ON_CLOSE);
//設定表單可見
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
//獲取點擊的按鈕
JButton clickBtn = (JButton) e.getSource();
//找到落子的位置
int[] places = location(clickBtn);
int i = places[0];
int j = places[1];
//判斷當前位置是否落子
if(place[i][j] == 1 || place[i][j] == -1){
JOptionPane.showMessageDialog(this, "該處已經落子,請選擇其他位置!");
return ;
}
//下棋
play(clickBtn, i, j);
//判斷輸贏
int judge = judge();
if(judge == 1){
JOptionPane.showMessageDialog(this, "X勝利!");
clear();
}else if(judge == -1){
JOptionPane.showMessageDialog(this, "O勝利!");
clear();
}else if(judge == -2){
return;
}else{
JOptionPane.showMessageDialog(this, "平局!");
clear();
}
}
//判斷輸贏
private int judge(){
int first = place[0][0] + place[0][1] + place[0][2];
int second = place[1][0] + place[1][1] + place[1][2];
int third = place[2][0] + place[2][1] + place[2][2];
int forth = place[0][0] + place[1][0] + place[2][0];
int fifth = place[0][1] + place[1][1] + place[2][1];
int sixth = place[0][2] + place[1][2] + place[2][2];
int seventh = place[0][0] + place[1][1] + place[2][2];
int eighth = place[0][2] + place[1][1] + place[2][0];
if(first == 3 || second == 3 || third == 3 || forth == 3 ||fifth == 3||sixth == 3||seventh == 3||eighth ==3){
return 1;//X勝利
}
else if(first == -3 || second == -3 || third == -3 || forth == -3 ||fifth == -3||sixth == -3||seventh == -3||eighth ==-3){
return -1;//O勝利
}
for (int i = 0; i < 3 ; i++) {
for (int j = 0; j < 3; j++) {
if(place[i][j] == 0)
return -2;//表示繼續進行
}
}
return 0;//表示平局
}
//下棋方法
private void play(JButton clickBtn,int i,int j){
if(flag == 0){
clickBtn.setText("X");
flag = 1;
place[i][j] = 1;
}else if(flag == 1){
clickBtn.setText("O");
flag = 0;
place[i][j] = -1;
}
}
//尋找按鈕位置
private int[] location(JButton clickBtn){
int[] location = new int[2];//location[0]表示第i行,location[1]表示第j列
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if(boards[i][j] == clickBtn){
location[0] = i;
location[1] = j;
}
}
}
return location;
}
//清屏方法
private void clear(){
flag = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
boards[i][j].setText("");
place[i][j] = 0;
}
}
}
public static void main(String[] args) {
new MyGameWindow();
}
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/297219.html
標籤:其他

