Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > битовый массив


Автор: krinart 28.11.2008, 01:56
хочу сделать карточную онлайн игру, для чего нужно хранить в БД карты игроков. Вроде придумал неплохой способ - битовый массив, где каждой карте сообветствует свой бит, и если она у игрока есть, значит этот бит=1. Так как карт 36, соответственно нужно в БД хранить число <= (2^36-1). 

Но почемуто иногда выскакивают отрицательные числа в самом алгоритме, не пойму почему
приведу код

Код

// список розданных карт      -    пустой
$card= array();
        
        // обнулим массив карт пользователей
        $users= array("1" => "0", "2" => "0", "3" => "0", "4" => "0", "5"=>"0");
        
        srand();
        
        // проход по количеству карт
        for($i= 0; $i<$NCards; $i++)
        {
            // проход по количеству игроков
            for($j= 1; $j<=4; $j++)
            {
                $f= 1;
                while($f)
                {
                    // выберем наугад одну карту
                    $c= rand(0, 35);                    
                    
                    // если её ещё ниукого нету
                    if(! in_array($c, $card))
                    {
                        $f= 0;
                    }
                }
                // добавим её в список отданых
                $card[]= $c;
                
                // отдадим её одному из игроков
                $users[$j] |= (1<<$c);
            }
        }    
        
        // запомним козырь  -   последняя отданная карта
        $users[5] = (1<<$c);


подскажите, в чём проблема

Автор: ZlojEzh 28.11.2008, 02:03
http://ua.php.net/int
Код

The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed). PHP does not support unsigned integers. Integer size can be determined using the constant PHP_INT_SIZE, and maximum value using the constant PHP_INT_MAX since PHP 4.4.0 and PHP 5.0.5.

какие у Вас значения PHP_INT_SIZE и PHP_INT_MAX?

Добавлено через 1 минуту и 24 секунды
да, похоже, и при стандратных 32 bits signed, крайний бит будет управлять знаком

Автор: krinart 28.11.2008, 02:09
ZlojEzh, а где это посмотреть? ни в php.ini ни в phpinfo() ничего такого нет

Автор: ZlojEzh 28.11.2008, 02:13
это константы
просто print PHP_INT_SIZE

Автор: krinart 28.11.2008, 02:24
PHP_INT_SIZE =4
PHP_INT_MAX= 2147483647 

я начинаю догадываться... а как их корректно изменить, чтобы всё заработало?
мне нужно 36 бит

Автор: ZlojEzh 28.11.2008, 03:05
сомневаюсь, что это меняется

да и вообще, битовый массив в php - это как-то странно
заведите массив boolean'ов
потери в производительности даже замерить будет сложно )

Автор: krinart 28.11.2008, 04:09
ZlojEzh, а как это вобще сделать? подскажите где можна почитать про массив boolean

Автор: solenko 28.11.2008, 08:30
krinart, если все таки хочется хранить массив битов, то можно просто разбить карты на два числа -- красное/черное. 18 бит поместятся на любой системе.

Вопрос -- а зачем вам вообще хранить карты в базе? Пользователи могут разлогинится, потом вернутся и продолжить игру?

Автор: krinart 29.11.2008, 00:30
solenko, дело в том что игра будет не с компьютером, а с другими игроками и сделана при помощи AJAX'a. Вот и придётся всю информацию хранить в базе для обмена с другими игроками. А за совет - спасибо, наверно придётся так и сделать

Автор: krinart 29.11.2008, 04:33
неужели никак невозможно сделать одним массивом? очень уж некрасиво получается дальше, когда для описания хода, то есть одной карты, нужно добавлять ещё один бит, чтобы хранить к какому цвету относится карта... и такая же ситуация возникает при сохранении козыря... вобщем несколько некрасивый способ, хотелось бы чтото более элегантное   smile 

Автор: solenko 29.11.2008, 08:27
krinart, вы не ответили на мой вопрос. Игда между жувумя игроками != игру можно продолжить по прошествии дня/недели/окончанию_сессии.
Это я к тому что зачем писать в базу? SESSION будет гораздо убоднее. Кроме того, зачем именно битовая карта? Чеи обусловлена такая экономия места в базе и нужно ли это. Искать по текущему раскладу вы явно не будете, так почему не хранить все тот же сериализованный массив?

Автор: krinart 29.11.2008, 13:37
использование битовой карты обусловлено её удобством. Для сравнения карт, не нужно знать достоинства карт, с помощью сдвигов можно узнать масть и просто сравнить как числа. 

А насчёт SESSION.. ведь всё равно придётся один раз записать в базу, при раздаче. Чтобы потом все смогли "забрать" свои карты, после чего уже можно и в сессии хранить. Да и ходы тоже придётся писать в базу, чтобы к этой информации имели доступ несколько пользователей. Или я неправильно понял саму идею?

Автор: ksnk 29.11.2008, 13:47
solenko, сессия вряд-ли будет удобнее. В конце концов игру можно отложить на пол-часа.  Просто не ходить. За это время сессия сдохнет, а запись в базе - не обязательно smile К тому-же сессия предназначена для идентификации одного игрока. Разделение сессии между 2-мя игроками представляется идеологически неверным решением ...

Добавлено через 1 минуту и 36 секунд
krinart, удобство битовой карты для php, imho, несколько преувеличено. 
Можно еще, к примеру, заюзать строку из 36 символов...

Автор: krinart 29.11.2008, 14:00
ksnk, а как же быть со сдвигами? или php настолько всеяден что даже такое сможет?  smile 

Автор: ksnk 29.11.2008, 14:19
krinart, а зачем вообще используются сдвиги? Чтобы узнать масть? Как, можно поинтересоваться?

Можно составить список задач программы-дилера и подобрать подходящий способ хранения данных.

- новая игра
-- раздать карты
- продолжение игры
-- проверка корректности хода игрока
--- карта, которой сделан ход у противника есть
--- ход не противоречит правилам игры
-- вывод резльтатов хода
- окончание игры
-- поздравление победителя



Автор: krinart 29.11.2008, 14:32
ksnk, насчёт программы-дилера это и так понятно, над ним сейчас и работаю. А вот по поводу способа хранения данных... 

Масть можно узнать заданной карты сравнивая с маской 255 (8 единиц) и сдвигая вправо, например так

Код

$mask= 255; 
$m= 0; // масть

while(!($card & $mask))
{
    $card = $card >> 8;
    $m++;
}


В данном случае в $card хранится 1 карта, то есть в дсс только одна единица. И как только эта единица появится в первых восьми разрядах, значит можно определить масть.

Таким образом в конце цикла будет известна масть в $m а в $card будет храниться достоинство карты.

Это всё удобно, единственный вопрос, можно ли заставить php хранить такое число, ведь $card должно иметь как минимум 36 битов, а лучше и 37 - для джокера, но это уже другая история...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)