⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gridcontrol.cs

📁 英国几乎所有的报纸都刊登数独游戏
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using System.Xml;

namespace SuDokuSolution
{
	/// <summary>
	/// The Main grid holding all cells
	/// </summary>
	public class GridControl : Control
	{
		
		/// <summary>
		/// Bitmap buffer to avoid flickering
		/// </summary>
		internal Bitmap bufferBitmap;

		/// <summary>
		/// Buffer Graphics to avoid flickering
		/// </summary>
		private Graphics bufferGraphics; 

		/// <summary>
		/// array of Graphical cell
		/// </summary>
		internal GraphicalCell [,] cellGrid;
		
		/// <summary>
		/// Size of cell
		/// </summary>
		private Size cellSize;

		/// <summary>
		/// Size of subcell
		/// </summary>
		private Size subCellSize;

		/// <summary>
		/// Starting location of the cell grid
		/// </summary>
		private Point offset;

		/// <summary>
		/// Whether to redraw or not the entire control
		/// </summary>
		private bool redrawBool=true;

		/// <summary>
		/// Has the Game started
		/// </summary>
		private bool isGameStarted=false;

		/// <summary>
		/// Flag to set auto updation of candidate nbs true
		/// </summary>
		internal bool autoUpdate=false;

		/// <summary>
		/// Flag to set simultaneous checking true
		/// </summary>
		internal bool simultaneousCheck=false;

		/// <summary>
		/// Raised when  a new gam starts
		/// </summary>
		public EventHandler StartGame;

		/// <summary>
		/// Raised when a Game Ends
		/// </summary>
		public EventHandler EndGame;

		/// <summary>
		/// Counter to keep track of filled cells
		/// </summary>
		private int currentlyFilledCells=0;

		/// <summary>
		/// whether generating a puzzle manually or not
		/// </summary>
		internal bool generatingPuzzle=false;

		/// <summary>
		/// Constructor for the grid control
		/// </summary>
		public GridControl()
		{  
			
		}

		/// <summary>
		/// Raises Start Game Event
		/// </summary>
		/// <param name="e">Eventargs e</param>
		public void OnStartGame(EventArgs e)
		{
			if(StartGame!=null)
				StartGame(this,e);
		}
        
		/// <summary>
		/// Raises End Game Event
		/// </summary>
		/// <param name="e">Eventargs e</param>
		public void OnEndGame(EventArgs e)
		{
			if(EndGame!=null)
				EndGame(this,e);
		}

		/// <summary>
		/// Initiallize all the data of the class
		/// </summary>
		public void InitiallizeGrid()
		{
			cellGrid=new GraphicalCell[Constants.nbOfCells,Constants.nbOfCells];
			Brush selBrush=DrawingTools.WhiteBrush;
			int HB,VB;
			for(int row=0;row<Constants.nbOfCells;row++)
			{
				HB=row/Constants.nbOfLines;
				for(int col=0;col<Constants.nbOfCells;col++)
				{					
					VB=col/Constants.nbOfLines;
					if((HB+VB)%2!=0)
						selBrush=DrawingTools.BackGroundBrush1;
					else
						selBrush=DrawingTools.BackGroundBrush2;
					cellGrid[row,col]=new GraphicalCell(this,selBrush);
				}
			}

			computeLocations();
		}

