width = $width; $this->height = $height; } /** * Set the state of a cell. */ public function set(int $pos, bool $pressed = true) : self { if ($this->hasGameEnded()) { return $this; } if ($pressed) { $this->state[$pos] = self::STATE_PRESSED; } else { unset($this->state[$pos]); } $this->update(); return $this; } /** * Toggle pressed state of a cell. */ public function toggle(int $pos) : self { return $this->set($pos, !$this->isPressed($pos)); } /** * Check if a cell is pressed or not. */ public function isPressed(int $pos) : bool { return isset($this->state[$pos]); } /** * Check if a cell is part of a winning row/column. */ public function isWin(int $pos) : bool { return isset($this->state[$pos]) && $this->state[$pos] == self::STATE_WIN; } /** * Get the sate of the cells. */ public function getState() : array { return $this->state; } /** * Get the size of the board. */ public function getSize() : int { return $this->width * $this->height; } /** * Clear the board. */ public function clear() : self { $this->state = []; $this->winning = 0; return $this; } // TODO: Rename public function getNumWinRows() : int { return $this->winning; } /** * Check if the board only has winning cards */ public function hasGameEnded() : bool { if (count($this->state) < $this->width * $this->height) { return false; } foreach($this->state as $pos) { if ($pos !== self::STATE_WIN) { return false; } } return true; } /** * Check if the board is full and all positions is in a given state. */ public function isFull($state) : bool { // Board not filled, impossible to have all positions set. if (count($this->state) < $this->width * $this->height) { return false; } foreach($this->state as $pos) { if ($pos !== $state) { return false; } } return true; } /** * */ protected function update() { foreach($this->state as $pos => $_) { $this->state[$pos] = self::STATE_PRESSED; } $patterns = $this->checkWinningState(); foreach($patterns as $cards) { foreach($cards as $pos) { $this->state[$pos] = self::STATE_WIN; } } $this->winning = count($patterns); } /** * Check if the board is in a winning state. */ protected function checkWinningState() : array { $win = []; // Rows for($y=0; $y < $this->height; $y++) { $c = $this->checkRow($y); if (count($c)) { $win[] = $c; } } // Columns for($x=0; $x < $this->width; $x++) { $c = $this->checkCol($x); if (count($c)) { $win[] = $c; } } return $win; } /** * Check if a row is in a winning state (all cells pressed) */ protected function checkRow($y) : array { $cards = []; $y = $y * $this->width; for($x = 0; $x < $this->width; $x++) { $pos = $x + $y; if (!$this->isPressed($pos)) { return []; } /* if ($this->state[$pos] == self::STATE_WIN) { continue; } */ $cards[] = $pos; } return $cards; } /** * Check if a column is in a winning state (all cells pressed) */ protected function checkCol($x) : array { $cards = []; for($y = 0; $y < $this->height; $y++) { $pos = $x + ($y * $this->width); if (!$this->isPressed($pos)) { return []; } /* if ($this->state[$pos] == self::STATE_WIN) { continue; } */ $cards[] = $pos; } return $cards; } }