//版本一:吃完一个就结束了。unit Unit1;interfaceuses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;type TForm1 = class(TForm) Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure Timer1Timer(Sender: TObject); procedure FormPaint(Sender: TObject); private { Private declarations } Snake: array[0..499] of TPoint; SnakeLength: Integer; Food: TPoint; Direction: TPoint; procedure DrawSnake; procedure DrawFood; procedure MoveSnake; procedure CheckCollision; public { Public declarations } end;var Form1: TForm1;implementation{$R *.dfm}const BlockSize = 10;procedure TForm1.FormCreate(Sender: TObject);begin SnakeLength := 1; Snake[0].X := 10; Snake[0].Y := 10; Food.X := 30; Food.Y := 30; Direction.X := 1; Direction.Y := 0; Timer1.Enabled := True; DoubleBuffered := True;end;procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);begin case Key of VK_UP: begin Direction.X := 0; Direction.Y := -1; end; VK_DOWN: begin Direction.X := 0; Direction.Y := 1; end; VK_LEFT: begin Direction.X := -1; Direction.Y := 0; end; VK_RIGHT: begin Direction.X := 1; Direction.Y := 0; end; end;end;procedure TForm1.FormPaint(Sender: TObject);begin DrawSnake; DrawFood;end;procedure TForm1.Timer1Timer(Sender: TObject);begin MoveSnake; CheckCollision; Repaint;end;procedure TForm1.DrawSnake;var i: Integer;begin for i := 0 to SnakeLength - 1 do begin Canvas.Brush.Color := clGreen; Canvas.FillRect(Rect(Snake[i].X * BlockSize, Snake[i].Y * BlockSize, Snake[i].X * BlockSize + BlockSize, Snake[i].Y * BlockSize + BlockSize)); end;end;procedure TForm1.DrawFood;begin Canvas.Brush.Color := clRed; Canvas.FillRect(Rect(Food.X * BlockSize, Food.Y * BlockSize, Food.X * BlockSize + BlockSize, Food.Y * BlockSize + BlockSize));end;procedure TForm1.MoveSnake;var i: Integer;begin for i := SnakeLength - 1 downto 1 do Snake[i] := Snake[i - 1]; Snake[0].X := Snake[0].X + Direction.X; Snake[0].Y := Snake[0].Y + Direction.Y;end;procedure TForm1.CheckCollision;var i: Integer;begin if (Snake[0].X = Food.X) and (Snake[0].Y = Food.Y) then begin Inc(SnakeLength); Snake[SnakeLength - 1] := Snake[SnakeLength - 2]; Food.X := Random(ClientWidth div BlockSize); Food.Y := Random(ClientHeight div BlockSize); end; if Snake[0].X < 0 then Snake[0].X := ClientWidth div BlockSize - 1; if Snake[0].X > ClientWidth div BlockSize - 1 then Snake[0].X := 0; if Snake[0].Y < 0 then Snake[0].Y := ClientHeight div BlockSize - 1; if Snake[0].Y > ClientHeight div BlockSize - 1 then Snake[0].Y := 0; for i := 1 to SnakeLength - 1 do if (Snake[0].X = Snake[i].X) and (Snake[0].Y = Snake[i].Y) then Timer1.Enabled := False;end;end.
// 吃完第一个食物就完了。哈哈。于是要求写一个完善一点的。
存在一些小问题,稍微改了一下,可以运行,还算完美。
版本二:
unit Unit1;interfaceuses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;type TDirection = (dLeft, dUp, dRight, dDown); TSnake = array[0..100] of TPoint;type TForm1 = class(TForm) Timer1: TTimer; Button1: TButton; procedure FormCreate(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure Timer1Timer(Sender: TObject); procedure Paint; override; procedure Button1Click(Sender: TObject); private { Private declarations } procedure MoveSnake; procedure DrawSnake; procedure CheckCollision; public { Public declarations } end;var Form1: TForm1; Snake: TSnake; SnakeLength: Integer; Direction: TPoint; Food: TPoint; BlockSize: Integer;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);begin Randomize; SnakeLength := 5; BlockSize := 10; Snake[0].X := ClientWidth div BlockSize div 2; Snake[0].Y := ClientHeight div BlockSize div 2; Food.X := Random(ClientWidth div BlockSize); Food.Y := Random(ClientHeight div BlockSize); Direction.X := 1; Direction.Y := 0;end;procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);begin case Key of VK_LEFT: if Direction.X <> 1 then begin Direction.X := -1; Direction.Y := 0; end; VK_UP: if Direction.Y <> 1 then begin Direction.X := 0; Direction.Y := -1; end; VK_RIGHT: if Direction.X <> -1 then begin Direction.X := 1; Direction.Y := 0; end; VK_DOWN: if Direction.Y <> -1 then begin Direction.X := 0; Direction.Y := 1; end; end;end;procedure TForm1.Timer1Timer(Sender: TObject);begin MoveSnake; CheckCollision; Repaint;end;procedure TForm1.Button1Click(Sender: TObject);begin Timer1.Enabled := True;end;procedure TForm1.DrawSnake;var i: Integer;begin Canvas.Pen.Color := clBlack; Canvas.Brush.Color := clGreen; for i := 0 to SnakeLength - 1 do Canvas.Rectangle(Snake[i].X * BlockSize, Snake[i].Y * BlockSize, Snake[i].X * BlockSize + BlockSize, Snake[i].Y * BlockSize + BlockSize); Canvas.Brush.Color := clRed; Canvas.Rectangle(Food.X * BlockSize, Food.Y * BlockSize, Food.X * BlockSize + BlockSize, Food.Y * BlockSize + BlockSize);end;procedure TForm1.MoveSnake;var i: Integer;begin for i := SnakeLength - 1 downto 1 do Snake[i] := Snake[i - 1]; Snake[0].X := Snake[0].X + Direction.X; Snake[0].Y := Snake[0].Y + Direction.Y;end;procedure TForm1.CheckCollision;var i: Integer;begin if (Snake[0].X >= ClientWidth div BlockSize) or (Snake[0].X < 0) or (Snake[0].Y >= ClientHeight div BlockSize) or (Snake[0].Y < 0) then begin Timer1.Enabled := False; ShowMessage('Game Over'); end; for i := 1 to SnakeLength - 1 do if Snake[0].X = Snake[i].X then if Snake[0].Y = Snake[i].Y then begin Timer1.Enabled := False; ShowMessage('Game Over'); end; if Snake[0].X = Food.X then if Snake[0].Y = Food.Y then begin Inc(SnakeLength); Food.X := Random(ClientWidth div BlockSize); Food.Y := Random(ClientHeight div BlockSize); end;end;procedure TForm1.Paint;var i: Integer;begin inherited; Canvas.Pen.Color := clBlack; Canvas.Brush.Color := clGreen; for i := 0 to SnakeLength - 1 do Canvas.Rectangle(Snake[i].X * BlockSize, Snake[i].Y * BlockSize, Snake[i].X * BlockSize + BlockSize, Snake[i].Y * BlockSize + BlockSize); Canvas.Brush.Color := clRed; Canvas.Rectangle(Food.X * BlockSize, Food.Y * BlockSize, Food.X * BlockSize + BlockSize, Food.Y * BlockSize + BlockSize);end;end.
object Form1: TForm1 Left = 0 Top = 0 Caption = 'Form1' ClientHeight = 455 ClientWidth = 656 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] KeyPreview = True OldCreateOrder = False OnCreate = FormCreate OnKeyDown = FormKeyDown PixelsPerInch = 96 TextHeight = 13 object Button1: TButton Left = 504 Top = 24 Width = 75 Height = 25 Caption = 'Button1' TabOrder = 0 Visible = False OnClick = Button1Click end object Timer1: TTimer Interval = 100 OnTimer = Timer1Timer Left = 304 Top = 256 endend
第三版,让他加上了网格。没有大问题,有些小细节要自己修改。
unit Unit1;interfaceuses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;type TDirection = (dLeft, dUp, dRight, dDown); TSnake = array[0..100] of TPoint;type TForm1 = class(TForm) Timer1: TTimer; Button1: TButton; procedure FormCreate(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure Timer1Timer(Sender: TObject); procedure Paint; override; procedure Button1Click(Sender: TObject); private { Private declarations } procedure MoveSnake; procedure DrawSnake; procedure DrawGrid; procedure CheckCollision; public { Public declarations } end;var Form1: TForm1; Snake: TSnake; SnakeLength: Integer; Direction: TPoint; Food: TPoint; BlockSize: Integer = 10; PlayFieldSize: Integer;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);begin Randomize; SnakeLength := 5; self.Height := self.Width; PlayFieldSize := self.Width div BlockSize - 1; Snake[0].X := ClientWidth div BlockSize div 2; Snake[0].Y := ClientHeight div BlockSize div 2; Food.X := Random(ClientWidth div BlockSize); Food.Y := Random(ClientHeight div BlockSize); Direction.X := 1; Direction.Y := 0;end;procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);begin case Key of VK_LEFT: if Direction.X <> 1 then begin Direction.X := -1; Direction.Y := 0; end; VK_UP: if Direction.Y <> 1 then begin Direction.X := 0; Direction.Y := -1; end; VK_RIGHT: if Direction.X <> -1 then begin Direction.X := 1; Direction.Y := 0; end; VK_DOWN: if Direction.Y <> -1 then begin Direction.X := 0; Direction.Y := 1; end; end;end;procedure TForm1.Timer1Timer(Sender: TObject);begin MoveSnake; CheckCollision; Repaint;end;procedure TForm1.Button1Click(Sender: TObject);begin Timer1.Enabled := True;end;procedure TForm1.DrawGrid;var i: Integer;begin Canvas.Pen.Color := clBlack; for i := 0 to PlayFieldSize do begin Canvas.MoveTo(i * BlockSize, 0); Canvas.LineTo(i * BlockSize, PlayFieldSize * BlockSize); Canvas.MoveTo(0, i * BlockSize); Canvas.LineTo(PlayFieldSize * BlockSize, i * BlockSize); end;end;procedure TForm1.DrawSnake;var i: Integer;begin Canvas.Pen.Color := clBlack; Canvas.Brush.Color := clGreen; for i := 0 to SnakeLength - 1 do Canvas.Rectangle(Snake[i].X * BlockSize, Snake[i].Y * BlockSize, Snake[i].X * BlockSize + BlockSize, Snake[i].Y * BlockSize + BlockSize); Canvas.Brush.Color := clRed; Canvas.Rectangle(Food.X * BlockSize, Food.Y * BlockSize, Food.X * BlockSize + BlockSize, Food.Y * BlockSize + BlockSize);end;procedure TForm1.MoveSnake;var i: Integer;begin for i := SnakeLength - 1 downto 1 do Snake[i] := Snake[i - 1]; Snake[0].X := Snake[0].X + Direction.X; Snake[0].Y := Snake[0].Y + Direction.Y;end;procedure TForm1.CheckCollision;var i: Integer;begin if (Snake[0].X >= ClientWidth div BlockSize) or (Snake[0].X < 0) or (Snake[0].Y >= ClientHeight div BlockSize) or (Snake[0].Y < 0) then begin Timer1.Enabled := False; ShowMessage('Game Over'); end; for i := 1 to SnakeLength - 1 do if Snake[0].X = Snake[i].X then if Snake[0].Y = Snake[i].Y then begin Timer1.Enabled := False; ShowMessage('Game Over'); end; if Snake[0].X = Food.X then if Snake[0].Y = Food.Y then begin Inc(SnakeLength); Food.X := Random(ClientWidth div BlockSize); Food.Y := Random(ClientHeight div BlockSize); end;end;procedure TForm1.Paint;var i: Integer;begin inherited; DrawGrid; Canvas.Pen.Color := clBlack; Canvas.Brush.Color := clGreen; for i := 0 to SnakeLength - 1 do Canvas.Rectangle(Snake[i].X * BlockSize, Snake[i].Y * BlockSize, Snake[i].X * BlockSize + BlockSize, Snake[i].Y * BlockSize + BlockSize); Canvas.Brush.Color := clRed; Canvas.Rectangle(Food.X * BlockSize, Food.Y * BlockSize, Food.X * BlockSize + BlockSize, Food.Y * BlockSize + BlockSize);end;end.