Access the random value of parent class - php

So, let's say I have this dummy code in one file:
<?php
class Dice
{
public $maxPossibleNo;
public $secretNumber;
function __construct($no_of_dice=1)
{
// how many possible dice number to enroll
$this->maxPossibleNo = $no_of_dice * 6;
// do shaking dice
$this->secretNumber = $this->getSecretNumber();
}
function getSecretNumber()
{
return rand(1, $this->maxPossibleNo);
}
function roll()
{
$found = false;
list($array1, $array2) = array_chunk(range(1, $this->maxPossibleNo), ceil($this->maxPossibleNo/2));
/*
Array
(
[0] => 1
[1] => 2
[2] => 3
)
Array
(
[0] => 4
[1] => 5
[2] => 6
)
*/
$guess = new Guess();
echo $this->secretNumber;
echo $guess->checkSecretNumber();
}
}
class Guess extends Dice
{
function checkSecretNumber()
{
return $this->secretNumber;
}
function isGreaterThan($x)
{
return $x > $this->secretNumber;
}
function isLessThan($x)
{
return $x < $this->secretNumber;
}
function isEqual($x)
{
return $x == $this->secretNumber;
}
}
$game = new Dice('1');
$game->roll();
Result:
65
43
54
Expected Result:
66
33
55
I want the Guess class to be able to access the secret number of the Dice class without having to roll it again. So I can manipulate the Guess class with other function.
EDIT:
Expectation flow: The main class will only called once (to generate
the secret number), while i will need to do loop checking for the
secret number for many times. (I guess the way is to create another
class of it, and it will be able to be called repeatly for auto
checking purpose, but i had did mistake here and dont have any idea
how to correct this part.)
Any suggested correction will be appreciated.
Thank you

when you create a new Guess(), it runs the constructor of Dice automatically, since Guess extends dice. The secret number in the Guess instance is not the secret number of the first Dice instance, it's a separate instance. I think your design is flawed. Why does Guess need to extend Dice? A guess is not logically a different implementation of a Dice (which is what you'd (logically) normally use subclasses for).
Here's how I would do it (without knowing anything further about what exactly you want to achieve):
<?php
class Dice
{
public $maxPossibleNo;
public $secretNumber;
function __construct($no_of_dice=1)
{
// how many possible dice number to enroll
$this->maxPossibleNo = $no_of_dice * 6;
// do shaking dice
$this->secretNumber = $this->getSecretNumber();
}
function getSecretNumber()
{
return rand(1, $this->maxPossibleNo);
}
function roll()
{
$found = false;
list($array1, $array2) = array_chunk(range(1, $this->maxPossibleNo), ceil($this->maxPossibleNo/2));
/*
Array
(
[0] => 1
[1] => 2
[2] => 3
)
Array
(
[0] => 4
[1] => 5
[2] => 6
)
*/
}
}
class Guess
{
private $dice;
function __construct(Dice $d)
{
$this->dice = $d;
}
function checkSecretNumber()
{
return $this->dice->secretNumber;
}
function isGreaterThan($x)
{
return $x > $this->dice->secretNumber;
}
function isLessThan($x)
{
return $x < $this->dice->secretNumber;
}
function isEqual($x)
{
return $x == $this->dice->secretNumber;
}
}
$dice = new Dice('1');
$dice->roll();
$guess = new Guess($dice);
echo $dice->secretNumber;
echo $guess->checkSecretNumber();

Related

Include DB output from a file in an class

