I'm building a chess game that randomly places 7 Queens on the board without hitting each other. The board is constructed of 7 rows and 7 columns. So far I made the following steps
Now I want to place the first queen in a random box on the board, but I don't know how to access the object of a multidimensional array. The set_piece method should access the board object and place a Q in a random box and then mark the box as occupied = true. Anyone an idea how the set_piece method in the Game class should be constructed?
Game class:
class Game {
var $board;
var $length;
public function createBoard($length) {
$this->board = new Board($length);
$this->length = $length;
}
public function showBoard() {
// Create table
$table_str = '<table border="1px">';
for($row=1; $row <= $this->length; $row++) {
$table_str .= "<tr>";
for($col=1; $col <= $this->length; $col++) {
$total = $row + $col;
if($total%2==0) {
$table_str .= "<td height=100px width=100px bgcolor=#FFFFFF></td>";
} else {
$table_str .= "<td height=60px width=60px bgcolor=#000000></td>";
}
}
$table_str .= "</tr>";
}
return $table_str;
}
public function set_piece() {
}
}
Board class:
class Board {
public $box;
public function __construct($length) {
for($i=0; $i < $length; $i++){
for($j=0; $j< $length; $j++){
$this->box[$i+1][$j+1] = new Box($i+1, $j+1);
}
}
}
}
Box class:
class Box {
public $piece;
public $occupied = false;
}
Piece class:
class Piece {
}
Queen class:
class Queen extends Piece {
}
Index:
$game = new Game();
$game->createBoard(7);
$game->set_piece();
echo $game->showBoard();
echo "<pre>";
print_r($game->board);
echo "</pre>";
The array I'm trying to access looks like this:
Board Object
(
[box] => Array
(
[1] => Array
(
[1] => Box Object
(
[piece] =>
[occupied] =>
)
[2] => Box Object
(
[piece] =>
[occupied] =>
)
[3] => Box Object
(
[piece] =>
[occupied] =>
)
[4] => Box Object
(
[piece] =>
[occupied] =>
)
[5] => Box Object
(
[piece] =>
[occupied] =>
)
[6] => Box Object
(
[piece] =>
[occupied] =>
)
[7] => Box Object
(
[piece] =>
[occupied] =>
)
)
[2] => Array
(
[1] => Box Object
(
[piece] =>
[occupied] =>
)
[2] => Box Object
(
[piece] =>
[occupied] =>
)
[3] => Box Object
(
[piece] =>
[occupied] =>
)
[4] => Box Object
(
[piece] =>
[occupied] =>
)
[5] => Box Object
(
[piece] =>
[occupied] =>
)
[6] => Box Object
(
[piece] =>
[occupied] =>
)
[7] => Box Object
(
[piece] =>
[occupied] =>
)
)
[3] => Array
(
[1] => Box Object
(
[piece] =>
[occupied] =>
)
[2] => Box Object
(
[piece] =>
[occupied] =>
)
[3] => Box Object
(
[piece] =>
[occupied] =>
)
[4] => Box Object
(
[piece] =>
[occupied] =>
)
[5] => Box Object
(
[piece] =>
[occupied] =>
)
[6] => Box Object
(
[piece] =>
[occupied] =>
)
[7] => Box Object
(
[piece] =>
[occupied] =>
)
)
[4] => Array
(
[1] => Box Object
(
[piece] =>
[occupied] =>
)
[2] => Box Object
(
[piece] =>
[occupied] =>
)
[3] => Box Object
(
[piece] =>
[occupied] =>
)
[4] => Box Object
(
[piece] =>
[occupied] =>
)
[5] => Box Object
(
[piece] =>
[occupied] =>
)
[6] => Box Object
(
[piece] =>
[occupied] =>
)
[7] => Box Object
(
[piece] =>
[occupied] =>
)
)
[5] => Array
(
[1] => Box Object
(
[piece] =>
[occupied] =>
)
[2] => Box Object
(
[piece] =>
[occupied] =>
)
[3] => Box Object
(
[piece] =>
[occupied] =>
)
[4] => Box Object
(
[piece] =>
[occupied] =>
)
[5] => Box Object
(
[piece] =>
[occupied] =>
)
[6] => Box Object
(
[piece] =>
[occupied] =>
)
[7] => Box Object
(
[piece] =>
[occupied] =>
)
)
[6] => Array
(
[1] => Box Object
(
[piece] =>
[occupied] =>
)
[2] => Box Object
(
[piece] =>
[occupied] =>
)
[3] => Box Object
(
[piece] =>
[occupied] =>
)
[4] => Box Object
(
[piece] =>
[occupied] =>
)
[5] => Box Object
(
[piece] =>
[occupied] =>
)
[6] => Box Object
(
[piece] =>
[occupied] =>
)
[7] => Box Object
(
[piece] =>
[occupied] =>
)
)
[7] => Array
(
[1] => Box Object
(
[piece] =>
[occupied] =>
)
[2] => Box Object
(
[piece] =>
[occupied] =>
)
[3] => Box Object
(
[piece] =>
[occupied] =>
)
[4] => Box Object
(
[piece] =>
[occupied] =>
)
[5] => Box Object
(
[piece] =>
[occupied] =>
)
[6] => Box Object
(
[piece] =>
[occupied] =>
)
[7] => Box Object
(
[piece] =>
[occupied] =>
)
)
)
)
As you already have an almost perfect OO-Layout, try to reduce the problem: Instead of accessing a multi-dimensional array, try to add getter's and setter's to explicitly address a certain level.
One approach:
$Game->getBoard()->getBox($row, $col)->getPiece()->set($queen);
Where the more complex function would be the getBox($row, $col)
:
class Board {
public $box;
public function __construct($length) {
for($i=0; $i < $length; $i++){
for($j=0; $j< $length; $j++){
$this->box[$i+1][$j+1] = new Box($i+1, $j+1);
}
}
}
public function getBox($row, $col) {
return $this->box[$row][$col]; // should ave some eception handling here!
}
}
I'd say this is the method you are looking for:
public function set_piece(Piece $piece, $x, $y) {
$this->board->box[$x][$y]->piece = $piece;
$this->board->box[$x][$y]->occupied = true;
}
However you should think of refactoring your code a bit. The above code takes advantage of the fact that you designed the boards properties as public
. That might look convenient at first, since you can simply access and alter the internals of the objects. But it contradicts the idea behind OOP which is that this is exactly what you should not do, or should not be allowed to do. Instead you should hide the internals of the objects by declaring them private
or protected
. Access should only get possible by getters and setters methods for the properties.
You should use setPiece
instead of mixing up camelCase and snake_case. Here's one implementation. You might also consider using private instance variables instead of public variables. Once public, you can't really go back, but you can always make private variables public later. Here, what would happen if occupied
became false, but piece
contained a Piece
. Then you'd have inconsistent state. In fact, I'd advise you to chuck the occupied
property altogether, and just have a piece property.
class Game {
private $board; // use private vars since you're already doing accessors
...
public function setPiece ($row, $col, Piece $piece) {
$this->board->setPiece($row, $col, $piece);
}
}
class Board {
...
public function setPiece ($row, $col, Piece $piece) {
// since box is an array, make it plural
$this->boxes[$row][$col]->setPiece($piece);
}
}
class Box {
...
public function setPiece (Piece $piece) {
$this->piece = $piece;
}
public function isOccupied () {
return !empty($this->piece);
}
}
And a minor thing: do you really need public $occupied
in the Box
class? If $piece
is NULL
than it's not occupied?