IPB
ЛогинПароль:

 
 Ответить  Открыть новую тему 
> Все таже змейка, добить раз и навсегда, сделать хвост
a100
сообщение 15.12.2010 12:45
Сообщение #1





Группа: Пользователи
Сообщений: 6
Пол: Мужской
Реальное имя: a100

Репутация: -  0  +


Здравствуйте! Благодаря информации с вашего форума, получилось написать, так сказать. костяк программы) не просто списать, а понять что для чего, это получилось. Опыт программирования еще совсем маленький.
Вот мой код:

Program Snake;
  uses crt;
const 
	xn=1;  		{предел экрана слева}
	xx=80;      {предел экрана справа}
	yn=1;       {верхний предел экрана} 
	yx=25;      {нижний предел экрана}
	H='0';      {голова змеи}
	dt=400;     {задержка}

var 
	x:integer=xx div 2; {начальное расположение змеи}
	y:integer=yx div 2;
	vx:integer=-1;  {начальное направление змеи}
	vy:integer=0;
    xe:integer=15; {начальные координаты яблока}
    ye:integer=15;
var 
	c:char;
	

begin
randomize;
clrscr;
gotoxy(xe,ye);     {рисуем первое яблоко}
write ('$');

while (x>=xn) and (x<=xx) and (y>=yn) and (y<=yx) do {обозначаем границы экрана}
  begin
	GoToXY(x,y);    {рисуем новое положение символа}
	write(H);
	Delay(dt);      {задержка, иначе символ будет бегать быстро}
	if keypressed then      {если нажата клавиша читаем ее}
		begin
			c:=readkey;
			case c of               {если это был управляющий символ, изменяем движение}
			'w':begin vx:=0; vy:=-1 end;  {изменяем движение на движение вверх}
			's':begin vx:=0; vy:=1 end;   {изменяем движение на движение вниз}
			'a':begin vx:=-1; vy:=0 end;  {изменяем движение на движение влево} 
			'd':begin vx:=1; vy:=0 end;   {изменяем движение на движение вправо}
			end;
		end;
    gotoxy(x,y); 
    write(' ');
    inc(x,vx);    {вычисляем новое положение змейки}
    inc(y,vy);
    if (x=xe) and (y=ye) then {если координаты змеи совпадают с координатами яблока}
		begin
			xe:=random(75);  {рисуем новое яблоко, случайным образом}
			ye:=random(20);
			gotoXY(xe,ye);
			write('$');
		end;
  end;
end.



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

надеюсь на вашу помощь
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Lapp
сообщение 15.12.2010 13:37
Сообщение #2


Уникум
*******

Группа: Модераторы
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

Репутация: -  159  +


Цитата(a100 @ 15.12.2010 12:45) *
надеюсь на вашу помощь
Самый лучший вариант - завести двумерный массив из байтов по числу клеток игрового поля
  b: array [xn..xx,yn..yx] of byte;