I'm trying to edit an class with an DB driven result.
I use ColorInterpreter by Our Code World, which is a PHP port of the JavaScript library NTC JS.
In this class is a public variable which is a array of hex/colorname pairs. This is hardcoded into the class. I want to make this dynamic with the use of an DB output.
I'm still struggeling with classes so I can't get my head around this.
colornames.inc.php:
Outputs something like this:
Array
(
[b0bf1a] => Acid Green
[7cb9e8] => Aero
[c9ffe5] => Aero Blue
[b284be] => African Violet
[00308f] => Air Force Blue (USAF)
[72a0c1] => Air superiority Blue
...
}
ColorInterpreter.php:
class ColorInterpreter
{
public function __construct()
{
$color = null;
$rgb = null;
$hsl = null;
$name = null;
for($i = 0; $i < count($this->names); $i++)
{
$color = "#".$this->names[$i][0];
$rgb = $this->rgb($color);
$hsl = $this->hsl($color);
array_push
(
$this->names[$i],
$rgb[0],
$rgb[1],
$rgb[2],
$hsl[0],
$hsl[1],
$hsl[2]
);
}
}
public function name($color)
{
...
}
// adopted from: Farbtastic 1.2
// http://acko.net/dev/farbtastic
public function hsl($color)
{
...
}
// adopted from: Farbtastic 1.2
// http://acko.net/dev/farbtastic
public function rgb($color)
{
...
}
public function color($name)
{
...
}
// Below is the part I need to replace with the output given from colornames.inc.php
public $names = array(
// Pink colors
array("FFC0CB", "Pink"),
array("FFB6C1", "Light Pink"),
array("FF69B4", "Hot Pink"),
array("FF1493", "Deep Pink"),
array("DB7093", "Pale Violet Red"),
array("C71585", "Medium Violet Red"),
array("E0115F", "Ruby"),
array("FF6FFF", "Ultra"),
...
);
}
I don't know how, if or where I could/should include the colornames.inc.php
And I don't know where to correctly declare the needed variables. Obviously, $this->names represent the hardcoded array, but how has this to be changed to reflect the DB output I have?
I'm completely lost here.
Your best option is to create a function that returns the values, and then pass that as the constructor when you create the class. e.g.
include 'file_with_function.php';
include 'file_with_class.php';
$initialColorValues = my_get_color_values();
$newObject = new ColorObject($initialColorValues);
Now you can process that array in the constructor, and you have an object that is seeded with the correct color values
class XYZ {
public $names;
public function __construct($names){
// ... do work
$this->names = $work;
}
}

Alternative to a while loop in PHP

I am trying to develop my understanding of php and would really appreciate any help. I have used a while loop to compare some values posted in my form with what is stored in a csv file.
This code works well. However, is it possible to achieve the same result using a FOR EACH loop or even a Do Until?? Or both?? Many thanks for any support
$file_handle = fopen("games.csv", "r"); # identify which file is being used.
while(!feof($file_handle))
{
$gameinfo = fgetcsv($file_handle);
if ($gameinfo[0] == $_POST["gameID"])
{
$GameName = "$gameinfo[2]";
$GameCost = "$gameinfo[4]";
$GameFound = true;
}
}
fclose($file_handle);
while is the best suited statement for this task, because you want to check for EOF before doing any read.
You can transform it in a do-while (there is no do-until in PHP) as an exercise:
do
{
if (!feof($file_handle))
{
$gameinfo = fgetcsv($file_handle);
if ($gameinfo[0] == $_POST["gameID"])
{
...
}
}
}
while(!feof($file_handle));
or shorter
do
{
if (feof($file_handle))
break;
$gameinfo = fgetcsv($file_handle);
if ($gameinfo[0] == $_POST["gameID"])
{
...
}
}
while(true);
but that's just a bad way to write a while.
Regarding foreach, quoting the doc
The foreach construct provides an easy way to iterate over arrays. foreach works only on arrays and objects, and will issue an error when you try to use it on a variable with a different data type or an uninitialized variable.
You can customize iteration over objects, this let you (Warning, layman language) use foreach on "custom objects" so that you can, in a way, extend the functionality of foreach.
For example to iterate over CSV files you can use this class
<?php
class FileIterator implements Iterator
{
private $file_handle = null;
private $file_name;
private $line;
public function __construct($file_name)
{
$this->file_name = $file_name;
$this->rewind();
}
public function rewind()
{
if (!is_null($this->file_handle))
fclose($this->file_handle);
$this->line = 1;
$this->file_handle = fopen($this->file_name, "r");
}
public function current()
{
return fgetcsv($this->file_handle);
}
public function key()
{
return $this->line;
}
public function next()
{
return $this->line++;
}
public function valid()
{
$valid = !feof($this->file_handle);
if (!$valid)
fclose($this->file_handle);
return $valid;
}
}
?>
and use it this way
$it = new FileIterator("game.csv");
foreach ($it as $line => $gameObj)
{
echo "$line: " . print_r($gameObj, true) . "<br/>";
}
Which produce something like
1: Array ( [0] => 0 [1] => Far Cry 3 )
2: Array ( [0] => 1 [1] => Far Cry Primal )
3: Array ( [0] => 2 [1] => Alien Isolation )
for this file
0,Far Cry 3
1,Far Cry Primal
2,Alien Isolation