		/// <summary>
		/// To compute location,size etc of grid or cells
		/// </summary>
		public void computeLocations()
		{
			if(cellGrid==null)
				return;
			
			cellSize=new Size(((Size.Width/Constants.nbOfCells)/Constants.nbOfLines)*Constants.nbOfLines,
                ((Size.Height/Constants.nbOfCells)/Constants.nbOfLines)*Constants.nbOfLines);
            subCellSize=new Size(cellSize.Width/Constants.nbOfLines,cellSize.Height/Constants	.nbOfLines);
            
			//Fonts
			DrawingTools.SelectedFont=new Font(FontFamily.GenericSansSerif,cellSize.Height/2,FontStyle.Bold);
			DrawingTools.miniSelectedFont=new Font(FontFamily.GenericSansSerif,subCellSize.Height/2,FontStyle.Regular); 

			offset=new Point();
			offset.X=(Size.Width-cellSize.Width*Constants.nbOfCells)/2;
			offset.Y=(Size.Height-cellSize.Height*Constants.nbOfCells)/2;

			for(int row=0;row<Constants.nbOfCells;row++)
			{
				for(int col=0;col<Constants.nbOfCells;col++)
				{
					cellGrid[row,col].cellSize=cellSize;
					cellGrid[row,col].subCellSize=subCellSize;
					cellGrid[row,col].cellLocation=new Point(offset.X+col*cellSize.Width,
						offset.Y+row*cellSize.Height);
					cellGrid[row,col].cellRect=new Rectangle(cellGrid[row,col].cellLocation.X+1,
						cellGrid[row,col].cellLocation.Y+1,cellSize.Width-2,cellSize.Height-2);
				}
			}
            redrawBool=true;
			Invalidate();
		}


		/// <summary>
		/// Method called when control is resized
		/// </summary>
		/// <param name="e"> Event Args</param>
		protected override void OnResize(EventArgs e)
		{
			if(bufferBitmap==null || bufferBitmap.Size!=Size)
			{
				if(Size.Width!=0 && Size.Height!=0)//if not minimized
				{
                    bufferBitmap=new Bitmap(Size.Width,Size.Height);
					bufferGraphics=Graphics.FromImage(bufferBitmap);
					computeLocations();
				}
			}

            base.OnResize(e);
		}


		/// <summary>
		/// called when Control has to be painted
		/// </summary>
		/// <param name="e">Paint Event Args</param>
		protected override void OnPaint(PaintEventArgs e)
		{
			if(redrawBool)
			{
				Pen selPen=DrawingTools.MediumPen;
				bufferGraphics.FillRectangle(DrawingTools.WhiteBrush,e.ClipRectangle);
				for(int i=0;i<=Constants.nbOfCells;i++)
				{
					if(i%Constants.nbOfLines==0)
						selPen=DrawingTools.DarkPen;
					else
						selPen=DrawingTools.MediumPen;
					//horizontal line
					bufferGraphics.DrawLine(selPen,offset.X,offset.Y+cellSize.Height*i,
						offset.X+cellSize.Width*Constants.nbOfCells,offset.Y+cellSize.Height*i);
					
					//vertical line
					bufferGraphics.DrawLine(selPen,offset.X+cellSize.Width*i,offset.Y,
						offset.X+cellSize.Width*i,offset.Y+cellSize.Height*Constants.nbOfCells); 					
				}

				for(int row=0;row<Constants.nbOfCells;row++)
				{
					for(int col=0;col<Constants.nbOfCells;col++)
					{
						cellGrid[row,col].Paint(bufferGraphics);
					}
				}
			}	

			e.Graphics.DrawImage(bufferBitmap,0,0);
			redrawBool=false;
		}
		
		/// <summary>
		/// OnPaintBackground - overrides PaintBackground to avoid flickering
		/// </summary>
		/// <param name="e">paint event args</param>
		protected override void OnPaintBackground(PaintEventArgs e)
		{}

		/// <summary>
		/// force cell repaint 
		/// </summary>
		/// <param name="rcell">the cell to be redrawn</param>
		public void RedrawCell(GraphicalCell rcell)
		{
			rcell.Paint(bufferGraphics);
			Invalidate();
		}

