📄 gridcontrol.cs
字号:
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 + -