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; } } }