PHP Classes and Objects construct and destruct

I´m trying to learn construct and destruct.
So, I made this
<?php
class Numbers {
public function __construct($numberint,$numbername,$numberletter,$numberpos) {
$this->numberint = $numberint;
$this->numbername = $numbername;
$this->numberletter = $numberletter;
$this->numberpos = $numberpos;
}
public function __destruct() {
unset($this->numberpos);
}
}
$number1 = new Numbers(1,"One","A",0);
print_r($number1);
?>
As you can see, I create the class Number and then, use construct for the Objects. But after construct, I want to use destruct, in this case, unset numberpos. I´m trying to put them together to understand how the work.
Anyone can help me?
My idea is to change the result:
Numbers Object ( [numberint] => 1 [numbername] => One [numberletter] => A [numberpos] => 0 )
To...
Numbers Object ( [numberint] => 1 [numbername] => One [numberletter] => A )
Thanks and remember that I´m learning :D
The destructor is there to destroy the whole object, not parts of an object. If you want your desired output, you could just do:
$number1 = new Numbers(1,"One","A",0);
print_r($number1);
unset($number1->numberpos);
print_r($number1);
Demo.
If you want to see your destructor getting called, unset the object:
class Numbers {
public function __destruct() {
echo "Destructing!\n";
}
}
$number1 = new Numbers();
unset($number1);
echo "Done!";
Outputs:
Destructing!
Done!

Printing relations between members

