static private void QR_D() { int numTestCases = Int32.Parse(Console.ReadLine()); for (int zz = 0; zz < numTestCases; zz++) { string dimensionsText = Console.ReadLine(); string[] dimSplits = dimensionsText.Split(' '); int h = Int32.Parse(dimSplits[0]); int w = Int32.Parse(dimSplits[1]); int d = Int32.Parse(dimSplits[2]); MapContents[,] map = new MapContents[w, h]; int youH = -1; int youW = -1; // read the map for (int hLoop = 0; hLoop < h; hLoop++) { string rowText = Console.ReadLine(); for (int wLoop = 0; wLoop < w; wLoop++) { if (rowText[wLoop] == '#') { map[wLoop, hLoop] = MapContents.Mirror; } else if (rowText[wLoop] == '.') { map[wLoop, hLoop] = MapContents.Empty; } else if (rowText[wLoop] == 'X') { map[wLoop, hLoop] = MapContents.You; youH = hLoop; youW = wLoop; } } } List <Slope> slopesToCheck = new List <Slope>(); // find slopes to check in a circle for (int x = -d; x <= d; x++) { for (int y = -d; y <= d; y++) { if (x != 0 || y != 0) { if ((x * x + y * y) <= (d * d)) { // the grid point is within d distance, check for it if (slopesToCheck.Any(s => s.Matches(x, y))) { // already have something going that way } else { slopesToCheck.Add(new Slope(x, y)); } } } } } // now i got slopes to check, do crappy raycasting in those directions to a distance of D to see if the ray comes home // since the duplicated slopes were removed, every successful ray cast from the list is a visible ME int successfulCasts = 0; foreach (Slope currentSlope in slopesToCheck) { // work on a doubled grid so the center of me is on a grid point just like mirrors double startX = 2 * youW + 1; double startY = 2 * youH + 1; double currentX = startX; double currentY = startY; int currentXChange = currentSlope.XChange; int currentYChange = currentSlope.YChange; double distanceRemaining = 2 * d + 0.0001; // 1/10k should be plenty of error, and not something I'l get near, considering the size of the room while (distanceRemaining > 0) { double nextX; double nextY; if (currentXChange == 0) { nextX = currentX; if (currentYChange > 0) { // move up to the next integer nextY = Math.Floor(currentY + 1); } else { // move down to the next integer nextY = Math.Ceiling(currentY - 1); } } else if (currentYChange == 0) { nextY = currentY; if (currentXChange > 0) { // move up to the next integer nextX = Math.Floor(currentX + 1); } else { // move down to the next integer nextX = Math.Ceiling(currentX - 1); } } else { // currentXChange and currentYChange are non-zero // advance to the next grid line double xChangeToLine; if (currentXChange > 0) { xChangeToLine = Math.Floor(currentX + 1) - currentX; } else { xChangeToLine = Math.Ceiling(currentX - 1) - currentX; } double yChangeToLine; if (currentYChange > 0) { yChangeToLine = Math.Floor(currentY + 1) - currentY; } else { yChangeToLine = Math.Ceiling(currentY - 1) - currentY; } if (xChangeToLine / currentXChange > yChangeToLine / currentYChange) { // x to line needs more time, use y change to line nextY = currentY + yChangeToLine; nextX = currentX + currentXChange * (yChangeToLine / currentYChange); } else { // y to line needs more time, use x change to line nextX = currentX + xChangeToLine; nextY = currentY + currentYChange * (xChangeToLine / currentXChange); } } // fix nextX and nextY for close-enough if (Math.Abs(Math.Round(nextX) - nextX) < 0.0001) { nextX = Math.Round(nextX); } if (Math.Abs(Math.Round(nextY) - nextY) < 0.0001) { nextY = Math.Round(nextY); } // update distanceRemaining double xDiff = nextX - currentX; double yDiff = nextY - currentY; distanceRemaining -= Math.Sqrt(xDiff * xDiff + yDiff * yDiff); if (distanceRemaining < 0) { // outta gas break; } else { if (nextX == startX && nextY == startY) { // back to 'me' successfulCasts++; break; } else { bool xAtEvenGridline = (nextX == Math.Round(nextX) && ((int)nextX) % 2 == 0); bool yAtEvenGridline = (nextY == Math.Round(nextY) && ((int)nextY) % 2 == 0); if (xAtEvenGridline && yAtEvenGridline) { // hitting both even grid lines at once // check for mirror surface hit, or either corner hit, or squeezing int nextGridX = ((int)(nextX + ((currentXChange > 0) ? 0.5 : -0.5))) / 2; int nextGridY = ((int)(nextY + ((currentYChange > 0) ? 0.5 : -0.5))) / 2; if (map[nextGridX, nextGridY] == MapContents.Mirror) { int oldGridX = ((int)(nextX + ((currentXChange > 0) ? -0.5 : 0.5))) / 2; int oldGridY = ((int)(nextY + ((currentYChange > 0) ? -0.5 : 0.5))) / 2; bool otherXisMirror = (map[oldGridX, nextGridY] == MapContents.Mirror); bool otherYisMirror = (map[nextGridX, oldGridY] == MapContents.Mirror); if (otherXisMirror && otherYisMirror) { // mirror corner, double bounce currentXChange = -currentXChange; currentYChange = -currentYChange; } else if (otherXisMirror) { // both x blocks are mirrors, bounce along y currentYChange = -currentYChange; } else if (otherYisMirror) { // both y blocks are mirrors, bounce along x currentXChange = -currentXChange; } else { // nailing a mirror corner - die break; } } else { // not crashing into a mirror, so keep going } } else if (xAtEvenGridline) { // check for mirror surface hit int gridX; if (currentXChange > 0) { gridX = ((int)(nextX + 0.5)) / 2; } else { gridX = ((int)(nextX - 0.5)) / 2; } int gridY = ((int)nextY) / 2; if (map[gridX, gridY] == MapContents.Mirror) { // bounce currentXChange = -currentXChange; } } else if (yAtEvenGridline) { // check for mirror surface hit int gridY; if (currentYChange > 0) { gridY = ((int)(nextY + 0.5)) / 2; } else { gridY = ((int)(nextY - 0.5)) / 2; } int gridX = ((int)nextX) / 2; if (map[gridX, gridY] == MapContents.Mirror) { // bounce currentYChange = -currentYChange; } } } } currentX = nextX; currentY = nextY; } } Console.WriteLine(String.Format("Case #{0}: {1}", zz + 1, successfulCasts)); } }
public override void OnApplyTemplate() { MapContentControlContainer = GetTemplateChild(PART_MAP_CONTENT_CONTAINER_CONTROL) as ContentControl; if (MapContentControlContainer != null) { MapContentControl = new MapContents(); MapContentControl.Name = PART_MAP_CONTENT_CONTROL; MapContentControl.Map = View.Map; MapContentControl.Configuration = new MapContentsConfiguration { ContextMenuToolPanelName = "EditModeLayerConfigurationContextMenu", Mode = Mode.TopLevelLayersOnly }; if (MapContentControlContainer.Resources != null) { MapContentControl.ScrollViewerStyle = MapContentControlContainer.Resources["BuilderMapContentsScrollViewerStyle"] as Style; MapContentControl.SelectionColorBrush = MapContentControlContainer.Resources["BuilderSelectedLayerColorBrush"] as Brush; MapContentControl.SelectionOutlineColorBrush = MapContentControlContainer.Resources["BuilderSelectedLayerOutlineColorBrush"] as Brush; MapContentControl.ToggleButtonStyle = MapContentControlContainer.Resources["MapContentsControlNodeToggleButton"] as Style; } // Push foreground and background to map contents Binding b = new Binding("Foreground") { Source = this }; MapContentControl.SetBinding(MapContents.ForegroundProperty, b); b = new Binding("Background") { Source = this }; MapContentControl.SetBinding(MapContents.BackgroundProperty, b); MapContentControlContainer.Content = MapContentControl; } layerConfigurationLayout = GetTemplateChild(PART_CONFIGURE_LAYER_CONTROL_LAYOUT) as Grid; LayerConfiguration = GetTemplateChild("LayerConfigurationDialog") as LayerConfiguration; if (LayerConfiguration != null) { LayerConfiguration.View = View.Instance; } mapContentLayerConfigurationLayout = GetTemplateChild(PART_MAP_CONTENTS_LAYER_CONFIGURATION_LAYOUT) as Grid; if (mapContentLayerConfigurationLayout != null) { mapContentLayerConfigurationLayout.Loaded -= mapContentLayerConfigurationLayout_Loaded; mapContentLayerConfigurationLayout.Loaded += mapContentLayerConfigurationLayout_Loaded; mapContentLayerConfigurationLayout.SizeChanged -= mapContentLayerConfigurationLayout_SizeChanged; mapContentLayerConfigurationLayout.SizeChanged += mapContentLayerConfigurationLayout_SizeChanged; } mapContentsLayout = GetTemplateChild(PART_MAP_CONTENT_CONTROL_LAYOUT) as Grid; btnConfigurationComplete = GetTemplateChild(PART_CONFIGURE_COMPLETE_BUTTON) as Button; _layerConfigToolbar = GetTemplateChild(PART_TOOLPANEL) as ToolPanel; _allLayersConfigToolbar = GetTemplateChild(PART_ALLLAYERSTOOLPANEL) as ToolPanel; _mapContentsContenxtMenuToolbar = GetTemplateChild(PART_EDIT_MODE_LAYER_CONFIGURATION_CONTEXT_MENU) as ToolPanel; _layerConfigPanel = GetTemplateChild(PART_LAYERCONFIGPANEL) as FrameworkElement; InitializeToolbars(); // hide the layer configuration elements until we need them RemoveLayerConfigurationVisualElements(); }