winforms Exception (C#)
本文关键字:Exception winforms | 更新日期: 2023-09-27 18:11:43
我目前正在制作一款可以自行解决问题的贪吃蛇游戏,但是当我激活它时,通常是在成功点击30次之后,我的应用程序在System.drawing.dll或System.Windows.Forms.dll中崩溃。
这个问题通常发生在命令"Application.DoEvents()"中,但它也发生在其他几个地方。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Threading;
using System.IO;
namespace Snake
{
enum Directions
{
Right = 1,
Left = -1,
Up = 2,
Down = -2,
NoDirection = 0
}
public partial class GameForm : Form
{
#region Data Members
SnakeGame gmGame;
Point pCurrFood;
Directions dirFirstDirection;
Directions dirSecondDirection;
Directions dirHelpDirection;
Color DEFAULT_COLOUR = Color.White;
const int SEGMENT_HEIGHT = 10;
const int SEGMENT_WIDTH = 10;
#endregion
#region Ctor
public GameForm()
{
InitializeComponent();
this.gmGame = new SnakeGame();
this.dirFirstDirection = Directions.NoDirection;
this.dirSecondDirection = Directions.NoDirection;
}
#endregion
#region Other Methods
private void PaintSegment(Graphics gGraphics, Point pnPoint, Color cColour)
{
Pen Pen = new Pen(cColour);
Rectangle Rectangle = new Rectangle(pnPoint.X,
pnPoint.Y,
SEGMENT_HEIGHT,
SEGMENT_WIDTH);
gGraphics.DrawRectangle(Pen, Rectangle);
Brush Brush = new SolidBrush(cColour);
gGraphics.FillRectangle(Brush, Rectangle);
}
private void PlaceNewFood()
{
Random rRand = new Random();
int nHeight = rRand.Next(this.panel1.Size.Height);
int nWidth = rRand.Next(this.panel1.Size.Width);
while ((nHeight % 10 != 0) || (nWidth % 10 != 0))
{
nHeight = rRand.Next(this.panel1.Size.Height - 10);
nWidth = rRand.Next(this.panel1.Size.Width - 10);
while (this.gmGame.SnakeQueue.Contains(new Point(nWidth, nHeight)))
{
nHeight = rRand.Next(this.panel1.Size.Height);
nWidth = rRand.Next(this.panel1.Size.Width);
}
}
this.pCurrFood = new Point(nWidth, nHeight);
this.PaintSegment(this.panel1.CreateGraphics(), this.pCurrFood, Color.Red);
}
private void SelfSolve()
{
this.dirFirstDirection = (Directions)(Math.Sign(this.gmGame.SnakeHead.Y -
this.pCurrFood.Y) * 2);
this.dirSecondDirection = (Directions)Math.Sign(this.pCurrFood.X -
this.gmGame.SnakeHead.X);
this.ManageSnake(this.dirFirstDirection, this.dirSecondDirection);
}
private bool WillCollide(Point pnPointToCheck)
{
return ((pnPointToCheck.X > this.panel1.Size.Width) ||
(pnPointToCheck.Y > this.panel1.Size.Height) ||
(pnPointToCheck.X * pnPointToCheck.Y < 0) ||
(this.gmGame.SnakeQueue.Contains(pnPointToCheck)));
}
private void ManageSnake(Directions dirFirstSnakeDirection,
Directions dirSecondSnakeDirection)
{
Point pnNewHead = this.gmGame.SnakeHead;
switch (dirFirstSnakeDirection)
{
case (Directions.Down):
{
if (this.WillCollide(new Point(pnNewHead.X, pnNewHead.Y + SEGMENT_HEIGHT)))
{
this.ManageSnake(Directions.NoDirection, dirSecondSnakeDirection);
}
else
{
pnNewHead.Y += SEGMENT_HEIGHT;
dirHelpDirection = Directions.Down;
}
break;
}
case (Directions.Up):
{
if (this.WillCollide(new Point(pnNewHead.X, pnNewHead.Y - SEGMENT_HEIGHT)))
{
this.ManageSnake(Directions.NoDirection, dirSecondSnakeDirection);
}
else
{
pnNewHead.Y -= SEGMENT_HEIGHT;
dirHelpDirection = Directions.Up;
}
break;
}
case (Directions.NoDirection):
{
switch (dirSecondSnakeDirection)
{
case (Directions.Right):
{
if (this.WillCollide(new Point(pnNewHead.X + SEGMENT_WIDTH, pnNewHead.Y)))
{
this.ManageSnake(this.dirHelpDirection, dirSecondSnakeDirection);
}
else
{
pnNewHead.X += SEGMENT_WIDTH;
}
break;
}
case (Directions.Left):
{
if (this.WillCollide(new Point(pnNewHead.X - SEGMENT_WIDTH, pnNewHead.Y)))
{
this.ManageSnake(this.dirHelpDirection, dirSecondSnakeDirection);
}
else
{
pnNewHead.X -= SEGMENT_WIDTH;
}
break;
}
}
break;
}
}
this.gmGame.AddSegment(pnNewHead);
if (this.gmGame.SnakeHead.Equals(this.pCurrFood))
{
this.lblScoreNum.Text = (int.Parse(this.lblScoreNum.Text) + 1).ToString();
this.PlaceNewFood();
}
else
{
this.PaintSegment(this.panel1.CreateGraphics(),
(Point)this.gmGame.SnakeQueue.Peek(),
DEFAULT_COLOUR);
this.gmGame.RemoveSegment();
}
this.PaintSegment(this.panel1.CreateGraphics(),
this.gmGame.SnakeHead,
Color.Green);
Thread.Sleep(5);
Application.DoEvents();
this.SelfSolve();
}
#endregion
#region Events
private void GameForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
this.PlaceNewFood();
this.SelfSolve();
}
else if (e.KeyCode == Keys.Escape)
{
this.Close();
}
else if (e.KeyCode == Keys.Space)
{
MessageBox.Show("Frozen, press OK to continue");
}
}
private void GameForm_ClientSizeChanged(object sender, EventArgs e)
{
this.PaintSegment(this.panel1.CreateGraphics(), new Point(210, 250), Color.Green);
this.PaintSegment(this.panel1.CreateGraphics(), new Point(220, 250), Color.Green);
this.PaintSegment(this.panel1.CreateGraphics(), new Point(230, 250), Color.Green);
this.PaintSegment(this.panel1.CreateGraphics(), new Point(240, 250), Color.Green);
this.PaintSegment(this.panel1.CreateGraphics(), new Point(250, 250), Color.Green);
}
#endregion
}
}
我知道这是很多代码,但由于我不确定问题的根源在哪里,我不得不复制所有的代码。
如果您能给我指个方向,我将不胜感激。Thanks in advance:)
注:我知道这个算法有缺陷,稍后我会讲到。
这是因为您在方法中不断进行递归。例如:
Thread.Sleep(5);
Application.DoEvents();
this.SelfSolve();
你的方法基本上永远不会结束。
你应该使用一个计时器,并在计时器内调用SelfSolve(),这应该可以解决你的问题。当使用计时器时,你不必自己调用DoEvents,因为winforms计时器无论如何都会将调用作为消息发送给你的方法,消息循环将处理调用和其他消息。
SelfSolve
不应该直接调用ManageSnake
,而应该将其调度到稍后的某个时刻运行。否则你会得到无限递归SelfSolve
-> ManageSnake
-> SelfSolve
等等