(English version) Belagerungen fand ich schon immer sehr interessant, daher muss es also auch Burgen in meinem Gelände geben. Zuerst will ich nun also mit dem einfachsten Teil der Burg anfangen, dem geraden Mauerstück.
Zuerst muss man sich überlegen, wie die unterschiedlichen Elemente zusammenpassen sollen. Meine Planung war die folgende:
Man sieht links wie die Zinnen aussehen sollen, sodass an einer Verbindungsstelle immer zwei 1 cm breite hohe Teile aufeinander treffen und so ein "normales" 2 cm breites hohes Teil formen:
Die Mauer habe ich aus Styropor gebaut, einmal 6 cm Dicke für den Mauerkörper und dann noch 1 cm Dicke für die Zinnen. All das wird dann zusammen geklebt und angemalt und sieht dann folgendermaßen aus. Vor dem Anmalen:
Die erste Schicht Farbe - ich benutze hier Voll- und Abtönfarbe von Obi (gibt es 0,5 l für 6 Euro, damit sollte man eigentlich eine komplette Burg anmalen können).
Als nächstes wird noch mit weißer Farbe trockengebürstet. Dazu wird einfach der Pinsel in sehr wenig weiße Farbe getaucht, welche dann auf einem Stück Papier größtenteils wieder abgestreift wird. Nun nimmt man den trockenen Pinsel und bürstet über die graue Farbe - das Ergebnis kann man hier sehen:
Ich finde, dass die Struktur vom Styropor (welche durch das Trockenbürsten gut zur Geltung kommt) die Mauer ziemlich gut aussehen lässt. Alternativ kann man auch Styrodur (auch bekannt als XPS) benutzen, dieses hat eine glatte Oberfläche und lässt sich leichter schneiden. Will man nun eine Struktur haben, muss man diese selber reinritzen. Das kann am Ende besser aussehen als beim Styropor ist jedoch teurer und mit mehr Aufwand verbunden.
Eine Sammlung von meinen Projekten aus den Bereichen Physik, Elektronik, Informatik und sogar ein bisschen Botanik. Dieser Blog soll einerseits Hilfestellung bei Problemen geben aber andererseits auch als Anregung für weitere Projekte dienen. Falls es zu einem Thema Fragen oder Anregungen gibt: Einfach schnell einen Kommentar schreiben oder das Kontaktformular rechts unten benutzen, ich beantworte das normalerweise innerhalb von einem Tag.
AdSense
Sonntag, 2. November 2014
Tabletop Gelände - ein See
(English version) Einen See zu bauen ist nicht schwer. Zuerst wird eine normale Gelände-Platte gebaut. Danach zeichnet man sich den See auf:
Danach fängt man an, den See aus dem Styropor zu schneiden/reißen:
Nun wird die Platte braun angemalt. Anschließend der See blau. Für ein besseres optisches Ergebnis wird noch Sand an den Rand hinzugefügt:
Zum Schluss noch Gras:
Und wenn man Lust hat kann man noch etwas Islandmoos drauf verteilen:
Danach fängt man an, den See aus dem Styropor zu schneiden/reißen:
Nun wird die Platte braun angemalt. Anschließend der See blau. Für ein besseres optisches Ergebnis wird noch Sand an den Rand hinzugefügt:
Zum Schluss noch Gras:
Und wenn man Lust hat kann man noch etwas Islandmoos drauf verteilen:
Kategorien:
Tabletop
Tabletop Gelände - die erste Platte
(English version) Wollen wir nun zu der ersten und einfachsten Platte kommen: Grasland. Die Platte sieht so aus:
Sie besteht aus einer 10 mm dicken MDF-Platte und darüber einer 10 mm dicken Styropor-Platte (Dadurch ist es möglich, Strukturen, welche bis zu 1 cm tiefer als die Basis-Höhe sind zu bauen). Ganz oben ist dann eine Schicht Gras drauf. Gras gibt es z.B. billig bei ebay. Um das Gras an der Platte festzumachen verwende ich ein 1:1 Gemisch aus Ponal Holzleim und Wasser. Dadurch kann man den Leim schön über die Fläche verteilen ohne dass der Leim trocknet bevor man überhaupt alles eingeschmiert hat. Als Farbe würde ich Voll- bzw. Abtönfarbe benutzen, diese gibt es in großen Mengen für wenig Geld. Alternativ Spraydosen (Nussbraun), diese kosten jedoch recht viel.
Damit hat man schon eine vernünftige Geländeplatte. Ein Problem was es allerdings noch gibt ist das Halten auf dem Tisch. Benutzt man die Platten nun so, verrutschen sie und es entstehen Lücken. Daher habe ich mir ein möglichst simpletes Prinzip überlegt, sodass die Platten ineinander einrasten. An der Unterseite der Platten gibt es in jeder Ecke ein Dreieck aus Holz was herausschaut, ebenso gibt es eine Einkerbung, welche dann einrastet. Das einzelne Teil sieht so aus:
Ich benutze dafür eine Holz-Latte mit den Maßen 20x10 mm welche ich zu Stücken der Länge 4 und 2 cm zurechtschneide. Das lange Stück kommt mit der langen Seite an eine Diagonale der Platte sodass seine Ecke mit der Ecke der Platte übereinstimmt. Das kurze Stück wird dann auf die andere Seite der Diagonalen geklebt, sodass seine andere Ecke mit der Kante der Platte übereinstimmt.
Wenn zwei Platten nebeneinander liegen sieht das so aus:
Bzw. bei 4:
Als nächstes ist nun noch geplant, kleine Magnete unten an die Platte anzubringen, sodass die Platten sich nicht von alleine auseinander bewegen bzw. sich sogar zusammenziehen und dann perfekt passen. Bei den Magneten warte ich noch auf die Bestellung, wenn diese da ist werde ich weiter darüber berichten.
Hat man erstmal 3 Platten konstruiert ist das anbringen der Hölzer an der Unterseite total einfach: Man legt 3 fertige Platten L-förmig aneinander und legt eine rohe Holz-Platte dazu. Danach klebt man einfach die Hölzer so fest, dass sie exakt in die anderen reinpassen.
Sie besteht aus einer 10 mm dicken MDF-Platte und darüber einer 10 mm dicken Styropor-Platte (Dadurch ist es möglich, Strukturen, welche bis zu 1 cm tiefer als die Basis-Höhe sind zu bauen). Ganz oben ist dann eine Schicht Gras drauf. Gras gibt es z.B. billig bei ebay. Um das Gras an der Platte festzumachen verwende ich ein 1:1 Gemisch aus Ponal Holzleim und Wasser. Dadurch kann man den Leim schön über die Fläche verteilen ohne dass der Leim trocknet bevor man überhaupt alles eingeschmiert hat. Als Farbe würde ich Voll- bzw. Abtönfarbe benutzen, diese gibt es in großen Mengen für wenig Geld. Alternativ Spraydosen (Nussbraun), diese kosten jedoch recht viel.
Damit hat man schon eine vernünftige Geländeplatte. Ein Problem was es allerdings noch gibt ist das Halten auf dem Tisch. Benutzt man die Platten nun so, verrutschen sie und es entstehen Lücken. Daher habe ich mir ein möglichst simpletes Prinzip überlegt, sodass die Platten ineinander einrasten. An der Unterseite der Platten gibt es in jeder Ecke ein Dreieck aus Holz was herausschaut, ebenso gibt es eine Einkerbung, welche dann einrastet. Das einzelne Teil sieht so aus:
Ich benutze dafür eine Holz-Latte mit den Maßen 20x10 mm welche ich zu Stücken der Länge 4 und 2 cm zurechtschneide. Das lange Stück kommt mit der langen Seite an eine Diagonale der Platte sodass seine Ecke mit der Ecke der Platte übereinstimmt. Das kurze Stück wird dann auf die andere Seite der Diagonalen geklebt, sodass seine andere Ecke mit der Kante der Platte übereinstimmt.
Wenn zwei Platten nebeneinander liegen sieht das so aus:
Bzw. bei 4:
Als nächstes ist nun noch geplant, kleine Magnete unten an die Platte anzubringen, sodass die Platten sich nicht von alleine auseinander bewegen bzw. sich sogar zusammenziehen und dann perfekt passen. Bei den Magneten warte ich noch auf die Bestellung, wenn diese da ist werde ich weiter darüber berichten.
Hat man erstmal 3 Platten konstruiert ist das anbringen der Hölzer an der Unterseite total einfach: Man legt 3 fertige Platten L-förmig aneinander und legt eine rohe Holz-Platte dazu. Danach klebt man einfach die Hölzer so fest, dass sie exakt in die anderen reinpassen.
Kategorien:
Tabletop
Tabletop Gelände - Die Grundlagen
(English version) Für Tabletop-Spiele braucht man nicht zwingend ein Gelände. Normalerweise tut es ein Teppich oder Tisch auch schon. Das funktioniert ganz ok, sieht aber nicht so schön aus und taktische Tiefe, z.B. durch Hindernisse, Hügel, Flüsse und weiteres ist dann auch nicht gegeben.
Um das Optische etwas zu verbessern kann man nun z.B. zu der preisgünstigen Variante einer Spielmatte übergehen. Spielmatten gibt es in verschiedenen Ausführungen, manche mit Gras, andere eher im Wüsten-Look. Alternativ kann man auch einfach ein großes grünes Stück Filz-Stoff benutzen. Für die taktische Tiefe gibt es Geländeteile, welche einfach auf die Matte gestellt werden (z.B. Hügel oder Wälder).
Um nun noch eine Stufe höher zu steigen kann man sich überlegen, das komplette Gelände aus einem Guss zu bauen. Für jemanden der viel Platz hat ist das sicherlich akzeptabel, ansonsten stellt sich die Frage wohin man eine 1,2x1,8 m große Platte hinstellen soll (die auch noch eine unebene und empfindliche Oberfläche hat).
Das Optimale sind nun modulare Spieltische. Diese gibt es von viele Firmen wie z.B. Ziterdes, Citadel oder Kallistra.
Die Geländeteile von Ziterdes oder Citadel sind ziemlich ähnlich, beide bestehen aus 60x60 cm großen Platten, welche auch Hügel beinhalten. Citadel ist dabei deutlich teurer als Ziterdes, beide bieten relativ wenig Vielfalt (es gibt eine Hügelecken, bei Ziterdes auch noch Flüsse, aber mehr nicht), zudem sind die Platten sehr groß, sodass man wenig mögliche Kombinationen hat.
Kallistra finde ich persönlich sehr schön, das Spielfeld besteht aus kleinen Sechsecken, welche dann beliebig miteinander kombiniert werden können (fast wie bei Die Siedler von Catan). Es gibt alle möglichen Teile wie Flüsse, Wege, Brücken, Hügel, Berge und sogar Festungen. Leider ist Kallistra auf den 15 mm Maßstab ausgelegt, das heißt dass man mit 28 mm Figuren auf sehr kleine Türme und Mauerstücke treffen würde. Dies ist auch der einzige Grund, welcher mich davon abgehalten hat, Gelände von Kallistra zu kaufen, wer keine Festungen braucht/will kann also Kallistra-Gelände problemlos für 28 mm benutzen.
Nachdem nun alle verfügbaren Lösungen nicht meinen Anforderungen entsprechen, habe ich mich entschieden, selber Gelände zu bauen. Die Grundidee ähnelt der von Citadel/Ziterdes: Ich benutze Platten, welche modular kombinierbar sind. Allerdings habe ich mich auf eine Kantenlänge von 20 cm festgelegt, um mehr mögliche Kombinationen zu haben. Mein Gelände soll dabei wie das von Kallistra viele verschiedene Aspekte besitzen: Seen, Hügelecken, -Kanten und Hochebenen, Festungen und vielleicht sogar Meer. In den nächsten Posts werde ich erkären wie ich das Gelände gebaut habe bzw. wie man es selber ganz einfach bauen kann (Und dabei auch noch wenig Geld ausgibt). Um einen kleinen Vergleich zu haben möchte ich "Grundpreise" des jeweiligen Geländes vergleichen.
Ziterdes: Eine 60x60 cm Platte (bemalt und ein bisschen Gras drauf) kostet 28 €, wenn man das Set kauft ca. 22 €. Heruntergerechnet auf 20x20 cm sind das 2,4 €.
Citadel: Das Set aus 6 Platten (unbemalt, kein Gras) kostet 230 €, das macht ca. 38 € pro Platte bzw. 4,3 € pro 20x20 cm.
Kallistra: Ein Set aus 21 Platten reicht etwas für 90x120 cm und kostet 50 Pfund, mit Gras 75, was etwa 60/90 € entspricht. Somit kosten hier 20x20 cm etwa 2,2/3,3 €.
Um einen Vergleich mit meinem System zu haben: Für eine 20x20 Platte (Grasland) habe ich ohne Begrasung etwa 85 ct ausgegeben, mit Gras kommt man auf maximal 1 €.
Um jetzt nochmal alles zusammenzufassen: Um einen Tisch mit 180x120 cm abzudecken kostet das Gelände:
Ziterdes: 130 €
Citadel: 230 €
Kallistra: 120/180 €
Selbstbau (mein System): ca. 54 €
Um das Optische etwas zu verbessern kann man nun z.B. zu der preisgünstigen Variante einer Spielmatte übergehen. Spielmatten gibt es in verschiedenen Ausführungen, manche mit Gras, andere eher im Wüsten-Look. Alternativ kann man auch einfach ein großes grünes Stück Filz-Stoff benutzen. Für die taktische Tiefe gibt es Geländeteile, welche einfach auf die Matte gestellt werden (z.B. Hügel oder Wälder).
Um nun noch eine Stufe höher zu steigen kann man sich überlegen, das komplette Gelände aus einem Guss zu bauen. Für jemanden der viel Platz hat ist das sicherlich akzeptabel, ansonsten stellt sich die Frage wohin man eine 1,2x1,8 m große Platte hinstellen soll (die auch noch eine unebene und empfindliche Oberfläche hat).
Das Optimale sind nun modulare Spieltische. Diese gibt es von viele Firmen wie z.B. Ziterdes, Citadel oder Kallistra.
Die Geländeteile von Ziterdes oder Citadel sind ziemlich ähnlich, beide bestehen aus 60x60 cm großen Platten, welche auch Hügel beinhalten. Citadel ist dabei deutlich teurer als Ziterdes, beide bieten relativ wenig Vielfalt (es gibt eine Hügelecken, bei Ziterdes auch noch Flüsse, aber mehr nicht), zudem sind die Platten sehr groß, sodass man wenig mögliche Kombinationen hat.
Kallistra finde ich persönlich sehr schön, das Spielfeld besteht aus kleinen Sechsecken, welche dann beliebig miteinander kombiniert werden können (fast wie bei Die Siedler von Catan). Es gibt alle möglichen Teile wie Flüsse, Wege, Brücken, Hügel, Berge und sogar Festungen. Leider ist Kallistra auf den 15 mm Maßstab ausgelegt, das heißt dass man mit 28 mm Figuren auf sehr kleine Türme und Mauerstücke treffen würde. Dies ist auch der einzige Grund, welcher mich davon abgehalten hat, Gelände von Kallistra zu kaufen, wer keine Festungen braucht/will kann also Kallistra-Gelände problemlos für 28 mm benutzen.
Nachdem nun alle verfügbaren Lösungen nicht meinen Anforderungen entsprechen, habe ich mich entschieden, selber Gelände zu bauen. Die Grundidee ähnelt der von Citadel/Ziterdes: Ich benutze Platten, welche modular kombinierbar sind. Allerdings habe ich mich auf eine Kantenlänge von 20 cm festgelegt, um mehr mögliche Kombinationen zu haben. Mein Gelände soll dabei wie das von Kallistra viele verschiedene Aspekte besitzen: Seen, Hügelecken, -Kanten und Hochebenen, Festungen und vielleicht sogar Meer. In den nächsten Posts werde ich erkären wie ich das Gelände gebaut habe bzw. wie man es selber ganz einfach bauen kann (Und dabei auch noch wenig Geld ausgibt). Um einen kleinen Vergleich zu haben möchte ich "Grundpreise" des jeweiligen Geländes vergleichen.
Ziterdes: Eine 60x60 cm Platte (bemalt und ein bisschen Gras drauf) kostet 28 €, wenn man das Set kauft ca. 22 €. Heruntergerechnet auf 20x20 cm sind das 2,4 €.
Citadel: Das Set aus 6 Platten (unbemalt, kein Gras) kostet 230 €, das macht ca. 38 € pro Platte bzw. 4,3 € pro 20x20 cm.
Kallistra: Ein Set aus 21 Platten reicht etwas für 90x120 cm und kostet 50 Pfund, mit Gras 75, was etwa 60/90 € entspricht. Somit kosten hier 20x20 cm etwa 2,2/3,3 €.
Um einen Vergleich mit meinem System zu haben: Für eine 20x20 Platte (Grasland) habe ich ohne Begrasung etwa 85 ct ausgegeben, mit Gras kommt man auf maximal 1 €.
Um jetzt nochmal alles zusammenzufassen: Um einen Tisch mit 180x120 cm abzudecken kostet das Gelände:
Ziterdes: 130 €
Citadel: 230 €
Kallistra: 120/180 €
Selbstbau (mein System): ca. 54 €
Kategorien:
Tabletop
Freitag, 31. Oktober 2014
Arduino Nano V3.0 Klon mit CH340G in Betrieb nehmen
Bei Ebay gibt es einen Klon des Arduino Nano schon für unter 3 Euro zu kaufen. Meist unter dem Namen "Nano V3.0 ATmega328 CH340G" mit dem Zusatz "for Arduino" oder "Arduino compatible", wie zum Beispiel hier. Bei diesen Klonen kommt als USB-Seriell-Wandler nicht wie beim Original ein FT232R sondern (wie der Name schon erkennen lässt) ein CH340G zum Einsatz. Daher sind auch die Treiber der Arduino IDE ungeeignet, stattdessen muss ein extra Treiber von Hand installiert werden. Dieser kann hier beim Hersteller herunter geladen werden. Sollte der Link direkte nicht mehr funktionieren, einfach nach "ch341ser.zip" suchen. Es sind auch Treiber für MAC oder Linux erhältlich. Ich werde hier nur auf die Installation unter Windows eingehen. Zuerst muss das ZIP-Archiv entpackt werden. Falls die Version für 64bit-Windows benötigt wird, muss dann die Datei "DRVSETUP64.exe" aus dem Ordner "DRVSETUP64" in den darüberliegenden Ordner (der unter anderem die Datei "CH341SER.INF" enthält) kopiert werden. Je nach System muss dann die "SETUP.EXE" (32bit) oder die "DRVSETUP64.exe" (64bit) ausgeführt werden. Dann wird auf "INSTALL" geklickt und der Treiber damit installiert. Damit die Installation des Treibers reibungslos abläuft, darf das Board dabei NICHT eingesteckt sein. Erst NACH der Installation wird der Arduino Nano eingestöpselt. Er sollte dann von Windows erkannt werden.
Kategorien:
Arduino
Sonntag, 5. Oktober 2014
C# - Programm zum Lösen von Sudokus
(English version) Ein Sudoku von Hand lösen ist nicht weiter schwer, irgendwann überkommt einen Programmierer aber dann die Lust, ein Programm zu schreiben, was Sudokus selber löst. Die Grundidee ist einfach. Das erste freie Kästchen wird ausgefüllt (mit einer 1). Dann wird geprüft ob das Sudoku noch korrekt ist. Falls ja, wird das nächste Kästchen ausgefüllt, falls nicht wird das vorige Kästchen eins hochgezählt. Das wird wiederholt, bis das Sudoku komplett ausgefüllt ist.
Zuallererst habe ich ein Fenster erstellt, welches das Sudoku anzeigt:
Und der dazugehörige Code:
Dies wird nun benutzt um das Sudoku anzuzeigen. Das Löseprogramm zeigt das aktuelle Sudoku und öffnet für jede gefundene Lösung ein neues Fenster. MainWindow ist leer, wird lediglich zum Starten des Programmes benötigt.
Zuallererst habe ich ein Fenster erstellt, welches das Sudoku anzeigt:
<Window x:Class="SudokuSolver.SudokuShowWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SudokuShowWindow" Height="550" Width="550">
<Grid Name="Grid1" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
</Grid.RowDefinitions>
</Grid>
</Window>
Und der dazugehörige Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace SudokuSolver
{
/// <summary>
/// Interaktionslogik für SudokuShowWindow.xaml
/// </summary>
public partial class SudokuShowWindow : Window
{
public SudokuShowWindow()
{
InitializeComponent();
}
public int[] numbers;
public TextBlock[] TextBlocks;
public void refreshValues(int[] _numbers)
{
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
if (_numbers[i * 9 + j] != numbers[i * 9 + j])
{
TextBlocks[i * 9 + j].Text = _numbers[i * 9 + j].ToString();
}
}
}
}
public static SudokuShowWindow newSudokuShowWindow(int[] numbers)
{
SudokuShowWindow window = new SudokuShowWindow();
window.numbers = new int[81];
window.TextBlocks = new TextBlock[81];
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
window.numbers[i * 9 + j] = numbers[i * 9 + j];
TextBlock tb = new TextBlock();
tb.Text = numbers[i * 9 + j].ToString();
tb.HorizontalAlignment = HorizontalAlignment.Center;
tb.VerticalAlignment = VerticalAlignment.Center;
Grid.SetRow(tb, i);
Grid.SetColumn(tb, j);
Thickness thk = new Thickness(0, 0, 0, 0);
if (i == 2 || i == 5)
{
thk.Bottom = 1;
}
if (i == 3 || i == 6)
{
thk.Top = 1;
}
if (j == 2 || j == 5)
{
thk.Right = 1;
}
if (j == 3 || j == 6)
{
thk.Left = 1;
}
Border border = new Border();
border.BorderThickness = thk;
border.BorderBrush = Brushes.Black;
Grid.SetRow(border, i);
Grid.SetColumn(border, j);
window.Grid1.Children.Add(border);
window.Grid1.Children.Add(tb);
window.TextBlocks[i * 9 + j] = tb;
}
}
window.Show();
return window;
}
}
}
Dies wird nun benutzt um das Sudoku anzuzeigen. Das Löseprogramm zeigt das aktuelle Sudoku und öffnet für jede gefundene Lösung ein neues Fenster. MainWindow ist leer, wird lediglich zum Starten des Programmes benötigt.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SudokuSolver
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Thread thread = new Thread(workLoop);
thread.Start();
}
private SudokuShowWindow window;
private int numberCounter;
private int[] initialNumbers;
private int[] numbers;
List<int[]> Solutions = new List<int[]>();
private void workLoop()
{
//The initial Sudoku which should be solved
initialNumbers = new int[81]
{
5,3,0, 0,7,0, 0,0,0,
6,0,0, 1,9,5, 0,0,0,
0,9,8, 0,0,0, 0,6,0,
8,0,0, 0,6,0, 0,0,3,
4,0,0, 8,0,3, 0,0,1,
7,0,0, 0,2,0, 0,0,6,
0,6,0, 0,0,0, 2,8,0,
0,0,0, 4,1,9, 0,0,5,
0,0,0, 0,8,0, 0,7,9
};
numbers = new int[81];
for (int i = 0; i < 81; i++)
{
numbers[i] = 0;
}
//Invoke window actions because we are not in the main thread
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
window = SudokuShowWindow.newSudokuShowWindow(initialNumbers);
}));
//Position of the "cursor" in the sudoku
numberCounter = 0;
int ctr = 0;
bool noi = false;
while (true)
{
if (isItValid())
{
noi = false;
//A valid solution!
if (numberCounter > 80)
{
int[] totalNumbers = new int[81];
for (int i = 0; i < 81; i++)
{
totalNumbers[i] = initialNumbers[i];
if (totalNumbers[i] == 0)
{
totalNumbers[i] = numbers[i];
}
}
bool eq = false;
foreach (int[] solution in Solutions)
{
bool leq = true;
for (int i = 0; i < 81; i++)
{
if (solution[i] != totalNumbers[i])
{
leq = false;
}
}
if (leq)
{
eq = true;
}
}
if (!eq)
{
int[] tmp = new int[81];
for (int i = 0; i < 81; i++)
{
tmp[i] = totalNumbers[i];
}
Solutions.Add(tmp);
}
else
{
System.Console.WriteLine("Done!");
break;
}
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
SudokuShowWindow.newSudokuShowWindow(totalNumbers);
}));
//Check for other solutions?
noi = true;
while (true)
{
numberCounter--;
if (initialNumbers[numberCounter] == 0)
{
if (numbers[numberCounter] >= 9)
{
numbers[numberCounter] = 0;
}
else
{
numbers[numberCounter]++;
break;
}
}
}
}
if (numberCounter > 80)
{
break;
}
if (numbers[numberCounter] == 0 && initialNumbers[numberCounter] == 0)
{
iterateOne();
}
else
{
if (!noi)
{
increaseNumberCounter();
}
}
}
else
{
if (numberCounter > 80 || numberCounter < 0)
{
break;
}
if (numbers[numberCounter] >= 9)
{
decreaseOne();
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
int[] totalNumbers = new int[81];
for (int i = 0; i < 81; i++)
{
totalNumbers[i] = initialNumbers[i];
if (totalNumbers[i] == 0)
{
totalNumbers[i] = numbers[i];
}
}
window.refreshValues(totalNumbers);
}));
}
else
{
iterateOne();
}
}
ctr++;
if (ctr > 1000)
{
ctr = 0;
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
int[] totalNumbers = new int[81];
for (int i = 0; i < 81; i++)
{
totalNumbers[i] = initialNumbers[i];
if (totalNumbers[i] == 0)
{
totalNumbers[i] = numbers[i];
}
}
window.refreshValues(totalNumbers);
}));
Thread.Sleep(1);
}
}
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
window.Close();
}));
}
void increaseNumberCounter()
{
numberCounter++;
while (numberCounter <= 80 && initialNumbers[numberCounter] != 0)
{
numberCounter++;
}
}
void iterateOne()
{
if (numberCounter > 80)
{
return;
}
while (initialNumbers[numberCounter] != 0)
{
numberCounter++;
}
numbers[numberCounter]++;
}
void decreaseOne()
{
if (numberCounter > 80)
{
numberCounter = 80;
}
numbers[numberCounter] = 0;
if (numberCounter == 0)
{
return;
}
while (numberCounter >= 0)
{
numberCounter--;
while (numberCounter > 0 && initialNumbers[numberCounter] != 0)
{
numberCounter--;
}
if (numberCounter < 0)
{
return;
}
if (numbers[numberCounter] < 9)
{
numbers[numberCounter]++;
return;
}
else
{
numbers[numberCounter] = 0;
}
}
}
bool isItValid()
{
int[] totalNumbers = new int[81];
for (int i = 0; i < 81; i++)
{
totalNumbers[i] = initialNumbers[i];
if (totalNumbers[i] == 0)
{
totalNumbers[i] = numbers[i];
}
}
//Check Horizontal
List<int> testList;
for (int i = 0; i < 9; i++)
{
testList = new List<int>();
for (int j = 0; j < 9; j++)
{
if (testList.Contains(totalNumbers[i * 9 + j]))
{
//Invalid
return false;
}
if (totalNumbers[i * 9 + j] != 0)
{
testList.Add(totalNumbers[i * 9 + j]);
}
}
}
//Check Vertical
for (int j = 0; j < 9; j++)
{
testList = new List<int>();
for (int i = 0; i < 9; i++)
{
if (testList.Contains(totalNumbers[i * 9 + j]))
{
//Invalid
return false;
}
if (totalNumbers[i * 9 + j] != 0)
{
testList.Add(totalNumbers[i * 9 + j]);
}
}
}
//Check squares
for (int ii = 0; ii < 3; ii++)
{
for (int jj = 0; jj < 3; jj++)
{
testList = new List<int>();
for (int i = ii * 3; i < ii * 3 + 3; i++)
{
for (int j = jj * 3; j < jj * 3 + 3; j++)
{
if (testList.Contains(totalNumbers[i * 9 + j]))
{
//Invalid
return false;
}
if (totalNumbers[i * 9 + j] != 0)
{
testList.Add(totalNumbers[i * 9 + j]);
}
}
}
}
}
//Valid
return true;
}
}
}
Kategorien:
C#
Visual Studio - Anwendung mit automatischen Updates benötigt lange zum Starten
(English version) Wenn man in Visual Studio ein Projekt veröffentlicht und dann die Anwendung startet wird normalerweise zuerst nach Updates gesucht. Dies kann einige Zeit in Anspruch nehmen und ist nervig wenn man die Anwendung möglichst schnell haben will. Glücklicherweise kann man den Zeitpunkt der Updates umstellen, sodass erst nach Updates geprüft wird, wenn die Anwendung schon gestartet ist. Die Updates kann man dann beim nächsten Start installieren ohne lange Wartezeiten zu haben.
Um dies einzustellen muss man in die Projekteigenschaften gehen. Hier gibt es dann den Unterpunkt "Veröffentlichen", wo es dann die Schaltfläche "Updates" gibt. Hier ist man dann auch bei der gewünschten Einstellung: "Zeitpunkt für Updateüberprüfungen auswählen". Hier ist standartmäßig "Vor Start der Anwendung" ausgewählt, um die Startzeit zu verkürzen muss man nun "Nach dem Starten der Anwendung" auswählen.
Um dies einzustellen muss man in die Projekteigenschaften gehen. Hier gibt es dann den Unterpunkt "Veröffentlichen", wo es dann die Schaltfläche "Updates" gibt. Hier ist man dann auch bei der gewünschten Einstellung: "Zeitpunkt für Updateüberprüfungen auswählen". Hier ist standartmäßig "Vor Start der Anwendung" ausgewählt, um die Startzeit zu verkürzen muss man nun "Nach dem Starten der Anwendung" auswählen.
Abonnieren
Posts (Atom)













