Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > [Delphi] Создание игры морской бой


Автор: hqpz 12.12.2009, 20:39
Всем привет. Буду краток. У меня есть код игры морской бой на Delphi, но там кораблики всегда стоят в одном положении. Помогите пожалуйста сделать рандомную расстановку корабликов. Ничего не получается. =(  Там в самом конце кода прописаны ячейки с корабликами. Помогите переделать на рандомную, как для меня так и для противника
Код

Unit Unit1;

Interface

Uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

Type
  TPole = Array [1..10, 1..10] Of Byte;
  TForm1 = Class(TForm)
    Pole1: TImage;
    Pole2: TImage;
    procedure Pole2MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
  Private
    { Private declarations }
  Public
    { Public declarations }
    // процедура отрисовки поля.
    Procedure PrintPole(Pole : TImage; P : TPole);
    // Бот
    Procedure Bot;
  End;


Var
  Form1: TForm1;
  // игровое поле 1 - поле игрока. 2 - пполе врага.
  // 1 - выстрел. 2 -корабль 20 - мертвый корабль. 3 - корабль врага.
  P1, P2 : TPole;
  P1Win, P2Win : Integer; // отслеживаем выигрыш.


Implementation


{$R *.dfm}


// бот
Procedure TForm1.Bot;
Var
  x, y : integer;
Begin
Randomize;
// определим координаты выстрела
Repeat
  x := Random(10) + 1;
  y := Random(10) + 1;
Until (P1[x,y] <> 1) And (P1[x,y] <> 20);
// если бот промахнулся
If (P1[x,y] <> 1) And (P1[x,y] <> 2) Then P1[x,y] := 1;
// если бот попал в корабль
If P1[x,y] = 2 Then Begin
  P1[x,y] := 20;
  P2Win := P2Win + 1;
End;
// отрисуем наше поле
PrintPole(Pole1, P1);
End;



// процедура отрисовки поля
// Pole - компонент TImage на котором надо рисовать
// P - массив, который надо отрисовать
Procedure TForm1.PrintPole(Pole : TImage; P : TPole);
Var
  i, x, y : Integer;
Begin
// заливка цветом "вода".
Pole.Canvas.Brush.Style := bsSolid;
Pole.Canvas.Brush.Color := RGB(200, 200, 200);
Pole.Canvas.Rectangle(0,0,200,200);
// рисуем сетку.
For i := 1 To 10 Do
  Begin
    Pole.Canvas.MoveTo(i * 20, 0);
    Pole.Canvas.LineTo(i * 20, 200);
    Pole.Canvas.MoveTo(0, i * 20);
    Pole.Canvas.LineTo(200, i * 20);
  End;
// пройдемся по массиву и отрисуем поля
For x := 1 To 10 Do
  Begin
    For y := 1 To 10 Do
      Begin
        If P[x, y] = 1 Then Begin // рисуем выстрел
          Pole.Canvas.Brush.Style := bsSolid;
          Pole.Canvas.Brush.Color := RGB(0, 0, 0);
          Pole.Canvas.Ellipse((x-1) * 20 + 4, (y-1) * 20 + 4, (x-1) * 20 + 16, (y-1) * 20 + 16);
        End;
        // если мы пытаемся отрисовать вражеский кораблик, то цикл начинается снова
        If IntToStr(P[x, y])[1] = '3' Then Continue;
        If IntToStr(P[x, y])[1] = '2' Then Begin // рисуем корабли
            Pole.Canvas.Brush.Style := bsSolid;
            Pole.Canvas.Brush.Color := RGB(200, 5, 5);
            Pole.Canvas.Rectangle((x-1) * 20, (y-1) * 20, (x-1) * 20 + 21, (y-1) * 20 + 21);
        End;
        If IntToStr(P[x, y])[2] = '0' Then Begin // рисуем мертвые части корабля
          Pole.Canvas.Brush.Color := RGB(0, 0, 0);
          Pole.Canvas.MoveTo((x-1) * 20 , (y-1) * 20);
          Pole.Canvas.LineTo((x-1) * 20 + 20, (y-1) * 20 + 20);
          Pole.Canvas.MoveTo((x-1) * 20 + 20 , (y-1) * 20);
          Pole.Canvas.LineTo((x-1) * 20, (y-1) * 20 + 20);
        End;
      End;
  End;
// проверим, а может ктото уже выйграл
If P1Win = 20 Then Begin ShowMessage('вы победитель!'); Application.Terminate; End;
If P2Win = 20 Then Begin ShowMessage('пока неудачник'); Application.Terminate; End;
End;



// процедура обработки целчка по вражескому полю
Procedure TForm1.Pole2MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
Var
  i : Integer;
  Mis : Boolean;
Begin
// определим чему равен x.
For i := 0 To 9 Do
  If (x >= 20 * i) And (x <= 20 + i * 20) Then
    Begin
      x := i + 1;
      Break;
    End;
// определим чему равен y.
For i := 0 To 9 Do
  If (y >= 20 * i) And (y <= 20 + i * 20) Then
    Begin
      y := i + 1;
      Break;
    End;
// присвоим значение выстрела указанному элементу массива
// если мы сюда уже стреляли
If (P2[x,y] = 1) Or (P2[x,y] = 20) Then Begin
  ShowMessage('тут уже стреляли');
  Mis := True;
End;
// если мы промахнулись
If (P2[x,y] <> 1) And (P2[x,y] <> 3) And (P2[x,y] <> 20) Then P2[x,y] := 1;
// если мы попали в корабль врага
If P2[x,y] = 3 Then Begin
  P2[x,y] := 20;
  P1Win := P1Win + 1;
End;
// Оотрисуем поле врага
PrintPole(Pole2, P2);
// заставим бота ответить нам (если мы не промахнулись).
If Mis = False Then Bot;
End;



// при создании формы
Procedure TForm1.FormCreate(Sender: TObject);
Begin
//заполним массив  (сделаем вид игры)
// наше поле
// рисуем пару кораблей
P1[8,8] := 2;
P1[7,1] := 2;
P1[7,10] := 2;
P1[6,10] := 2;
P1[5,5] := 2; P1[5,6] := 2;
P1[8,3] := 2; P1[9,3] := 2;
P1[4,8] := 2; P1[5,8] := 2;
P1[3,3] := 2; P1[4,3] := 2; P1[5,3] := 2;
P1[2,7] := 2; P1[2,8] := 2; P1[2,9] := 2;
P1[1,1] := 2; P1[1,2] := 2; P1[1,3] := 2; P1[1,4] := 2;
// поле врага
// нарисуем пару кораблей
P2[1,1] := 3;
P2[10,1] := 3;
P2[1,8] := 3;
P2[8,5] := 3;
P2[6,6] := 3; P2[6,7] := 3;
P2[9,9] := 3; P2[9,10] := 3;
P2[9,7] := 3; P2[10,7] := 3;
P2[5,2] := 3; P2[6,2] := 3; P2[7,2] := 3;
P2[3,10] := 3; P2[4,10] := 3; P2[5,10] := 3;
P2[3,3] := 3; P2[3,4] := 3; P2[3,5] := 3; P2[3,6] := 3;
// заставим отрисовать поля
PrintPole(Pole1, P1);
PrintPole(Pole2, P2);
End;

End.


Автор: Sanaff 13.12.2009, 18:35
Рандомная расстановка кораблей - дело непростое. они же разнонго размера и положение можно менять (ветик/гориз)
В принципе можно, алгоритм примерно такой:
Ставим в ранд. место самый большой корабль
Вокруг его клетки помечаем как занятые.
Генерируем ранд. координаты. если это свободная клетка, ставим корабль, если нет, повтор генерации.
Повторяем, пока не поставим все корабли.
Если не поставились все, то самое простое -тупо всё начать заново, чтобы окатов не делать.
Всё равно не на скорость этот кусок кода.


А вот это меня поразило:
// определим чему равен x.
For i := 0 To 9 Do
  If (x >= 20 * i) And (x <= 20 + i * 20) Then
    Begin
      x := i + 1;
      Break;
    End;

Вот так не проще
If (x >= 0) And (x <= 200) Then
x = (x\20)+1;
или как там целочисленное деление


Автор: hqpz 13.12.2009, 21:40
Да там проблема собственно в том, что кораблик постоянно вылезает за пределы поля- либо на следующую строчку или просто за пределы, ну или залезает на поле противника. Как только я не пробовал прописывать условия, ничего не получается, он их просто не замечает. Щас сижу в отчаянии =(  не знаю что и делать. А срок курсовой следующая неделя ((((((

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)