using CDSAE3_Lian_Lian_Kan.Boards; using CDSAE3_Lian_Lian_Kan.Forms.Interface; using NAudio.Gui; using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using static CDSAE3_Lian_Lian_Kan.Etcs; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window; namespace CDSAE3_Lian_Lian_Kan.Forms { public partial class GameControl : UserControl, IGameControl { IBoard board = Etcs.curAlgorithm switch { Algorithm.Array => new Board(), Algorithm.Graph => new Graph_Board(), _ => new Board() }; IGameMode? iGameMode; Queue<((int, int), Single_Block)> queue = new Queue<((int, int), Single_Block)>();//y,x bool do_search = false; List hint_blocks = new List(); bool doRandomGift = false; bool doSubScore = false; Dictionary<(int, int), (GiftArgs.GiftType, PictureBox)> giftBlock = new(); public GameControl() { } public GameControl(ActionloadFinished) { InitializeComponent(); DoubleBuffered = true; initWorker.WorkerReportsProgress = true; initWorker.WorkerSupportsCancellation = true; this.loadFinished = loadFinished; initWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWorker); initWorker.RunWorkerCompleted += InitWorker_RunWorkerCompleted; } Action? loadFinished = null; private void InitWorker_RunWorkerCompleted(object? sender, RunWorkerCompletedEventArgs e) { Etcs.loadFinished = true; loadFinished?.Invoke(0); } public void GameControl_Load(object sender, EventArgs e) { if (Etcs.current_difficulty == Etcs.Difficulty.challenge) doSubScore = doRandomGift = true; Etcs.gameForm = this; iGameMode = Etcs.gameModeForm; Console.WriteLine("start"); Etcs.loadFinished = false; initWorker.RunWorkerAsync(); Console.WriteLine("end"); } protected override void OnPaint(PaintEventArgs e) { Console.WriteLine(e); base.OnPaint(e); } private void bgWorker_DoWorker(object? sender, DoWorkEventArgs e) { playPanel_set(board.make_board()); } void playPanel_set(int[,] bd) { SuspendLayout(); playPanel_size_change(); for (int i = 0; i < _row; i++) for (int j = 0; j < _column; j++) { Console.WriteLine(i.ToString() + j.ToString()); if (bd[i, j] == -1) { var x = new Single_Block((j, i)); AddItem(x, i, j); _index.Add((j, i), x); } else { var x = new Single_Block(bd[i, j], Etcs.def_Color, Etcs.sel_Color, (j, i)); AddItem(x, i, j); _index.Add((j, i), x); } } Invoke(() => ResumeLayout()); } private void AddItem(Single_Block x, int i, int j) { Invoke(() => { x.Size = new Size((int)single_width, (int)single_height); x.Location = new Point((int)(j * single_width), (int)(i * single_height)); Controls.Add(x); }); } /// /// 由form和to两个点获取方向 /// /// 起始点 /// 终点 /// Etcs.Direction get_Direction((int, int) from, (int, int) to) //x,y { if (from.Item1 == to.Item1) if (from.Item2 > to.Item2) return Etcs.Direction.up; else return Etcs.Direction.down; else if (from.Item1 > to.Item1) return Etcs.Direction.left; else return Etcs.Direction.right; } /// /// 设置单个点方向 /// /// /// /// /// /// async Task set_PathAsync((int, int) point, Etcs.Direction direction, List blocks, int wait_time, bool is_hint) { if (wait_time != 0) await Task.Delay(wait_time); Single_Block? control = _index.ContainsKey((point.Item1, point.Item2)) ? _index[(point.Item1, point.Item2)] : null; if (control != null) { if (is_hint) control.hint_path(direction); else control.to_path(direction); blocks.Add(control); } } async Task to_path((int, int) from, (int, int) to, bool include_end, Etcs.Direction extra_Direction, List blocks, int wait_time, bool is_hint) { var direction = get_Direction(from, to); switch (direction) { case Etcs.Direction.up: for (int i = from.Item2 - 1; i != to.Item2; i--) await set_PathAsync((from.Item1, i), Etcs.Direction.up_down, blocks, wait_time, is_hint); break; case Etcs.Direction.down: for (int i = from.Item2 + 1; i != to.Item2; i++) await set_PathAsync((from.Item1, i), Etcs.Direction.up_down, blocks, wait_time, is_hint); break; case Etcs.Direction.right: for (int i = from.Item1 + 1; i != to.Item1; i++) await set_PathAsync((i, from.Item2), Etcs.Direction.left_right, blocks, wait_time, is_hint); break; case Etcs.Direction.left: for (int i = from.Item1 - 1; i != to.Item1; i--) await set_PathAsync((i, from.Item2), Etcs.Direction.left_right, blocks, wait_time, is_hint); break; } if (include_end) { direction = ((int)direction & 3) > 0 ? (Etcs.Direction)((int)direction << 2) : (Etcs.Direction)((int)direction >> 2); direction = direction | extra_Direction; await set_PathAsync(to, direction, blocks, wait_time, is_hint); } } async Task path_drawerAsync(List<(int, int)> path, int wait_time, List blocks, bool is_hint) { switch (path.Count) { case 2: await to_path(path[0], path[1], false, Etcs.Direction.none, blocks, wait_time, is_hint); break; case 3: var extra_direction = get_Direction(path[1], path[2]); await to_path(path[0], path[1], true, extra_direction, blocks, wait_time, is_hint); await to_path(path[1], path[2], false, Etcs.Direction.none, blocks, wait_time, is_hint); break; case 4: Etcs.Direction extra_directionA = get_Direction(path[1], path[2]), extra_directionB = get_Direction(path[2], path[3]); await to_path(path[0], path[1], true, extra_directionA, blocks, wait_time, is_hint); await to_path(path[1], path[2], true, extra_directionB, blocks, wait_time, is_hint); await to_path(path[2], path[3], false, Etcs.Direction.none, blocks, wait_time, is_hint); break; } } internal void set_tip() { if (queue.Count != 1) return; List> paths = board.get_tip(queue.Peek().Item1); foreach (var path in paths) _ = path_drawerAsync(path, 0, hint_blocks, true); } internal void de_set_tip() { for (int i = 0; i < hint_blocks.Count; i++) hint_blocks[i].de_path(); hint_blocks.Clear(); } public void Selected_Handler(Single_Block sender, SelectedEventArgs e) { Task.Run(() => { iGameMode?.De_pause(this, e); if (e.be_selected) { switch (queue.Count) { case 0: queue.Enqueue((e.position, sender)); if (do_search) { de_set_tip(); set_tip(); } break; case 1: var (posa, sendera) = queue.Dequeue(); var posb = e.position; var (could, path) = board.test(posa, posb); if (could) { board.decrease(posa, posb); _ = Block_ClearAsync(path); while (queue.Count() > 0) queue.Dequeue(); foreach (var item in new[] { posa, posb }) { if (giftBlock.TryGetValue(item, out (GiftArgs.GiftType, PictureBox) result)) { iGameMode!.GetGift_Handler(this, new GiftArgs { giftType = result.Item1 }); DeleteGiftPicture(item, result); } } if (doRandomGift) { Random random = new(); if (random.Next(0, 10) < 1) { SetGiftPicture(board.GetRandomBlock(), (GiftArgs.GiftType)(random.Next(1, 3) - 1)); } } } else { if (do_search) { de_set_tip(); set_tip(); } if (doSubScore) { iGameMode!.Score_Change(this, new ChangeScoreArgs { add = false, score = 200 }); } queue.Enqueue((e.position, sender)); sendera.deselect(); } break; } } else { switch (queue.Count) { case 0: break; case 1: if (queue.Peek().Item1 == e.position) { queue.Dequeue(); if (do_search) de_set_tip(); } break; } } }); } private void DeleteGiftPicture((int, int) item, (GiftArgs.GiftType, PictureBox) result) { Invoke(() => { result.Item2.Visible = false; result.Item2.SendToBack(); result.Item2.Dispose(); giftBlock.Remove(item); }); } private void SetGiftPicture((int, int)pos , GiftArgs.GiftType type) { var (picWidth, picHeight) = (single_width / 3, single_height / 3); PictureBox picture = new PictureBox { Image = type switch { GiftArgs.GiftType.Search => Properties.Resources.w_search, GiftArgs.GiftType.ReMake => Properties.Resources.w_exchange, _ => Properties.Resources.trans }, Size = new Size((int)picWidth, (int)picHeight), SizeMode = PictureBoxSizeMode.Zoom, Location = new Point((int)(((pos.Item1 + 1) * single_width) - picWidth), (int)(pos.Item2 * single_height)) }; Invoke(() => Controls.Add(picture)); Invoke(() => picture.BringToFront()); giftBlock.TryAdd(pos, (type, picture)); } async Task Block_ClearAsync(List<(int, int)>? path) { if (do_search == true) foreach (Single_Block single_Block in hint_blocks) single_Block.de_path(); List blocks = new List(); if (path == null) return; await path_drawerAsync(path, 20, blocks, false); Single_Block? controlA = _index.ContainsKey((path[0].Item1, path[0].Item2)) ? _index[(path[0].Item1, path[0].Item2)] : null; Single_Block? controlB = _index.ContainsKey((path.Last().Item1, path.Last().Item2)) ? _index[(path.Last().Item1, path.Last().Item2)] : null; Etcs.info_Audio_Processer.play_random_break_soundScape(); if (controlA != null && controlB != null) { controlA.destroyAsync(); controlB.destroyAsync(); } await Task.Delay(200); foreach (var control in blocks) control.de_path(); iGameMode?.Score_Change(this, new ChangeScoreArgs { score = (blocks.Count + 2) * 10 }); } private int _row = 0, _column = 0; private double single_width = 0, single_height = 0; private Dictionary<(int, int), Single_Block> _index = new(); void playPanel_size_change() { var (width, height) = board.size; (_row, _column) = (height + 2, width + 2); single_width = (double)Width / _column; single_height = (double)Height / _row; } public void Exchange_Handler(object? sender, EventArgs e) { int[,] bd = board.remake_board(); SuspendLayout(); for (int i = 0; i < bd.GetLength(0); i++) for (int j = 0; j < bd.GetLength(1); j++) if (bd[i, j] == -1) continue; else { Single_Block? control = _index.ContainsKey((j, i)) ? _index[(j, i)] : null; if (control != null) control.Re_create(bd[i, j], null, null, null); } int length = giftBlock.Count(); foreach (var item in giftBlock) { DeleteGiftPicture(item.Key, item.Value); } for (int i = 0; i < length; i++) { Random random = new(); SetGiftPicture(board.GetRandomBlock(), (GiftArgs.GiftType)(random.Next(1, 3) - 1)); } ResumeLayout(); } public void Search_Handler(object? sender, SearchEventArgs e) { if (e.set_search) { do_search = true; set_tip(); } else { do_search = false; de_set_tip(); } } } }