Страницы

пятница, 9 мая 2014 г.

Игра кости

Разработка программы, моделирующей игру «Кости» (Delphi 7)

Создаем в Delphi программу – игру «Кости». Приложение должно предоставлять пользователю возможность сделать ставку, ввести загаданное число, получить результат броска кубиков. Значит, нужно реализовать игровую логику и графический интерфейс. Создадим главную форму, в которой и будет происходить все действие, еще пару форм можно добавить самостоятельно (например, форму справки или сведений о разработчике).

 Правила игры:

Играющий называет любое число в диапазоне от 2 до 12 и ставку, которую он делает в этот ход. Программа с помощью датчика случайных чисел дважды выбирает числа от 1 до 6 (“бросает кубик”, на гранях которого цифры от 1 до 6). Если сумма выпавших цифр меньше 7 и играющий задумал число меньшее 7, он выигрывает сделанную ставку. Если сумма выпавших цифр больше 7 и играющий задумал число большее 7, он также выигрывает сделанную ставку. Если играющий угадал сумму цифр, он получает в четыре раза больше очков, чем сделанная ставка. Ставка проиграна, если не имеет места ни одна из описанных ситуаций. В начальный момент у играющего 100 очков. В программе должно присутствовать графическое изображение поверхности кубика при каждом ходе игрока.

Алгоритм работы приложения

Запишем алгоритм в словесной форме:
1) Ввод загаданного числа.
2) Ввод ставки.
3) Бросок кубиков.
4) Вычисления
5) Новая ставка или завершение работы в случае отсутствия денег на счете пользователя.
Блок-схема на рисунке:


Входными данными являются введенное число и ставка, выходными – результат вычислений и сумма на счете.
Разработка программы
Опишем главную форму приложения – frmMain (на первом рисунке).
На следующем рисунке приведена форма в режиме разработки


Свойства формы:
BorderIcons = [biSystemMenu, biMinimize]
Caption = Игра в кости
Icon- Cast.ico  (свой рисунок)
ClientWidth = 800
ClientHeight = 580
Position = poScreenCenter ( по центру экрана)
Menu = MainMenu1
События:
OnCreate – FormCreate - проводит действия по настройке интерфейса при запуске программы

Свойства и события компонентов формы:
1 - Компонент MainMenu1: TMainMenu.
2 - Компонент edNumber: TEdit. Это поле ввода для ввода загаданного числа от 2 до 12.
Свойства: стандартные
3 - Компонент edRate: TEdit. Это поле ввода для ввода ставки.. Ставка должна быть меньше суммы на счете. Сумма на счет в начале работы программы равна 100 очков.
4 - Компонент btnThrow: TButton. Кнопка для начала имитации броска.
Свойства: стандартные
События:
OnClick – btnThrowClick, обрабатывает нажатие левой кнопки мыши.
5 - Компонент m1: TMemo. Многострочное поле. В программе используется для отображения информации о ходе игры (очень удобный протокол).
6 - Компонент btnNewGame: TButton. Кнопка, начинающая новую игру.
Событие: OnClick – btnNewGameClick.
7 - Компонент btnClose: TButton. Кнопка для завершения работы программы
События:
OnClick - btnCloseClick .
8 - Компонент lblResult: TLabel. Надпись для отображения выпавших чисел и их суммы.
9 - Компонент lblWin: TLabel. Надпись для информирования о проигрыше или победе.
10 - Компоненты im1: TImage и im2: TImage. Используются для рисования граней кубиков.
Свойства: стандартные , без изменений
События: нет
11 - Компонент lblSum: TLabel. Надпись, отображающая сумму на счете пользователя.