		protected override void OnMouseDown(MouseEventArgs e)
		{
            if(!Enabled)
				return;
			
			if(e.X<offset.X || e.Y<offset.Y || 
				e.X>(offset.X+cellSize.Width*Constants.nbOfCells)||
				e.Y>(offset.Y+cellSize.Height*Constants.nbOfCells))
				return;
			
			int row,col;
			col=(e.X-offset.X)/cellSize.Width;
			row=(e.Y-offset.Y)/cellSize.Height;
			if(col>=Constants.nbOfCells || row >=Constants.nbOfCells)
				return;                    

			#region Code for processing clicks while playing game
			if(!generatingPuzzle)
			{
				if(!isGameStarted)
					ExecuteStartGame();
            
				bool changed=false;
				if(e.Clicks==1)
				{
					cellGrid[row,col].MouseDown(e);
				}
				else if(e.Clicks==2)
				{
					cellGrid[row,col].DoubleClick(e);
					changed=true;
				}

				if(changed)
				{
					//if an invalid nb has been selected mark it as error
					if(cellGrid[row,col].cellData.problemNb!=Constants.NoNumber 
						&& !cellGrid[row,col].cellData.candidateNb.Contains(cellGrid[row,col].cellData.problemNb))
					{
						cellGrid[row,col].MarkError=true;      //if an invalid nb has been clicked
					}
					else
					{
						cellGrid[row,col].MarkError=false;
						autoUpdateMarkedCandidates(row,col);					
					}				
					this.redrawBool=true;
					currentlyFilledCells+=(cellGrid[row,col].cellData.problemNb==Constants.NoNumber )?(-1):1;
					if(currentlyFilledCells==Constants.nbOfCells*Constants.nbOfCells)
						CheckEndGame();
				}
				base.OnMouseDown(e);
				Invalidate();
			}
				#endregion

			#region code for processing clicks while generating a problem manually
			else
			{
				GraphicalCell gr=cellGrid[row,col];
				int clickedNb=gr.getClickedNb(e.X-gr.cellLocation.X,e.Y-gr.cellLocation.Y);
			
				if(gr.cellData.problemNb==Constants.NoNumber)
				{
					gr.cellData.problemNb=clickedNb;
					gr.cellData.readOnly=true;
				}
				else
					gr.cellData.problemNb=Constants.NoNumber;
                RedrawCell(gr);
			}
			#endregion
		}
		

	
		/// <summary>
		///autometically update all candidate nbs when a valid nb is selected in a cell
		///  The Validity check should be performed by the calling function
		/// </summary>
		/// <param name="row"></param>
		/// <param name="col"></param>
		private void autoUpdateMarkedCandidates(int row,int col)
		{
			if(autoUpdate)
			{			
				for(int i=0;i<9;i++)
				{
					searchCandidates(row,i);
					cellGrid[row,i].CheckedNbs.Clear();				
					foreach(object ob in cellGrid[row,i].cellData.candidateNb)
						cellGrid[row,i].CheckedNbs.Add(ob);
					if(row!=i)
					{
						searchCandidates(i,col);
						cellGrid[i,col].CheckedNbs.Clear();				
						foreach(object ob in cellGrid[i,col].cellData.candidateNb)
							cellGrid[i,col].CheckedNbs.Add(ob);				
					}
				}
			
				int HB=(int)(row/Constants.nbOfLines);
				int VB=(int) (col/Constants.nbOfLines);            
                          
				for(int i=HB*Constants.nbOfLines;i<(HB+1)*Constants.nbOfLines;i++)
				{
					for(int j=VB*Constants.nbOfLines;j<(VB+1)*Constants.nbOfLines;j++)
					{
						if(i!=row && j!=col )
						{
							//MessageBox.Show("Row ="+i+",col="+j);
							searchCandidates(i,j);
							cellGrid[i,j].CheckedNbs.Clear();				
							foreach(object ob in cellGrid[i,j].cellData.candidateNb)
								cellGrid[i,j].CheckedNbs.Add(ob);				
						}
					}
				}
			}

			else
			{
				for(int i=0;i<9;i++)
				{
					searchCandidates(row,i);
					if(row!=i)
					{
						searchCandidates(i,col);
					}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -