Модераторы: Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [BCB] Найти наименьшее число ходов шахматным конём 
V
    Опции темы
KAINK2
Дата 22.9.2006, 11:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Дали задачу про шахматного коня. Смысл этой задачи состоит в том чтоб найти наименьшее число ходов шахматным конём из а1 в b8, а поле само 8х8 . Если можите помогите.
PM MAIL   Вверх
MAKCim
Дата 22.9.2006, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



Обычный поиск с возвратом с отсечением вариантов
Код

typedef std::pair<int, int> coord_t;

const int runs[8][2]={
    {-2,1},
    {-1.2},
    {1,2},
    {2,1},
    {2,-1},
    {1,-2},
    {-1,-2},
    {-2,-1}
};

void find(coord_t place, coord_t& fin, int run, int& min)
{
    if (run>=min) 
        return;
    else if (place==fin)
    {
        if (run<min) min=run;
        return;
    }
    for (int i=0; i<8; ++i)
    {
        place.first+=runs[i][0];
        place.second+=runs[i][1];
        if (check(temp)) find(place,fin,++run,min);
        place.first-=runs[i][0];
        place.second-=runs[i][1];
    }
}



--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
darkart
Дата 23.9.2006, 04:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 379
Регистрация: 9.11.2005

Репутация: 26
Всего: 31



С примером...
main.h:
Код

//---------------------------------------------------------------------------

#ifndef mainH
#define mainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TfrmMain : public TForm
{
__published:    // IDE-managed Components
        TGroupBox *gbxData;
        TGroupBox *gbxStart;
        TGroupBox *gbxFinish;
        TComboBox *cbxStartX;
        TComboBox *cbxStartY;
        TComboBox *cbxFinishX;
        TComboBox *cbxFinishY;
        TButton *btnFind;
        TGroupBox *gbxChessBoard;
        TImage *imgChessBoard;
        TGroupBox *gbxResult;
        TListBox *lstResult;
        void __fastcall FormPaint(TObject *Sender);
        void __fastcall btnFindClick(TObject *Sender);
        void __fastcall FormCreate(TObject *Sender);
private:    // User declarations
public:        // User declarations
        __fastcall TfrmMain(TComponent* Owner);
        void __fastcall InitChessBoard();
        void __fastcall DrawChessBoard();
        void __fastcall Wave(int x,int y,int cost);
        int __fastcall GetCost(int x,int y);
        bool __fastcall GetStep(int&x,int&y);
        void __fastcall GetPath();
};
//---------------------------------------------------------------------------
extern PACKAGE TfrmMain *frmMain;
//---------------------------------------------------------------------------
#endif

main.cpp:
Код

