I am wondering if there is a rot5 function for PHP equalivant too
function rot5(str) {
var s = [];
for (i = 0; i < str.length; i ++)
{
idx = str.charCodeAt(i);
if ((idx >= 48) && (idx <= 57))
{
if (idx <= 52)
{
s[i] = String.fromCharCode(((idx + 5)));
}
else
{
s[i] = String.fromCharCode(((idx - 5)));
}
}
else
{
s[i] = String.fromCharCode(idx);
}
}
return s.join('');
}
In javascript? If not then how can I do fromCharCode and charCodeAt in PHP?
Here you got generic strrot with default to strrot5
<?php
function strrot($str, $n=5){
$replace = [];
for($i=0;$i<26;$i++){
$replace[chr(65+$i)] = chr(65+(($i+$n)%26));
$replace[chr(97+$i)] = chr(97+(($i+$n)%26));
}
return strtr($str, $replace);
}
You can use 'ord' for 'charCodeAt'.
ord($yourstring[$yourindex])
You can use 'chr' for 'fromCharCode'
chr($yourcharcode)
Related
I have a php function to detect multiple rar file completion. The problem i have is that when old style rar is used eg:
archive.rar
archive.r01
archive.r02
archive.r03
......
archive.r99
The limit is archive.r99 and then goes to:
archive.s01
archive.s02
archive.s03
I can't do anything about the source.. and I have no idea how to adjust this function.
I tried do a || in strpos:
if (strpos($b[0], '.r') > - 1 || strpos($b[0], '.s') > - 1 ) {
but that doesn't work. It doesn't detect the s01 and keeps saying incomplete archive/missing files s01, s02, s03 etc...
here is the function:
private function detectMissingFiles($array) {
$typ = 0;
$tid = $t["id"];
$breaked = false;
$arr = array();
foreach($array as $b) {
if (stripos($b[0], 'disc') > - 1) {
return false;
}
if (strpos($b[0], '/') > - 1) {
continue;
}
if ($typ == 0) {
if (strpos($b[0], '.part0') > - 1) {
$typ = 2;
}
else
if (strpos($b[0], '.r') > - 1) {
$typ = 1;
}
else {
continue;
}
}
if ($typ == 1) {
if (is_numeric($s = substr($b[0], -2))) {
$arr[] = array(
id => $s,
s => $b[1]
);
}
}
else
if ($typ == 2) {
if (is_numeric($s = substr($b[0], -6, 2)) && substr($b[0], -4) == '.rar') {
$arr[] = array(
id => $s,
s => $b[1]
);
}
}
}
asort($arr);
if ($typ == 1) $sista = - 1;
else
if ($typ == 2) $sista = 0;
$status = "";
$antal = count($arr) - 1;
if ($antal > 30) {
foreach($arr as $ar) {
if ($antal > $ar["id"]) {
if ($ar["s"] < 50000000) {
$status.= L::get("WRONG_RAR_FILE_SIZE", [$ar["id"]]);
}
}
if ($sista + 1 != $ar["id"]) {
$status.= L::get("MISSING_FILE", [$sista + 1]);
}
$sista = $ar["id"];
}
if (strlen($status) > 1 && strlen($status) < 200) return $status;
else return 0;
}
}
I am hoping someone can enlighten me here. Thank you in advance!
my best guess is that the "old style rar" name algorithm is as follows:
function rar_int_to_string(int $i):string{
$c="r";
while($i>99){
++$c;
$i-=99;
}
if($i<10){
$c=$c."0";
}
return $c.$i;
}
which produces
r01>r02>r03>r04>r05>r06>r07>r08>r09>r10>r11>r12>r13>r14>r15>r16>r17>r18>r19>r20>r21>r22>r23>r24>r25>r26>r27>r28>r29>r30>r31>r32>r33>r34>r35>r36>r37>r38>r39>r40>r41>r42>r43>r44>r45>r46>r47>r48>r49>r50>r51>r52>r53>r54>r55>r56>r57>r58>r59>r60>r61>r62>r63>r64>r65>r66>r67>r68>r69>r70>r71>r72>r73>r74>r75>r76>r77>r78>r79>r80>r81>r82>r83>r84>r85>r86>r87>r88>r89>r90>r91>r92>r93>r94>r95>r96>r97>r98>r99>s01>s02>s03>s04>s05>s06>s07>s08>s09>s10>s11>s12>s13>s14>s15>s16>s17>s18>s19>s20>s21>s22>s23>s24>s25>s26>s27>s28>s29>s30>s31>s32>s33>s34>s35>s36>s37>s38>s39>s40>s41>s42>s43>s44>s45>s46>s47>s48>s49>s50>s51>s52>s53>s54>s55>s56>s57>s58>s59>s60>s61>s62>s63>s64>s65>s66>s67>s68>s69>s70>s71>s72>s73>s74>s75>s76>s77>s78>s79>s80>s81>s82>s83>s84>s85>s86>s87>s88>s89>s90>s91>s92>s93>s94>s95>s96>s97>s98>s99>t01>t02>t03>t04>t05>t06>t07>t08>t09>t10>t11>t12>t13>t14>t15>t16>t17>t18>t19>t20>t21>t22>t23>t24>t25>t26>t27>t28>t29>t30>t31>t32>t33>t34>t35>t36>t37>t38>t39>t40>t41>t42>t43>t44>t45>t46>t47>t48>t49>t50>t51>t52>t53>t54>t55>t56>t57>t58>t59>t60>t61>t62>t63>t64>t65>t66>t67>t68>t69>t70>t71>t72>t73>t74>t75>t76>t77>t78>t79>t80>t81>t82>t83>t84>t85>t86>t87>t88>t89>t90>t91>t92>t93>t94>t95>t96>t97>t98>t99>u01>u02>u03>u04>u05>u06>u07>u08>u09>u10>u11>u12>u13>u14>u15>u16>u17>u18>u19>u20>u21>u22>u23>u24>u25>u26>u27>u28>u29>u30>u31>u32>u33>u34>u35>u36>u37>u38>u39>u40>u41>u42>u43>u44>u45>u46>u47>u48>u49>u50>u51>u52>u53>u54>u55>u56>u57>u58>u59>u60>u61>u62>u63>u64>u65>u66>u67>u68>u69>u70>u71>u72>u73>u74>u75>u76>u77>u78>u79>u80>u81>u82>u83>u84>u85>u86>u87>u88>u89>u90>u91>u92>u93>u94>u95>u96>u97>u98>u99>v01>v02>v03>v04>v05>v06>v07>v08>v09>v10>v11>v12>v13>v14>v15>v16>v17>v18>v19>v20>v21>v22>v23>v24>v25>v26>v27>v28>v29>v30>v31>v32>v33>v34>v35>v36>v37>v38>v39>v40>v41>v42>v43>v44>v45>v46>v47>v48>v49>v50>v51>v52>v53>v54>v55>v56>v57>v58>v59>v60>v61>v62>v63>v64>v65>v66>v67>v68>v69>v70>v71>v72>v73>v74>v75>v76>v77>v78>v79>v80>v81>v82>v83>v84>v85>v86>v87>v88>v89>v90>v91>v92>v93>v94>v95>v96>v97>v98>v99>w01>w02>w03>w04>w05>w06>w07>w08>w09>w10>w11>w12>w13>w14>w15>w16>w17>w18>w19>w20>w21>w22>w23>w24>w25>w26>w27>w28>w29>w30>w31>w32>w33>w34>w35>w36>w37>w38>w39>w40>w41>w42>w43>w44>w45>w46>w47>w48>w49>w50>w51>w52>w53>w54>w55>w56>w57>w58>w59>w60>w61>w62>w63>w64>w65>w66>w67>w68>w69>w70>w71>w72>w73>w74>w75>w76>w77>w78>w79>w80>w81>w82>w83>w84>w85>w86>w87>w88>w89>w90>w91>w92>w93>w94>w95>w96>w97>w98>w99>x01>x02>x03>x04>x05>x06>x07>x08>x09>x10>x11>x12>x13>x14>x15>x16>x17>x18>x19>x20>x21>x22>x23>x24>x25>x26>x27>x28>x29>x30>x31>x32>x33>x34>x35>x36>x37>x38>x39>x40>x41>x42>x43>x44>x45>x46>x47>x48>x49>x50>x51>x52>x53>x54>x55>x56>x57>x58>x59>x60>x61>x62>x63>x64>x65>x66>x67>x68>x69>x70>x71>x72>x73>x74>x75>x76>x77>x78>x79>x80>x81>x82>x83>x84>x85>x86>x87>x88>x89>x90>x91>x92>x93>x94>x95>x96>x97>x98>x99>y01>y02>y03>y04>y05>y06>y07>y08>y09>y10>y11>y12>y13>y14>y15>y16>y17>y18>y19>y20>y21>y22>y23>y24>y25>y26>y27>y28>y29>y30>y31>y32>y33>y34>y35>y36>y37>y38>y39>y40>y41>y42>y43>y44>y45>y46>y47>y48>y49>y50>y51>y52>y53>y54>y55>y56>y57>y58>y59>y60>y61>y62>y63>y64>y65>y66>y67>y68>y69>y70>y71>y72>y73>y74>y75>y76>y77>y78>y79>y80>y81>y82>y83>y84>y85>y86>y87>y88>y89>y90>y91>y92>y93>y94>y95>y96>y97>y98>y99>z01>z02>z03>z04>z05>z06>z07>z08>z09>z10>z11>z12>z13>z14>z15>z16>z17>z18>z19>z20>z21>z22>z23>z24>z25>z26>z27>z28>z29>z30>z31>z32>z33>z34>z35>z36>z37>z38>z39>z40>z41>z42>z43>z44>z45>z46>z47>z48>z49>z50>z51>z52>z53>z54>z55>z56>z57>z58>z59>z60>z61>z62>z63>z64>z65>z66>z67>z68>z69>z70>z71>z72>z73>z74>z75>z76>z77>z78>z79>z80>z81>z82>z83>z84>z85>z86>z87>z88>z89>z90>z91>z92>z93>z94>z95>z96>z97>z98>z99>aa01>aa02>aa03>aa04>aa05>aa06>aa07>aa08>aa09>aa10>aa11>aa12>aa13>aa14>aa15>aa16>aa17>aa18>aa19>aa20>aa21>aa22>aa23>aa24>aa25>aa26>aa27>aa28>aa29>aa30>aa31>aa32>aa33>aa34>aa35>aa36>aa37>aa38>aa39>aa40>aa41>aa42>aa43>aa44>aa45>aa46>aa47>aa48>aa49>aa50>aa51>aa52>aa53>aa54>aa55>aa56>aa57>aa58>aa59>aa60>aa61>aa62>aa63>aa64>aa65>aa66>aa67>aa68>aa69>aa70>aa71>aa72>aa73>aa74>aa75>aa76>aa77>aa78>aa79>aa80>aa81>aa82>aa83>aa84>aa85>aa86>aa87>aa88>aa89>aa90>aa91>aa92>aa93>aa94>aa95>aa96>aa97>aa98>aa99>ab01>ab02>ab03>ab04>ab05>ab06>ab07>ab08->ab09
and so on, with "ab09" meaning "file chunk #999"
I want to make an auto-increment alphanumeric and this is just for output
if i press a button , there is an output AA001 and then i press a button again there is an output AA002
This doesn't use any 'clever' tricks but is shorter and easier to understand and tweak. It also uses numbers so it doesn't grow the length of the string as quickly. It increments from 0-9 then a-z, but it is intended that you should feed in 'a' to start with. Output always starts with an alphabet character, as long as your input also starts with an alphabet character, so it can be used as PHP variable names
var nextVarName = function(str) {
// Position of char to change.
var change = str.length - 1;
// The value of that char.
var change_char = str[change];
// Number of zeros to append when flipping.
var zeros = 0;
// Iterate backwards while there's a z (flipping).
while (change_char == 'z') {
// Increase the length of appended zeros
zeros++;
// Move the char to change back.
change_char = str[--change];
}
if (change_char == undefined) {
// Full flip - string increases in length.
str = 'a' + Array(str.length + 1).join("0");
} else {
// Normal increment with partial flip and 9->a handling.
str = str.substr(0, change)
+ (change_char == '9' ? 'a' : String.fromCharCode(str.charCodeAt(change) + 1))
+ Array(zeros + 1).join('0');
}
return str;
};
var vname = 'a';
for (var i = 0; i < 5; i++) {
vname = nextVarName(vname);
console.log(vname);
}
The results will be as follows:
z ---> a0
9z ---> a0 (unexpected input)
ab1zde ---> ab1zdf
abcdzz ---> abce00
zzzzz ---> a00000
abcyzz ---> abcz00
9000 ---> 9001 (unexpected input)
https://jsfiddle.net/e20kfvky/
The schedule of how many variables (that start with an alphabet char) are created of each length is as follows:
1: 26, 2: 936, 3: 33696, 4: 1213056 ... n: 36 ^ n - 10 * 36 ^ (n - 1)
The following code will generate a token that you can advance by one. It uses some small classes to make it modular. The function you attach to the button will call the function next on the token as shown in the very bottom.
//Element in a big token
function Increment(startval, endval) {
this.start = startval.charCodeAt(0);
this.cur = this.start;
this.end = endval.charCodeAt(0);
//Returns the current value
this.get = function() {
if (this.cur <= this.end) {
return String.fromCharCode(this.cur);
} else {
return null;
}
}
//Advances the value we will show
this.next = function() {
this.cur += 1;
return this.get();
}
//Reset it to the beginning
this.reset = function() {
this.cur = this.start;
}
}
function Token() {
this.token = [
new Increment("A", "Z"),
new Increment("A", "Z"),
new Increment("0", "9"),
new Increment("0", "9"),
new Increment("0", "9")
];
this.get = function() {
return this.token.map(function(cur) {
return cur.get();
}).join("");
}
this.next = function() {
//From the back to the front
for (var i = this.token.length - 1; i >= 0; i--) {
if (this.token[i].next() == null) {
//If we exhausted all possible values, continue
this.token[i].reset();
} else {
//Until we advance one that has still values left
break;
}
}
return this.get();
}
}
//Now we are just showing off...
var a = new Token();
for (var i = 0; i < 15; i++) {
console.log(a.next());
}
const getNextAlphaString = function (str) {
"use strict";
str=str.toUpperCase();
let chars;
chars = str.split("");
const strLen = str.length;
let continueIncermenting = true;
for (let i = strLen - 1; i >= 0; i = i - 1) {
let asciiVal;
asciiVal = chars[i].charCodeAt(0);
if (isNaN(asciiVal)) {
return str;
}
if (continueIncermenting === true) {
if (asciiVal >= 48 && asciiVal < 57) {
chars[i] = String.fromCharCode(asciiVal + 1);
continueIncermenting = false;
break;
} else if (asciiVal == 57) {
chars[i] = '0';
continueIncermenting = true;
}
if (asciiVal >= 65 && asciiVal < 90) {
chars[i] = String.fromCharCode(asciiVal + 1);
continueIncermenting = false;
break;
} else if (asciiVal == 90) {
chars[i] = String.fromCharCode(65);
continueIncermenting = true;
}
} else {
if (asciiVal == 90) {
continueIncermenting = true;
chars[i] = String.fromCharCode(65);
}
if (asciiVal == 57) {
continueIncermenting = true;
chars[i] = '0';
}
}
}
if (continueIncermenting === true) {
let firstAcii = chars[0].charCodeAt(0);
if (isNaN(firstAcii)) {
return str;
}
if ((firstAcii >= 65 && firstAcii <= 90) || (firstAcii >= 97 && firstAcii <= 122)) {
return 'A' + chars.join('').toUpperCase();
}
if (firstAcii >= 48 && firstAcii <= 57) {
return '0' + chars.join('').toUpperCase();
}
}
return chars.join('').toUpperCase();
};
The results will be as follows:
ab1zde ---> AB1ZDF
abcdzz ---> ABCEAA
zzzzz ---> AAAAAA
abcyzz ---> ABCZAA
9000 ---> 9001
I have this PHP code which is supposed to increase a URL shortener mask on each new entry.
My problem is that it dosen't append a new char when it hits the last one (z).
(I know incrementing is a safety issue since you can guess earlier entries, but this is not a problem in this instance)
If i add 00, it can figure out 01 and so on... but is there a simple fix to why it won't do it on its own?
(The param is the last entry)
<?php
class shortener
{
public function ShortURL($str = null)
{
if (!is_null($str))
{
for($i = (strlen($str) - 1);$i >= 0;$i--)
{
if($str[$i] != 'Z')
{
$str[$i] = $this->_increase($str[$i]);
#var_dump($str[$i]);
break;
}
else
{
$str[$i] = '0';
if($i == 0)
{
$str = '0'.$str;
}
}
}
return $str;
}
else {
return '0';
}
}
private function _increase($letter)
{
//Lowercase: 97 - 122
//Uppercase: 65 - 90
// 0 - 9 : 48 - 57
$ord = ord($letter);
if($ord == 122)
{
$ord = 65;
}
elseif ($ord == 57)
{
$ord = 97;
}
else
{
$ord++;
}
return chr($ord);
}
}
?>
Effectively, all you are doing is encoding a number into Base62. So if we take the string, decode it into base 10, increment it, and reencode it into Base62, it will be much easier to know what we are doing, and the length of the string will take care of itself.
class shortener
{
public function ShortURL($str = null)
{
if ($str==null) return 0;
$int_val = $this->toBase10($str);
$int_val++;
return $this->toBase62($int_val);
}
public function toBase62($num, $b=62) {
$base='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$r = $num % $b ;
$res = $base[$r];
$q = floor($num/$b);
while ($q) {
$r = $q % $b;
$q =floor($q/$b);
$res = $base[$r].$res;
}
return $res;
}
function toBase10( $num, $b=62) {
$base='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$limit = strlen($num);
$res=strpos($base,$num[0]);
for($i=1;$i<$limit;$i++) {
$res = $b * $res + strpos($base,$num[$i]);
}
return $res;
}
}
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am working on a personal project, a bot that plays connect 4. So something is seriously wrong with the recursive function I have written to manage the bots move. No errors are thrown, and any debug info I can be shown does not tell me anything useful. Additionally, I am sure that I have not overflown my stack and that my php.ini file is good to go. This script just runs (consumes a sane amount of memory) and never returns. Only about 2400 function calls should be happening, so this script should return after only a second or two. This has stumped me for days. I believe there is something I have not properly researched. Additonally I should mention that the game board is a simple 2D array to simulate a 7 x 7 board. ai_move_helper is the recursive function and I just cannot figure out why it will not function correctly.
// this class is a code igniter library
class ConnectFour
{
public function __construct()
{
// these are expensive opperations this will give the server enough time
set_time_limit(0);
ini_set('memory_limit', '2048M');
}
public $board_width = 7;
public $board_length = 7;
public $game_array = array();
public $depth_limit = 3;
// this function gets a human made move from a CI controller ($game board)
// and returns the board after the new AI move is applied
public function ai_player_move($game_array, $active_players_move)
{
$this->game_array = $game_array;
$this->game_array = $this->calculate_ai_move($active_players_move);
return $this->game_array;
}
public function calculate_ai_move($active_players_move)
{
$move_weight_array = array();
$prime_game_board = array();
// we hardcast the active player because at this point we know it is the AI
// here we also have to prime the move computer
for($q = 0; $q < $this->board_length; $q++)
{
// MAGIC NUMBERS are the active players!!!
$prime_game_board[] = $this->apply_prime_move($q, 2, $this->game_array);
$move_weight_array[] = $this->ai_move_helper($prime_game_board[$q], 2, 0);
}
//choose your move
for($u = 0; $u < $this->board_length; $u)
{
if($move_weight_array[$u][0] == 1)
{
return $prime_game_board[$u];
}
}
// otherwise return a random acceptable move
$random = rand(0, 6);
return $prime_game_board[$random];
}
public function ai_move_helper($game_board, $active_player, $depth)
{
// build the object that will be needed at this level of recusion
$depth = $depth + 1;
$score_object = new stdClass;
$move_array = array();
$game_boards_generated_at_this_level = array();
$new_game_boards_generated_at_this_level = array();
$return_end_state_detected = 0;
$score_agregate = array();
if($this->depth_limit < $depth)
{
$score_agregate[0] = 0;
$score_agregate[1] = 0;
return $score_agregate;
}
$active_player = ($active_player == 1) ? 2 : 1;
// check for possible moves
for($i=0; $i < $this->board_width; $i++)
{
// calculate all of the possible recusions (all of the next moves)
$game_boards_generated_at_this_level[$i] = $this->apply_ai_move($i, $active_player, $game_board);
// this is the recusive level
$score_agregate = $this->ai_move_helper($game_boards_generated_at_this_level[$i]->game_board, $active_player, $depth);
}
// check to see if there are more moves of if it is time to return
foreach($game_boards_generated_at_this_level as $game_state)
{
//compute the agragate of the scores only for player two (AI)
if($active_player == 2)
{
$score_agregate[0] = $score_agregate[0] + $game_state->score_array[0];
$score_agregate[1] = $score_agregate[1] + $game_state->score_array[1];
}
}
return $score_agregate;
}
public function apply_ai_move($move, $active_players_move, $board_to_use)
{
$board_for_function = array();
$location_of_new_pieces = 0;
$return_object = new stdClass;
// this makes sure that this function is being called with the right board
if(!empty($board_to_use))
{
$board_for_function = $board_to_use;
} else {
$board_for_function = $this->game_array;
}
// check that this move is possible
if(!$this->move_possible($move, $board_for_function))
{
$return_object->game_board = NULL;
$return_object->score_array = NULL;
return $return_object;
}
// this part of the function applies a valid move
foreach($board_for_function[$move] as $column_key => $column_space)
{
// check if you are at the edge of an empty row
if(!array_key_exists(($location_of_new_pieces + 1), $board_for_function[$move]) && $column_space == '_')
{
$board_for_function[$move][$location_of_new_pieces] = ($active_players_move == 1) ? 'x' : 'o';
break;
}
// check if the next place has stuff in it too
if($column_space != '_')
{
// check the edge of the board to make sure that exists
if(array_key_exists(($location_of_new_pieces - 1), $board_for_function))
{
$board_for_function[$move][$location_of_new_pieces - 1] = ($active_players_move == 1) ? 'x' : 'o';
break;
} else {
echo "well fuck...1"; exit;
}
}
$location_of_new_pieces++;
}
$return_object->game_board = $board_for_function;
// now check if this state is a win loss or draw
$test_for_complete = $this->check_for_winner_or_draw($board_for_function, $active_players_move);
// this is a draw
if($test_for_complete == -1)
{
$return_object->score_array = array(0, 1);
} else if($test_for_complete > 3) {
$return_object->score_array = array(1, 0);
} else {
$return_object->score_array = array(0, 0);
}
return $return_object;
}
public function apply_prime_move($move, $active_players_move, $board_to_use)
{
$location_of_new_pieces = 0;
foreach($board_to_use[$move] as $column_key => $column_space)
{
// check if you are at the edge of an empty row
if(!array_key_exists(($location_of_new_pieces + 1), $board_to_use[$move]) && $column_space == '_')
{
$board_to_use[$move][$location_of_new_pieces] = ($active_players_move == 1) ? 'x' : 'o';
break;
}
// check if the next place has stuff in it too
if($column_space != '_')
{
// check the edge of the board to make sure that exists
if(array_key_exists(($location_of_new_pieces - 1), $board_to_use))
{
$board_to_use[$move][$location_of_new_pieces - 1] = ($active_players_move == 1) ? 'x' : 'o';
break;
} else {
echo "well fuck...1"; exit;
}
}
$location_of_new_pieces++;
}
return $board_to_use;
}
public function move_possible($move, $game_board)
{
// check that this move is not going to fall out of the board
if($game_board[$move][0] != "_")
{
return FALSE;
} else {
return TRUE;
}
}
public function check_for_winner_or_draw($game_array, $active_player_move)
{
$present_possible_winner = "";
$count_to_win = 0;
$game_not_a_draw = FALSE;
for($i = 0; $i < $this->board_length; $i++)
{
for($j = 0; $j < $this->board_width; $j++)
{
// start checking for a winner
if($game_array[$i][$j] != "_")
{
$present_possible_winner = $game_array[$i][$j];
// check for a winner horizontally
for($x = 0; $x < 4; $x++)
{
if($j+$x < $this->board_width)
{
if($game_array[$i][$j+$x] == $present_possible_winner)
{
$count_to_win = $count_to_win + 1;
}
}
}
if($count_to_win > 3)
{
return $present_possible_winner; // this player has won
} else {
$count_to_win = 0;
}
// check for a winner horizontally
for($y = 0; $y < 4; $y++)
{
if($i+$y < $this->board_width)
{
if($game_array[$i+$y][$j] == $present_possible_winner)
{
$count_to_win = $count_to_win + 1;
}
}
}
if($count_to_win > 3)
{
return $present_possible_winner; // this player has won
} else {
$count_to_win = 0;
}
// check for a winner up to down diagonal
for($z = 0; $z < 4; $z++)
{
if(($i+$z < $this->board_width) && ($j+$z < $this->board_length))
{
if($game_array[$i+$z][$j+$z] == $present_possible_winner)
{
$count_to_win = $count_to_win + 1;
}
}
}
if($count_to_win > 3)
{
return $present_possible_winner; // this player has won
} else {
$count_to_win = 0;
}
// check for a winner down to up diagonal
for($w = 0; $w < 4; $w++)
{
if(($i+$w < $this->board_width) && ($j-$w >= 0))
{
if($game_array[$i+$w][$j-$w] == $present_possible_winner)
{
$count_to_win = $count_to_win + 1;
}
}
}
if($count_to_win > 3)
{
return $present_possible_winner; // this player has won
} else {
$count_to_win = 0;
}
}
}
}
// check for a drawed game and return accordingly
for($i = 0; $i < $this->board_length; $i++)
{
for($j = 0; $j < $this->board_width; $j++)
{
if($game_array[$i][$j] == "_")
{
$game_not_a_draw = TRUE;
}
}
}
if(!$game_not_a_draw)
{
return -1;
}
return 0;
}
// this is a private debugging function that I wrote for this script
public function debug($value = NULL, $name = NULL, $exit = NULL)
{
if(!empty($name))
{
echo $name . "<br />";
}
echo "<pre>";
var_dump($value);
echo "</pre>";
if($exit)
{
exit;
}
}
}
Well I found it: The calculate ai move had an infinite loop in it...
//choose your move
for($u = 0; $u < $this->board_length; $u)
{
if($move_weight_array[$u][0] == 1)
{
return $prime_game_board[$u];
}
}
Should be
//choose your move
for($u = 0; $u < $this->board_length; $u++)
{
if($move_weight_array[$u][0] == 1)
{
return $prime_game_board[$u];
}
}
Back to work for me...
I have an actionscript class that serializes and unserializes data compatible with php's serialization functions. I expanded it to support binary data but now the unserialization does not seem to work.
For example, this data is not unserialized correctly:
a:2:{i:0;s:1:"õ";i:1;a:2:{i:0;s:32:"mÎiyl·T=doÁ°ýNd_¤ÁÝ`:AåÁˆ#";i:1;s:32:"ÿ^ò`d^|“T¶&JÐÞG[±iÏ*Ÿ!–Ü’IÍ";}}
Here is the class:
package pack
{
import flash.utils.ByteArray;
import flash.utils.Dictionary;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.core.*;
use namespace mx_internal;
public class Serializer extends Object
{
public static const version:String = "3.0.0";
mx_internal static var c:uint;
mx_internal static var pattern:RegExp = /[A-Z][a-z]{2}, \d{2} [A-Z][a-z]{2} \d{4} \d{2}:\d{2}:\d{2} \+|\-\d{4}/g
public static function serialize(data:*):ByteArray
{
var bas:ByteArray = new ByteArray();
var tmp:ByteArray = new ByteArray();
var i:int = 0;
var key:String;
if(data is Boolean){
bas.writeUTFBytes('b:');
bas.writeUnsignedInt(data);
bas.writeUTFBytes(';');
} else if(data is int){
bas.writeUTFBytes('i:');
bas.writeUTFBytes(data);
bas.writeUTFBytes(';');
} else if(data is Number){
bas.writeUTFBytes('d:');
bas.writeUTFBytes(data);
bas.writeUTFBytes(';');
} else if(data is ByteArray){
bas.writeUTFBytes('s:');
bas.writeUTFBytes(data.length.toString());
bas.writeUTFBytes(':"');
bas.writeBytes(data);
bas.writeUTFBytes('";');
} else if(data is String){
bas.writeUTFBytes('s:');
bas.writeUTFBytes(data.length.toString());
bas.writeUTFBytes(':"');
bas.writeUTFBytes(data);
bas.writeUTFBytes('";');
} else if(data is Date){
bas.writeUTFBytes('s:');
bas.writeUTFBytes(data.toString().length.toString());
bas.writeUTFBytes(':"');
bas.writeUTFBytes(data);
bas.writeUTFBytes('";');
} else if(data is ArrayCollection){
for(key in data){
tmp.writeBytes(Serializer.serialize(i));
tmp.writeBytes(Serializer.serialize(data[key]));
i += 1;
}
bas.writeUTFBytes('a:');
bas.writeUTFBytes(i.toString());
bas.writeUTFBytes(':{');
bas.writeBytes(tmp);
bas.writeUTFBytes('}');
} else if(data is Array){
for(key in data){
tmp.writeBytes(Serializer.serialize(i));
tmp.writeBytes(Serializer.serialize(data[key]));
i += 1;
}
bas.writeUTFBytes('a:');
bas.writeUTFBytes(i.toString());
bas.writeUTFBytes(':{');
bas.writeBytes(tmp);
bas.writeUTFBytes('}');
} else if(data is Object){
for(key in data){
tmp.writeBytes(Serializer.serialize(key));
tmp.writeBytes(Serializer.serialize(data[key]));
i += 1;
}
bas.writeUTFBytes('O:8:"stdClass":');
bas.writeUTFBytes(i.toString());
bas.writeUTFBytes(':{');
bas.writeBytes(tmp);
bas.writeUTFBytes('}');
} else if(data == null || data == undefined){
bas.writeUTFBytes('N;');
} else {
bas.writeUTFBytes('i:0;');
}
return bas;
}
public static function unserialize(data:ByteArray):*
{
Serializer.c = 0;
return Serializer.unserialize_internal(data);
}
mx_internal static function unserialize_internal(data:ByteArray):*
{
var result:*;
var tmpvar:*;
var tmp:Array = new Array();
var type:String = Serializer.charAt(data, Serializer.c);
var pos:uint = 0;
var islist:Boolean = true;
var i:uint;
switch(type){
case "N":
Serializer.c += 2;
break;
case "b":
result = Serializer.substr(data, Serializer.c+2, 1).toString() == '1'
//result = data.substr(Serializer.c+2, 1) == "1"
Serializer.c += 4
break;
case "i":
tmp.push(Serializer.indexOf(data, ';', Serializer.c));
//tmp.push(data.indexOf(";", Serializer.c))
pos = Serializer.c+2
Serializer.c = tmp[0]+1
result = int(Serializer.substring(data, pos, tmp[0]));
//result = int(data.substring(pos,tmp[0]))
break;
case "d":
tmp.push(Serializer.indexOf(data, ';', Serializer.c));
//tmp.push(data.indexOf(";", Serializer.c))
pos = Serializer.c + 2
Serializer.c = tmp[0]+1
result = Number(Serializer.substring(data, pos, tmp[0]));
//result = Number(data.substring(pos,tmp[0]))
break;
case "s":
tmp.push(int(Serializer.indexOf(data, ':', Serializer.c+2)));
//tmp.push(int(data.indexOf(":", Serializer.c+2)))
tmp.push(tmp[0]+2)
pos = Serializer.c+2
tmp.push(0)
tmp.push(int(Serializer.substring(data, pos, tmp[0])));
//tmp.push(int(data.substring(pos, tmp[0])));
if(tmp[3] == 0)
{
result = "";
Serializer.c = pos+5
} else {
var lenc:uint = Serializer.stringBCLenght(data, Serializer.c, tmp[3]);
if(lenc != tmp[3])
{
result = Serializer.substr(data, tmp[0]+2, lenc);
//result = data.substr(tmp[0]+2, lenc);
Serializer.c = tmp[0]+4+lenc;
} else {
result = Serializer.substr(data, tmp[0]+2, tmp[3]);
//result = data.substr(tmp[0]+2, tmp[3]);
Serializer.c = tmp[0]+4+tmp[3];
}
}
if(Serializer.pattern.test(result))
{
result = new Date(result)
}
break;
case "a":
//result:ByteArray;
pos = Serializer.c+2
tmp.push(int(Serializer.indexOf(data, ":", pos)))
tmp.push(int(Serializer.substring(data, pos, tmp[0])))
//tmp.push(int(data.indexOf(":", pos)))
//tmp.push(int(data.substring(pos, tmp[0])))
Serializer.c = tmp[0]+2
result = []
for(i = 0; i < tmp[1]; i++){
tmpvar = Serializer.unserialize_internal(data)
result[tmpvar] = Serializer.unserialize_internal(data)
if(!(tmpvar is int) || tmpvar < 0){
islist = false
}
}
if(islist){
tmp.push([])
for(var key:uint = 0; key < result.length; key++){
pos = tmp[2].length
while(key > pos){
tmp[2].push(null)
pos +=1
}
tmp[2].push(result[key])
}
result = tmp[2]
}
Serializer.c += 1
break;
case "O":
pos = Serializer.indexOf(data, "\"", Serializer.c)+1;
Serializer.c = Serializer.indexOf(data, "\"", pos);
tmp.push(Serializer.substring(data, pos, Serializer.c))
//pos = data.indexOf("\"", Serializer.c)+1;
//Serializer.c = data.indexOf("\"", pos);
//tmp.push(data.substring(pos, Serializer.c))
Serializer.c += 2
i = Serializer.c
Serializer.c = Serializer.indexOf(data, ":", i)
i = int(Serializer.substring(data, i, Serializer.c))
//Serializer.c = data.indexOf(":", i)
//i = int(data.substring(i, Serializer.c))
Serializer.c +=2;
result = {};
var tmps:*;
while(i > 0){
tmps = Serializer.unserialize_internal(data)
result[tmps] = Serializer.unserialize_internal(data)
i -= 1
}
break;
}
return result;
}
mx_internal static function stringCLenght(data:String, from:uint = 0, len:uint = 0):int
{
var i:uint;
var j:uint = len;
var startIndex:uint = from + 4 + len.toString().length;
for (i = 0; i < j; i++){
if (data.charCodeAt(i+startIndex) > 128)
{
j = j - 1
}
}
return j;
}
mx_internal static function stringBCLenght(data:ByteArray, from:uint = 0, len:uint = 0):int
{
var i:uint;
var j:uint = len;
var startIndex:uint = from + 4 + len.toString().length;
for (i = 0; i < j; i++){
if (Serializer.charCodeAt(data, i+startIndex) > 128)
{
j = j - 1
}
}
return j;
}
mx_internal static function stringLength(data:String):uint
{
var code:int = 0
var result:int = 0
var slen:int = data.length;
while(slen){
slen = slen - 1
try
{
code = data.charCodeAt(slen)
} catch(e:Error){
code = 65536
}
if(code < 128){
result = result + 1
} else if(code < 2048){
result = result + 2
} else if(code < 65536){
result = result + 3
} else {
result = result + 4
}
}
return result
}
public static function charAt(bytes:ByteArray, index:int):String {
if (bytes.length <= index) return null;
return String.fromCharCode(bytes[index]);
}
public static function charCodeAt(bytes:ByteArray, index:int):int {
if (bytes.length <= index) return -1;
return bytes[index];
}
public static function substr(bytes:ByteArray, start:int, length:int=0):ByteArray {
var res:ByteArray = new ByteArray();
bytes.position = start;
bytes.readBytes(res, 0, length);
return res;
}
public static function substring(bytes:ByteArray, start:int, end:int=0):ByteArray {
return substr(bytes, start, end-start);
}
public static function indexOf(bytes:ByteArray, str:String, startIndex:int):int {
var num:int = 0;
for (var i:int=0; i<bytes.length; i++) {
var strPos:int = 0;
while (bytes[i+strPos] == str.charCodeAt(strPos)) {
strPos++;
if (strPos == str.length) {
num++;
if(num == startIndex) {
return i;
}
}
}
}
return -1;
}
}
}
I resolved the issue, no need for answers.