Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.06.2012, 07:21   #1
rainbow
Форумчанин
 
Регистрация: 06.09.2008
Сообщений: 156
По умолчанию Запись заданного количества нулей в StringGrid

Доброго времени суток! Возникла следующая проблема: есть код, который по нажатию кнопки заполняет StringGrid случайными значениями от 1 до 9 и добавляет в него заданное количество значений 0 (в данном случае 4)
Код:
var
  Form1: TForm1;
  i1,j1:integer;
.................

procedure TForm1.Button1Click(Sender: TObject);
var
i,j,k:integer;
begin
randomize;
for i := 0 to StringGrid1.RowCount-1 do //проходим по всем ячейкам
for j := 0 to StringGrid1.ColCount-1 do
StringGrid1.Cells[i,j]:=IntToStr(random(9)+1); //заполняем ячейки случайными значениями от 1 до 9
for k:=4 downto 1 do //заполняем заданное количество ячеек (в данном случае четыре) значениями 0
begin
repeat //это для того чтобы в одну и ту же ячейку не записать два раза 0
i:=random(StringGrid1.RowCount); //получаем номер пары случайной ячейки
j:=random(StringGrid1.ColCount);
until (i<>i1) or (j<>j1); //сравнение: если номер пары сгенерированной ячейки совпадает с предыдущей, генерируем снова
i1:=i;//запоминаем текущий номер пары
j1:=j;
StringGrid1.Cells[i,j]:='0';//записываем 0 в ячейку
end; //for k:=4
end;
Работает вроде нормально, но после множества нажатий на кнопку в StringGrid иногда получается так, что значений 0 во всём StringGrid оказывается 3 а не 4. Вопрос: почему? И как это можно исключить?
Ужас, как я устал от тупизны...

Последний раз редактировалось rainbow; 13.06.2012 в 07:28.
rainbow вне форума Ответить с цитированием
Старый 13.06.2012, 08:00   #2
astecenko
Homo Interneticus
Форумчанин
 
Аватар для astecenko
 
Регистрация: 04.03.2011
Сообщений: 611
По умолчанию

Начальные значения для i1, j1 задаются где-то? Скорее всего надо их инициализировать -1.
И условие в repeat возможно лучше заменить на: not((i=i1) and (j=j1))
astecenko вне форума Ответить с цитированием
Старый 13.06.2012, 08:35   #3
rainbow
Форумчанин
 
Регистрация: 06.09.2008
Сообщений: 156
По умолчанию

Цитата:
Сообщение от astecenko Посмотреть сообщение
Начальные значения для i1, j1 задаются где-то? Скорее всего надо их инициализировать -1.
И условие в repeat возможно лучше заменить на: not((i=i1) and (j=j1))
Их по нажатию кнопки нельзя инициализировать, иначе будет сбрасываться предыдущее состояние, да и по умолчанию должно быть значение 0. Если только в обработчике FormCreate, сделал:
Код:
procedure TForm1.FormCreate(Sender: TObject);
begin
i1:=-1;
j1:=-1;
end;
Условие также заменил на вышеприведенное, но это не помогло.
Я похоже понял в чём дело: генератор СЧ может генерировать одинаковые пары не один раз, и может получиться например так, что из 4 ячеек - 2 может попасть в одну и ту же ячейку, а при помощи i1,j1 исключается лишь одна. Видимо генерируемые пары i,j придется записывать в массив и при следующей генерации сравнивать пары с элементами массива, либо наполнять массив номерами пар, каждый раз сравнивая их, чтобы не было одинаковых пар и заполнять из массива StringGrid.
Ужас, как я устал от тупизны...

Последний раз редактировалось rainbow; 13.06.2012 в 09:12.
rainbow вне форума Ответить с цитированием
Старый 13.06.2012, 09:13   #4
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Цитата:
Код:
until (i<>i1) or (j<>j1); //сравнение: если номер пары сгенерированной ячейки совпадает с предыдущей, генерируем снова
код Вы писали? Комментарий, главное, правильный. Вы действительно генерите повторно пару индексов, если она совпадает с предыдущей. Исключительно - с предыдущей. Но никак не проверяете, если она совпадает с теми, которые были один\два\X шагов назад...
Вы попробуйте сделать на 4 нуля, а, скажем, 10 - разница (из-за этой ошибки) станет ещё наглядней!