Текст программы с комментариями приведен ниже.
При создании формы устанавливается начальная сумма, равная 100, и выводятся пустые кубики.
Вывод на экран изображений кубиков осуществляет функция DrawBones. Каждый при рисовании она вызывается два раза, так как кубика всегда два. Аргументы функции – компонент TImage и выпавшая сумма. В зависимости от суммы выводится количество кружков на рисунке.
Кнопка btnNewGame отвечает за начало новой игры. При этом все поля, включая поле memo, очищаются, а сумма очков становится равной 100.
При нажатии кнопки btnThrow начинается процесс вбрасывания кубиков и расчета сумм. При этом сначала проверяется, все ли данные введены (ставка, загаданное число). Если данные не все, то выдается предупреждение. Ставка не должна превышать имеющуюся сумму очков.
Остальные процедуры в тексте осуществляют действия по кнопкам меню и закрытие формы.
Текст программного модуля MainFrm.pas
unit MainFrm;
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, Menus, jpeg;

type
  TfrmMain = class(TForm)
    Panel1: TPanel;
    Image1: TImage;
    MainMenu1: TMainMenu;
    N1: TMenuItem;
    N2: TMenuItem;
    N3: TMenuItem;
    Label1: TLabel;
    lblSum: TLabel;
    Label2: TLabel;
    edNumber: TEdit;
    Label3: TLabel;
    edRate: TEdit;
    btnThrow: TButton;
    im1: TImage;
    im2: TImage;
    Label4: TLabel;
    lblResult: TLabel;
    btnNewGame: TButton;
    btnClose: TButton;
    lblWin: TLabel;
    Bevel2: TBevel;
    m1: TMemo;
    Bevel3: TBevel;
    N4: TMenuItem;
    N5: TMenuItem;
    N6: TMenuItem;
    N7: TMenuItem;
    procedure btnThrowClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btnCloseClick(Sender: TObject);
    procedure btnNewGameClick(Sender: TObject);
    procedure DrawBones(im: TImage; num: integer);
    procedure N6Click(Sender: TObject);
    procedure N4Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

  {переменные - сумма на счете и счетчик бросков}
  sum, iThrowCount: integer;


implementation

uses AboutFrm, HelpFrm;

{$R *.dfm}

{рисование кубика, в параметрах - изображение и выпавшая сумма}
procedure TfrmMain.DrawBones(im: TImage; num: integer);
begin
  with im.Canvas do
  begin
  {рисуем пустой белый прямоугольник}
    brush.color := clWhite;
    rectangle(0,0,105,105);

    {в начале игры выпавших чисел нет, поэтому рисуем линии}
    if num = 0 then
    begin
      moveto(0,0);
      LineTo(105,105);
      moveto(105,0);
      LineTo(0,105);
    end
    else
    begin
    {в зависимости от выпавшего числа рисуем разное количество точек на грани}
      brush.Color := clBlack;
      case num of
      1: begin
        ellipse(45,45,60,60);
      end;
      2: begin
        ellipse(15,75,30,90);
        ellipse(75,15,90,30);
      end;
      3: begin
        ellipse(15,75,30,90);
        ellipse(45,45,60,60);
        ellipse(75,15,90,30);
      end;
      4: begin
        ellipse(15,75,30,90);
        ellipse(75,15,90,30);
        ellipse(15,15,30,30);
        ellipse(75,75,90,90);
      end;
      5: begin
        ellipse(15,75,30,90);
        ellipse(75,15,90,30);
        ellipse(45,45,60,60);
        ellipse(15,15,30,30);
        ellipse(75,75,90,90);
      end;
      6: begin
        ellipse(15,75,30,90);
        ellipse(45,55,60,30);
        ellipse(75,15,90,30);
        ellipse(15,15,30,30);
        ellipse(45,75,60,90);
        ellipse(75,75,90,90);
      end;
      end;
    end;
  end;
end;

procedure TfrmMain.btnThrowClick(Sender: TObject);
var
  num1, num2, number, rate: integer;
  {первое и второе выпавшие числа, загаданное число, ставка}
