ProgrammieraufgabenHier wird regelmäßig eine neue Programmieraufgabe gestellt, die dann gelöst werden soll und in Zusammenarbeit mit den Moderatoren auch besprochen werden kann.
Binäruhr
Diskussion: Binäruhr im Forum Programmieraufgaben, in der Kategorie Code Kitchen; Anzeige
Eingereicht von Ook!
Zitat:
Eine Idee für eine Programmieraufgabe, Schwierigkeit 1,5
Wie wäre es mit einer Binären Uhr? Stunden, ...
Eine Idee für eine Programmieraufgabe, Schwierigkeit 1,5
Wie wäre es mit einer Binären Uhr? Stunden, Minuten & Sekunden sollten angezeigt werden, binär sowohl als auch dezimal...
Wenn möglich natürlich mit Oberfläche, Konsolenbasiert geht auch... wie Ihr wollt.
Für eine Anregung, wie das ganze ausschauen könnte, bietet sich wikipedia an: http://de.wikipedia.org/wiki/Bin%C3%A4re_Uhr
Schwierigkeit 2 wegen GUI-Fummelei ;)
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf!
Selig, wer nichts zu sagen hat und trotzdem schweigt.
#!/usr/bin/env perl
use warnings;
use strict;
use Tk;
my $mw = MainWindow->new(
-title => "binary-clock 10111",
-background => "black",
);
$mw->geometry('150x120');
$mw->resizable(0, 0);
my $secFrame = $mw->Frame(
-width => 50,
-height => 100,
-borderwidth => 10,
-background => "black"
);
my $minFrame = $mw->Frame(
-width => 50,
-height => 100,
-borderwidth => 10,
-background => "black"
);
my $hourFrame = $mw->Frame(
-width => 50,
-height => 100,
-borderwidth => 10,
-background => "black"
);
my %LED = setupLEDS($secFrame, $minFrame, $hourFrame);
my $decTime;
$mw->repeat(1000, [\&myMainLoop, \$decTime, \%LED]);
myMainLoop(\$decTime, \%LED);
$mw->Label(
-textvariable => \$decTime,
-background => "black",
-foreground => "grey"
)->grid();
Tk::grid($hourFrame, $minFrame, $secFrame);
MainLoop();
sub myMainLoop {
my ($timeVarRef, $LED) = @_;
updateTime($timeVarRef);
my ($hours, $min, $sec) = $$timeVarRef =~ /^(\d{2}):(\d{2}):(\d{2})$/;
updateLEDS($hours, $min, $sec, $LED);
return;
}
sub updateTime {
my ($timeVarRef) = @_;
my ($sec, $min, $hours) = localtime;
$$timeVarRef = sprintf "%02d:%02d:%02d", ($hours, $min, $sec);
return;
}
sub separateTenOne {
my ($decimal) = @_;
my ($ten, $one) = (0, 0);
$ten = int $decimal / 10;
$one = $decimal - $ten * 10;
return ($ten, $one);
}
sub updateLEDS {
my ($hour, $min, $sec, $LED) = @_;
my ($secTen, $secOne) = separateTenOne($sec);
my ($minTen, $minOne) = separateTenOne($min);
my ($hourTen, $hourOne) = separateTenOne($hour);
# seconds:
for my $i (1, 2, 4) {
my $color = ($i & $secTen) ? "blue" : "black";
$$LED{"sec10_$i"}->configure(-background => $color);
}
for my $i (1, 2, 4, 8) {
my $color = ($i & $secOne) ? "blue" : "black";
$$LED{"sec1_$i"}->configure(-background => $color);
}
# minutes:
for my $i (1, 2, 4) {
my $color = ($i & $minTen) ? "green" : "black";
$$LED{"min10_$i"}->configure(-background => $color);
}
for my $i (1, 2, 4, 8) {
my $color = ($i & $minOne) ? "green" : "black";
$$LED{"min1_$i"}->configure(-background => $color);
}
# and finally hours:
for my $i (1, 2) {
my $color = ($i & $hourTen) ? "red" : "black";
$$LED{"hour10_$i"}->configure(-background => $color);
}
for my $i (1, 2, 4, 8) {
my $color = ($i & $hourOne) ? "red" : "black";
$$LED{"hour1_$i"}->configure(-background => $color);
}
}
sub setupLEDS {
# now i'll put the "LED"s (label widgets) into a hash and grid them.
my ($secFrame, $minFrame, $hourFrame) = @_;
my %LED;
# seconds first:
for my $i (1, 2, 4, 8) {
$LED{"sec1_$i"} = $secFrame->Label(
-text => ' ',
-background => "blue",
-relief => "groove"
);
}
for my $i (1, 2, 4) {
$LED{"sec10_$i"} = $secFrame->Label(
-text => ' ',
-background => "blue",
-relief => "groove"
);
}
Tk::grid("x", $LED{"sec1_8"});
Tk::grid($LED{"sec10_4"}, $LED{"sec1_4"});
Tk::grid($LED{"sec10_2"}, $LED{"sec1_2"});
Tk::grid($LED{"sec10_1"}, $LED{"sec1_1"});
# now minutes:
for my $i (1, 2, 4, 8) {
$LED{"min1_$i"} = $minFrame->Label(
-text => ' ',
-background => "green",
-relief => "groove"
);
}
for my $i (1, 2, 4) {
$LED{"min10_$i"} = $minFrame->Label(
-text => ' ',
-background => "green",
-relief => "groove"
);
}
Tk::grid("x", $LED{"min1_8"});
Tk::grid($LED{"min10_4"}, $LED{"min1_4"});
Tk::grid($LED{"min10_2"}, $LED{"min1_2"});
Tk::grid($LED{"min10_1"}, $LED{"min1_1"});
# and hours:
for my $i (1, 2, 4, 8) {
$LED{"hour1_$i"} = $hourFrame->Label(
-text => ' ',
-background => "red",
-relief => "groove"
);
}
for my $i (1, 2) {
$LED{"hour10_$i"} = $hourFrame->Label(
-text => ' ',
-background => "red",
-relief => "groove"
);
}
Tk::grid("x", $LED{"hour1_8"});
Tk::grid("x", $LED{"hour1_4"});
Tk::grid($LED{"hour10_2"}, $LED{"hour1_2"});
Tk::grid($LED{"hour10_1"}, $LED{"hour1_1"});
return %LED;
}
Sind zwar ziemlich viele Zeilen code, aber vieles wurde durch stumpfes copy'n'paste erstellt. (Speziell in den subs updateLEDS und setupLEDS, da sind die Blöcke für Sekunden, Minuten und Stunden jeweils fast exakt gleich.)
Auch wird jede Zelle neu "configured", nicht nur die, für die sich der Status geändert hat. Aber bei einem frame-per-second darf man sich sowas wohl mal erlauben ):
ps: ich hatte das eigentlich grade schon gepostet, aber das Forum hats wohl irgendwie "verschluckt".
'Binäruhr von Spyx
'Variablen definieren
DIM AS INTEGER kreisbreite, kreishoehe
DIM AS UBYTE stunden, minuten, sekunden, i, farbe
DIM uhrzeit AS STRING * 8
DIM key AS STRING * 2
'Grafikmodus initialisieren
SCREENRES 92, 175
Color 15,0
'Beim drücken der Escapetaste oder des Kreuzes oben rechts Schleife beenden
WHILE (key<>CHR(27)) and key<>(Chr(255, 107))
'Bildschirm leeren
CLS
'Zeit als String abrufen
uhrzeit = TIME
'Stunden, Minuten, Sekunden als unsigned Byte speichern
stunden = 10*CAST(BYTE,CHR(uhrzeit[0])) + CAST(BYTE,CHR(uhrzeit[1]))
minuten = 10*CAST(BYTE,CHR(uhrzeit[3])) + CAST(BYTE,CHR(uhrzeit[4]))
sekunden = 10*CAST(BYTE,CHR(uhrzeit[6])) + CAST(BYTE,CHR(uhrzeit[7]))
'Anzeige
FOR i = 0 to 5
'Stunden anzeigen
IF BIT(stunden, i) THEN
farbe = 15
ELSE
farbe = 8
ENDIF
CIRCLE (14,31+i*25), 10,farbe,,,1.2,F
DRAW STRING (8,5),STR(stunden)
'Minuten anzeigen
IF BIT(minuten, i) THEN
farbe = 15
ELSE
farbe = 8
ENDIF
CIRCLE (45,31+i*25), 10,farbe,,,1.2,F
DRAW STRING (39,5),STR(minuten)
'Sekunden anzeigen
IF BIT(sekunden, i) THEN
farbe = 15
ELSE
farbe = 8
ENDIF
CIRCLE (76,31+i*25), 10,farbe,,,1.2,F
DRAW STRING (70,5),STR(sekunden)
NEXT
'Tastaturabfrage
key = INKEY
'Flimmern reduzieren
SCREENSYNC
WEND
END
Wie man die Uhr lesen muss, sollte sich eigentlich selbst erklären. Falls es jmd. kompilieren möchte, so gibt es hier den Compiler: http://freebasic.net/index.php/download
Original von LX
CDW:
Nanu, hast ja deine ASM-Binäruhr noch gar net mit gepostet
Naja, ich hab das vor ein paar Jahren mal in JavaScript und HTML umgesetzt.
Also, wenn du mich schon verrätst - ich wurde damals von DEINEM Script inspiriert. Das heißt: das was du uns hier als fast neuwertig unterschieben möchtest (nur "paar Jahre" alt) hat in Wirklichkeit schon 5 Jährchen auf dem Buckel
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf!
Selig, wer nichts zu sagen hat und trotzdem schweigt.
Hier mal meine Version in C# .NET. Ich weiß, man könnte die Anzahl der Zeilen noch drastisch optimieren, aber mir ging es erstmal nur darum, dass es läuft :
BinaryClock.cs
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace BinaryClock
{
public partial class BinaryClock : Form
{
Image img0 = Image.FromFile(Path.GetDirectoryName(Application.ExecutablePath) + @"\gfx\0.jpg");
Image img1 = Image.FromFile(Path.GetDirectoryName(Application.ExecutablePath) + @"\gfx\1.jpg");
bool[] zHours = new bool[2];
bool[] eHours = new bool[4];
bool[] zMinutes = new bool[3];
bool[] eMinutes = new bool[4];
bool[] zSeconds = new bool[3];
bool[] eSeconds = new bool[4];
BackgroundWorker bgw = new BackgroundWorker();
public BinaryClock()
{
InitializeComponent();
bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
bgw.WorkerSupportsCancellation = true;
bgw.RunWorkerAsync();
}
void bgw_DoWork(object sender, DoWorkEventArgs e)
{
DateTime dt = DateTime.Now.ToLocalTime();
while (true)
{
if (dt == DateTime.Now.ToLocalTime())
continue;
dt = DateTime.Now.ToLocalTime();
#region zHours
int zHour = dt.Hour;
zHours[0] = false;
zHours[1] = false;
if (zHour >= 20)
{
zHours[0] = true;
zHours[1] = false;
}
else if (zHour >= 10)
{
zHours[0] = false;
zHours[1] = true;
}
#endregion
#region eHours
int eHour = dt.Hour % 10;
eHours[0] = false;
eHours[1] = false;
eHours[2] = false;
eHours[3] = false;
if (eHour >= 8)
{
eHours[0] = true;
eHour -= 8;
}
if (eHour >= 4)
{
eHours[1] = true;
eHour -= 4;
}
if (eHour >= 2)
{
eHours[2] = true;
eHour -= 2;
}
if (eHour >= 1)
{
eHours[3] = true;
}
#endregion
#region zMinutes
int zMinute = dt.Minute;
zMinutes[0] = false;
zMinutes[1] = false;
zMinutes[2] = false;
if (zMinute >= 40)
{
zMinutes[0] = true;
zMinute -= 40;
}
if (zMinute >= 20)
{
zMinutes[1] = true;
zMinute -= 20;
}
if (zMinute >= 10)
{
zMinutes[2] = true;
}
#endregion
#region eMinutes
int eMinute = dt.Minute % 10;
eMinutes[0] = false;
eMinutes[1] = false;
eMinutes[2] = false;
eMinutes[3] = false;
if (eMinute >= 8)
{
eMinutes[0] = true;
eMinute -= 8;
}
if (eMinute >= 4)
{
eMinutes[1] = true;
eMinute -= 4;
}
if (eMinute >= 2)
{
eMinutes[2] = true;
eMinute -= 2;
}
if (eMinute >= 1)
{
eMinutes[3] = true;
}
#endregion
#region zSeconds
int zSecond = dt.Second;
zSeconds[0] = false;
zSeconds[1] = false;
zSeconds[2] = false;
if (zSecond >= 40)
{
zSeconds[0] = true;
zSecond -= 40;
}
if (zSecond >= 20)
{
zSeconds[1] = true;
zSecond -= 20;
}
if (zSecond >= 10)
{
zSeconds[2] = true;
}
#endregion
#region eSeconds
int eSecond = dt.Second % 10;
eSeconds[0] = false;
eSeconds[1] = false;
eSeconds[2] = false;
eSeconds[3] = false;
if (eSecond >= 8)
{
eSeconds[0] = true;
eSecond -= 8;
}
if (eSecond >= 4)
{
eSeconds[1] = true;
eSecond -= 4;
}
if (eSecond >= 2)
{
eSeconds[2] = true;
eSecond -= 2;
}
if (eSecond >= 1)
{
eSeconds[3] = true;
}
#endregion
doubleBufferedPanel.Invalidate();
}
}
private void BinaryClock_FormClosing(object sender, FormClosingEventArgs e)
{
bgw.CancelAsync();
}
private void doubleBufferedPanel_Paint(object sender, PaintEventArgs e)
{
//198 Breit
//132 Hoch
for (int i = 0; i < 2; i++)
{
if (zHours[i] == true)
{
e.Graphics.DrawImage(img1, new Point(0, (i + 2) * 33));
}
else
{
e.Graphics.DrawImage(img0, new Point(0, (i + 2) * 33));
}
}
for (int i = 0; i < 4; i++)
{
if (eHours[i] == true)
{
e.Graphics.DrawImage(img1, new Point(33, i * 33));
}
else
{
e.Graphics.DrawImage(img0, new Point(33, i * 33));
}
}
for (int i = 0; i < 3; i++)
{
if (zMinutes[i] == true)
{
e.Graphics.DrawImage(img1, new Point(66, (i + 1) * 33));
}
else
{
e.Graphics.DrawImage(img0, new Point(66, (i + 1) * 33));
}
}
for (int i = 0; i < 4; i++)
{
if (eMinutes[i] == true)
{
e.Graphics.DrawImage(img1, new Point(99, i * 33));
}
else
{
e.Graphics.DrawImage(img0, new Point(99, i * 33));
}
}
for (int i = 0; i < 3; i++)
{
if (zSeconds[i] == true)
{
e.Graphics.DrawImage(img1, new Point(132, (i + 1) * 33));
}
else
{
e.Graphics.DrawImage(img0, new Point(132, (i + 1) * 33));
}
}
for (int i = 0; i < 4; i++)
{
if (eSeconds[i] == true)
{
e.Graphics.DrawImage(img1, new Point(165, i * 33));
}
else
{
e.Graphics.DrawImage(img0, new Point(165, i * 33));
}
}
}
}
}
BinaryClock.Designer.cs
Code:
namespace BinaryClock
{
partial class BinaryClock
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Windows Form-Designer generierter Code
/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
this.doubleBufferedPanel = new DoubleBufferedPanel();
this.SuspendLayout();
//
// doubleBufferedPanel
//
this.doubleBufferedPanel.BackColor = System.Drawing.Color.Black;
this.doubleBufferedPanel.ForeColor = System.Drawing.SystemColors.Control;
this.doubleBufferedPanel.Location = new System.Drawing.Point(0, 0);
this.doubleBufferedPanel.Name = "doubleBufferedPanel";
this.doubleBufferedPanel.Size = new System.Drawing.Size(198, 132);
this.doubleBufferedPanel.TabIndex = 0;
this.doubleBufferedPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.doubleBufferedPanel_Paint);
//
// BinaryClock
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(198, 132);
this.Controls.Add(this.doubleBufferedPanel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
this.MaximizeBox = false;
this.Name = "BinaryClock";
this.Text = "BinaryClock";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BinaryClock_FormClosing);
this.ResumeLayout(false);
}
#endregion
private DoubleBufferedPanel doubleBufferedPanel;
}
}
DoubleBufferedPanel.cs
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace BinaryClock
{
public class DoubleBufferedPanel : Panel
{
public DoubleBufferedPanel()
{
this.DoubleBuffered = true;
}
}
}
Program.cs
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace BinaryClock
{
static class Program
{
/// <summary>
/// Der Haupteinstiegspunkt für die Anwendung.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new BinaryClock());
}
}
}
Das wars dann auch schon
*EDIT: Hier noch die Grafik-Quellen, hatte ich vergessen^^: Klick
Ich habe mal unsere beiden Uhren neben der Systemuhr laufen lassen und irgendwie scheint es mir, als wenn unsere Uhren der Systemuhr immer einen Tick voraus sind
Liegt wahrscheinlich an den Bildern.
Die haben etwas magisches an sich.
Letztendlich hat mich die Seite dazu verleitet, eine Binäähhr Uhr zu erschaffen