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;
namespace WinSnakeGame
{
public partial class frmSnakePlus : Form
{
#region 遊戲變量
/// <summary>
/// 貪食蛇初始長度
/// </summary>
private int snakeCount
{
get { return Convert.ToInt32(cmbSnakeCount.SelectedItem); }
}
/// <summary>
/// 貪食蛇初始大小
/// </summary>
private int snakeSize
{
get { return Convert.ToInt32(cmbSnakeSize.SelectedItem); }
}
/// <summary>
/// 食物數量
/// </summary>
private int foodCount
{
get { return Convert.ToInt32(cmbFoodCount.SelectedItem); }
}
/// <summary>
/// 爬行速度
/// </summary>
private int snakeSpeed
{
get { return Convert.ToInt32(cmbSpeed.SelectedItem); }
}
/// <summary>
/// 貪食蛇分數
/// </summary>
private int snakeScore = 0;
/// <summary>
/// 正在爬行
/// </summary>
private bool snakeAction = false;
/// <summary>
/// 爬行方向
/// </summary>
private Keys KeyCode = Keys.Right;
/// <summary>
/// 組成貪食蛇的集合
/// </summary>
private List<Label> snakeCells = new List<Label>();
/// <summary>
/// 食物集合
/// </summary>
private List<Label> foodCells = new List<Label>();
#endregion
#region 構造函數
public frmSnakePlus()
{
InitializeComponent();
}
private void frmSnakePlus_Load(object sender, EventArgs e)
{
cmbSnakeCount.SelectedItem = "1";
cmbSnakeSize.SelectedItem = "10";
cmbFoodCount.SelectedItem = "10";
cmbSpeed.SelectedItem = "100";
chbNodie.Checked = false;
InitGame();
}
#endregion
#region 遊戲控制
/// <summary>
/// 初始遊戲
/// </summary>
private void InitGame()
{
this.SnakeTimer.Stop();
this.snakeAction = false;
this.KeyPreview = true;
this.DrawPanel.Focus();
this.KeyCode = Keys.Right;
this.snakeScore = this.snakeCount;
btnStart.Enabled = true;
btnClose.Enabled = btnStop.Enabled = false;
// 清空貪食蛇
snakeCells.Clear();
// 清空食物
foodCells.Clear();
// 清空遊戲區域
DrawPanel.Controls.Clear();
InitSnake();
InitFood();
}
/// <summary>
/// 初始化貪食蛇
/// </summary>
private void InitSnake()
{
// 初始化貪食蛇
for (int i = snakeScore - 1; i >= 0; i--)
{
// 建立方格
Label _cell = CreateCell(new Point(i * this.snakeSize, 0));
// 将方格添加到蛇身集合
snakeCells.Add(_cell);
// 繪制到遊戲區域
this.DrawPanel.Controls.Add(_cell);
}
// 顯示資訊
SnakePoint.Text = string.Format("X:{0} Y:{1} snakeScore:{2}", snakeCells[0].Location.X, snakeCells[0].Location.Y, snakeScore);
}
/// <summary>
/// 開始遊戲
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStart_Click(object sender, EventArgs e)
{
btnStop.Enabled = btnClose.Enabled = true;
btnStart.Enabled = false;
this.snakeAction = true;
this.SnakeTimer.Start();
}
/// <summary>
/// 暫停遊戲
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStop_Click(object sender, EventArgs e)
{
btnStart.Enabled = btnClose.Enabled = true;
btnStop.Enabled = false;
this.snakeAction = false;
this.SnakeTimer.Stop();
}
/// <summary>
/// 結束遊戲
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnClose_Click(object sender, EventArgs e)
{
btnStart.Enabled = true;
btnStop.Enabled = btnClose.Enabled = false;
this.InitGame();
}
/// <summary>
/// 定時控件:控制貪食蛇的自動運動
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SnakeTimer_Tick(object sender, EventArgs e)
{
int xRan = snakeCells[0].Location.X;
int yRan = snakeCells[0].Location.Y;
if (this.KeyCode == Keys.Up)
{
yRan -= this.snakeSize; //向上移動
}
else if (this.KeyCode == Keys.Down)
{
yRan += this.snakeSize; //向下移動
}
else if (this.KeyCode == Keys.Left)
{
xRan -= this.snakeSize; //向左移動
}
else if (this.KeyCode == Keys.Right)
{
xRan += this.snakeSize; //向右移動
}
bool isOut = (xRan < 0 || xRan > (this.DrawPanel.Height - this.snakeSize) || yRan < 0 || yRan > (this.DrawPanel.Height - this.snakeSize));
// 檢測貪食蛇是否在遊戲區域中
if (isOut && !chbNodie.Checked)
{
this.SnakeTimer.Stop();
MessageBox.Show("Game Over!");
this.InitGame();
return;
}
// 無敵模式:穿牆設定
else if (isOut && chbNodie.Checked)
{
if (xRan > this.DrawPanel.Width)
{
xRan = 0;
}
if (xRan < 0)
{
xRan = this.DrawPanel.Width;
}
if (yRan > this.DrawPanel.Height)
{
yRan = 0;
}
if (yRan < 0)
{
yRan = this.DrawPanel.Height;
}
}
for (int i = snakeScore - 1; i > 0; i--)
{
// 蛇身所有格子前進到前一個格子的位置
snakeCells[i].Location = new Point(snakeCells[i - 1].Location.X, snakeCells[i - 1].Location.Y);
}
// 蛇頭前進一個格子
snakeCells[0].Location = new Point(xRan, yRan);
List<Label> _findFoods = foodCells.Where(n => n.Location == snakeCells[0].Location).ToList<Label>();
for (int i = 0; i < _findFoods.Count(); i++)
{
// 消除遊戲區域中的食物
this.DrawPanel.Controls.Remove(_findFoods[i]);
//消除數組中的食物
foodCells.Remove(_findFoods[i]);
// 蛇身變長
Label _cell = CreateCell(snakeCells[snakeCells.Count - 1].Location, Color.Blue);
snakeCells.Add(_cell);
this.DrawPanel.Controls.Add(_cell);
//增加蛇身長度
snakeScore++;
}
if (foodCells.Count == 0)
{
InitFood();
}
SnakePoint.Text = string.Format("X:{0} Y:{1} snakeScore:{2}", snakeCells[0].Location.X, snakeCells[0].Location.Y, snakeScore);
}
/// <summary>
/// 監控方向鍵:改變貪食蛇的運動方向(上下左右)
/// </summary>
/// <param name="keyCode"></param>
/// <returns></returns>
protected override bool ProcessDialogKey(Keys _keyCode)
{
// 隻對上下左右按鍵做出響應
if (_keyCode == Keys.Up || _keyCode == Keys.Down || _keyCode == Keys.Left || _keyCode == Keys.Right)
{
// 記錄按下的方向鍵
this.KeyCode = _keyCode;
if (!snakeAction)
{
snakeAction = true;
SnakeTimer.Start();
btnStop.Enabled = btnClose.Enabled = true;
btnStart.Enabled = false;
}
return false;
}
else
{
return base.ProcessDialogKey(_keyCode);
}
}
#endregion
#region 生産食物
/// <summary>
/// 食物初始化
/// </summary>
private void InitFood()
{
CreateFood(foodCount);
}
/// <summary>
///生産食物
/// </summary>
/// <param name="foodCount"></param>
private void CreateFood(int foodCount)
{
Random ran = new Random();//随機類
int xRan, yRan;
for (int i = 0; i < foodCount; i++)
{
// 随機生成食物放置的X、Y坐标
xRan = ran.Next(0, this.DrawPanel.Width / this.snakeSize) * this.snakeSize;
yRan = ran.Next(0, this.DrawPanel.Height / this.snakeSize) * this.snakeSize;
if (xRan > this.DrawPanel.Width - 10 || xRan > this.DrawPanel.Height - 10)
{
xRan = ran.Next(0, this.DrawPanel.Width / snakeSize) * snakeSize;
yRan = ran.Next(0, this.DrawPanel.Height / snakeSize) * snakeSize;
}
Point FoodPoint = new Point(xRan, yRan);
// 檢索指定坐标處的子控件
var newFood = this.DrawPanel.GetChildAtPoint(FoodPoint);
if (newFood == null)
{
// 建立方格
Label _cell = CreateCell(FoodPoint, Color.White);
// 将方格添加到食物集合
foodCells.Add(_cell);
// 繪制到遊戲區域
this.DrawPanel.Controls.Add(_cell);
}
}
}
#endregion
#region 通用方法
/// <summary>
/// 建立格子
/// </summary>
/// <returns></returns>
private Label CreateCell(Point point)
{
Label _cell = new Label();
_cell.Size = new Size(this.snakeSize, this.snakeSize);
_cell.Location = point;
_cell.BackColor = Color.Red;
_cell.BorderStyle = BorderStyle.FixedSingle;
return _cell;
}
/// <summary>
/// 建立格子
/// </summary>
/// <returns></returns>
private Label CreateCell(Point point, Color color)
{
Label _cell = new Label();
_cell.Size = new Size(this.snakeSize, this.snakeSize);
_cell.Location = point;
_cell.BackColor = color;
_cell.BorderStyle = BorderStyle.FixedSingle;
return _cell;
}
#endregion
#region Event
private void btnSetting_Click(object sender, EventArgs e)
{
if (this.Height == 589)
{
this.Height = 660;
}
else
{
this.Height = 589;
}
}
/// <summary>
/// 設定初始長度
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cmbSnakeCount_SelectedIndexChanged(object sender, EventArgs e)
{
InitGame();
}
/// <summary>
/// 設定初始大小
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cmbSnakeSize_SelectedIndexChanged(object sender, EventArgs e)
{
InitGame();
}
/// <summary>
/// 設定食物數量
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cmbFoodCount_SelectedIndexChanged(object sender, EventArgs e)
{
InitGame();
}
/// <summary>
/// 開啟無敵模式
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void chbNodie_CheckedChanged(object sender, EventArgs e)
{
//InitGame();
this.KeyPreview = true;
this.DrawPanel.Focus();
}
/// <summary>
/// 設定爬行速度
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cmbSpeed_SelectedIndexChanged(object sender, EventArgs e)
{
SnakeTimer.Interval = this.snakeSpeed;
this.KeyPreview = true;
this.DrawPanel.Focus();
}
#endregion
}
}