begin
  Randomize();
  {если не введено число}
  if length(edNumber.Text)=0 then
  begin
    ShowMessage('Загадайте и введите число от 1 до 6');
    exit;
  end;
   {если не введена ставка}
  if length(edRate.Text)=0 then
  begin
    ShowMessage('Сделайте ставку');
    exit;
  end;
   {если ставка больше суммы на счете}
  if StrToInt(edRate.Text) > sum then
  begin
    ShowMessage('Введенная ставка превышает сумму вашего счета');
    edRate.Text:=inttostr(sum);
  end;
   {если загаданное число меньше 2 или больше 12}
  if (StrToInt(edNumber.Text) > 12) or (StrToInt(edNumber.Text) < 2) then
  begin
    ShowMessage('Загаданное число должно быть больше 2 и меньше 12');
    exit;
  end;

  number := StrToInt(edNumber.Text);
  rate := StrToInt(edRate.Text);
   {кидаем кубики}
  num1 := random(5) + 1;
  DrawBones(im1,num1);
  num2 := random(5) + 1;
   {рисуем кубики с учетом выпавших чисел}
  DrawBones(im2,num2);
  lblResult.Caption := IntToStr(num1) + ' + ' + IntToStr(num2) +  ' = ' + IntToStr(num1+num2);

   {записываем все в поле Мемо}
  iThrowCount := iThrowCount + 1;
  m1.Lines.Add('-------------');
  m1.Lines.Add(IntToStr(iThrowCount) + ' бросок');
  m1.Lines.Add('-------------');
  m1.Lines.Add('Загадано число: ' + edNumber.Text);
  m1.Lines.Add('Выпали числа: ' + IntToStr(num1) + ' + ' + IntToStr(num2) +  ' = ' + IntToStr(num1+num2));
  m1.Lines.Add('Ставка: ' + edRate.Text);
   {расчет выигрыша или проигрыша}
  if (number=(num1+num2)) then
  begin
    lblWin.Caption := 'Вы угадали выпавшее число!';

    sum := sum + 4*rate;
    lblSum.Caption := IntToStr(sum);
    m1.Lines.Add('Угадано выпавшее число. Сумма ставки увеличивается в четыре раза');
    m1.Lines.Add('Выигранная сумма: ' + IntToStr(4*rate));
  end
  else if (((number>7) and ((num1+num2)>7)) or ((number<7) and ((num1+num2)<7))) then
  begin
     lblWin.Caption := 'Вы выиграли!';
     sum := sum + rate;
     lblSum.Caption := IntToStr(sum);
     m1.Lines.Add('Игрок выиграл ' +  IntToStr(rate));
  end
  else
  begin
     lblWin.Caption := 'Вы проиграли!';
     sum := sum - rate;
     m1.Lines.Add('Игрок проиграл ' +  IntToStr(rate));

     if sum <= 0 then
     begin
        lblSum.Font.Color:=clRed;
        lblWin.Caption := 'Вы проиграли! Игра окончена.';
        edNumber.Enabled:=false;
        edRate.Enabled:=false;
        btnThrow.Enabled:=false;
        m1.Lines.Add('Игра окончена');
     end;
     lblSum.Caption := IntToStr(sum);
  end;
  m1.Lines.Add('Сумма на счете ' +  IntToStr(sum));

end;

 {при создании формы}
procedure TfrmMain.FormCreate(Sender: TObject);
begin
  sum := 100;
  DrawBones(im1,0);
  DrawBones(im2,0);
  m1.Lines.Add('Начальная сумма - 100 очков');
end;

procedure TfrmMain.btnCloseClick(Sender: TObject);
begin
  Close();
end;

{новая игра}
procedure TfrmMain.btnNewGameClick(Sender: TObject);
var
 i: integer;
begin
    edNumber.Enabled:=true;
    edRate.Enabled:=true;
    btnThrow.Enabled:=true;
    lblSum.Font.Color:= clTeal;
    lblSum.Caption := '100';
    lblResult.Caption := '';
    lblWin.Caption := '';
    edNumber.Clear;
    edRate.Clear;
    sum := 100;
    iThrowCount := 0;
    DrawBones(im1,0);
    DrawBones(im2,0);
    if m1.Lines.Count > 0 then
      for i := 0 to m1.Lines.Count-1 do
        m1.Lines.Delete(0);
    m1.Lines.Add('Начальная сумма - 100 очков');
end;

procedure TfrmMain.N6Click(Sender: TObject);
begin
  frmAbout.Show();
end;

procedure TfrmMain.N4Click(Sender: TObject);
begin
  frmHelp.Show;
end;
end.