195 lines
5.5 KiB
C#
195 lines
5.5 KiB
C#
using laba3.Subprograms;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using static System.Formats.Asn1.AsnWriter;
|
|
|
|
namespace ProgLab1.GUI
|
|
{
|
|
public partial class SnakeForm : Form
|
|
{
|
|
private System.Windows.Forms.Timer gameTimer = new System.Windows.Forms.Timer();
|
|
private List<Point> snake = new List<Point>();
|
|
private Point food = Point.Empty;
|
|
private int tileSize = 20;
|
|
private string direction = "Right";
|
|
private string nextDirection = "Right";
|
|
private bool isGameOver = false;
|
|
private int score = 0;
|
|
|
|
private Level level;
|
|
private int sizex;
|
|
private int sizey;
|
|
|
|
private Random rand = new Random();
|
|
|
|
public SnakeForm(Level level, int sizex, int sizey, Form onCloseForm)
|
|
{
|
|
this.level = level;
|
|
this.sizex = sizex;
|
|
this.sizey = sizey;
|
|
InitializeComponent();
|
|
InitializeGame();
|
|
|
|
this.FormClosing += new FormClosingEventHandler((object sender, FormClosingEventArgs e) => {onCloseForm.Show();});
|
|
}
|
|
|
|
private void InitializeGame()
|
|
{
|
|
this.Text = "Snake Game";
|
|
this.ClientSize = new Size(sizex*tileSize, sizey*tileSize);
|
|
this.DoubleBuffered = true;
|
|
this.KeyDown += OnKeyDown;
|
|
this.Paint += OnPaint;
|
|
|
|
gameTimer.Interval = level switch
|
|
{
|
|
Level.Low => 250,
|
|
Level.Medium => 125,
|
|
Level.High => 50,
|
|
_ => 500,
|
|
}; ;
|
|
gameTimer.Tick += OnGameTick;
|
|
gameTimer.Start();
|
|
|
|
ResetGame();
|
|
}
|
|
|
|
private void ResetGame()
|
|
{
|
|
snake.Clear();
|
|
snake.Add(new Point(2, sizey/2)); // Initial snake head
|
|
snake.Add(new Point(1, sizey/2)); // Initial snake body
|
|
snake.Add(new Point(0, sizey/2)); // Initial snake tail
|
|
direction = "Right";
|
|
nextDirection = "Right";
|
|
isGameOver = false;
|
|
SpawnFood();
|
|
}
|
|
|
|
private void SpawnFood()
|
|
{
|
|
int maxX = sizex;
|
|
int maxY = sizey;
|
|
do
|
|
{
|
|
food = new Point(rand.Next(0, maxX), rand.Next(0, maxY));
|
|
} while (snake.Contains(food));
|
|
}
|
|
|
|
private void OnGameTick(object sender, EventArgs e)
|
|
{
|
|
if (isGameOver) return;
|
|
|
|
// Update direction
|
|
direction = nextDirection;
|
|
|
|
// Calculate new head position
|
|
Point newHead = snake[0];
|
|
switch (direction)
|
|
{
|
|
case "Up": newHead.Y--; break;
|
|
case "Down": newHead.Y++; break;
|
|
case "Left": newHead.X--; break;
|
|
case "Right": newHead.X++; break;
|
|
}
|
|
|
|
// Check collisions
|
|
if (newHead.X < 0 || newHead.Y < 0 ||
|
|
newHead.X >= sizex ||
|
|
newHead.Y >= sizey ||
|
|
snake.Contains(newHead))
|
|
{
|
|
isGameOver = true;
|
|
gameTimer.Stop();
|
|
Dialogs.GameOver($"Счёт: {score}");
|
|
this.Close();
|
|
return;
|
|
}
|
|
|
|
// Move snake
|
|
snake.Insert(0, newHead);
|
|
if (newHead == food)
|
|
{
|
|
SpawnFood();
|
|
addScore();
|
|
}
|
|
else
|
|
{
|
|
snake.RemoveAt(snake.Count - 1); // Remove tail
|
|
}
|
|
|
|
this.Invalidate(); // Redraw
|
|
}
|
|
|
|
private void OnPaint(object sender, PaintEventArgs e)
|
|
{
|
|
Graphics g = e.Graphics;
|
|
|
|
// Draw snake
|
|
foreach (Point p in snake)
|
|
{
|
|
DrawTile(g, p.X, p.Y, Brushes.Green);
|
|
}
|
|
|
|
// Draw food
|
|
DrawTile(g, food.X, food.Y, Brushes.Red);
|
|
|
|
// Draw grid (optional)
|
|
for (int x = 0; x < this.ClientSize.Width; x += tileSize)
|
|
{
|
|
for (int y = 0; y < this.ClientSize.Height; y += tileSize)
|
|
{
|
|
g.DrawRectangle(Pens.Gray, x, y, tileSize, tileSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawTile(Graphics g, int x, int y, Brush brush)
|
|
{
|
|
g.FillRectangle(brush, x * tileSize, y * tileSize, tileSize, tileSize);
|
|
}
|
|
|
|
private void OnKeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
if (isGameOver && e.KeyCode == Keys.R)
|
|
{
|
|
ResetGame();
|
|
gameTimer.Start();
|
|
return;
|
|
}
|
|
|
|
switch (e.KeyCode)
|
|
{
|
|
case Keys.Up: if (direction != "Down") nextDirection = "Up"; break;
|
|
case Keys.Down: if (direction != "Up") nextDirection = "Down"; break;
|
|
case Keys.Left: if (direction != "Right") nextDirection = "Left"; break;
|
|
case Keys.Right: if (direction != "Left") nextDirection = "Right"; break;
|
|
}
|
|
}
|
|
|
|
private void addScore()
|
|
{
|
|
score += level switch
|
|
{
|
|
Level.Low => 50,
|
|
Level.Medium => 100,
|
|
Level.High => 250,
|
|
_ => 1,
|
|
};
|
|
}
|
|
public enum Level
|
|
{
|
|
Low,
|
|
Medium,
|
|
High
|
|
}
|
|
}
|
|
}
|