You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Candy Crush类OOP项目:Player类legal_length方法实现求助

问题:如何在Player类中获取Board实例属性以实现合法坐标验证?

我正在开发一个仿Candy Crush的OOP项目,包含三个核心类:

  • Board类:生成由黄色(Y)、蓝色(B)、粉色(P)水果组成的m*n矩阵棋盘
  • main入口:让用户创建棋盘,输入新旧坐标来移动水果(功能未完成)
  • Player类:需要实现legal_length方法,验证用户输入的old_x、old_y、new_x、new_y是否在棋盘范围内,但目前不知道如何在不重复创建Board实例的前提下获取其属性,请求帮助完成该方法。

现有代码

Board类代码

import numpy as np
from Player import *

class Board:

    def __init__(self, x=None, y=None):
        if x is None:
            x = int(input("Enter the width of the board: "))
        if y is None:
            y = int(input("Enter the height of the board: "))
        self.x = x
        self.y = y
        self.board_flaeche = np.zeros((x, y), dtype=str)
        fruits_liste = ["Y", "B", "P"]

        for i in range(x):
            for j in range(y):
                self.board_flaeche[i][j] = np.random.choice(fruits_liste)

        print(self.board_flaeche)
        # do I need it??
        self.player = Player(0, 0, 0, 0)


    def move(self):

        old_x = self.player.getOldX()
        old_y = self.player.getOldY()
        new_x = self.player.getNewX()
        new_y = self.player.getNewY()

        # Update position of the player instance
        # self.player.setPosition(new_x, new_y)

Player类代码

# from numpy import np
import main
from Board import *

# from x, y to newX, newY
class Player:
    def __init__(self, old_x, old_y, new_x, new_y):
        self.old_x = old_x
        self.old_y = old_y
        self.new_x = new_x
        self.new_y = new_y

    def getOldX(self):
        return self.old_x

    def getOldY(self):
        return self.old_y

    def getNewX(self):
        return self.new_x

    def getNewY(self):
        return self.new_y

    # switching positions - not finished yet
    # def move(self):
        # Board.board_flaeche[x][y] = Board.board_flaeche[newX][newY]

    # ToDo:
    #  Task: Write a method legal_length where old_x, old_y, new_x, new_y
    #        must be checked if they are within the self.board_area[i][j] range

    def legal_length(self):
        # ToDo Problem:
        # how do I get the attributes from another class in Python without creating an instance each time
        pass

    def setPosition(self, new_x, new_y):
        pass

Main入口代码

from Board import *
from Player import *

if __name__ == "__main__":
    b = Board()

    while True:
        old_x_input = int(input("x: "))
        old_y_input = int(input("y: "))
        new_x_input = int(input("move to newX: "))
        new_y_input = int(input("move to newY: "))
        p = Player(old_x_input - 1, old_y_input - 1, new_x_input - 1, new_y_input - 1)
        print(b.board_flaeche)
        print(b.move())

解决方案

核心思路:让Player持有Board实例引用

不需要重复创建Board实例,而是让Player类在初始化时接收一个Board实例作为参数,通过这个引用直接获取棋盘的尺寸属性,同时解决原代码中的循环导入问题。

修改后的代码示例

1. 重构Player类

class Player:
    def __init__(self, board, old_x, old_y, new_x, new_y):
        # 持有Board实例引用,用于获取棋盘尺寸
        self.board = board
        self.old_x = old_x
        self.old_y = old_y
        self.new_x = new_x
        self.new_y = new_y

    # 保留原有的get方法
    def getOldX(self):
        return self.old_x

    def getOldY(self):
        return self.old_y

    def getNewX(self):
        return self.new_x

    def getNewY(self):
        return self.new_y

    def legal_length(self):
        # 通过board实例获取棋盘的宽高
        max_x = self.board.x
        max_y = self.board.y
        
        # 验证所有坐标是否在合法范围内(0 <= 坐标 < 棋盘尺寸)
        old_valid = 0 <= self.old_x < max_x and 0 <= self.old_y < max_y
        new_valid = 0 <= self.new_x < max_x and 0 <= self.new_y < max_y
        
        return old_valid and new_valid

    def setPosition(self, new_x, new_y):
        self.old_x = self.new_x
        self.old_y = self.new_y
        self.new_x = new_x
        self.new_y = new_y

2. 重构Board类

移除默认创建的Player实例,改为在move方法中接收Player参数,避免循环依赖:

import numpy as np

class Board:
    def __init__(self, x=None, y=None):
        if x is None:
            x = int(input("Enter the width of the board: "))
        if y is None:
            y = int(input("Enter the height of the board: "))
        self.x = x
        self.y = y
        self.board_flaeche = np.zeros((x, y), dtype=str)
        fruits_liste = ["Y", "B", "P"]

        for i in range(x):
            for j in range(y):
                self.board_flaeche[i][j] = np.random.choice(fruits_liste)

        print(self.board_flaeche)

    def move(self, player):
        # 先验证坐标合法性
        if not player.legal_length():
            print("Invalid coordinates!")
            return
        
        # 执行水果交换逻辑
        old_x, old_y = player.getOldX(), player.getOldY()
        new_x, new_y = player.getNewX(), player.getNewY()
        
        self.board_flaeche[old_x][old_y], self.board_flaeche[new_x][new_y] = \
            self.board_flaeche[new_x][new_y], self.board_flaeche[old_x][old_y]
        
        print(self.board_flaeche)

3. 重构Main入口

创建Player时传入Board实例,并调用Board的move方法:

from Board import Board
from Player import Player

if __name__ == "__main__":
    b = Board()

    while True:
        try:
            old_x_input = int(input("x: "))
            old_y_input = int(input("y: "))
            new_x_input = int(input("move to newX: "))
            new_y_input = int(input("move to newY: "))
            
            # 创建Player时传入Board实例
            p = Player(b, old_x_input - 1, old_y_input - 1, new_x_input - 1, new_y_input - 1)
            
            # 调用Board的move方法执行交换
            b.move(p)
        except ValueError:
            print("Please enter valid integers!")

额外说明

  • 解决循环导入:原代码中Board和Player互相import导致循环依赖,修改后Player通过参数接收Board实例,无需提前import Board类。
  • 坐标合法性验证:legal_length方法确保所有坐标都在棋盘的索引范围内,避免数组越界错误。
  • OOP设计优化:通过依赖注入的方式传递Board实例,让Player与Board的关系更清晰,代码更易维护和扩展。

内容的提问来源于stack exchange,提问作者CGD 16

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 14:46:02