бороться с этим можно - либо накапливая в массиве ВСЕ сгенерённые координаты (вам хватит массива от 1 до K (k - нужное количество нулей).
Либо, генерить нули до тех пор, пока функция - ПодсчитатьКоличествоНулейвStringGri d не вернёт нужное число:
Код:
repeat 
  i:=random(StringGrid1.RowCount); //получаем номер пары случайной ячейки
  j:=random(StringGrid1.ColCount);
  StringGrid1.Cells[i,j]:='0';//записываем 0 в ячейку
until CountZeroInStringGrid(StringGrid1) = 4;
очевидно, что первый способ намного эффективней (я бы рекомендовал остановится именно на нём!), но второй намного проще в реализации (но тем не менее, пользоваться им не рекомендую).
Serge_Bliznykov вне форума Ответить с цитированием
Старый 13.06.2012, 09:45   #5
rainbow
Форумчанин
 
Регистрация: 06.09.2008
Сообщений: 156
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
код Вы писали? Комментарий, главное, правильный. Вы действительно генерите повторно пару индексов, если она совпадает с предыдущей. Исключительно - с предыдущей. Но никак не проверяете, если она совпадает с теми, которые были один\два\X шагов назад...
Вы попробуйте сделать на 4 нуля, а, скажем, 10 - разница (из-за этой ошибки) станет ещё наглядней!

бороться с этим можно - либо накапливая в массиве ВСЕ сгенерённые координаты (вам хватит массива от 1 до K (k - нужное количество нулей).
Либо, генерить нули до тех пор, пока функция - ПодсчитатьКоличествоНулейвStringGri d не вернёт нужное число:
Код:
repeat 
  i:=random(StringGrid1.RowCount); //получаем номер пары случайной ячейки
  j:=random(StringGrid1.ColCount);
  StringGrid1.Cells[i,j]:='0';//записываем 0 в ячейку
until CountZeroInStringGrid(StringGrid1) = 4;
очевидно, что первый способ намного эффективней (я бы рекомендовал остановится именно на нём!), но второй намного проще в реализации (но тем не менее, пользоваться им не рекомендую).
Это всё хорошо, но проблема в том, что на самом деле у меня k динамический, задается с клавиатуры, придется создавать динамический массив:
Код:
var 
massivij: array of array of integer;
.............................................
Его инициализировать:
Код:
SetLength(massivij,1,k);
И записывать в него координаты.
Ужас, как я устал от тупизны...
rainbow вне форума Ответить с цитированием
Старый 13.06.2012, 11:07   #6
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Цитата:
Это всё хорошо, но проблема в том, что на самом деле у меня k динамический, задается с клавиатуры, придется создавать динамический массив:
Код:
var 
massivij: array of array of integer;
ну, это Вы зря!
у вас же НЕ ОБА параметра динамические!

я бы предложил примерно такое решение:
Код:
procedure TForm1.Button2Click(Sender: TObject);
var
  massivij: array of TPoint;
  i, j, k, i0, AllreadyFillIndex: integer;
  WasBefore: boolean;
begin
  k := StrToIntDef(Edit1.Text, 0);
  if k > 0 then begin
    AllreadyFillIndex := -1;
    SetLength(massivij, k);
    repeat
      repeat
        i := random(StringGrid1.RowCount); //получаем номер пары случайной ячейки
        j := random(StringGrid1.ColCount);
        WasBefore := false;
        for i0 := 0 to AllreadyFillIndex do
          if (massivij[i0].x = i) and
            (massivij[i0].y = j) then begin
            WasBefore := true;
            break
          end;
        if Not WasBefore then begin
          StringGrid1.Cells[i, j] := '0'; //записываем 0 в ячейку
          inc(AllreadyFillIndex); // увеличим счётчик заполненных координат
          massivij[AllreadyFillIndex].x := i; // сохраним заполненные координаты для проверки
          massivij[AllreadyFillIndex].y := j
        end;
      until not WasBefore;
    until AllreadyFillIndex = (k - 1); // нужное число нулей заполнено! миссия выполнена
    SetLength(massivij, 0); // освободим память массива
  end;
end;
Serge_Bliznykov вне форума Ответить с цитированием
Старый 13.06.2012, 12:20   #7
rainbow
Форумчанин
 
Регистрация: 06.09.2008
Сообщений: 156
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
ну, это Вы зря!
у вас же НЕ ОБА параметра динамические!

я бы предложил примерно такое решение:
Спасибо! Через TPoint я что то не подумал сделать.
Ужас, как я устал от тупизны...
rainbow вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Перевод числа из 10 в 16 систему счисления и подсчет количества нулей ksenox Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 3 23.05.2012 16:58
подсчет количества заданного слова в текстовом файле Old2691 Помощь студентам 0 14.01.2012 07:16
Упорядочить строки в StringGrid по характеристике: наибольшее количество идущих подряд нулей (Delphi) Bizikov Помощь студентам 0 26.05.2011 18:54
С++ Написать программу, для вывода предложений, состоящих из заданного количества слов uropb992 Помощь студентам 0 28.05.2010 18:54
Суммирование заданного количества цифр fs444 Общие вопросы C/C++ 7 01.02.2010 17:43