В нем рисуй тело от хвоста до головы. Вот такие обозначения:
0 - пустая клетка
1 - тело идет вверх
2 - тело идет вправо
3 - тело идет вниз
4 - тело идет влево
5 - голова (тело закончилось
6 - кролик
7 - мангуста
8 - препятствие
....

Вот тебе пример такого поля и змеи на нем:
0000000000
0002222300
0001000300
0021000500
0010000000
0014440000
0000000000

При этом храни в двух парах переменных текущие координаты головы и хвоста. Так ты сможешь "двигать змею". Если змея в этот момент движется вправо, то следующий кадр будет такой:
0000000000
0002222300
0001000300
0021000250
0010000000
0014400000
0000000000

Подумай над этим как следует. Если будут вопросы - задавай. Меня не будет до ночи, но кто-то еще может подсказать..


--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
TarasBer
сообщение 15.12.2010 14:30
Сообщение #3


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


Цитата(Lapp @ 15.12.2010 13:37) *

  b: array [xn..xx,yn..yx] of byte;

В нем рисуй тело от хвоста до головы. Вот такие обозначения:
0 - пустая клетка
1 - тело идет вверх
2 - тело идет вправо
3 - тело идет вниз
4 - тело идет влево
5 - голова (тело закончилось
6 - кролик
7 - мангуста
8 - препятствие


Фу, это же магические числа.
Я предпочитаю делать так:


  type 
    TField = (fEmpty, fUp, fRight, fDown, fLeft, fHead, fFood, fEnemy, fBorder);

  var  
    b: array [xn..xx,yn..yx] of TField;




--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Lapp
сообщение 15.12.2010 14:34
Сообщение #4


Уникум
*******

Группа: Модераторы
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

Репутация: -  159  +


Цитата(TarasBer @ 15.12.2010 14:30) *
Фу, это же магические числа.
Я предпочитаю делать так:


  type 
    TField = (fEmpty, fUp, fRight, fDown, fLeft, fHead, fFood, fEnemy, fBorder);

  var  
    b: array [xn..xx,yn..yx] of TField;


yes2.gif Одобрямс! good.gif
Только тогда с отладкой и промежуточными печатями могут быть проблемы.. Не совсем проблемы, просто дополнительная писанина + значения могут случайно съехать..
Но это все мелочи. Правильно, нужно именно так делать.


--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
TarasBer
сообщение 15.12.2010 14:37
Сообщение #5


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


Как раз с отладкой проблем меньше, потому что когда видишь в отладчике число 3, то долго думаешь, что бы оно значило, а когда видишь fDown, то всё понятно.
Что касается печати, то тут да, язык в данной реализации не содержит модные фичи (рефлексия, или как её), позволяющие без ретипизации написать WriteLn(f[i, j]) так, что выведется "fDown".

Сообщение отредактировано: TarasBer - 15.12.2010 14:38


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Lapp
сообщение 15.12.2010 14:59
Сообщение #6


Уникум
*******

Группа: Модераторы
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

Репутация: -  159  +


Цитата(TarasBer @ 15.12.2010 14:37) *
Что касается печати, то тут да, язык в данной реализации не содержит модные фичи (рефлексия, или как её), позволяющие без ретипизации написать WriteLn(f[i, j]) так, что выведется "fDown".
Да даже если выведется Up или Down - как тогда будет выглядет карта типа той, что я выше привел? )) Так что все равно нужно вывод организовывать с фильтром.


--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
a100
сообщение 15.12.2010 19:54
Сообщение #7





Группа: Пользователи
Сообщений: 6
Пол: Мужской
Реальное имя: a100

Репутация: -  0  +


Цитата(Lapp @ 15.12.2010 13:37) *

Самый лучший вариант - завести двумерный массив из байтов по числу клеток игрового поля
  b: array [xn..xx,yn..yx] of byte;

