How to remove duplicate playing cards from player's hand? - php

I am trying to deal a hand of five cards to a player and score them. My scoring program seems to be working fine, but I am running into the issue of duplicate cards getting dealt from time to time. I tried using a while loop to check for duplicate cards, but this seems kind of hackish. My code is below. Please keep in mind that I am definitely a neophyte, so the simpler the solution the better! Thanks so much.
// create suits array
$suits = array("996", "997", "998", "999");
// create faces array
$faces = array();
$faces[1] = "1";
$faces[2] = "2";
$faces[3] = "3";
$faces[4] = "4";
$faces[5] = "5";
$faces[6] = "6";
$faces[7] = "7";
$faces[8] = "8";
$faces[9] = "9";
$faces[10] = "10";
$faces[11] = "11";
$faces[12] = "12";
$faces[13] = "13";
// create player's hand
$card = array();
for ($i = 0; $i < 5; $i++)
{
$face_value = shuffle($faces);
$suit_value = shuffle($suits);
$card[$i] = $faces[$face_value].$suits[$suit_value];
$counter = 0;
while ($counter < 100)
{
if (in_array($card[$i], $card))
{
$face_value = shuffle($faces);
$suit_value = shuffle($suits);
$card[$i] = $faces[$face_value].$suits[$suit_value];
}
$counter++;
}
print ("<img src=\"../images/4/$card[$i].gif\">");
}

It might be more efficient to simply set up an array that has 52 elements, one for each of the cards.
$cards = range(0,51);
shuffle($cards);
$hand = array();
for ($i = 0; $i < 5; $i++)
{
$hand[$i] = $cards[$i];
}
Note that you can extract the suit and rank of a card $i simply, by doing
$suit = $hand[$i] % 4;
$rank = $hand[$i] / 4;
This will prevent duplicates.
EDIT: Suit and rank were reversed. They should be correct now.

Because you said you like it easy, you could create your arrays with range().
To avoid getting duplicate hands, check the $card array with before assigning the new hand.
the new code would look like:
// create suits array
$suits = range(996, 999);
// create faces array
$faces = range(0, 13);
// create player's hand
$card = array();
while ( count($card) < 5 )
{
$face_value = shuffle($faces);
$suit_value = shuffle($suits);
$newcard = $faces[$face_value].$suits[$suit_value];
if ( in_array($card, $newcard) ) {
$card[] = $newcard;
print ("<img src=\"../images/4/$newcard.gif\">");
}
}

I would definitely create a deck with all 52 cards in it like so:
// create suits array
$suits = range(996, 999);
// create entire deck
$deck = range(0, 51);
shuffle($deck);
// create player's hand
for ($i = 0; $i < 5; $i++) {
$suit_value = $suits[$deck[$i] % 4];
$face_value = floor($deck[$i] / 4) + 1;
print ("<img src=\"../images/4/{$face_value}{$suit_value}.gif\">");
}

Related

Switch elements of 2d array

