Кресты / Говнокод #27474 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
Game::Game()
{
    run = true;//флаг признак нажатия кнопки выхода F5
    Matrix = new int* [8];//Поле 64 ячейки - значения 0 - для пустой ячейки, для игрока каждая пешка-шашка от 1 до 9, для компьютера значения в матрице от 10 до 18
    for (int i = 0; i < 8; i++)
        Matrix[i] = new int[8];
    //Квадраты координат нужны чтобы программа знала какие ячейки над указателем мыши, 64 квадрата
    QuadCoorXleft = new int* [8];//каждой ячейки матрицы Matrix соответстует квадрат координат для мыши xleft означает левую координату x
    QuadCoorXright = new int* [8];//xright - правая x
    QuadCoorYdown = new int* [8];//верхняя y координата
    QuadCoorYup = new int* [8];//нижняя y координата
    for (int i = 0; i < 8; i++)
    {
        QuadCoorXleft[i] = new int[8];
        QuadCoorXright[i] = new int[8];
        QuadCoorYdown[i] = new int[8];
        QuadCoorYup[i] = new int[8];
    }
    //Координаты пешек для отрисовки
    ChessX = new double[18];//X
    ChessY = new double[18];//Y
    //Выделяемая пешка ее координаты и значения
    ActiveX = -1;//X
    ActiveY = -1;//Y
    Active = -1;//Value
    firstplayer = true;//флаг того что можете игрок 1й ходить
    secondplayer = false;//флаг того что можете игрок 2й ходить
    ai = new bool[18];//ячейки флаги того что пешка на финишной позиции
    chessai tmp;
    for (int i = 0; i < 18; i++)
    {
        ai[i] = false;
        if (i > 8)
        {
            tmp.ai = ai[i];
            tmp.value = i+1;
            Ai.push_back(tmp);//Вектор с флагами финиша каждой пешки для искуственного интеллекта
        }
    }
    aicountfirstrow = 0;//счетчик кол-ва пешек ИИ(искуственного интеллекта) на верхней строчке(0-я)
    aicountsecondrow = 0;//счетчик кол-ва пешек ИИ на предверхней строчке(1-я)
    aicountthirdrow = 0;//счетчик кол-ва пешек ИИ на предпредверхней строчке(2-я)
}

https://github.com/Beginerok/DominiGames/blob/master/Domini/Chess/Chess/Game.cpp

https://habr.com/ru/post/563398/
Странные шахматы как тестовое задание

Запостил: PolinaAksenova PolinaAksenova, (Updated )

