• Java编程实践:使用面向对象编程(OOP)概念构建简单的国际象棋游戏


    介绍

    国际象棋是一个两人玩的策略游戏。使用Java和面向对象编程(OOP)概念来模拟这个游戏可以帮助我们更好地理解OOP的核心原理。本教程将带领您一步步地使用Java构建一个简单的国际象棋游戏。

    OOP概念概述

    面向对象编程(OOP)是一种计算机编程范式,其中程序被组织成对象。主要的OOP概念包括:

    1. 类(Class):定义对象的属性和方法的蓝图。
    2. 对象(Object):类的实例。
    3. 封装(Encapsulation):将对象的状态(属性)和行为(方法)包裹在一起。
    4. 继承(Inheritance):一个类可以继承另一个类的属性和方法。
    5. 多态(Polymorphism):让一个接口被多个数据类型所实现。

    创建棋盘和棋子

    1. 定义棋盘类(Board)
    public class Board {
        private final int SIZE = 8;
        private Square[][] squares = new Square[SIZE][SIZE];
    
        public Board() {
            for (int i = 0; i < SIZE; i++) {
                for (int j = 0; j < SIZE; j++) {
                    squares[i][j] = new Square(i, j, null);
                }
            }
        }
    
        public Square getSquare(int x, int y) {
            return squares[x][y];
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    2. 定义方格类(Square)

    每个棋格可以是空的或被一个棋子占据。

    public class Square {
        private int x;
        private int y;
        private Piece piece;
    
        public Square(int x, int y, Piece piece) {
            this.x = x;
            this.y = y;
            this.piece = piece;
        }
    
        public Piece getPiece() {
            return piece;
        }
    
        public void setPiece(Piece piece) {
            this.piece = piece;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    3. 定义棋子的基类(Piece)
    public abstract class Piece {
        private boolean isKilled = false;
        private boolean isWhite;
    
        public Piece(boolean isWhite) {
            this.isWhite = isWhite;
        }
    
        public boolean isWhite() {
            return isWhite;
        }
    
        public boolean isKilled() {
            return isKilled;
        }
    
        public void setKilled(boolean isKilled) {
            this.isKilled = isKilled;
        }
    
        // 每个棋子的移动方式都不同,所以我们在基类中定义一个抽象方法。
        public abstract boolean canMove(Board board, Square start, Square end);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    至此,我们已经为象棋游戏定义了基础的框架,并使用OOP的概念如类和封装。在下一部分中,我们将继续介绍如何定义具体的棋子(如兵、车、马等)并实现它们的移动逻辑。

    注意:为了简洁和清晰,本文中的代码可能不是最优的或最完整的实现。为了获得完整的项目和更多的优化技巧,请下载完整项目

    定义各种棋子及其移动逻辑

    1. 兵(Pawn)

    兵的移动逻辑相对简单:它通常向前移动一格,但在其首次移动时可以向前移动两格。当攻击时,它会沿对角线移动。

    public class Pawn extends Piece {
    
        public Pawn(boolean isWhite) {
            super(isWhite);
        }
    
        @Override
        public boolean canMove(Board board, Square start, Square end) {
            // 我们可以添加更多的逻辑来检查棋子是否可以移动到end位置
            // 例如:检查end位置是否有其他棋子
            
            int moveX = Math.abs(start.getX() - end.getX());
            int moveY = end.getY() - start.getY();
    
            if (isWhite()) {
                return (moveX == 0 && moveY == 1) || (moveX == 1 && moveY == 1);
            } else {
                return (moveX == 0 && moveY == -1) || (moveX == 1 && moveY == -1);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    2. 车(Rook)

    车可以在任何方向上移动,但只能直线移动。

    public class Rook extends Piece {
    
        public Rook(boolean isWhite) {
            super(isWhite);
        }
    
        @Override
        public boolean canMove(Board board, Square start, Square end) {
            // 检查路径上是否有其他棋子
            // 确保start和end在同一行或同一列上
            if (start.getX() == end.getX()) {
                int col = start.getX();
                for (int row = Math.min(start.getY(), end.getY()) + 1; row < Math.max(start.getY(), end.getY()); row++) {
                    if (board.getSquare(col, row).getPiece() != null) {
                        return false;
                    }
                }
            } else if (start.getY() == end.getY()) {
                int row = start.getY();
                for (int col = Math.min(start.getX(), end.getX()) + 1; col < Math.max(start.getX(), end.getX()); col++) {
                    if (board.getSquare(col, row).getPiece() != null) {
                        return false;
                    }
                }
            } else {
                return false;  // 不在同一行或同一列上
            }
    
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    3. 马(Knight)

    马有一个特殊的移动模式,它首先向一个方向移动两格,然后再垂直于之前的方向移动一格。

    public class Knight extends Piece {
    
        public Knight(boolean isWhite) {
            super(isWhite);
        }
    
        @Override
        public boolean canMove(Board board, Square start, Square end) {
            int moveX = Math.abs(start.getX() - end.getX());
            int moveY = Math.abs(start.getY() - end.getY());
    
            return (moveX == 2 && moveY == 1) || (moveX == 1 && moveY == 2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    到目前为止,我们已经为兵、车和马定义了移动逻辑。我们还需要为其他棋子(如象、王、后)定义移动逻辑。

    定义其它棋子及其移动逻辑

    4. 象(Bishop)

    象可以沿对角线移动,但不能跳过其他棋子。

    public class Bishop extends Piece {
    
        public Bishop(boolean isWhite) {
            super(isWhite);
        }
    
        @Override
        public boolean canMove(Board board, Square start, Square end) {
            int moveX = Math.abs(start.getX() - end.getX());
            int moveY = Math.abs(start.getY() - end.getY());
    
            if(moveX != moveY) {
                return false; // 检查是否沿对角线移动
            }
    
            int directionX = (end.getX() - start.getX()) > 0 ? 1 : -1;
            int directionY = (end.getY() - start.getY()) > 0 ? 1 : -1;
    
            int x = start.getX() + directionX;
            int y = start.getY() + directionY;
    
            while(x != end.getX()) {
                if(board.getSquare(x, y).getPiece() != null) {
                    return false; // 路径上有其他棋子
                }
                x += directionX;
                y += directionY;
            }
    
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    5. 后(Queen)

    后结合了车和象的移动能力,可以直线或对角线移动。

    public class Queen extends Piece {
    
        public Queen(boolean isWhite) {
            super(isWhite);
        }
    
        @Override
        public boolean canMove(Board board, Square start, Square end) {
            Rook rook = new Rook(isWhite());
            Bishop bishop = new Bishop(isWhite());
    
            return rook.canMove(board, start, end) || bishop.canMove(board, start, end);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    6. 王(King)

    王可以在任何方向上移动一格。

    public class King extends Piece {
    
        public King(boolean isWhite) {
            super(isWhite);
        }
    
        @Override
        public boolean canMove(Board board, Square start, Square end) {
            int moveX = Math.abs(start.getX() - end.getX());
            int moveY = Math.abs(start.getY() - end.getY());
    
            return moveX <= 1 && moveY <= 1;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    实现游戏管理

    为了控制游戏的主要流程,我们需要一个管理类,例如ChessGame

    public class ChessGame {
        private Board board;
        private Player whitePlayer;
        private Player blackPlayer;
    
        public ChessGame() {
            board = new Board();
            whitePlayer = new Player(true);
            blackPlayer = new Player(false);
        }
    
        public boolean movePiece(Player player, int startX, int startY, int endX, int endY) {
            Square startSquare = board.getSquare(startX, startY);
            Square endSquare = board.getSquare(endX, endY);
    
            Piece piece = startSquare.getPiece();
    
            if (piece == null) {
                System.out.println("No piece at the selected position!");
                return false;
            }
    
            if (player.isWhite() != piece.isWhite()) {
                System.out.println("This is not your piece!");
                return false;
            }
    
            if (piece.canMove(board, startSquare, endSquare)) {
                endSquare.setPiece(piece);
                startSquare.setPiece(null);
                return true;
            } else {
                System.out.println("Invalid move!");
                return false;
            }
        }
    
        public void startGame() {
            // Here we can initiate the game, setup the board and manage the game turns
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    总结

    在这篇教程中,我们使用Java和面向对象编程(OOP)概念构建了一个简单的国际象棋游戏。通过这个实践,我们学习了如何使用类、对象、封装、继承和多态这些OOP的基本概念。

    希望您能通过这个教程深入理解OOP,并在实际项目中灵活运用这些知识!

    注意:为了简洁和清晰,本文中的代码可能不是最优的或最完整的实现。为了获得完整的项目和更多的优化技巧,请下载完整项目

  • 相关阅读:
    死磕 36 个 JS 手写题(搞懂后,提升真的大)
    【Spring Cloud】如何确定微服务项目的Spring Boot、Spring Cloud、Spring Cloud Alibaba的版本
    【消息队列:优势、劣势与应用】
    Ubuntu - 安装 、配置 Redis 远程连接和密码
    R语言使用is.numeric函数判断数据对象是否是数值型
    Seata学习
    2023.10.02 win7x64sp1下Navicat_Premium15_x86连接Oracle_10g(安装在win2003x86)
    PyTorch for Audio + Music Processing(2/3/4/5/6/7) :构建数据集和提取音频特征
    pip命令大全
    云计算期末复习(3)
  • 原文地址:https://blog.csdn.net/m0_57781768/article/details/133034244