using CDSAE3_Lian_Lian_Kan.Boards; 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 System.Windows.Forms.VisualStyles.VisualStyleElement.Window; namespace CDSAE3_Lian_Lian_Kan.Forms { public partial class GameControl : UserControl, IGameControl { IBoard board = new Graph_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(); public GameControl() { InitializeComponent(); DoubleBuffered = true; Etcs.game_form = this; playPanel_set(board.make_board()); iGameMode = Etcs.game_mode_form; } void playPanel_set(int[,] bd) { playPanel.SuspendLayout(); 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(Etcs.trans_Image, (j, i)); x.Dock = DockStyle.Fill; playPanel.Controls.Add(x, j, i); } else { var x = new Single_Block(bd[i, j], Etcs.def_Color, Etcs.sel_Color, (j, i)); x.Dock = DockStyle.Fill; playPanel.Controls.Add(x, j, i); } } playPanel.ResumeLayout(); } /// /// 由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); Control? control = playPanel.GetControlFromPosition(point.Item1, point.Item2); if (control != null && control is Single_Block single_Block) { if (is_hint) single_Block.hint_path(direction); else single_Block.to_path(direction); blocks.Add(single_Block); } } 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() { foreach (var control in hint_blocks) control.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(); } else { if (do_search) { de_set_tip(); set_tip(); } 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; } } }); } 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); Control? controlA = playPanel.GetControlFromPosition(path[0].Item1, path[0].Item2), controlB = playPanel.GetControlFromPosition(path.Last().Item1, path.Last().Item2); Etcs.info_Audio_Processer.play_random_break_soundScape(); 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 blocks) control.de_path(); iGameMode?.Score_Add(this, new AddScoreArgs { score = (blocks.Count + 2) * 10 }); } 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)); } public void Exchange_Handler(object? sender, EventArgs e) { int[,] bd = board.remake_board(); playPanel.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 { Control? control = playPanel.GetControlFromPosition(j, i); if (control != null && control is Single_Block single_Block) single_Block.Re_create(bd[i, j], null, null, null); } playPanel.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(); } } } }