I have a problem: I can't make my script working with penalties, but I made it work with bonuses.
Start: two-dimensional array of users, each has id, name, start position and modificator (if modificator < 0 its bonus; if modificator > 0 its penalty).
How modificators work: for example, I have a queue of users Test1, Test2, Test3. If I give user Test3 bonus 1, he will switch places with user Test 2 and final queue will be Test1, Test3, Test2. If I give him bous 2, than he will be first at queue.
Penalties works the other way around. If I give user Test1 penalty 1, he will be second in a queue. If I give him penalty 3, he will be moved to the end of the queue.
This is my working code for bonuses:
<?
$new = array(); $orders = array();
$new[111]['position'] = 1; $new[111]['user'] = 'Test1'; $orders[1] = 111; $new[111]['shift'] = 0;
$new[222]['position'] = 2; $new[222]['user'] = 'Test2'; $orders[2] = 222; $new[222]['shift'] = 0;
$new[333]['position'] = 3; $new[333]['user'] = 'Test3'; $orders[3] = 333; $new[333]['shift'] = 0;
$new[444]['position'] = 4; $new[444]['user'] = 'Test4'; $orders[4] = 444; $new[444]['shift'] = 0;
$new[555]['position'] = 5; $new[555]['user'] = 'Test5'; $orders[5] = 555; $new[555]['shift'] = 0;
$new[666]['position'] = 6; $new[666]['user'] = 'Test6'; $orders[6] = 666; $new[666]['shift'] = 0;
$new[777]['position'] = 7; $new[777]['user'] = 'Test7'; $orders[7] = 777; $new[777]['shift'] = 0;
$new[888]['position'] = 8; $new[888]['user'] = 'Test8'; $orders[8] = 888; $new[888]['shift'] = 0;
//shift function
function bonus($start, $bonus)
{
global $new, $orders;
//for bonuses, shift to start, $bonus is negative number
if ($bonus < 0)
{
for ($i = $start; $i > ($start - abs($bonus)); $i--)
{
$order_id = intval($orders[$i]);
$prev = intval($orders[$i - 1]);
if ($prev != 0)
{
$temp = $new[$order_id]['position'];
$new[$order_id]['position'] = $new[$prev]['position'];
$new[$prev]['position'] = $temp;
$orders[$i] = $prev;
$orders[$i - 1] = $order_id;
}
}
}
//end for bonuses
}
// Now I set modificator (bonus negative, penalty positive)
$new[555]['shift'] = -2;
// sort by bonuses
$i = 1;
foreach($new as $value)
{
$order_id = $orders[$i];
bonus($new[$order_id]['position'], $new[$order_id]['shift']);
$i++;
}
// sort 2d array with field position
usort($new, function($a, $b){
return $a['position'] <=> $b['position'];
});
//DATA OUTPUT
$i = 1;
foreach($new as $value)
{
echo $i . '. ' . $value['user'] . ' ; shift: ' . $value['shift'];
echo '<br>';
$i++;
}
?>
At this code I set bonus with: $new[555]['shift'] = -2;
So, penalty will be like: $new[444]['shift'] = 3;
Code for penalties I think must be something like this:
//for penalty, shift to the end, $bonus positive number
if ($bonus > 0)
{
$total_new = count($new);
for ($i = $start; $i < ($start + $bonus); $i++)
{
$order_id = intval($orders[$i]);
$next = intval($orders[$i + 1]);
if ($next < $total_new)
{
$temp = $new[$order_id]['position'];
$new[$order_id]['position'] = $new[$next]['position'];
$new[$next]['position'] = $temp;
$orders[$i] = $next;
$orders[$i + 1] = $order_id;
}
}
}
//end code for penalty
Here is something wrong with $orders. I tried many different types of code all day long, including array enumeration in asc/desc order, but it didn't work correcty...
P.S. I know about array_multisort, but I dont need to sort, I need to switch elements with each other.
Again: bonus 2 means that user must switch places with previous number 2 times. Penalty 3 means that user must switch places with next user 3 times.

Get average of array subkey until other subkey contains "xx"

I'm trying to find a way to extract an average of a subkey of several arrays (up to 80) UNTIL another subkey has a certain value.
The full code contains the following:
$element = $html->find('table',3);
$i = 0;
foreach($element->find('tr') as $row){
if($i >= 2){
$racelapno = $row->find('td',0)->plaintext;
$racelaptime = $row->find('td',1)->plaintext;
$raceposition = $row->find('td',2)->plaintext;
$racetyre = $row->find('td',3)->plaintext;
$raceweather = $row->find('td',4)->plaintext;
$racetemp = $row->find('td',5)->plaintext;
$racehum = $row->find('td',6)->plaintext;
$raceevent = $row->find('td',7)->plaintext;
$racelap[$i] = Array();
$racelap[$i][0] = $racelapno;
$racelap[$i][1] = $racelaptime;
$racelap[$i][2] = $raceposition;
$racelap[$i][3] = $racetyre;
$racelap[$i][4] = $raceweather;
$racelap[$i][5] = $racetemp;
$racelap[$i][6] = $racehum;
$racelap[$i][7] = $raceevent;
}
$i+=1;
}
So I want to find the average of all $racetemp in the different arrays until an array returns "pit" on $raceevent.
Browsing on here I have found a way to find the average of all arrays which looks as followed:
$counter = 0;
$total = 0;
foreach($racelap as $row) {
$counter++;
$total += $row['5'];
}
$avgracetemp = $total / $counter;
But now I need to add some sort of stop when $racelap[$i][7] contains "pit", but also continue again until it contains "pit" again.
Hope anyone can help me, it is appreciated :)
If I understand you correctly, in foreach you can just use something like:
if (strpos($row['7'], 'pit') !== false) {
$counter++;
$total += $row['5'];
}

Calculate from an array the number that is equal or higher and closest to a given number