В нем рисуй тело от хвоста до головы. Вот такие обозначения:
0 - пустая клетка
1 - тело идет вверх
2 - тело идет вправо
3 - тело идет вниз
4 - тело идет влево
5 - голова (тело закончилось
6 - кролик
7 - мангуста
8 - препятствие
....

Вот тебе пример такого поля и змеи на нем:
0000000000
0002222300
0001000300
0021000500
0010000000
0014440000
0000000000

При этом храни в двух парах переменных текущие координаты головы и хвоста. Так ты сможешь "двигать змею". Если змея в этот момент движется вправо, то следующий кадр будет такой:
0000000000
0002222300
0001000300
0021000250
0010000000
0014400000
0000000000

Подумай над этим как следует. Если будут вопросы - задавай. Меня не будет до ночи, но кто-то еще может подсказать..


получается, сначала надо заполнить массив нулями, а потом в ячейки добавить значения? чтот пока не доходит
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Lapp
сообщение 16.12.2010 12:03
Сообщение #8


Уникум
*******

Группа: Модераторы
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

Репутация: -  159  +


Цитата(a100 @ 15.12.2010 19:54) *
получается, сначала надо заполнить массив нулями, а потом в ячейки добавить значения? чтот пока не доходит
Заполнить нулями, начальным телом змеи и поставить кролика.
Вот, смотри. Тут практически все готово кроме вывода. То есть вывод самый примитивный. Нужно добавить визуализацию на основе либо CRT, либо графики. Когда разберешься с основой, можно будет этим заняться.
uses
  CRT;

const
  MaxSize= 100;            // m and n not to exceed this number
  StartLen= 5;             // start length of the snake
  LenInc= 2;               // length increase when rabbit eaten
  MaxSizeX= MaxSize;
  MaxSizeY= MaxSize;

  // cell legend:
  Clear=    0;  Cl=Clear;
  Up=       1;
  Right=    2;  Rt=Right;
  Down=     3;  Dn=Down;
  Left=     4;  Lt=Left;
  Head=     5;  He=Head;
  Rabbit=   6;  Ra=Rabbit;
  Wall=     7;  Wa=Wall;
  Hole=     8;  Ho=Hole;
  Mongoose= 9;  Mo=Mongoose;
  // representatin on prints
  CellPrint: string= ' ^>v<0RWOM..........';
  //                  01234567890

  // keyboard
  PreKey= #0;
  UpKey= #72;
  LtKey= #75;
  RtKey= #77;
  DnKey= #80;
  EscKey= #27;



type
  tCell= byte;
  tBoard= array [0..MaxSizeY,0..MaxSizeX] of tCell;

var
  b: tBoard;
  i,j,x,y,mx,my,Len,dLen,Hx,Hy,Tx,Ty,Rx,Ry: integer;
  Crash: boolean;

procedure PrintBoard;
begin
  WriteLn('Len=',Len,'  x=',Hx,'  y=',Hy,'  dLen=',dLen);
  for j:=0 to my+1 do begin
    for i:=0 to mx+1 do Write(CellPrint[b[j,i]+1]);
    WriteLn
  end
end;

var
  c: char;
  d: byte;
  dx,dy: integer;

begin
  // board preparation
  mx:= 30;
  my:= 15;
  for j:=0 to my+1 do for i:=0 to mx+1 do
    if (i=0)or(j=0)or(i>mx)or(j>my)then b[j,i]:=Wall else b[j,i]:=Clear;

  // filling in inicial data
  Len:= StartLen;
  dLen:= 0;
  Hx:= mx div 2+1;
  Hy:= my div 2+1;
  Tx:= Hx-Len;
  Ty:= Hy;
  Rx:= mx*3 div 4;
  Ry:= Hy;
  b[Hy,Hx]:= Head;
  for i:=0 to Len-1 do b[Ty,Tx+i]:= Right;
  b[Ry,Rx]:= Rabbit;

  Crash:=false;
  repeat
    PrintBoard;
    dx:=0;
    dy:=0;
    repeat
      c:= ReadKey;
      if c=PreKey then begin
        c:=ReadKey;
        case c of
          UpKey: begin dy:=-1; d:=Up end;
          RtKey: begin dx:= 1; d:=Rt end;
          DnKey: begin dy:= 1; d:=Dn end;
          LtKey: begin dx:=-1; d:=Lt end;
        end;
        c:=PreKey
      end
    until (c=EscKey) or (dx+dy<>0);
    x:=Hx+dx;
    y:=Hy+dy;
    WriteLn(x,'  ',y);
    case b[y,x] of
      // rabbit
      Rabbit: begin
        dLen:=dLen+LenInc;
        repeat
          Rx:=Random(mx)+1;
          Ry:=Random(my)+1
        until b[Ry,Rx]=Clear;
        b[Ry,Rx]:=Rabbit
      end;
      // body or wall
      Up,Rt,Dn,Lt,Wa: begin
        Crash:=true;
        WriteLn('Crash!!')
      end
    end;
    // moving the snake
    if not Crash then begin
      b[Hy,Hx]:=d;
      Hx:=x;
      Hy:=y;
      b[y,x]:=He;
      if dLen=0 then begin
        dx:=0;
        dy:=0;
        case b[Ty,Tx] of
          Up: dy:=-1;
          Rt: dx:= 1;
          Dn: dy:= 1;
          Lt: dx:=-1;
        end;
        b[Ty,Tx]:=Clear;
        Tx:=Tx+dx;
        Ty:=Ty+dy
      end
      else begin
        Dec(dLen);
        Inc(Len)
      end;
    end
  until (c=EscKey) or Crash;
end.



--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
a100
сообщение 16.12.2010 22:45
Сообщение #9





Группа: Пользователи
Сообщений: 6
Пол: Мужской
Реальное имя: a100

Репутация: -  0  +


спаааааасибо! буду разбираться
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
a100
сообщение 21.12.2010 11:50
Сообщение #10





Группа: Пользователи
Сообщений: 6
Пол: Мужской
Реальное имя: a100

Репутация: -  0  +


в принципе более менее разобрался)
но есть куча вопросов%)
Подскажите пожалуйста...

