using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing;
using System.Data;
using FastReport;
using FastReport.Matrix;
using FastReport.Data;
using FastReport.Dialog;
using FastReport.Barcode;
using FastReport.Table;
using FastReport.Utils;
namespace FastReport
{
public class ReportScript
{
const string BOMB = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAABmJLR0QA9QD1APUHT9P6AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAB3RJTUUH4wMaCBo1zI1h5wAABDFJREFUSMe1lltsVFUUhr+158ylFGgRKZcgBLEKJBRCXwhPQjQ+gQQYifFB1CkxNcCUBjtUZCIkdQq9AS/QGY0amkAo0WcTX9GYQKAKMUUw0jQCLQpF2rnu5cO0Y1s62GlwJyfZ5/x7r/+s+xIKXarUtX62CqCx5r0riBR03eQDQqdOTAyIgNFqjFbnIzvc8mXhhAz5NoXaosvWqRIOh3PaAQiyXpD1o7+Fw2FeVeXDltiyRya5KZ/YvPbYe7R9psdtHqi1bzTu3XkOINQWq7Qqa4xoO4BV2WlEL0WCgYsAdS3t28WYM2lNlzTVvD9QEGGWINoPMhvlC0XfcrlcbrfjQkQQYCiRHDmaUvS0IO8AfZFgoCyfTOeJHhb5GiVgjOx4acliZhYXYYwZtqTy/ZVrSNaP7mEyBL4pKGjCp04BUNcW26FWA4vml7Fu9QpS6RRXb/zOjz/9woXLV7lwOUc2NoihKtQWfRugpvnsxCYNNUdn4og7sidwD2D/8dhKtXTNmVXK4gVlXLtxi78HB3PaTSp7MCsbg+/+DBA6FptNWlOR2qoBCTVHwYgb4S5QimofInOG/xZUJ9Rkkjk7Ius+ShlWUzlJH0RPF814FO8GFvJ0Vw+WFyN7A/F/fajK/Dv9cYVKgIy1udOj9wVjqhiTWYOQGBs0Ihw4EFSsXeTzuKlcXo61irVK5YpyfB4PAD6PpzDM6yWdMYsiNQGdOC2MWRVPpui6fhNjstbu6r6Jtdnz8WSyYEyE1cClCQkrypdUJZKpp+pAr8ddBXyeLw+V/3mN0bDr+m8xgbXGSM5Uo/fj3yeDqdVo3kqjqpd9Hg8V5Utzzq8oXzomMArBbCbN3T/7+x8v3qq0fNQof8x9do5LuZOxFtdwVRm9H//+JCyRTNLT28sMb9GCh/HB253HG3RMWvz6/EKfS7kIjBHiGlfO/gsTIJVKcaunB1R5GB/8AfDkNBxf2hS9Lci8qQbFgwcD9N3rz04GqndQnYvIX2opE7dNm0htFVgtsujSSDAgjcGq+VZdK7OKT66GGmMYHBqip7eXu/19iAjPlM54ufN4w7zOE59KJiMviNtO62yNPN6Aa5rP0lq7nTdrD+6fVjStobi4GLfj4DgORgxIthdmMhnS6TTxeJz7AwMkEgmMMRgRfEW+uq8iHx+pPXqU5n37Jt/x/Xvq21WpUtU8/VkmmrGi54417Cx8iALUsgnA5/V95zhOjmTkGen8jsvB6/N+m51zdOOUxsTN1QenI8xVq9s6msKvnG09LCWlJX6vxxsaVbbqZpWWbDvTekg6joRfU6vbBJm3ufrg9IIJXU56g5JZrpWvn/f7/QA8Z4Y6O5rCjUA30N3R9MmR2OHQeQC/30967cbzGJa5nPSGgsN7Y/BQXmzrrvqTW3fVn5zK3SmtLbv3r9qyu75iKnf/AUwGAJZD/bErAAAAAElFTkSuQmCC\"/>";
const string FLAG = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAB3RJTUUH4wMWDhQIRD3DcgAAALVJREFUSMftlb0NwkAMhT+bCiZhAJKGhI4lkOioqBiFnYDmwhqsQIGUmJYiiu4XUfAaS6fT+/xOlg++re3uIJ+1iNr90QBsXQjwWGK2wQ0NVSpIxw6fMwAqEZy1OJN4kHrcSQJpQDNRII141iCQJsyCF0gzDN1KBDc0nOVWBnA3o9Yrp9wJOjNquVCL0QHkSuBlHAMIMg4BRBlPAhZ9uvGkmozbdDTBvH+Rq2OlsP6AH/30c+oNWNZbLqWMv1wAAAAASUVORK5CYII=\"/>";
private FastM1nesweeper fastM1nesweeper = new FastM1nesweeper();
private TableObject table = null;
private bool IsUpdated = false;
private FillBase backUpFill;
private int clickCount;
private DateTime startTime;
private int bombCount;
private void RefreshPreview(Base obj)
{
if(obj!=null)
{
Report.PreparedPages.ModifyPage(0, obj.Page as ReportPage);
foreach(System.Reflection.PropertyInfo info in Report.GetType().GetProperties())
{
if(info.Name == "Preview")
{
object preview = info.GetValue(Report, null);
if(preview !=null)
foreach(System.Reflection.MethodInfo method in preview.GetType().GetMethods())
{
if(method.Name == "Refresh")
{
try{
method.Invoke(preview, null);
}
catch{
}
}
}
}
}
}
table = null;
}
private bool IsRightClick(EventArgs e)
{
foreach(System.Reflection.PropertyInfo info in e.GetType().GetProperties())
{
if(info.Name == "Button")
{
try{
return 2097152 == (int)info.GetValue(e, null);
}
catch{
return false;
}
}
}
return false;
}
private void TableCell_Click(object sender, EventArgs e)
{
if(clickCount == 0)
startTime = DateTime.Now;
clickCount++;
IsUpdated = false;
TextObjectBase cell = sender as TextObjectBase;
if(table == null)
{
table = cell.Parent.Parent as TableObject;
}
if(!fastM1nesweeper.IsGameOver)
{
if(table!=null )
{
for(int i =0; i< fastM1nesweeper.Width; i ++)
for(int j = 0; j < fastM1nesweeper.Height; j++)
{
if(sender == table[i,j])
{
if(IsRightClick(e))
fastM1nesweeper.FlagClick(i,j);
else
fastM1nesweeper.OpenClick(i,j);
}
}
if(bombCount != fastM1nesweeper.BombCount)
{
bombCount = fastM1nesweeper.BombCount;
TextObject tBombsBox = table.Page.FindObject("tBombs") as TextObject;
if(tBombsBox!=null)
{
tBombsBox.Text = fastM1nesweeper.BombCount.ToString();
IsUpdated = true;
}
}
if(fastM1nesweeper.IsGameOver)
{
TextObject labelGameOver = table.Page.FindObject("LabelGameOver") as TextObject;
TextObject labelClicks = table.Page.FindObject("LabelClicks") as TextObject;
TextObject labelTime = table.Page.FindObject("LabelTime") as TextObject;
TextObject labelScore = table.Page.FindObject("LabelScore") as TextObject;
TextObject tClicksBox = table.Page.FindObject("tClicks") as TextObject;
TextObject tTimeBox = table.Page.FindObject("tTime") as TextObject;
TextObject tScoreBox = table.Page.FindObject("tScore") as TextObject;
if(labelGameOver!=null)
{
if(fastM1nesweeper.IsVictory)
{
labelGameOver.Text="Victory!";
labelGameOver.TextFill = new SolidFill(Color.Green);
}
else
{
labelGameOver.Text="GAME OVER";
labelGameOver.TextFill = new SolidFill(Color.Red);
}
IsUpdated = true;
}
if(labelClicks!=null)
{
labelClicks.Text = "Clicks:";
IsUpdated = true;
}
if(labelTime!=null)
{
labelTime.Text = "Time:";
IsUpdated = true;
}
if(labelScore!=null)
{
labelScore.Text = "Score:";
IsUpdated = true;
}
if(tClicksBox !=null)
{
tClicksBox.Text = clickCount.ToString();
IsUpdated = true;
}
if(tTimeBox !=null)
{
TimeSpan span = DateTime.Now - startTime;
tTimeBox.Text = span.ToString();
IsUpdated = true;
}
if(tScoreBox != null)
{
tScoreBox.Text = fastM1nesweeper.Score.ToString();
IsUpdated = true;
}
}
if(IsUpdated)
RefreshPreview(table);
}
}
}
private void TableMap_ManualBuild(object sender, EventArgs e)
{
for(int i =0; i< fastM1nesweeper.Height; i ++)
{
TableMap.PrintRow(0);
for(int j =0; j< fastM1nesweeper.Width; j ++)
{
TableMap.PrintColumn(0);
}
}
}
private void _StartReport(object sender, EventArgs e)
{
fastM1nesweeper.CellUpdated += CellUpdated;
clickCount = 0;
}
private void CellUpdated(object sender, FastM1nesweeperCellUpdateEventArgs e)
{
ReDraw(e.X,e.Y,e.Cell);
}
private void ReDraw(int x, int y, FastM1nesweeperCell cell)
{
if(cell != null)
{
IsUpdated = true;
if(cell.IsFlag)
{
table[x,y].Text = FLAG;
}
else if(!cell.IsOpened)
{
table[x,y].Text = "";
}
else if(cell.IsBomb)
{
table[x,y].Font = new Font(table[x,y].Font.FontFamily, 0.1f);
table[x,y].Text = BOMB;
}
else if(cell.Number > 0)
{
table[x,y].Text = cell.Number.ToString();
}
else table[x,y].Text = "";
if(cell.IsDefused)
{
table[x,y].Fill = new SolidFill(Color.LightGreen);
table[x,y].Border.Color = Color.Green;
table[x,y].Border.Lines = BorderLines.All;
table[x,y].Border.Width = 1;
}
else if (cell.IsOpened)
{
if(cell.IsBomb)
{
table[x,y].Fill = new SolidFill(Color.MistyRose);
table[x,y].Border.Color = Color.Red;
table[x,y].Border.Lines = BorderLines.All;
table[x,y].Border.Width = 1;
}
else
{
table[x,y].Fill = new SolidFill(Color.WhiteSmoke);
}
}
else
{
table[x,y].Fill = backUpFill.Clone();
}
//table[x,y].Border.Style = LineStyle.Solid;
//table[x,y].Border.Color = Color.Gainsboro;
}
}
private void Page1_StartPage(object sender, EventArgs e)
{
int width;
int height;
bombCount = 0;
Int32.TryParse(tRows.Text, out height);
if(height < 5) height = 5; else if (height > 25) height = 25;
Int32.TryParse(tColumns.Text, out width);
if(width < 5) width = 5; else if (width > 25) width = 25;
Int32.TryParse(tBombs.Text, out bombCount);
if(bombCount < 1) bombCount = 1; else if (bombCount > height * width ) bombCount = height * width ;
TableMap[0,0].Width = 28;
TableMap[0,0].Height = 28;
TableMap.Left = (Data1.Width - (TableMap[0,0].Width * width))/2;
fastM1nesweeper.ReStart(width,height,bombCount);
backUpFill = TableMap[0,0].Fill.Clone();
}
}
public class FastM1nesweeper
{
private bool isGameOver = true;
public event EventHandler<FastM1nesweeperCellUpdateEventArgs> CellUpdated;
public int Score
{
get
{
try
{
int result = 0;
if(map!=null && isStarted)
{
for(int i =0; i< Width; i++)
for(int j = 0; j< Height; j++)
{
if (map[i, j].IsOpened || IsVictory)
result += GetScore(map[i, j].Number);
}
}
return result;
}
catch
{
}
return 0;
}
}
private int GetScore(int number)
{
switch(number)
{
case 1: return 1;
case 2: return 3;
case 3: return 6;
case 4: return 10;
case 5: return 15;
case 6: return 21;
case 7: return 28;
case 8: return 36;
default: return 0;
}
}
public FastM1nesweeperCell GetCell(int x, int y)
{
if (IsAllRight(x, y))
{
return map[x, y];
}
return null;
}
public bool IsGameOver
{
get { return isGameOver; }
}
public bool IsVictory
{
get { return isVictory; }
}
public int Width
{
get { return width; }
}
public int Height
{
get { return height; }
}
public int BombCount
{
get { return bombCount; }
}
private FastM1nesweeperCell[,] map;
private int width;
private int height;
private int bombCount;
private bool isStarted;
private bool isVictory;
public void ReStart(int width, int height, int bombCount)
{
isStarted = false;
isGameOver = false;
this.width = width;
this.height = height;
this.bombCount = bombCount;
isVictory = false;
map = new FastM1nesweeperCell[width, height];
for(int i =0; i< width; i++)
for(int j =0; j< height; j++)
{
map[i, j] = new FastM1nesweeperCell();
}
}
private bool IsAllRight(int x, int y)
{
return map!=null && !IsGameOver && x >= 0 && x < width && y >= 0 && y < height;
}
public void FlagClick(int x, int y)
{
if (isStarted && IsAllRight(x,y))
{
if (!map[x, y].IsOpened)
{
map[x, y].IsFlag = !map[x, y].IsFlag;
if (CellUpdated != null)
{
CellUpdated.Invoke(this, new FastM1nesweeperCellUpdateEventArgs(x, y, map[x, y]));
}
}
}
}
private void GenerateMap(int x, int y)
{
if (!isStarted)
{
Random r = new Random();
int bombs = 0;
if(bombCount > width * height / 2)
{
bombCount = width * height / 2;
}
for(int i = 0; i< bombCount; i++)
{
int tryes = 256;
while(tryes > 0)
{
int left = r.Next(0, width);
int top = r.Next(0, height);
if (left == x && top == y || map[left, top].IsBomb)
tryes--;
else
{
map[left, top].IsBomb = true;
bombs++;
break;
}
}
}
for(int i =0; i< width; i++)
{
for(int j = 0; j< height; j++)
{
if (!map[i, j].IsBomb)
{
for (int i1 = -1; i1 <= 1; i1++)
for (int j1 = -1; j1 <= 1; j1++)
{
FastM1nesweeperCell cell = GetCell(i + i1, j + j1);
if (cell != null && cell.IsBomb)
{
map[i, j].Number++;
}
}
}
}
}
bombCount = bombs;
isStarted = true;
}
}
public void OpenClick(int x, int y)
{
GenerateMap(x, y);
if (IsAllRight(x, y))
{
if (!map[x, y].IsOpened && !map[x,y].IsFlag)
{
if(map[x,y].IsBomb)
{
GameOverBomb();
}
else
{
OpenRecursive(x, y);
}
CheckGameOverDefused();
}
}
}
private void CheckGameOverDefused()
{
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
if (!map[i, j].IsOpened && !map[i, j].IsBomb)
{
return;
}
}
}
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
if (map[i, j].IsBomb)
{
map[i, j].IsOpened = true;
map[i, j].IsDefused = true;
if (CellUpdated != null)
{
CellUpdated.Invoke(this, new FastM1nesweeperCellUpdateEventArgs(i, j, map[i, j]));
}
}
}
}
isVictory = true;
isGameOver = true;
}
private void OpenRecursive(int x, int y)
{
if (IsAllRight(x, y))
{
if(!map[x,y].IsOpened && !map[x,y].IsFlag )
{
map[x, y].IsOpened = true;
if (map[x, y].Number == 0)
{
for (int i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++)
if (!(i == 0 && j == 0))
OpenRecursive(x + i, y + j);
}
if (CellUpdated != null)
{
CellUpdated.Invoke(this, new FastM1nesweeperCellUpdateEventArgs(x, y, map[x, y]));
}
}
}
}
private void GameOverBomb()
{
for(int i =0; i< width; i++)
{
for(int j =0; j< height; j++)
{
if(map[i,j].IsBomb)
{
map[i, j].IsOpened = true;
if (CellUpdated != null)
{
CellUpdated.Invoke(this, new FastM1nesweeperCellUpdateEventArgs(i, j, map[i, j]));
}
}
}
}
isGameOver = true;
}
}
public class FastM1nesweeperCell
{
private bool isFlag;
private bool isBomb;
private int number;
private bool isOpened;
private bool isDefused;
public bool IsFlag
{
get { return isFlag; }
set { isFlag = value; }
}
public bool IsBomb
{
get { return isBomb; }
set { isBomb = value; }
}
public bool IsOpened
{
get { return isOpened; }
set { isOpened = value; }
}
public int Number
{
get { return number; }
set { number = value; }
}
public bool IsDefused
{
get { return isDefused; }
set { isDefused = value; }
}
}
public class FastM1nesweeperCellUpdateEventArgs : EventArgs
{
private int x;
private int y;
FastM1nesweeperCell cell;
public int X
{
get { return x; }
}
public int Y
{
get { return y; }
}
public FastM1nesweeperCell Cell
{
get { return cell; }
}
public FastM1nesweeperCellUpdateEventArgs(int x, int y, FastM1nesweeperCell cell)
{
this.x = x;
this.y = y;
this.cell = cell;
}
}
}