Комментарии (175) RSS

  • > Где-то более года назад мне пришлось делать одно тестовое задание чтобы устроится на работу. Выполнил я его в срок, но конкуренция была большая и скорее всего взяли человека который сделал его с помощью рекомендованных технологий и красочнее.
    (╥﹏╥)
    Ответить
    • void Game::Move_Up()
      {
      	//Ход игрока вверх
      	if (Active > 0 && ActiveX != 0 && Matrix[ActiveX-1][ActiveY] == 0)//Если выделенная пешка и не самая верхняя строчка и ячейка выше пустая
      	{
      		Matrix[ActiveX-1][ActiveY] = Matrix[ActiveX][ActiveY] ;//присваиваем ячейке выше текущюю(выделенную пешку)
      		Matrix[ActiveX][ActiveY] = 0;//затираем старую ячейку на пустую 
      		ChessY[Active-1] += 0.2;//перемещаем координату У пешки вверх для отрисовки
      		ActiveX = -1;//стираем координаты выделенной пешки
      		ActiveY = -1;//стираем координаты выделенной пешки
      		Active = -1;//делаем неактивной текущую выделенную фигуру
      		std::cout << " Player MoveUp " << Active << std::endl;
      		firstplayer = false;
      		secondplayer = true;//меняем флаги хода от игрока к ИИ
      	}
      }
      void Game::Move_Down()
      {
      	//Ход игрока вниз
      	if (Active > 0 && ActiveX != 7 && Matrix[ActiveX+1][ActiveY] == 0)//Если выделенная пешка и не самая нижняя строчка и ячейка ниже пустая
      	{
      		Matrix[ActiveX+1][ActiveY] = Matrix[ActiveX][ActiveY] ;//присваиваем ячейке ниже текущюю(выделенную пешку)
      		Matrix[ActiveX][ActiveY] = 0;//затираем старую ячейку на пустую 
      		ChessY[Active-1] -= 0.2;//перемещаем координату У пешки вниз для отрисовки
      		ActiveX = -1;//стираем координаты выделенной пешки
      		ActiveY = -1;//стираем координаты выделенной пешки
      		Active = -1;//делаем неактивной текущую выделенную фигуру
      		std::cout << "Player MoveDown " << Active << std::endl;
      		firstplayer = false;
      		secondplayer = true;//меняем флаги хода от игрока к ИИ
      	}
      }
      Ответить
      • void Game::Move_Right()
        {
        	//Ход игрока вправо
        	if (Active > 0 && ActiveY != 7 && Matrix[ActiveX][ActiveY+1] == 0)//Если выделенная пешка и не самая правая строчка и ячейка справа пустая
        	{
        		Matrix[ActiveX][ActiveY+1] = Matrix[ActiveX][ActiveY] ;//присваиваем ячейке справа текущюю(выделенную пешку)
        		Matrix[ActiveX][ActiveY] = 0;//затираем старую ячейку на пустую 
        		ChessX[Active-1] += 0.2;//перемещаем координату Х пешки вправо для отрисовки
        		ActiveX = -1;//стираем координаты выделенной пешки
        		ActiveY = -1;//стираем координаты выделенной пешки
        		Active = -1;//делаем неактивной текущую выделенную фигуру
        		std::cout << "MoveRight " << Active << std::endl;
        		firstplayer = false;
        		secondplayer = true;//меняем флаги хода от игрока к ИИ
        	}
        }
        void Game::Move_Left()
        {
        	//Ход игрока влево 
        	if (Active > 0 && ActiveY != 0 && Matrix[ActiveX][ActiveY-1] == 0)//Если выделенная пешка и не самая левая строчка и ячейка слева пустая
        	{
        		Matrix[ActiveX][ActiveY-1] = Matrix[ActiveX][ActiveY] ;//присваиваем ячейке слева текущюю(выделенную пешку)
        		Matrix[ActiveX][ActiveY] = 0;//затираем старую ячейку на пустую 
        		ChessX[Active-1] -= 0.2;//перемещаем координату Х пешки влево для отрисовки
        		ActiveX = -1;//стираем координаты выделенной пешки
        		ActiveY = -1;//стираем координаты выделенной пешки
        		Active = -1;//делаем неактивной текущую выделенную фигуру
        		std::cout << "MoveLeft " << Active << std::endl;
        		firstplayer = false;
        		secondplayer = true;//меняем флаги хода от игрока к ИИ
        	}
        }


        Это надо было одной функцией оформить?
        Ответить
          • Надеюсь, он эти координаты хоть не сравнивает. А то потом получится, что две пешки на одной клетке рисуются, а ChessX[Passive-1] != ChessX[Active-1]. // 0.200000000001
            Ответить
  • «Вашим следующим шагом должно быть либо удаление этой статьи, либо вторая часть: работа над ошибками. В ней Вы должны рассказать нам (а не мы Вам), почему Вас не взяли и как Вы исправили бы свой код, чтобы стать лучше»

    Главное отличие хабра от говнокода. Не в пользу хабра.
    Ответить
    • Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
      Ответить
  • >> Game::Game()
    какое имя метода ))

    >> Matrix = new int* [8]
    >> Matrix[i] = new int[8];
    какая структура ))


    > //Координаты пешек для отрисовки
    >> ChessX = new double[18];
    надеюсь, для каждой фигуры есть такой массив?

    >>double
    пешка может на пол шышечки на клеточку залезть?

    >>if (i > 8)
    я понял, это потому что 8x8?

    >aicountthirdrow
    а есть eighthrow?
    Ответить
  • Автор еще интересную статью написал
    https://habr.com/ru/post/541462/

    Рассмотрим 5 сортировок. Это пузырьковая(bubble), шейкерная(shake), пирамидальная(heap), вставками(insertion) и быстрая(quick).

    Для анализа их скорости будет использоваться функция clock()

    Каковы же результаты?

    С большим отрывом идет sort из stl, потом вставками, пирамидальная, шейкерная и заканчивает пузырьковая.

    -----

    и как всегда в таких штуках меня поражает, что автору совсем не 16 лет, как вы бы могли подумать
    Ответить
    • Ну и как бы ты их соревновал?)

      Кстати, в почему сорт из СТЛ такой быстрый?
      Ответить
      • В общем, для своего приложения я выбрал mysql и посмотрел что есть на Linux. Там уже был установлен он, но пароль никто не знает, а те кто знали забыли (те кто работал до меня). Узнав что он никому не нужен, я его удалил и попытался установить заново. Память не хватало и поскольку чтобы исправить эту ошибку пришлось бы подключать к нему монитор и клавиатуру с мышью, я решил бросить это дело
        Ответить
        • > поскольку чтобы исправить эту ошибку пришлось бы подключать к нему монитор и клавиатуру с мышью, я решил бросить это дело

          КАКОЙ ЛИНУКС !!! ))))))
          Ответить
        • > я его удалил и попытался установить заново
          Мартышка и очки Вендоадмин и линукс
          Ответить
          • ну а что делать, когда в линуксе нет "sfc /scannow" (в солярке есть pkg verify, лол)
            Ответить
  • А вот тут
    https://habr.com/ru/post/520400/
    автор показывает, что бывает, если накопипастить разные строчки с разных мест часть на си, часть на плюсах)

    newsockfd = new int[maxclients];
    thread = (HANDLE*)malloc(sizeof(HANDLE) * maxclients);
    args = new struct arg_sa[maxclients];
    ///
    unsigned long long id;
    std::vector<uint64_t>* plaintext = new std::vector<uint64_t>();
    ///
    #define ROL(x,n,xsize)((x<<n)|(x>>(xsize-n)))
    #define RKEY(r)((ROR(K,r*3,size64*8))&F32)
    const uint64_t K = 0x96EA704CFB1CF671;//ключ шифрования


    там еще много прекрасного, вроде такго
    >Вкратце в вечном цикле создаются потоки для каждого клиента и ждут accept

    сама задача такая: автор не знал, что в активном режиме FTP не работает за NATом, и "Не найдя ответа на куче форумов" решил написать свой сервер и клиент на винсок, а за одно и реализовать шифрование (про TLS автор не знает)
    Ответить
    • > = new std::vector<uint64_t>();
      Повеяло корпоративным духом джавамэня.
      (ノ´ヮ`)ノ*: ・゚
      Ответить
      • для полноты картины нужно хранить в векторе указатели на int

        ну хотя да: автор думает, что векторы всегда нужно создавать через new.

        вообще по какому приниципу он выбирает место для хранения не очень понятно. Кажется, что если код напоминает ему C++, то он делает new, а иначе автоматическую (или статическую) перерменную
        Ответить
        • Ну стэк вообще-то не бесконечный, чтобы на нём вектора хранить.
          Ответить
          • Ну стэк вообще-то не бесконечный, чтобы на нём указатели на вектора хранить:)

            Если без зеленого, то вектор же хранит свои данные в алокаторе (вероятнее всего в куче), а на стеке там только такая куржопенькая ручка из трёх указателей (или двух указателей и размера?) (потому вектор обычно sizeof 24, но не обязан)
            Ответить
            • Ну тогда ладно, я спокоен. А никак нельзя вектор на куче выделить? Это багор, ведь код с вектором уже нельзя перенести на юмбеддед платформу.
              Ответить
              • можно, например автор так и сделал) только зачем? чтобы была лишняя косвенность?

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

                Про юбмедед не понял. У тебя там скорее всего заранее известно сколько памяти нужно, и можно взять вообще массив
                Ответить
                • Ой, я оговорился: не на куче, а на стеке. Конечно же, трудностей в выделении вектора (вернее, его элементов) в куче нет. Но если это дефолтный способ занять память, то в эмбеддеде его уже не используешь. Наверное, j123123 поэтому ненавидит «С++».

                  Кстати, а как тебе языки с возможностью шаманить с аллокаторами? Типа «Odin».
                  Ответить
                  • > Кстати, а как тебе языки с возможностью шаманить с аллокаторами?
                    Типа "C++"?
                    Ответить
                  • а ты уверен, что тебе нужен std::vector - контейнер, который способен динамически менять свой размер при жизни, который аллоцирует обычно с запасом, т.к. позволяет вставлять новые элементы в т.ч. в середину - а не std::array?
                    j123123 ненавидит С++, потому что не смог, вот и бесится
                    Ответить
                    • std::vector и std::array это как Chad и Virgin, так что я за std::vector.

                      Кстати, смотри какой аллокатор:
                      #include <memory>
                      #include <stdio.h>
                      
                      namespace mmap_allocator_namespace
                      {
                              // See StackOverflow replies to this answer for important commentary about inheriting from std::allocator before replicating this code.
                              template <typename T>
                              class mmap_allocator: public std::allocator<T>
                              {
                      public:
                                      typedef size_t size_type;
                                      typedef T* pointer;
                                      typedef const T* const_pointer;
                      
                                      template<typename _Tp1>
                                      struct rebind
                                      {
                                              typedef mmap_allocator<_Tp1> other;
                                      };
                      
                                      pointer allocate(size_type n, const void *hint=0)
                                      {
                                              fprintf(stderr, "Alloc %d bytes.\n", n*sizeof(T));
                                              return std::allocator<T>::allocate(n, hint);
                                      }
                      
                                      void deallocate(pointer p, size_type n)
                                      {
                                              fprintf(stderr, "Dealloc %d bytes (%p).\n", n*sizeof(T), p);
                                              return std::allocator<T>::deallocate(p, n);
                                      }
                      
                                      mmap_allocator() throw(): std::allocator<T>() { fprintf(stderr, "Hello allocator!\n"); }
                                      mmap_allocator(const mmap_allocator &a) throw(): std::allocator<T>(a) { }
                                      template <class U>                    
                                      mmap_allocator(const mmap_allocator<U> &a) throw(): std::allocator<T>(a) { }
                                      ~mmap_allocator() throw() { }
                              };
                      }
                      Ответить
                        • Я не знаю, я его скопировал из интернета, чтобы вам показать.

                          Вроде бы, аллоцирует всякую фигню в ФАЙЛЕ, который находится в ОПЕРАТИВНОЙ ПАМЯТИ.
                          Ответить
                          • пока что он только срёт в stderr хелоу ворлдами, а всю работу делает std::allocator
                            Ответить
                            • То есть это плохой пример аллокатора, на который лучше не равняться?
                              Ответить
                              • Да. Рав-ня-йся лучше ня этот:
                                #include <memory>
                                #include <stdio.h>
                                
                                namespace logging_allocator_namespace
                                {
                                        // See StackOverflow replies to this answer for important commentary about inheriting from std::allocator before replicating this code.
                                        template <typename T>
                                        class logging_allocator: public std::allocator<T>
                                        {
                                public:
                                                typedef size_t size_type;
                                                typedef T* pointer;
                                                typedef const T* const_pointer;
                                
                                                template<typename _Tp1>
                                                struct rebind
                                                {
                                                        typedef logging_allocator<_Tp1> other;
                                                };
                                
                                                pointer allocate(size_type n, const void *hint=0)
                                                {
                                                        fprintf(stderr, "Alloc %d bytes.\n", n*sizeof(T));
                                                        return std::allocator<T>::allocate(n, hint);
                                                }
                                
                                                void deallocate(pointer p, size_type n)
                                                {
                                                        fprintf(stderr, "Dealloc %d bytes (%p).\n", n*sizeof(T), p);
                                                        return std::allocator<T>::deallocate(p, n);
                                                }
                                
                                                logging_allocator() throw(): std::allocator<T>() { fprintf(stderr, "Hello allocator!\n"); }
                                                logging_allocator(const logging_allocator &a) throw(): std::allocator<T>(a) { }
                                                template <class U>                    
                                                logging_allocator(const logging_allocator<U> &a) throw(): std::allocator<T>(a) { }
                                                ~logging_allocator() throw() { }
                                        };
                                }
                                Ответить
                  • ну ты можешь сделать свой аллокатор, и пытаться срать в стек

                    вот такая хернь есть

                    https://chromium.googlesource.com/chromium/chromium/+/refs/heads/main/base/stack_container.h

                    // This allocator can be used with STL containers to provide a stack buffer
                    // from which to allocate memory

                    Есть еще VLA, но вроде тока в няшной.

                    наконец, если ты статически знаешь размер, то есть std::array
                    ----

                    Вообще если ты заранее знаешь размер (в ембеде вероятно это так) то может и вектор тебе не нужен
                    Ответить
                    • Я до этого дня даже не подозревал, что в «С++» есть какие-то «аллокаторы»...
                      Ответить
                      • Степанов (или кто там делал STL) прекрасно знал, какие сишники байтоебы, и понимал, что если не дать им возможность контролировать выделение памяти для контейнеов, то они ими ни в жизни пользоваться не будут, а навелосипедят рядом свое, потому что "а зачем мне лишний brk"
                        Ответить
                        • Почему же этот Степанов не сделал в своих конь-тейнерах фунцкию realloc()?
                          Ответить
                            • Рассмотрим такой код
                              #include <stdio.h>
                              #include <stdlib.h>
                              #include <iostream>
                              #include <vector>
                              
                              
                              int main ()
                              {
                                
                                std::vector<int> myvector;
                              
                                for (int i = 0; i <= 9999999; i++ )
                                {
                                  myvector.push_back (i);
                                }
                                return 0;
                              }


                              Скомпилируем и запустим под strace:
                              ...
                              mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6dd1e9c000
                              brk(0x561f9bed0000)                     = 0x561f9bed0000
                              mmap(NULL, 266240, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6dd1e5b000
                              munmap(0x7f6dd1e9c000, 135168)          = 0
                              mmap(NULL, 528384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6dd1dda000
                              munmap(0x7f6dd1e5b000, 266240)          = 0
                              mmap(NULL, 1052672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6dd1cd9000
                              munmap(0x7f6dd1dda000, 528384)          = 0
                              mmap(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6dd1ad8000
                              munmap(0x7f6dd1cd9000, 1052672)         = 0
                              mmap(NULL, 4198400, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6dd16d7000


                              Почему я не вижу тут mremap() ?
                              Ответить
                              • Почему плюсы анмапят, и мапят заново -- я не знаю


                                но тока он mremap не использует, а не "realloc"


                                realloc тоже не обязан ремапить, если
                                он может рядышком выделить память

                                #include <stdlib.h>
                                
                                void main() {
                                	const size_t limit = 4;
                                	char* foo = malloc(4096);
                                	for(size_t i = 4096; i < 4096 * limit; i++) {
                                		foo = realloc(foo, i);
                                	}
                                }

                                realloc есть, а ремапа нет (у меня)

                                а если ``limit`` поменять на ``4096``, то появится


                                зы: во
                                https://news.ycombinator.com/item?id=23677695
                                Ответить
                            • А если сделать какую-то такую херню с realloc()
                              #include <stdlib.h>
                              #include <unistd.h>
                              #include <errno.h>
                              
                              typedef struct
                              {
                                size_t size;
                                size_t position;
                                int arrm[1];
                              } myarr;
                              
                              void arr_check_and_push(myarr **arr, int *a)
                              {
                              
                                
                                if ( (*arr)->size <= (*arr)->position)
                                {
                                  (*arr)->size <<= 1;
                                  //fprintf (stderr ,"realloc(%p, %zu)",*arr,(*arr)->size * sizeof(int) + sizeof(size_t) * 2);
                                  *arr = (myarr *)realloc(*arr, (*arr)->size * sizeof(int) + sizeof(size_t) * 2);
                                  if ((void *)*arr == NULL)
                                    exit(ENOMEM);
                                }
                                (*arr)->arrm[(*arr)->position++] = *a;
                              }
                              
                              int main ()
                              {
                              
                                myarr *arr = (myarr*)malloc(sizeof(size_t)*2+sizeof(int));
                                arr->size = 1;
                                arr->position = 0;
                                arr->arrm[0] = 0;
                              
                                for (int i = 0; i <= 9999999; i++ )
                                  arr_check_and_push(&arr, &i);
                                  
                                free(arr);
                                return 0;
                              }


                              И посмотреть на strace
                              mremap(0x7f6237a7a000, 266240, 528384, MREMAP_MAYMOVE) = 0x7f62379f9000
                              mremap(0x7f62379f9000, 528384, 1052672, MREMAP_MAYMOVE) = 0x7f62378f8000
                              mremap(0x7f62378f8000, 1052672, 2101248, MREMAP_MAYMOVE) = 0x7f62376f7000
                              mremap(0x7f62376f7000, 2101248, 4198400, MREMAP_MAYMOVE) = 0x7f62372f6000
                              mremap(0x7f62372f6000, 4198400, 8392704, MREMAP_MAYMOVE) = 0x7f6236af5000
                              mremap(0x7f6236af5000, 8392704, 16781312, MREMAP_MAYMOVE) = 0x7f6235af4000


                              Почему в контейнерах так не осилили сделать?
                              Ответить
                          • Потому что realloc() — это образцово-показательный пример говна, образовавшегося из-за нярушения SRP.
                            Вызов realloc(), в силу своей говённости, ня позволяет детерминированно контролировать, будет ли диапазон памяти просто расширен или скопирован в новую область. Это, в свою очередь, ня позволило добавить универсальную функцию realloc() в аллокаторы, и как следствие — распространённые реализации контейнеров ня используют realloc().
                            Ответить
                            • Кстати, очень удивлён был, что нет функции вроде max_expand_size, которая бы вернула максимальный размер до которого realloc расширяется на месте. Заткнуло бы большинство проблем.
                              Ответить
                            • > Вызов realloc(), в силу своей говённости, ня позволяет детерминированно контролировать, будет ли диапазон памяти просто расширен или скопирован в новую область.

                              А в чем проблема? Для этого достаточно сравнивать указатель до и после realloc.

                              Если вместо malloc() делать new() - копирования хуйни - delete(), мы разве лучше что-то контролируем?
                              Ответить
                              • В том, что таким способом о копировании ты узнаешь после, собственно, копирования. А в общем случае копировать объекты через memcpy(), как делает это говноrealloc(), няльзя.
                                Ответить
                                • > В том, что таким способом о копировании ты узнаешь после, собственно, копирования.

                                  Почему меня это должно волновать? Вот конкретно для кейса, когда я делаю push_back в вектор, какая мне разница, откопируется ли оно при realloc или останется на месте? Я уж не говорю о том, что никакого фактического копирования может и не происходить, учитывая что есть MMU

                                  Каким образом вариант "всегда выделяем новую память и копируем хуйню из старой в новую, а старую освобождаем" оказывается лучше?
                                  Ответить
                                  • > Почему меня это должно волновать?
                                    Тебя-то понятное дело не должно, ты на крестах ня пишешь.

                                    В общем случае копировать объекты через memcpy(), как делает это говноrealloc(), няльзя.
                                    Ответить
                                    • > В общем случае копировать объекты через memcpy(), как делает это говноrealloc(), няльзя.

                                      Почему тогда для частных случаев нельзя использовать realloc() ?
                                      Ответить
                                      • Потому что слишком много работы (как для стандартизаторов, так и для авторов стандартных либ/компиляторов) ради минимального прироста производительности в редких случаях, который ещё и в някоторых случаях приведёт к деградации (когда система ня поддерживает быстрый realloc, няпример).
                                        Ответить
                                        • зато можно сэкономить на копировании говна же, а для С++ это может быть важно


                                          почему нету ключика "prefer_realloc" и разрешать тока для тривиали копибл?
                                          Ответить
                                    • Кстати да, вполне можно сделать и особый вариант realloc(), например realloc_if_ptr_will_be_same() который бы успешно расширял память, если это возможно при неизменении указателя (т.е. если можно довыделить страниц сзади), но который бы нихуя не делал при невозможности такого расширения. Такой вариант realloc-а крестовики бы стали запихивать в свои аллокаторы?
                                      Ответить
                                      • Да, стали бы (примерня такой пропозал и есть по ссылке дяди Ди выше). Но проблема остаётся той же: это нужня только для няскольких редких кейсов, это сложня реализовывать, это приведёт к деградации (лишние рантайм-проверки) для случаев, когда довыделять страниц няльзя.

                                        Собственно, если в твоём приложении реаллоцирование вектора с тривиальня-копируемыми объектами является бутылочным горлышком, то всегда можня взять другую либу, няпример, https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md . Стандартные контейнеры — ня червонцы, всем и во всех случаях нрявиться не могут.
                                        Ответить
                                    • By default, if there is not sufficient space to expand a mapping
                                      at its current location, then mremap() fails


                                      Почему нельзя было сделть так:

                                      * Если можем расти на том же месте, то растем без копирования
                                      * Если не можем, и тривили копибл, то запускаемся с MREMAP_MAYMOVE

                                      А иначе делаем как сейчас


                                      Или это было бы не кросс-платформенно?
                                      Ответить
                                      • > Или это было бы не кросс-платформенно?

                                        Надо разобраться с тем, как эта херня с лоу-левельным выделением памяти работает например в той же винде. Наверняка можно что-то скостылить.
                                        Ответить
                                        • Ня винде анялогов mremap() нят. Там realloc() можня сделать только ручным юзермодным костылянием, что, конячно, по эффективности будет у GNU/Linux отсасывать.
                                          Ответить
                                          • > отсасывать

                                            От вас, Полина, не ожидал таких выражений
                                            Ответить
                                          • есть HeapReAlloc же, но это если ня мапить файл: виртпамять иначе на пинде работает
                                            Ответить
                                            • подведем итог:

                                              Реаллочить кококококтейнеры в общем случае нельзя, потому что в крестах (в отличие от няшки) бывают не тривиальные объекты, которые нельзя скокококококпировать просто так

                                              Можно было изъябнуца и сделать ооооптимизации, но всем опхуй
                                              Ответить
                                            • HeapCreate/HeapAlloc/HeapReAlloc — это и есть "можня сделать только ручным юзермодным костылянием". Эти функции работают поверх выделенного через VirtualAlloc блока, организуя в нём кучу исключительня юзермодными операциями, без помощи ядра/процессора.
                                              Ответить
                                              • Это верня: хипы это абстракции поверх VirtualAllocкнутой хуиты

                                                Интересно было бы няписать статью со сравнением работы виртуальной памяти прыщей и винды, и вообще серию статей со сравнением подсистем (tty vs ConsoleAPI итд)

                                                Я бы почитал
                                                Ответить
                      • Аллокаторы в С++ несколько неудобны. У них есть параметр — тип объекта, поэтому, казалось бы, ты можешь оптимизировать своё говно под конкретный тип и хранить только его? Но хуй! Твой аллокатор должен поддерживать произвольные типы, потому что половина сущностей в стандартной библиотеке хранит ни хера ни T, а какой-нибудь _No__de<T> ([forward_]list, [multi]set/map, shared_ptr...). В общем, я за кастомный memory_resource с доступом через polymorphic_allocator.
                        Ответить
                        • > потому что половина сущностей в стандартной библиотеке хранит ни хера ни T, а какой-нибудь _No__de<T>
                          А как иняче-то сделать неинтрузивные list, set/map, shared_ptr? Тебе в любом случае придётся выделять "struct Node {Node *next; T value; }" для списка, "struct Node {Node *left, *right; T value; }" для сета/мапы и так далее.
                          Ответить
  • Некоторые вещи, которые есть в этом коде, нельзя писать даже в прототипе. Их вообще нигде нельзя писать, их нельзя ничем оправдать — не существует случая, когда они хороши.

    Никогда не говори никогда...
    Ответить
    • приведи реальный пример когда нужно писать
      Matrix[i] = new int[8];
          //Квадраты координат нужны чтобы программа знала какие ячейки над указателем мыши, 64 квадрата
          QuadCoorXleft = new int* [8];//каждой ячейки матрицы Matrix соответстует квадрат координат для мыши xleft означает левую координату x
          QuadCoorXright = new int* [8];//xright - правая x
          QuadCoorYdown = new int* [8];//верхняя y координата
          QuadCoorYup = new int* [8];//нижняя y координата
      Ответить
      • Ну для какой-нибудь разрежённой структуры, где в половине этих ячеек null'ы.

        У меня одно время было желание восемь звёзд ебануть. Пришлось его пересиливать и заворачивать в шоблон.
        Ответить
        • и чем нул в ячейке лучше ноля в массиве интов?

          Если же речь о том, что целый ряд "Xleft" можно не создавать?
          Тогда всё таки лучше завернуть это в объект и нормально чистить за собой
          Ответить
          • > что целый ряд можно не создавать

            Ну да, я поэтому и пишу про разрежённую структуру... Яркий пример -- интеловские пейджтейблы.

            > завернуть это в объект

            Да, но внутри то у него эти new никуда не денутся. А вектор-из-указателей для этого юзать особого смысла нет.
            Ответить
            • А что бы ты сделал, если у тебя в ряду есть N и N+90000, а остальное ноли? Сделал бы связспиок с указанием сколько нолей до следующего элемента?
              Иными словами как пропустить ряды я понял, а как бы ты пропустил колонку?

              >Да, но внутри то у него эти new никуда не денутся.
              хотябы снаружи не выглядело бы как грязь
              foo.createRow(9000)
              foo[1] = 200;
              Ответить
              • > если у тебя в ряду есть N и N+90000, а остальное ноли

                Х.з., от плотности зависит... Хешмапу какую-нибудь, если плотность никакая. Если поплотнее -- N'арное дерево (те самые восемь звёзд).
                Ответить
                • То есть решение автора подходит только если у тебя много много пустых рядов (причем еще нужно где-то хранить расстояния между ними)
                  Ответить
                  • > решение автора

                    Мне лень вникать в эту портянку, сорри. Что за расстояния там хранятся?
                    Ответить
                    • всё же написино!
                      Matrix[i] = new int[8];
                          //Квадраты координат нужны чтобы программа знала какие ячейки над указателем мыши, 64 квадрата
                          QuadCoorXleft = new int* [8];//каждой ячейки матрицы Matrix соответстует квадрат координат для мыши xleft означает левую координату x
                          QuadCoorXright = new int* [8];//xright - правая x
                          QuadCoorYdown = new int* [8];//верхняя y координата
                          QuadCoorYup = new int* [8];//нижняя y координата


                      В общем тут вполне себе известный заранее, не разреженный и не очень большой массив какого-то говна, который не понятно зачем так сделан
                      Ответить
              • > как пропустить ряды я понял, а как бы ты пропустил колонку

                Нужно больше индирекций! На первом слое пусть будут условно блоки по 10000 строк и 10000 колонок. На втором -- внутри них блоки по 100. На третьем -- собственно сами значения.

                2D дерево, короче.
                Ответить
                • ну да, точно как таблицы страниц:)

                  сразу видно, что ты системщик ))
                  Ответить
                  • > точно как таблицы страниц

                    Я эту структуру хотела юзать чтобы карту для ММОРПГ хранить (зоны вокруг игроков префетчятся в память, остальные уходят спать на диск). Поэтому она действительно очень близка к пейджтейблам.

                    Обычный mmap тут не совсем подходил т.к. там куча вещей переменной длины и нужно было freeze/thaw обрабатывать явно.
                    Ответить
                    • звучит так, словно ты руками решил сделать работу за диспетчера виртуальной памяти

                      Нельзя было никак сделать свое "хранилище" из блоков размером в страницу, и как-то всё это туда упаковывать (ну переменной длинны, но можно же как-то всунуть?), чтобы он поднимал с диска страницы (и свопил их обратно)?
                      Ответить
                      • С mmap'ом консистентность данных поддерживать сложно... Он же вообще неуправляемый. Всё равно придётся какие-то журналы прикручивать и т.п.
                        Ответить
                        • а ты хотел сохранять состояние игры и переживать перезапуск типа?
                          тогда понятно

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

                            Охуенная будет ММО, если состояние не сохранять. Там ради этого второй процесс был, который в BDB изменения коммитил. На случай если основной наебнётся.

                            > гейдевки вполне могут и так

                            Да я сварщица не настоящая. Вангую, что в реале совсем другие архитектуры юзают. Здесь же даже масштабирование не было продумано.
                            Ответить
                            • По идее можно заммапленый мир переодически снепшотить как-то.. но правда не понятно как сделать консистентность не поставив всех раком
                              Ответить
                              • > снепшотить как-то

                                Ну можно классику -- бекап + лог транзакций от бекапа. Работать будет.
                                Ответить
                              • События в WAL (Write Ahead Log) дампить, и при рестарте проигрывать. Снапшотить асинхронно и как угодно, хоть грязными чтениями. По теореме Снаута главное чтобы WAL начинался с момента раньше первого грязного чтения.
                                Ответить
                                • Сначала писать в WAL, потом его проигрывать в mmapнутую память? Это годно, но нужно выбрать атомарность, если там каждый питушиный шажок это отдельная транзаккция, то будет неуободно

                                  вероятно можно делать транзакции по времени
                                  Ответить
                                  • > вероятно можно делать транзакции по времени

                                    Ну да, у меня каждый питушиный шажок отправлялся в соседний процесс на сохранение. А он каждую секунду коммитил пачками в BDB.

                                    Не обязательно же WAL флашить на каждый чих, если какие-то потери допустимы (секунда если процесс с базой помрёт, в районе одного кадра если основной).
                                    Ответить
                                  • > Сначала писать в WAL, потом его проигрывать в mmapнутую память? Это годно, но нужно выбрать атомарность, если там каждый питушиный шажок это отдельная транзаккция, то будет неуободно

                                    В няивной имплементации достаточно просто синхронизировать импорт операций из лога с чтениями, которые делает дампер снэпшотов, чтобы он мусор не прочитал. Транзакции не нужны по сути.
                                    Ответить
                                  • Обеспечивать высокий уровень нядёжности имеет смысл только для критических данных:
                                    \begin{enumerate}
                                    \item Различные балансы, как внутриигровых валют, так и донатных.
                                    \item Внутриигровые/донатные сделки (аукцион, магазины), письма.
                                    \item Характеристики персонажей (опыт, скиллы, достижения...).
                                    \item Инвентари персонажей, "банки"/"хранилища" и прочее.
                                    \item Характеристики предметов: кулдауны, прочности и так далее.
                                    \end{enumerate}
                                    Все эти данные желательня при падении процесса ня терять. Остальную же фигню, вроде положения ня карте, направления взгляда, скорости и прочего, можно хранить без особых церемоний: всё равно после аварийняго завершения процесса придётся всех персонажей телепортировать в безопасное место (стартовую локацию какую-нябудь).
                                    Ответить
                                    • > фигню, вроде положения ня карте, направления взгляда, скорости и прочего

                                      - спидраннеры оценят

                                      хотя какие конечно в мморпг спидраннеры
                                      Ответить
                                      • > спидраннеры оценят

                                        Блин, да в большинстве синглов чуть ли не всю карту резетят когда с чекпоинта перезагружаешься...

                                        З.Ы. Скучно стало, раньше можно было засейвиться за секунду до смерти и пытаться выбраться из этой ситуации.
                                        Ответить
                                        • ну да

                                          потому можно например прыгнуть с 100000 метров вниз, перед самым приземлением квиксейв-квиклоад и вуаля!
                                          Ответить
                                          • консольщина это когда ты в Contra на денди все три жизни потратил, и заново проходи всё с начала

                                            На девятьсот девяносто шестой раз научишься первый уровень проходить
                                            Ответить
                                            • хуйня полная, не понимаю, почему до сих пор многие на это дрочат
                                              Ответить
                                              • Правильня, эти стрелялки такая глупость! "Клуб Романтики: Секрет небес" мне больше нравится ☆*:.。.o(≧▽≦)o.。.:*☆.
                                                Ответить
                                            • > и заново проходи всё с начала

                                              Это олдскульная соснольщина. А в современной можно просто перекатиться за соседний ящик и смотреть кинцо в 30 FPS дальше.
                                              Ответить
                                              • В олдскульной тоже можно смотреть пока твой одноклассник играет:)

                                                впрочем, в моих любимых играх можно было сохраняться в некоторых местах (в домах, например)
                                                Ответить
                                              • нахрюк!

                                                можно поставить самый высокий уровень сложности в современной соснольщине и получать два чекпоинта на уровень и ваншоты-хедшоты от любого ашота
                                                Ответить
                                      • Речь идёт об обеспечении нядёжности хранения ня случай падения процесса игры. После падения сервера спидраннерам будет нямножко няплевать, сохранилось ли их положение ня карте или нят.
                                        Ответить
                                        • "А теперь мы сдаём квест. Обычно после этого нас телепортируют из инстанса, и необходимо проходить квестовую линейку на 2-3 часа, чтобы попасть в него снова и завершить необходимый нам квест. Но если уронить сервер специально сформированным запросом до начала диалога в следующей локации, после перезапуска мы останемся в инсте и сможем немедленно закончить всю линейку. Так как перезапус занимает около 30 минут, мы можем сэкономить до двух часов."
                                          Ответить
                                          • Имення поэтому, как я няписала в предыдущем комментарии, в реальных ММОРПГ после падения сервера персонажи телепортируются в "безопасные локации" (всякие там города) со сбросом повторяемых квестов/инстансов.
                                            Ответить
                            • а проблемы с сетью (дроп / пинг) как планировали решать? экстраполяцией?
                              Ответить
                              • > а проблемы с сетью

                                До клиентов? Никак, лол. Очень грубая экстраполяция на движение перса (чтобы уж совсем рывками не бежал) и всё.
                                Ответить
                      • Да обычная выживалка, где можно деревья рубить и всякую хуйню крафтить. В общем-то только это и запилили перед тем как забить, до боёвки дело не дошло.

                        Просто хотелось на чём-то потренироваться с boost::asio.
                        Ответить
  • я тоже делал похожее тестовое задание на заре карьеры, только не про уголки, а вроде про реверси

    там ещё хотели искусственный интеллект и чтоб за два дня

    когда джун и неадекватные собесеры выстраиваются в ряд, получается такое вот затмение
    Ответить
    • > уголки

      Но это не уголки, а странные шахматы! Это другое.
      Ответить
    • В данном конкретном случае у нас не джун, а мудак:) А так всё верно
      Ответить
    • > там ещё хотели искусственный интеллект и чтоб за два дня

      Что-то мне намекает, что потом так и пришлось бы писать уголки с ИИ за 2 дня каждую неделю. Мобильный гейдев такой мобильный.
      Ответить

Добавить комментарий

Я, guest, находясь в здравом уме и твердой памяти, торжественно заявляю:

    А не использовать ли нам bbcode?


    8