I've a university project in which I've to print the relations between students in different classes level by level. The idea is if we have John and Kris studying in the same class they are friends of first level, if Kris studies with Math in same class then John and Math are friends of second level. I researched the problem and I found algorithms like this, but my main problem is that I use objects as input data :
<?php
class Student {
private $id = null;
private $classes = [];
public function __construct($id) {
$this->id = $id;
}
public function getId() {
return $this->id;
}
public function getClasses() {
return $this->classes;
}
public function addClass(UClass $class) {
array_push($this->classes, $class);
}
}
class UClass {
private $id = null;
private $students= [];
public function __construct($id) {
$this->id = $id;
}
public function getId() {
return $this->id;
}
public function getStudents() {
return $this->students;
}
public function addStudent(Student $student) {
array_push($this->students, $student);
$student->addClass($this);
}
}
function getRelations(Student $start_student, &$tree = array(), $level = 2, &$visited) {
foreach ($start_student>Classes() as $class) {
foreach ($class->Students() as $student) {
if($start_student->getId() != $student->getId() && !is_int(array_search($student->getId(), $visited))) {
$tree[$level][] = $student->getId();
array_push($visited, $student->getId());
getRelations($student, $tree, $level+1, $visited);
}
}
}
}
$class = new UClass(1);
$class2 = new UClass(2);
$class3 = new UClass(3);
$student = new Student(1);
$student2 = new Student(2);
$student3 = new Student(3);
$student4 = new Student(4);
$student5 = new Student(5);
$student6 = new Student(6);
$class->addStudent($student);
$class->addStudent($student2);
$class->addStudent($student4);
$class2->addStudentr($student2);
$class2->addStudent($student4);
$class2->addStudent($student5);
$class3->addStudent($student4);
$class3->addStudent($student5);
$class3->addStudent($student6);
$tree[1][] = $student->getId();
$visited = array($student->getId());
getRelations($student, $tree, 2, $visited);
print_r($tree);
I'm stuck at writing getRelations() function that should create an array that is something like
Array ( [1] => Array ( [0] => 1 ) [2] => Array ( [0] => 2 [1] => 4 ) [3] => Array ( [0] => 5 [1] => 6 ) )
but I can't get the recursion right(or probably the whole algorithm). Any help will be greatly appreciated.
The logic in your recursive procedure is not correct. Example:
Say you enter the procedure for some level A and there are actually 2 students to be found for a connection at that level.
You handle the first, assign the correct level A, mark him as "visited".
Then, before getting to the second, you process level A+1 for the first student. Somewhere in his "chain" you may also find the second student that was waiting to get handled at level A. However, he now gets assigned some higher level A+n, and is then marked as visited.
Next, when the recursion for student1 is finished, you continue with the second. However, he has already been "visited"...
(By the way, I do not quite understand (but my php is weak...) why your first invocation of GetRelations specifies level=2.)
Anyway, to get your logic right there's no need for recursion.
Add a property "level" to each student. Put all students also in an overall collection "population".
Then, for a chosen "startStudent", give himself level=0, all other students level=-1.
Iterate levels and try to fill in friendship levels until there's nothing left to do. My php is virtually non-existent, so I try some pseudo-code.
for(int level=0; ; level++) // no terminating condition here
{
int countHandled = 0;
for each (student in population.students)
{
if (student.level==level)
{
for each (class in student.classes)
{
for each (student in class.students)
{
if(student.level==-1)
{
student.level = level+1;
countHandled++;
}
}
}
}
}
if(countHandled==0)
break;
}
Hope this helps you out. Of course, you still have to fill in the tree/print stuff; my contribution only addresses the logic of assigning levels correctly.
I come up with that function(not sure if it's the best solution, but it works with the class objects)
function print_students(Student $start_student, &$tree = array(), $lvl = 1) {
if (!$start_student) {
return;
}
$tree[$lvl][] = $start_student->getId();
$q = array();
array_push($q, $start_student);
$visited = array($start_student->getId());
while (count($q)) {
$lvl++;
$lvl_students = array();
foreach ($q as $current_student) {
foreach ($current_student->getClasses() as $class) {
foreach ($class->getStudents() as $student) {
if (!is_int(array_search($student->getId(), $visited))) {
array_push($lvl_students, $student);
array_push($visited, $student->getId());
$tree[$lvl][] = $student->getId();
}
}
}
}
$q = $lvl_students;
}
}

Passing object method to array_map() [duplicate]

This question already has answers here:
How to use class methods as callbacks
(5 answers)
Closed 3 months ago.
class theClass{
function doSomeWork($var){
return ($var + 2);
}
public $func = "doSomeWork";
function theFunc($min, $max){
return (array_map(WHAT_TO_WRITE_HERE, range($min, $max)));
}
}
$theClass = new theClass;
print_r(call_user_func_array(array($theClass, "theFunc"), array(1, 5)));
exit;
Can any one tell what i can write at WHAT_TO_WRITE_HERE, so that doSomeWork function get pass as first parameter to array_map. and code work properly.
And give out put as
Array
(
[0] => 3
[1] => 4
[2] => 5
[3] => 6
[4] => 7
)
To use object methods with array_map(), pass an array containing the object and the objects method name. For same-object scope, use $this as normal. Since your method name is defined in your public $func property, you can pass func.
As a side note, the parentheses outside array_map() aren't necessary.
return array_map( [$this, 'func'], range($min, $max));
The following code provides an array of emails from an $users array which contains instances of a class with a getEmail method:
if(count($users) < 1) {
return $users; // empty array
}
return array_map(array($users[0], "getEmail"), $users);
I tried search for solution but it not works, so I created custom small map function that will do the task for 1 variable passed to the function it simple but will act like map
class StyleService {
function check_css_block($str){
$check_end = substr($str,-1) == ';';
$check_sprator = preg_match_all("/:/i", $str) == 1;
$check_sprator1 = preg_match_all("/;/i", $str) == 1;
if ( $check_end && $check_sprator && $check_sprator1){
return $str;
} else {
return false;
}
}
function mymap($function_name, $data){
$result = array();
$current_methods = get_class_methods($this);
if (!in_array($function_name, $current_methods)){
return False;
}
for ($i=0; $i<count($data); $i++){
$function_result = $this->{$function_name}($data[$i]);
array_push($result, $function_result);
}
return $result;
}
function get_advanced_style_data($data)
{
return $this->mymap('check_css_block', $data);
}
}
this way you can call a function name as string $this->{'function_name'}() in php

Categories