procedure PrintBoard;
begin
  WriteLn('Len=',Len,'  x=',Hx,'  y=',Hy,'  dLen=',dLen);
  for j:=0 to my+1 do 
  begin
    for i:=0 to mx+1 do 
    Write(CellPrint[b[j,i]+1]);
    WriteLn
  end
end;



Вот это место, Write(CellPrint[b[j,i]+1]), что оно выводит на экран, что значит?

Потом, в каком месте в коде, написано, что когда змейка идет вверх, рисовать ^ вниз V вправо > влево < и т.д.?

И по периметру стенка обозначается буквой W?

Спасибо за внимание


 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
TarasBer
сообщение 21.12.2010 12:15
Сообщение #11


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


> Вот это место, Write(CellPrint[b[j,i]+1]), что оно выводит на экран, что значит?

> Потом, в каком месте в коде, написано, что когда змейка идет вверх, рисовать ^ вниз V вправо > влево < и т.д.?

Вот в нём и написано.
Посмотри описание строки CellPrint - в ней находятся все нужные символы. То есть для вывода нужного символа достаточно просто обратиться к нужному элементу строки. Например, CellPrint[1] - это первый символ строки CellPrint, CellPrint[i] - это i-ый символ этой строки итд.
Задание таких вещей в константный массив избавляет программиста от написания большого числа однообразных ветвлений и повторяющегося кода, а значит, и от попадания на ГК.


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Lapp
сообщение 21.12.2010 15:11
Сообщение #12


Уникум
*******

Группа: Модераторы
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

Репутация: -  159  +


Спасибо, Тарас, +1 (P.S. - сделаю завтра, на сегодня лимит исчерпал..)

Цитата(a100 @ 21.12.2010 11:50) *
Потом, в каком месте в коде, написано, что когда змейка идет вверх, рисовать ^ вниз V вправо > влево < и т.д.?
Обрати внимание на эти две строчки:
  CellPrint: string= ' ^>v<0RWOM..........';
  //                  01234567890
Комментарий внизу точно позиционирован, соотнеси цифры со строкой выше. Сам по себе комментарий, конечно, ни на что не влияет, но поможет разобраться.

Цитата
И по периметру стенка обозначается буквой W?
Да. Это та же самая стенка, которую можно при желании поставить и в поле (она обозначается числом 7). Установка такой стенки по краю избавляет от необходимости делать дополнительную проверку для выхода змеи за край поля.


--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
a100
сообщение 22.12.2010 6:46
Сообщение #13





Группа: Пользователи
Сообщений: 6
Пол: Мужской
Реальное имя: a100

Репутация: -  0  +


Друзья, огромное Вам спасибо за помощь!

попробуюс)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
a100
сообщение 22.12.2010 14:31
Сообщение #14





Группа: Пользователи
Сообщений: 6
Пол: Мужской
Реальное имя: a100

Репутация: -  0  +


не получается сделать, чтоб змейка постоянно была в движении((
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 

- Текстовая версия 18.07.2025 0:23
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"