using CDSAE3_Lian_Lian_Kan.Board_funcs; using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window; namespace CDSAE3_Lian_Lian_Kan.Forms { public partial class GameControl : UserControl, IBeSelected { Board board = new Board(); IGameMode iGameMode; public GameControl() { InitializeComponent(); board.make_board(); Settings.game_form = this; playPanel_set(); iGameMode = Settings.game_mode_form; } void playPanel_set() { int[,] bd; if (board.Bd == null) { board.make_board(); bd = board.Bd ?? new int[0, 0]; if (bd.Length == 0) throw new Exception("bd is null"); } else bd = board.Bd; playPanel_size_change(); for (int i = 0; i < playPanel.RowCount; i++) for (int j = 0; j < playPanel.ColumnCount; j++) { if (bd[i, j] == -1) { var x = new Single_Block(Settings.trans_Image, (j, i)); x.Dock = DockStyle.Fill; playPanel.Controls.Add(x, j, i); } else { var x = new Single_Block(bd[i, j], Settings.def_Color, Settings.sel_Color, (j, i)); x.Dock = DockStyle.Fill; playPanel.Controls.Add(x, j, i); } } } Queue<((int, int), Single_Block)> queue = new Queue<((int, int), Single_Block)>();//y,x 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)); break; case 1: var (posa, sendera) = queue.Dequeue(); var posb = e.position; var (could, path) = board.test(posa, posb); if (could) { _ = Block_ClearAsync(path); while (queue.Count() > 0) queue.Dequeue(); if (board.Bd is null) throw new Exception("No usable board. How come?"); board.Bd[posa.Item2, posa.Item1] = -1; board.Bd[posb.Item2, posb.Item1] = -1; } else { 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(); break; } } }); } async Task Block_ClearAsync(List<(int, int)>? path) { List paths = new List(); if (path == null) return; Func<(int, int), (int, int), Settings.Direction> get_Direction = ((int, int) from, (int, int) to) =>//x,y { if (from.Item1 == to.Item1) if (from.Item2 > to.Item2) return Settings.Direction.up; else return Settings.Direction.down; else if (from.Item1 > to.Item1) return Settings.Direction.left; else return Settings.Direction.right; }; Func<(int, int), Settings.Direction, Task> set_Path = async ((int, int) point, Settings.Direction direction) => { await Task.Delay(20); Control? control = playPanel.GetControlFromPosition(point.Item1, point.Item2); if (control != null && control is Single_Block single_Block) { single_Block.to_path(direction); paths.Add(single_Block); } }; Func<(int, int), (int, int), bool, Settings.Direction, Task> to_path = async ((int, int) from, (int, int) to, bool include_end, Settings.Direction extra_Direction) => { var direction = get_Direction(from, to); switch (direction) { case Settings.Direction.up: for (int i = from.Item2 - 1; i != to.Item2; i--) await set_Path((from.Item1, i), Settings.Direction.up_down); break; case Settings.Direction.down: for (int i = from.Item2 + 1; i != to.Item2; i++) await set_Path((from.Item1, i), Settings.Direction.up_down); break; case Settings.Direction.right: for (int i = from.Item1 + 1; i != to.Item1; i++) await set_Path((i, from.Item2), Settings.Direction.left_right); break; case Settings.Direction.left: for (int i = from.Item1 - 1; i != to.Item1; i--) await set_Path((i, from.Item2), Settings.Direction.left_right); break; } if (include_end) { direction = direction | extra_Direction; await set_Path(to, direction); } }; switch (path.Count) { case 2: await to_path(path[0], path[1], false, 0); break; case 3: var extra_direction = get_Direction(path[1], path[2]); await to_path(path[0], path[1], true, extra_direction); await to_path(path[1], path[2], false, Settings.Direction.none); break; case 4: Settings.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); await to_path(path[1], path[2], true, extra_directionB); await to_path(path[2], path[3], false, Settings.Direction.none); break; } Control? controlA = playPanel.GetControlFromPosition(path[0].Item1, path[0].Item2), controlB = playPanel.GetControlFromPosition(path.Last().Item1, path.Last().Item2); if (controlA != null && controlB != null && controlA is Single_Block single_BlockA && controlB is Single_Block single_BlockB) { single_BlockA.destroyAsync(); single_BlockB.destroyAsync(); } await Task.Delay(200); foreach (var control in paths) control.de_path(); iGameMode.Score_Add(this, new AddScoreArgs { score = (paths.Count + 2)*10 }); board.Total -= 2; } void playPanel_size_change() { var (width, height) = board.size; playPanel.RowCount = height + 2; playPanel.ColumnCount = width + 2; playPanel.ColumnStyles[0] = new ColumnStyle(SizeType.Percent, 100F); playPanel.RowStyles[0] = new RowStyle(SizeType.Percent, 100F); for (int i = 0; i < width + 1; i++) playPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F)); for (int i = 0; i < height + 1; i++) playPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); } } }