I need to calculate from a given array the number that is equal or higher and closest to a given number in PHP. Example:
Number to fetch:
6.85505196
Array to calculate:
3.11350000
4.38350000
4.04610000
3.99410000
2.86135817
0.50000000
Only correct combination should be:
3.99410000 + 2.86135817 = 6.85545817
Can somebody help me? It's been 3 hours I'm getting mad!
UPDATE: I finally finished my code as following:
$arr = array(3.1135, 4.3835, 4.0461, 3.9941, 2.86135817, 0.5);
$fetch = 6.85505196;
$bestsum = get_fee($arr, $fetch);
print($bestsum);
function get_fee($arr, $fetch) {
$bestsum = 999999999;
$combo = array();
$result = array();
for ($i = 0; $i<count($arr); $i++) {
combinations($arr, $i+1, $combo);
}
foreach ($combo as $idx => $arr) {
$sum = 0;
foreach ($arr as $value) {
$result[$idx] += $value;
}
if ($result[$idx] >= $fetch && $result[$idx] < $bestsum) $bestsum = $result[$idx];
}
return $bestsum;
}
function combinations($arr, $level, &$combo, $curr = array()) {
for($j = 0; $j < count($arr); $j++) {
$new = array_merge($curr, array($arr[$j]));
if($level == 1) {
sort($new);
if (!in_array($new, $combo)) {
$combo[] = $new;
}
} else {
combinations($arr, $level - 1, $combo, $new);
}
}
}
I hope the following example might help you. Please try this
<?php
$array = array(
"3.11350000",
"4.38350000",
"4.04610000",
"3.99410000",
"2.86135817",
"0.50000000"
);
echo "<pre>";
print_r($array);// it will print your array
for($i=0; $i<count($array); $i++)
{
$j=$i+1;
for($j;$j<count($array); $j++)
{
$sum = $array[$i] + $array[$j];
// echo $array[$i]. " + ".$array[$j]." = ".$sum."<br>"; //this will display all the combination of sum
if($sum >= 6.85505196 && ($sum <= round(6.85505196)) )//change the condition according to your requirement
{
echo "The correct combinations are:<br/><br/>";
echo "<b>". $array[$i]. " + ".$array[$j]." = ".$sum."<b>";
echo "<br/>";
}
}
echo "<br/>";
}
?>
We will get the result as below
Array
(
[0] => 3.11350000
[1] => 4.38350000
[2] => 4.04610000
[3] => 3.99410000
[4] => 2.86135817
[5] => 0.50000000
)
The correct combinations are:
4.04610000 + 2.86135817 = 6.90745817
3.99410000 + 2.86135817 = 6.85545817
You should do it in two steps:
a. Work out (or look up) an algorithm to do the job.
b. Implement it.
You don't say what you've managed in the three hours you worked on this, so here's a "brute force" (read: dumb) algorithm that will do the job:
Use a variable that will keep your best sum so far. It can start out as zero:
$bestsum = 0;
Try all single numbers, then all sums of two numbers, then all sums of three numbers, etc.: Every time you find a number that meets your criteria and is better than the current $bestsum, set $bestsum to it. Also set a second variable, $summands, to an array of the numbers you used to get this result. (Otherwise you won't know how you got the solution). Whenever you find an even better solution, update both variables.
When you've tried every number combination, your two variables contain the best solution. Print them out.
That's all. It's guaranteed to work correctly, since it tries all possibilities. There are all sorts of details to fill in, but you can get to work and ask here for help with specific tasks if you get stuck.
Thank you all for your help!
My code is working pretty cool when is needed to fetch one or two numbers (addition) only. But can't figure out how to add more combinations up to the total count of elements in my given array.
I mean if there are, let's say, 8 numbers in my array I want to try all possible combinations (additions to each other) as well.
My actual code is:
$bestsum = 1000000;
for ($i = 0; $i < count($txinfo["vout"]); $i++) {
if ($txinfo["vout"][$i]["value"] >= $spent && $txinfo["vout"][$i]["value"] < $bestsum) {
$bestsum = $txinfo["vout"][$i]["value"];
}
}
for($i = 0; $i < count($txinfo["vout"]); $i++) {
$j = $i + 1;
for($j; $j < count($txinfo["vout"]); $j++) {
$sum = $txinfo["vout"][$i]["value"] + $txinfo["vout"][$j]["value"];
if($sum >= $spent && $sum < $bestsum) {
$bestsum = $sum;
}
}
}
$fee = bcsub($bestsum, $spent, 8);
print("Fee: ".$fee);
New updated code.
<?php
$x = 6.85505196;
$num = array(3.1135, 4.3835, 4.0461, 3.9941, 2.86135817, 0.5);
asort($num); //sort the array
$low = $num[0]; // lowest value in the array
$maxpossible = $x+$low; // this is the maximum possible answer, as we require the number that is equal or higher and closest to a given number
$num = array_values($num);
$iterations = $x/$num[0]; // possible combinations loop, to equate to the sum of the given number using the lowest number
$sum=$num;
$newsum = $sum;
$k=count($num);
for($j=0; $j<=$iterations; $j++){
$l = count($sum);
for($i=0; $i<$l; $i++){
$genSum = $sum[$j]+$sum[$i];
if($genSum <= $maxpossible){
$newsum[$k] = $genSum;
$k++;
}
}
$newsum = array_unique($newsum);
$newsum = array_values($newsum);
$k = count($newsum);
$sum = $newsum;
}
asort($newsum);
$newsum = array_values($newsum);
for($i=0; $i<count($newsum); $i++){
if($x<=$newsum[$i]){
echo "\nMaximum Possible Number = ".$newsum[$i];
break;
}
}
?>

Get first value of array and store in new array php

I am trying to make card game.
I have 6 variable that are stored in array. Than I use fisherYates method to randomize array, and display four of them.
Problem is, when I randomize it this way only, it will give only random output of those six, with all different types.
So I want that some repeats like, if you draw four cards, you get output of
ex: club, club, diamond,heart, or heart, star,star,heart.. if you get a point..
I thought to do it like this way: put the array in loop of 4 times, and every time it loops, it stores first, or last value in new array, so that way, I can have greater chances of combination of same cards in output array.
But I'm stuck, and I don't know how to do it :/
this is what I've tried so far
$diamond = 'cube.jpg';
$heart = 'heart.jpg';
$spade = 'spade.jpg';
$club = 'tref.jpg';
$star='star.jpg';
$qmark='qmark.jpg';
$time=microtime(35);
$arr=[$diamond,$heart,$spade,$club,$star,$qmark];
function fisherYatesShuffle(&$items, $time)
{
for ($i = count($items) - 1; $i > 0; $i--)
{
$j = #mt_rand(0, $i);
$tmp = $items[$i];
$items[$i] = $items[$j];
$items[$j] = $tmp;
}
return $items;
}
$i=0;
do {
$niz[$i]=fisherYatesShuffle($arr,$time);
reset($niz);
$i++;
} while ($i <= 3);
Got a solution. Was just to simply do foreach of first element of multidimensional array :)
Code goes like this:
$diamond = 'cube.jpg';
$heart = 'heart.jpg';
$spade = 'spade.jpg';
$club = 'tref.jpg';
$star='star.jpg';
$qmark='qmark.jpg';
$time=microtime(35);
$arr=[$diamond,$heart,$spade,$club,$star,$qmark];
$niz=array();
$i=0;
do {
$niz[$i]=fisherYatesShuffle($arr,$time);
//reset($niz);
$i++;
} while ($i <= 3);
foreach ($niz as $key ) {
$randomArr[]=$key[0]; ;
}
function fisherYatesShuffle(&$items, $time)
{
for ($i = count($items) - 1; $i > 0; $i--)
{
$j = #mt_rand(0, $i);
$tmp = $items[$i];
$items[$i] = $items[$j];
$items[$j] = $tmp;
}
return $items;
}
print_r($randomArr);

