[Программирование] Странные шахматы как тестовое задание

Автор Сообщение
news_bot ®

Стаж: 6 лет 3 месяца
Сообщений: 27286

Создавать темы news_bot ® написал(а)
18-Июн-2021 02:31

Добрый вечер хаброжители!Сегодня я предоставлю вашему вниманию небольшую статью не связанную с моими предыдущими статьями. Где-то более года назад мне пришлось делать одно тестовое задание чтобы устроится на работу. Выполнил я его в срок, но конкуренция была большая и скорее всего взяли человека который сделал его с помощью рекомендованных технологий и красочнее.Суть задачи, есть доска 8 на 8 клеток. У игрока есть 9 шашек они расположены в углу доски в квадрате 3 на 3, у противника тоже столько же шашек и они расположены симметрично по диагонали в другом углу в квадрате 3 на 3. Каждый игрок ходит по очереди, нужно дойти шашками на места изначального положения соперника через всю доску, кто первый дошел тот и победил. Ходить можно только на пустые клетки и только вверх, вниз, влево и вправо(по диагонали нельзя!).
Управление я добавил мышью, а играть против компьютерного алгоритма. Черные - человек, белые - ИИ.Помимо всего прочего изначально необходимо отрисовать доску, шашки и делать манипуляции с полем.Немного кода для наглядности:
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-я)
}
Для отрисовки и захвата мыши используется библиотеки OpenGL и SDL2.
void Draw_Circle()
{
  //Отрисовка круга(пешек-шахмат) черного
  for (int i = 0; i <= 50; i++) {
    float a = (float)i / 50.0f * 3.1415f * 2.0f;
    glVertex2f(cos(a), sin(a));
  }
}
void Draw_Circle_Fill()
{
  //Отрисовка круга(пешек-шахмат) белого
  for (int i = 0; i <= 50; i++) {
    float a = (float)i / 50.0f * 3.1415f * 2.0f;
    glVertex2f(0.0, 0.0);
    glVertex2f(cos(a), sin(a));
  }
}
Самое удобное что можно использовать glTranslatef чтобы заполнить доску шашками с перемещениями
...
for (int i = 0; i < 9; i++)
    {
      glPushMatrix();
      glTranslatef(ChessX[i], ChessY[i], 0);
      glScalef(0.05, 0.05, 1);
      glBegin(GL_LINE_LOOP);
      Draw_Circle();
      glEnd();
      glPopMatrix();
    }
    //Рисуем белые пешки ИИ
    for (int i = 9; i < 18; i++)
    {
      glPushMatrix();
      glTranslatef(ChessX[i], ChessY[i], 0);
      glScalef(0.05, 0.05, 1);
      glBegin(GL_LINES);
      Draw_Circle_Fill();
      glEnd();
      glPopMatrix();
    }
...
Ходы игрока:
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;//меняем флаги хода от игрока к ИИ
  }
}
Ходы компьютера почти аналогичны ходам игрока, в конце будет ссылка на полный код игры, если кому интересно.
void Game::ReccurentWalk()
{
  //Реккурентный ход ИИ
  current = -1, currentI = -1, currentJ = -1;//изначально выделенная пешка не определена
  for (int i = 0; i < Ai.size(); i++)//поиск по массиву
    if (!Ai[i].ai)//если не завершены ходы для конкретных пешек
    {
      if (Check_MoveUp(Ai[i].value) || Check_MoveLeft(Ai[i].value))//Можно ли походить вверх или влево?
      {
        current = Ai[i].value;//запоминаем текущую пешку
        break;
      }
      else
      {
        //Если походить нельзя стираем из массива ходов пешку
        std::vector<chessai>::iterator position = std::find_if(Ai.begin(), Ai.end(), find_s(Ai[i].value));
        if (position != Ai.end()) // == vector.end() means the element was not found
          Ai.erase(position);
      }
    }
  for (int i = 0; i < 8; i++)
    for (int j = 0; j < 8; j++)
      if (Matrix[i][j] == current)//ищем в матрице пешку и запоминаем индексы
      {
        currentI = i;
        currentJ = j;
        break;
      }
  if (currentI != -1 && currentJ != -1)//если какая либо найдена ходим либо вверх либо влево
  {
    if (!Move_UpAI(currentI, currentJ))
      if (!Move_LeftAI(currentI, currentJ))
      {
        ReccurentWalk();
      }
  }
  else
  {
    //если не найдена заполняем массив ходов снова пешками
    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);
      }
    }
    //ищем ту которая может походить вправо или вниз
    for (int i = 0; i < Ai.size(); i++)
      if (!Ai[i].ai)
      {
        if (Check_MoveRight(Ai[i].value) || Check_MoveDown(Ai[i].value))
        {
          current = Ai[i].value;
          break;
        }
        else
        {
          //если не может то стираем из массива
          std::vector<chessai>::iterator position = std::find_if(Ai.begin(), Ai.end(), find_s(Ai[i].value));
          if (position != Ai.end()) // == Vector.end() means the element was not found
            Ai.erase(position);
        }
      }
    //ищем ее индексы в матрице
    for (int i = 0; i < 8; i++)
      for (int j = 0; j < 8; j++)
        if (Matrix[i][j] == current)
        {
          currentI = i;
          currentJ = j;
          break;
        }
    //ходим вправо или вниз
    if(!Move_RightAI(currentI, currentJ))
      if (!Move_DownAI(currentI, currentJ))
      {
        std::cout <<"Artificial Intellegence asked: WTF?" << std::endl;
      }
  }
  chessai tmp;
  if(Ai.empty())//если список ходов пуст заполняем снова всеми
    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);
      }
    }
}
Ну и собственно опишу словами, что делает ИИ. Он собирает три пешки вверху на 0-ой строке и если ходить нельзя влево, то двигает вверх остальные 3 пешки на 1 строку, аналогично и на 2-ю строку. Если ходить влево и вверх нельзя, то он берет любую шашку и двигает либо вниз либо вправо если можно конечно, то есть стремится всегда двигать влево или вверх( при условии что выше меньше трёх шашек в строке).Ну собственно и геймплей:Извините, данный ресурс не поддреживается. :( И ссылка на исходный код.
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_programmirovanie (Программирование), #_gejmdev (геймдев), #_shahmaty (шахматы), #_shashki (шашки), #_programmirovanie (
Программирование
)
Профиль  ЛС 
Показать сообщения:     

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

Текущее время: 17-Май 16:22
Часовой пояс: UTC + 5