/// <summary> /// User-click event handler /// </summary> /// <param name="e">Mouse options</param> public void MouseDown(MouseEventArgs e) { // Definition of checkers under the cursor at the moment of pressing Ruler ruler = new Ruler(_screen); Rectangle board_coord = ruler.GetBoardCoordinates(); Point click_coord = new Point(e.X - board_coord.X, e.Y - board_coord.Y); Point? checker_intersection = ruler.GetCellIntersection(e.Location); // Determining the selected checker and its visual characteristics if (!checker_intersection.HasValue) { return; } _clicked = checker_intersection; Rectangle checker_rect = ruler.GetCellCoordinates(checker_intersection.Value); // There are no checkers under the cursor if (_clicked == null) { return; } // Enemy checker is selected - the move is impossible if (_state.checkers[_clicked.Value.X, _clicked.Value.Y] != null && _state.checkers[_clicked.Value.X, _clicked.Value.Y].belong_to != _state.turn) { ShowIncorrectTurnMessage(Reason.EnemyChecker); return; } // Expected move continuation, another checker move is impossible. if (_continious != null && _clicked != _continious) { ShowIncorrectTurnMessage(Reason.TurnContinuationExpected); return; } // Checker selection _drag = _state.checkers[_clicked.Value.X, _clicked.Value.Y]; }
/// <summary> /// Event handler for releasing a mouse button by user /// </summary> /// <param name="e">Mouse options</param> public void MouseUp(MouseEventArgs e) { // Checker is not selected if (_drag == null) { return; } // Definition of the field under the cursor at the moment of pressing Ruler ruler = new Ruler(_screen); Point? cell_intersection = ruler.GetCellIntersection(e.Location); Reason status = Reason.OK; bool beating; // Assessment of the possibility and correctness of move if (cell_intersection.HasValue) { // Verify that the selected cell matches the game logic if (_state.checkers[cell_intersection.Value.X, cell_intersection.Value.Y] == null && cell_intersection.Value.X % 2 == cell_intersection.Value.Y % 2) { // Checking the move correctness status = _estimator.EvaluateStep(_clicked.Value, cell_intersection.Value, out beating); // Move is correct if (status == Reason.OK) { // Moving checkers to a new position _state.checkers[cell_intersection.Value.X, cell_intersection.Value.Y] = _drag; _state.checkers[cell_intersection.Value.X, cell_intersection.Value.Y].rect = ruler.GetCellRelativeCoord(new Point(cell_intersection.Value.X, cell_intersection.Value.Y)); _state.checkers[_clicked.Value.X, _clicked.Value.Y] = null; // Check for the need to convert checkers into a king if (!_state.checkers[cell_intersection.Value.X, cell_intersection.Value.Y].king) { // For white checkers if (cell_intersection.Value.Y == Properties.Settings.Default.low_bound && _drag.belong_to == Belonging.WhiteRose) { _state.checkers[cell_intersection.Value.X, cell_intersection.Value.Y].king = true; _state.checkers[cell_intersection.Value.X, cell_intersection.Value.Y].img = Properties.Resources.whiteking; } // For red checkers else if (cell_intersection.Value.Y == Properties.Settings.Default.high_bound && _drag.belong_to == Belonging.RedRose) { _state.checkers[cell_intersection.Value.X, cell_intersection.Value.Y].king = true; _state.checkers[cell_intersection.Value.X, cell_intersection.Value.Y].img = Properties.Resources.redking; } } // Determining the possibility of continuing the turn var next_move = _estimator.NeedCheckerBeating(cell_intersection.Value, _state.checkers[cell_intersection.Value.X, cell_intersection.Value.Y].king && Properties.Settings.Default.rules_russian ? Properties.Settings.Default.high_bound + 1 : 1, _state.checkers[cell_intersection.Value.X, cell_intersection.Value.Y].belong_to == Belonging.RedRose ? Belonging.WhiteRose : Belonging.RedRose); // Check the need of continuing the turn if (next_move.Count > 0) { // The need to beat (mandatory continuation of the course) if (beating) { ShowContiniousTurnMessage(); _continious = cell_intersection.Value; } else { // Moving side swap if (_state.turn == Belonging.RedRose) { _state.turn = Belonging.WhiteRose; } else { _state.turn = Belonging.RedRose; } // Check of conditions of loss of the opponent bool enemy_has_checkers = false; bool enemy_can_move = false; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { // Check for opponent’s checkers if (_state.checkers[j, i] != null && _state.checkers[j, i].belong_to == _state.turn) { // Definition of the enemy Belonging new_enemy; int distance = 1; if (_state.turn == Belonging.RedRose) { new_enemy = Belonging.WhiteRose; } else { new_enemy = Belonging.RedRose; } // Determining the distance of the checkers move if (_state.checkers[j, i].king) { if (Properties.Settings.Default.rules_russian) { distance = Properties.Settings.Default.high_bound + 1; } else { distance = 1; } } enemy_has_checkers = true; // Determining the possibility of moving if (_estimator.CanMove(new Point(j, i), distance, new_enemy)) { enemy_can_move = true; } } } } // Check win / lose event if (!enemy_has_checkers || !enemy_can_move) { // Winning Report CheckForVictory(); } else { // Computer turn ComputerTurn(); // Message about changing turn owner ShowTurnOwnerMessage(); } // Moving checker reset _continious = null; } } else { // Moving side swap if (_state.turn == Belonging.RedRose) { _state.turn = Belonging.WhiteRose; } else { _state.turn = Belonging.RedRose; } // Check of conditions of loss of the opponent bool enemy_has_checkers = false; bool enemy_can_move = false; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { // Check for opponent’s checkers if (_state.checkers[j, i] != null && _state.checkers[j, i].belong_to == _state.turn) { // Definition of the enemy Belonging new_enemy; int distance = 1; if (_state.turn == Belonging.RedRose) { new_enemy = Belonging.WhiteRose; } else { new_enemy = Belonging.RedRose; } // Determining the distance of the checkers move if (_state.checkers[j, i].king) { if (Properties.Settings.Default.rules_russian) { distance = Properties.Settings.Default.high_bound + 1; } else { distance = 1; } } enemy_has_checkers = true; // Determining the possibility of moving if (_estimator.CanMove(new Point(j, i), distance, new_enemy)) { enemy_can_move = true; } } } } // Check win / lose event if (!enemy_has_checkers || !enemy_can_move) { // Winning Report CheckForVictory(); } else { // Computer turn ComputerTurn(); // Message about changing turn owner ShowTurnOwnerMessage(); } // Moving checker reset _continious = null; } } else { // Return to the previous position _state.checkers[_clicked.Value.X, _clicked.Value.Y].rect = ruler.GetCellRelativeCoord(new Point(_clicked.Value.X, _clicked.Value.Y)); } } else { // Return to the previous position status = Reason.ImpossibleTurn; _state.checkers[_clicked.Value.X, _clicked.Value.Y].rect = ruler.GetCellRelativeCoord(new Point(_clicked.Value.X, _clicked.Value.Y)); } } else if (_clicked != null) { // Return to the previous position status = Reason.ImpossibleTurn; _state.checkers[_clicked.Value.X, _clicked.Value.Y].rect = ruler.GetCellRelativeCoord(new Point(_clicked.Value.X, _clicked.Value.Y)); } // Reset selected checker this._clicked = null; this._drag = null; // The message about the incorrectness of the move (if incorrect, an internal check is performed) ShowIncorrectTurnMessage(status); }