Correct way of php concatenation

Hey is this the correct way to do concatenation? it does not seem to want to work for me!.
$driver1points = 0;
$driver2points = 0;
$driver3points = 0;
$driver4points = 0;
for($i = 1; $i <= 4; $++){
if(${"driver".$i} == $driverrace["fastestlap"]) {
${"driver". $i ."points"} += $driver_points_system["fastestlap"];
$racepoints += $team_points_system["fastestlap"];
break;
}
}
I agree with what is said in the comments. An array is a much better way to handle this.
<?php
$driver1points = 0;
$driver2points = 0;
$driver3points = 0;
$driver4points = 0;
for($i = 1; $i <= 4; $++) {
$driver = "driver$i";
if($$driver == $driverrace["fastestlap"]) {
${$driver."points"} += $driver_points_system["fastestlap"];
$racepoints += $team_points_system["fastestlap"];
break;
}
}
Can be translated into:
<?php
$drivers['bill'] = 0;
$drivers['ted'] = 0;
$drivers['cheech'] = 0;
$drivers['chong'] = 0;
foreach ( $drivers as $driver => &$points ) {
if ( $driver == $race['fastestlap'] ) {
echo "$driver had the fastest lap!";
$points += $driver_points_system['fastestlap'];
$racepoints += $team_points_system['fastestlap'];
break;
}
}
You can obviously do this as a numerative array and replace all of the $drivers[$driverName] assignments to just $drivers[]. I used an associative array to demonstrate that arrays are not only more efficient for this application, they can also be much easier to work with.
I passed the value argument of the foreach by reference, the "&" prefix (similar to a pointer, variable stores the memory address as opposed to the value); this allows you to directly manipulate the value in your logic as opposed to being given a copy of the value and needing to reassign with something similar to a $drivers[$driver] = $points;

Categories