//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include "main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmMain *frmMain;
const int CHESS_BOARD_SIZE=8;//размерность доски
const int UNUSED_CELL=-1;//клетка не использована
int ChessBoard[CHESS_BOARD_SIZE][CHESS_BOARD_SIZE];//описание доски
void __fastcall TfrmMain::InitChessBoard()
//ф-ция инициализации доски
{
  for(int i=0;i<CHESS_BOARD_SIZE;i++)
    for(int j=0;j<CHESS_BOARD_SIZE;j++)
      ChessBoard[i][j]=UNUSED_CELL;//отмечаем все ячейки, как не использованные
}
void __fastcall TfrmMain::DrawChessBoard()
//ф-ция прорисовки доски
{
  RECT rect;
  for(int i=0;i<CHESS_BOARD_SIZE;i++)
    for(int j=0;j<CHESS_BOARD_SIZE;j++)
    {
      SetRect(&rect,i*21,j*21,(i+1)*21,(j+1)*21);//вычисляем положение ячейки
      if((i+j)%2)//чередование цветов
      {
        imgChessBoard->Canvas->Brush->Color=RGB(255,255,255);//белый цвет кисти
      }
      else
      {
        imgChessBoard->Canvas->Brush->Color=RGB(0,0,0);//черный цвет кисти
      }
      imgChessBoard->Canvas->FillRect(rect);//заполняем прямоугольник
      imgChessBoard->Canvas->Font->Size=12;//устанавливаем размер шрифта
      if(ChessBoard[i][j]!=UNUSED_CELL)//если ячейка уже использовалась
      {
        imgChessBoard->Canvas->Font->Color=RGB(128,128,128);//устанавливаем цвет текста
        imgChessBoard->Canvas->TextOutA(i*21,j*21,ChessBoard[i][j]);//выводим значение ячейки
      }
    }
    if(cbxStartX->ItemIndex!=cbxFinishX->ItemIndex||cbxStartY->ItemIndex!=cbxFinishY->ItemIndex)
    //если начальная и конечная позиция не совпадают
    {
      imgChessBoard->Canvas->Font->Color=RGB(255,0,0);//устанавливаем цвет текста
      imgChessBoard->Canvas->TextOutA(cbxStartX->ItemIndex*21,cbxStartY->ItemIndex*21,"S");//S - start
      imgChessBoard->Canvas->Font->Color=RGB(0,0,255);//устанавливаем цвет текста
      imgChessBoard->Canvas->TextOutA(cbxFinishX->ItemIndex*21,cbxFinishY->ItemIndex*21,"F");//F - finish
    }
}
void __fastcall TfrmMain::Wave(int x,int y,int cost)
//Ф-ция волны для ячейки
//Если положение (x,y) попадает на игровое поле, то
//если ячейка не использовалась или использовалась и её стоимость выше переданной(cost), то
//записываем в ячейку новое(меньшее значение) и проверяем всех соседей
{
  if(x>=0&&x<CHESS_BOARD_SIZE&&y>=0&&y<CHESS_BOARD_SIZE)
  {
    if(ChessBoard[x][y]==UNUSED_CELL||(ChessBoard[x][y]!=UNUSED_CELL&&ChessBoard[x][y]>cost))
    {
      ChessBoard[x][y]=cost;
      Wave(x-1,y-2,cost+1);
      Wave(x+1,y-2,cost+1);
      Wave(x+2,y-1,cost+1);
      Wave(x+2,y+1,cost+1);
      Wave(x+1,y+2,cost+1);
      Wave(x-1,y+2,cost+1);
      Wave(x-2,y+1,cost+1);
      Wave(x-2,y-1,cost+1);
    }
  }
}
int __fastcall TfrmMain::GetCost(int x,int y)
//ф-ция возвращает значение ячейки, если (x,y) на поле или UNUSED_CELL иначе
{
  if(x>=0&&x<CHESS_BOARD_SIZE&&y>=0&&y<CHESS_BOARD_SIZE)
  {
    return ChessBoard[x][y];
  }
  else
  {
    return UNUSED_CELL;
  }
}
bool __fastcall TfrmMain::GetStep(int&x,int&y)
//ф-ция возвращает true, если в окрестности (x,y) найдена точка с меньшей стоимостью
//и если это не конечная точка, а также координаты ячейки с наименьшей стоимостью
{
  int tempCost,tempx,tempy,newx,newy;
  int cost=ChessBoard[x][y];//инициализация стоимости
  bool bHaveResult=false;//инициализация переменной, отвечающей за нахождение след. ячейки
  //далее проверяем всевозможные варианты хода коня
  tempx=x-1;
  tempy=y-2;
  tempCost=GetCost(tempx,tempy);//вычисляем значение ячейки
  if(tempCost!=UNUSED_CELL&&tempCost<cost)
  //если ячейка использовалась и вычисленная стоимость ниже
  {
    cost=tempCost;//запоминаем новую мин. стоимость
    newx=tempx;//запоминаем
    newy=tempy;//координаты
    bHaveResult=true;//ячейка успешно найдена
  }
  tempx=x+1;
  tempy=y-2;
  tempCost=GetCost(tempx,tempy);
  if(tempCost!=UNUSED_CELL&&tempCost<cost)
  {
    cost=tempCost;
    newx=tempx;
    newy=tempy;
    bHaveResult=true;
  }
  tempx=x+2;
  tempy=y-1;
  tempCost=GetCost(tempx,tempy);
  if(tempCost!=UNUSED_CELL&&tempCost<cost)
  {
    cost=tempCost;
    newx=tempx;
    newy=tempy;
    bHaveResult=true;
  }
  tempx=x+2;
  tempy=y+1;
  tempCost=GetCost(tempx,tempy);
  if(tempCost!=UNUSED_CELL&&tempCost<cost)
  {
    cost=tempCost;
    newx=tempx;
    newy=tempy;
    bHaveResult=true;
  }
  tempx=x+1;
  tempy=y+2;
  tempCost=GetCost(tempx,tempy);
  if(tempCost!=UNUSED_CELL&&tempCost<cost)
  {
    cost=tempCost;
    newx=tempx;
    newy=tempy;
    bHaveResult=true;
  }
  tempx=x-1;
  tempy=y+2;
  tempCost=GetCost(tempx,tempy);
  if(tempCost!=UNUSED_CELL&&tempCost<cost)
  {
    cost=tempCost;
    newx=tempx;
    newy=tempy;
    bHaveResult=true;
  }
  tempx=x-2;
  tempy=y+1;
  tempCost=GetCost(tempx,tempy);
  if(tempCost!=UNUSED_CELL&&tempCost<cost)
  {
    cost=tempCost;
    newx=tempx;
    newy=tempy;
    bHaveResult=true;
  }
  tempx=x-2;
  tempy=y-1;
  tempCost=GetCost(tempx,tempy);
  if(tempCost!=UNUSED_CELL&&tempCost<cost)
  {
    cost=tempCost;
    newx=tempx;
    newy=tempy;
    bHaveResult=true;
  }
  if(bHaveResult)//если есть хотя бы одна удовл. усл. ячейка
  {
    x=newx;//возвращаем x
    y=newy;//возвращаем y
    return !(x==cbxFinishX->ItemIndex&&y==cbxFinishY->ItemIndex);
    //конечная ли позиция
  }
  else//нет ни одной ячейки
  {
    return false;
  }

}
void __fastcall TfrmMain::GetPath()
//ф-ция строит путь по волне
{
  int x,y,count;//x,y - координаты, count - кол-во шагов
  AnsiString str;//вспомогательная переменная
  x=cbxStartX->ItemIndex;//инициализируем
  y=cbxStartY->ItemIndex;//переменные координатами начальной ячейки
  count=0;//не было ни одного шага
  lstResult->Clear();//очищаем листбокс
  lstResult->AddItem("Path:",NULL);//Путь:
  if(GetStep(x,y))//если в окрестности существует хотя бы одна ячейка, то путь существует
  {
    do
    {
      count++;//есть очередной шаг
      str.sprintf("%i:%c%i",count,'a'+x,y+1);//записываем в строку
      lstResult->AddItem(str,NULL);//добавляем строку в листбокс
    }
    while(GetStep(x,y));//пока есть след. шаг
    count++;//последний шаг
    str.sprintf("%i:%c%i",count,'a'+x,y+1);
    lstResult->AddItem(str,NULL);
  }
  else
  {
    lstResult->AddItem("Path not found",NULL);//Пути нет
  }
}
//---------------------------------------------------------------------------
__fastcall TfrmMain::TfrmMain(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------



void __fastcall TfrmMain::FormPaint(TObject *Sender)
{
  DrawChessBoard();//перерисовываем доску
}
//---------------------------------------------------------------------------


void __fastcall TfrmMain::btnFindClick(TObject *Sender)
{
  InitChessBoard();//инициализируем доску
  DrawChessBoard();//рисуем доску
  if(cbxStartX->ItemIndex!=cbxFinishX->ItemIndex||cbxStartY->ItemIndex!=cbxFinishY->ItemIndex)
  //если нач. и конечн. позиция не совпадают
  {
    Wave(cbxFinishX->ItemIndex,cbxFinishY->ItemIndex,0);//Запускаем волну
    DrawChessBoard();//рисуем доску
    GetPath();//получаем путь
  }
  else
  {
    lstResult->Clear();//очищаем листбокс
    lstResult->AddItem("Начальная и конечная точки совпадают",NULL);
  }
}
//---------------------------------------------------------------------------

void __fastcall TfrmMain::FormCreate(TObject *Sender)
{
  InitChessBoard();//инициализация доски
}
//---------------------------------------------------------------------------




Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  ChessWave.rar 33,27 Kb
PM MAIL WWW ICQ Skype GTalk   Вверх
KAINK2
Дата 23.9.2006, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Респект и спасибо большое
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »


 




[ Время генерации скрипта: 0.0464 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.