0

我正在学习 Angular,作为第一个项目,我正在尝试制作一个网页来下棋。

为此,我制作了两个具有各自类的组件:SquareComponent 和 BoardComponent。

SquareComponent 类具有以下属性:

export class SquareComponent {

  @Input() board: BoardComponent;
  @Input() color: 'dark' | 'light';
  @Input() piece: '' | 'Pawn' | 'Rook' | 'Knight' | 'Bishop' | 'King' | 'Queen';
  @Input() player: '' | 'Black' | 'White';
  @Input() rank: string; // 1, 2, 3, ..., 8
  @Input() file: string; // a, b, c, ..., h
  @Input() selected: boolean;
  @Input() index: number;

一个板,它是 BoardComponent 类的一个对象,因为稍后我需要访问它的一些属性。它有颜色,知道我应该把它画成浅色还是深色。它上面有棋子的信息以及它属于谁,所以它是 Pawn 还是 Rook 或其他什么,以及它是属于白色玩家还是黑色,或者方格中根本没有棋子。

最后,我最感兴趣的一点是,它有一个文件和一个等级,如果你不知道它在国际象棋中是如何工作的,它基本上是正方形的坐标。(我将在后面解释最后两个属性)。

这将是我的 BoardComponent 类:

export class BoardComponent implements OnInit {

  squares: Array<SquareComponent>;
  whiteNext: boolean;
  winner: 'Black' | 'White';
  selectedSquareIndex: number;

它有一个 SquareComponent 类的对象数组(棋盘中的 64 个方格),一个布尔值,它告诉我轮到哪位玩家,以及获胜者。对于游戏的逻辑,如果每个方格都知道它在 BoardComponent 类中的数组中的索引位置,那将很有用squares,最后一个属性的解释将留待以后讨论。

使用我设置的模板和我描述的属性,我已经成功地使 Angular 绘制了一个包含所有初始棋子的棋盘(这是 BoardComponent 类的延续):

  constructor() { }

  ngOnInit(): void {
    this.newGame();
  }

  newGame() {

    this.winner = null;
    this.whiteNext = true;
    this.squares = Array(0);
    this.selectedSquareIndex = -1;

    let lightSquare = true;
    let squareIndex = 0;
    for (let i = 8; i >= 1; i--) {
      for (let j = 1; j <= 8; j++) {
        let square = new SquareComponent(this);
        square.rank = i + "";
        square.file = String.fromCharCode(j + 96);
        square.index = squareIndex;
        squareIndex ++;
        if (lightSquare) {
          square.color = 'light';
        } else {
          square.color = 'dark';
        }
        square.player = '';
        square.piece = '';
        this.squares.push(square);
        lightSquare = !lightSquare;
      }
      lightSquare = !lightSquare;
    }

    this.placeInitialPieces();

  }

这里的函数placeInitialPieces()使用方格的等级来识别一些方格来放置棋子并将棋盘的那一侧分配给玩家:

  placeInitialPieces() {

    // Players and Pawns:
    for (let i = 0; i < this.squares.length; i++) {
      this.squares[i].setSelected(false);
      if (this.squares[i].rank == '8') {
        this.squares[i].player = 'Black';
      }
      if (this.squares[i].rank == '7') {
        this.squares[i].piece = 'Pawn';
        this.squares[i].player = 'Black';
      }
      if (this.squares[i].rank == '2') {
        this.squares[i].piece = 'Pawn';
        this.squares[i].player = 'White';
      }
      if (this.squares[i].rank == '1') {
        this.squares[i].player = 'White';
      }
    }

    // Rooks:
    this.squares[0].piece = 'Rook';
    this.squares[7].piece = 'Rook';
    this.squares[56].piece = 'Rook';
    this.squares[63].piece = 'Rook';

    // Knights:
    this.squares[1].piece = 'Knight';
    this.squares[6].piece = 'Knight';
    this.squares[57].piece = 'Knight';
    this.squares[62].piece = 'Knight';

    // Bishops:
    this.squares[2].piece = 'Bishop';
    this.squares[5].piece = 'Bishop';
    this.squares[58].piece = 'Bishop';
    this.squares[61].piece = 'Bishop';

    // Kings and Queens:
    this.squares[3].piece = 'Queen';
    this.squares[4].piece = 'King';
    this.squares[59].piece = 'Queen';
    this.squares[60].piece = 'King';

  }

现在,为了游戏的逻辑,我想让你点击其中一个棋子,它会选择它,然后用浅蓝色突出显示它。然后,它可以移动的方块将以黄色突出显示,然后单击黄色方块以移动棋子。

或者,如果您错过了一个片段,您应该能够再次单击它以取消选择它,或者单击另一个片段来选择那个片段。

为此,我在selected: booleanSquareComponent 类中创建了属性,并且我还需要 BoardComponent 类知道当前选择了哪个正方形,这就是我selectedSquareIndex在 BoardComponent 类中定义属性的原因,该类最初设置为-1. 当您单击一个正方形时,它会转到以下select()功能:

  select() {

    console.log(this); // I use this line to see what's going on
    let condition1 = this.piece.length > 0;
    let condition2 = this.board.playerTurn === this.player;
    if (condition1 && condition2) {
      if (this.board.getSelectedSquareIndex() == -1) {
        this.selected = true;
        this.board.setSelectedSquareIndex(this.getIndex());
      } else if (this.getIndex() == this.board.getSelectedSquareIndex()) { // <-- undefined == undefined
        this.selected = false;
        this.board.setSelectedSquareIndex(-1);
      } else {
        console.log("We're in else");
        this.board.deleteSelection();
        this.selected = true;
        this.board.setSelectedSquareIndex(this.getIndex());
      }
    }

  }

这是我的问题出现的地方:

当我在函数中打印对象时,select()properties和简单地消失了,即使我之前使用 rank 放置块,如果我在创建后打印正方形数组,所有属性都在那里。我可以选择和取消选择一个正方形,但我不能交换它们(在语句中),因为当我使用这个方法时,正方形的索引不是一个定义的属性。rankfileindexelse

PD:有一些方法,如 getter、setter deleteSelection(),它们不在这里,但它们并不重要。但是,如果您想看到它们,可以询问。

如果您想查看整个内容并对其进行测试或审查,我也可以将我的代码发布到 GitHub 或其他地方。

4

0 回答 0