Schrift
[thread]4597[/thread]

SoDuKo: natürlich in Wx !

Leser: 1


<< |< 1 2 3 >| >> 22 Einträge, 3 Seiten
lichtkind
 2006-10-16 00:45
#38893 #38893
User since
2004-03-22
5697 Artikel
ModeratorIn + EditorIn
[Homepage]
user image
renes post neulich er habe seine zeit im zug mit sudoku verplämpert , und da ich in letzer zeit es hin und wieder auch tue, hat das mich dazu angeregt ein wxperl programm zu schreiben das sudokus stellen und lösen kann.

ich hab heut abend angefangen und nach 75 zeilen steht die oberfläche mit zahlenfeld kontextmenü mit dem man die zahlen am feld ändern kann, und einem hauptmenü das die menüs game, options(rules?) und Help.

so mehr hab ich noch nicht, bis auf einpaar grundsätzliche ideen wie man was lösen kann.

wer hätte interesse daran mitzumachen?

jaja ich weiss ich fange alles mögliche an. und ich hab mich wiedermal verschrieben hab das programm erstmal SokuDo genannt erinnert mich an aikido. dozo gozaimasu.\n\n

<!--EDIT|lichtkind|1160945331-->
Wiki:Tutorien in der Wiki, mein zeug:
kephra, baumhaus, garten, gezwitscher

Es beginnt immer mit einer Entscheidung.
sid burn
 2006-10-16 01:28
#38894 #38894
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Soetwas habe ich zufällig schonmal geschrieben. Allerdings ohne GUI. Okay der Algorhytmus ist wohl Grotten schlecht, aber es erledigt seine Aufgabe:

main.pl
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/perl -w

use strict;
use Time::HiRes 'time';

# Wenn kein Argument uebergeben wurde.
unless (@ARGV)
{
print "USAGE: ", $0=~m{.*/(.*)}, " sudokofile\n";
exit;
}

# Array das dass Sudoku Enthaelt.
our @su;

# Werte aus Datei in das Array @su kopieren
my ($x, $y) = qw/0 0/;
while (<>)
{
next if /^\s*$/;
$su[$x++][$y] = $1 while m/\G\s*(\S+)/gc;
$x=0;
$y++;
}

# Ruft die Rekursive Funktion auf, die das Sudoku loest
my $start = time();
my $end;
&try_num(0,0);
print "F&�r dieses Sudoku gibt es keine L&�sung.\n";



# Loese Sudoku
sub try_num
{
my ($x, $y) = @_;

# Wenn x == 9 dann naechste Zeile, erste Spalte
if ( $x >= 9 )
{
$x=0;
$y++;
# Wenn Zeile 9 erreicht (es gibt nur 8) dann wurde Sudoku bearbeitet.
if ( $y >= 9 )
{
&ausgabe;
$end = time();
printf "Die Zeit betrug %.4f Sekunden\n", $end - $start;
exit;
}
}

# Solange weiter gehen bis zum naechsten '-' Zeichen.
until ( $su[$x][$y] eq '-' )
{
$x++;
if ( $x >= 9 )
{
$x=0;
$y++;
if ( $y >= 9 )
{
&ausgabe;
exit;
}
}
}

# Probiere an dieser Stelle die Werte 1..9 und prufe ob die Zahl gueltig ist.
for my $w (1..9)
{
$su[$x][$y] = $w;
if ( check_num($x, $y) )
{
try_num(++$x, $y);
--$x;
}
else
{
next;
}
}
$su[$x][$y] = '-';
return 0;
}



# Ausgabe des Sudoku
sub ausgabe
{
for my $y (0..8)
{
for my $x (0..8)
{
print $su[$x][$y], " ";
print " " unless ($x+1) % 3;
}
print "\n";
print "\n" unless ($y+1) % 3;
}
}


# Zeile, Spalte, Block der uebergebenen Position Ueberprufen
sub check_num
{
my ($x, $y) = @_;
my %h = ();

# Zeile ueberprufen
for my $w ( 0..8 )
{
next if $su[$w][$y] eq '-';
return 0 if exists $h{$su[$w][$y]};

$h{$su[$w][$y]} = 1;
}
%h = ();

# Spalte ueberpruefen
for my $w ( @{$su[$x]} )
{
next if $w eq '-';
return 0 if exists $h{$w};

$h{$w} = 1;
}
%h = ();

# Block ueberpruefen
my (@bx, @by);
@bx = $x<3 ? qw/0 1 2/ : $x<6 ? qw/3 4 5/ : qw/6 7 8/;
@by = $y<3 ? qw/0 1 2/ : $y<6 ? qw/3 4 5/ : qw/6 7 8/;

for my $x (@bx)
{
for my $y (@by)
{
next if $su[$x][$y] eq '-';
return 0 if exists $h{$su[$x][$y]};

$h{$su[$x][$y]} = 1;
}
}
%h = ();

# Wert ist Okay.
return 1;
}


sudoku
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
5 3 -  - 7 -  - - -
6 - - 1 9 5 - - -
- 9 8 - - - - 6 -

8 - - - 6 - - - 3
4 - - 8 - 3 - - 1
7 - - - 2 - - - 6

- 6 - - - - 2 8 -
- - - 4 1 - - - 5
- - - - - - - 7 -


Aufruf in der Shell mit "./main.pl sudoku". Ausgabe:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
5 3 4  6 7 8  9 1 2
6 7 2 1 9 5 3 4 8
1 9 8 3 4 2 5 6 7

8 5 9 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6

9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 9

Die Zeit betrug 1.5638 Sekunden
\n\n

<!--EDIT|sid burn|1160948021-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
esskar
 2006-10-16 01:39
#38895 #38895
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
könnte man wohl einfach mit backtracking lösen
topeg
 2006-10-16 02:21
#38896 #38896
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Ich habe mal ein Progrämmchen geschreiben, welches sudokus löst. (Ich bin halt wahnsinnig faul :-) ) Ich hatte schon mit dem Gedanken gespielt das so um zu schreiben, daß es Sudokus erzeugen kann... aber bis jetzt hatte ich weder die Zeit noch die Lust dazu.

Das ganze ist vielleicht ein wenig kompliziert, aber dafür sollte es jedes Sudoku schnell lösen können.
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
#!/usr/bin/perl

use strict;


my @base=(
[0,0,9,0,0,0,0,0,4],
[0,0,0,9,8,0,0,5,0],
[0,0,0,0,6,1,0,0,7],
[0,0,5,0,3,7,2,0,0],
[0,1,0,0,2,0,0,4,0],
[0,0,2,6,1,0,7,0,0],
[3,0,0,8,5,0,0,0,0],
[0,8,0,0,9,6,0,0,0],
[6,0,0,0,0,0,8,0,0]
);
# @base=(
# [0,0,4,6,0,0,7,0,0],
# [0,0,1,4,0,7,0,6,0],
# [9,0,0,0,3,0,8,2,0],
# [8,4,0,0,0,0,0,0,0],
# [0,0,9,0,6,3,0,0,0],
# [0,0,2,5,9,0,0,0,7],
# [0,0,7,0,0,1,2,0,0],
# [1,0,3,2,7,0,6,0,5],
# [5,0,0,0,0,0,9,7,0]
# );
# @base=(
# [0,2,0,0,0,9,6,0,0],
# [0,5,6,0,0,0,8,3,0],
# [3,0,0,0,0,0,1,0,0],
# [4,0,0,0,9,0,3,2,6],
# [8,0,0,0,4,1,0,7,0],
# [0,0,3,0,0,5,4,0,0],
# [0,0,0,0,0,0,0,0,0],
# [0,0,1,0,8,0,0,6,3],
# [6,9,8,0,7,0,0,1,0]
# );

my $ot=time();
my $obj=make_obj(\@base);
show($obj);
print "\nBerechne Lösung...\n";
my $back;
($obj,$back)=run($obj,0);
print "für mich nicht lösbar!\n" if($back<81);
show($obj);
my $nt=time();
print "\n".($nt-$ot)." Sekunden\n";
exit(0);


############
# Funtionen
############

sub run($$)
{
my ($obj,$deep)=@_;
# print "DEEP:".($deep+0)."\n";
my $exit=0;
my $cnt=0;
while($exit<=0)
{
$cnt=0;
my $change=0;
# vergleichen
for my $i (@{$obj->{'points'}})
{
if($i->{'wert'}==0)
{
my @can=get_can($i);
if(@can==1)
{
$i->{'wert'}=shift(@can);
$change++;
}
}
else
{ $cnt++; }
}

# nichts gefunden
if($change==0 && 81>$cnt)
{
# clone erzegen
my $tmp=make_obj([get_matrix($obj)]);
my $found=0;
my $x=-1;
my $y=-1;
# Feld mit zwei Möglichkeiten finden
for my $i (@{$tmp->{'points'}})
{
if($i->{'wert'}==0)
{
my @can=get_can($i);
if(@can==2)
{
$x=$i->{'x'};
$y=$i->{'y'};
$i->{'wert'}=shift(@can);
$change++;
last();
}
}
}

#was gefunden
if($change)
{
my $back;
($tmp,$back)=run($tmp,$deep+1);
if($back==81)
{
$obj=$tmp;
$cnt=81;
$exit=1;
}
else
{
for my $i (@{$obj->{'points'}})
{
if($i->{'x'}==$x && $i->{'y'}==$y)
{
my @can=get_can($i);
$i->{'wert'}=pop(@can);
last();
}
}
}
}
else
{ $exit=1; }
}
$exit=1 if($change==0);
$exit=1 if($cnt==81);
}
return($obj,$cnt);
}

sub make_obj($)
{
my ($get)=@_;
my $obj=
{
'cluster'=>[
[[],[],[]],
[[],[],[]],
[[],[],[]]
],
'cols'=>[],
'rows'=>[],
'points'=>[]
};


for(my $i=0; $i<9; $i++)
{
${$obj->{'cols'}}[$i]=[];
}

for(my $i=0; $i<9; $i++)
{ ${$obj->{'rows'}}[$i]=[]; }

my $c=0;
my $a=0;
for(my $i=0; $i<@{$get}; $i++)
{
my @sub=();
for(my $ii=0; $ii<@{$$get[$i]}; $ii++)
{
my $point={
'wert'=>$$get[$i][$ii],
'cluster'=>${$obj->{'cluster'}}[int($i/3)-1][int($ii/3)-1],
'col'=>${$obj->{'cols'}}[$ii],
'row'=>${$obj->{'rows'}}[$i],
'x'=>$i, 'y'=>$ii
};
push(@{${$obj->{'cluster'}}[int($i/3)-1][int($ii/3)-1]},$point);
# print "POS=(".$i.",".$ii."); CLUSTER:[".(int($i/3))."][".(int($ii/3))."]\n";
push(@{${$obj->{'cols'}}[$ii]},$point);
push(@sub,$point);
}
push(@{$obj->{'points'}},@sub);
push(@{${$obj->{'rows'}}[$i]},@sub);
}
return $obj;
}

sub get_can($)
{
my ($i)=@_;
my @can=(1..9);
# print "\n COL: ";
for my $ii (@{$i->{'col'}})
{
# print $ii->{'wert'}.",";
$can[$ii->{'wert'}-1]=0 if($ii->{'wert'}>0);
}
# print "\n ROW: ";
for my $ii (@{$i->{'row'}})
{
# print $ii->{'wert'}.",";
$can[$ii->{'wert'}-1]=0 if($ii->{'wert'}>0);
}
# print "\n CLS: ";
for my $ii (@{$i->{'cluster'}})
{
# print $ii->{'wert'}.",";
$can[$ii->{'wert'}-1]=0 if($ii->{'wert'}>0);
}
# print "\n ";
for(my $ii=8; $ii>=0; $ii--)
{ splice(@can,$ii,1) if($can[$ii]==0); }
return @can;
}

sub get_matrix($)
{
my ($in)=@_;
my @mx=([1..9],[1..9],[1..9],[1..9],[1..9],[1..9],[1..9],[1..9],[1..9]);
for my $i (@{$in->{'points'}})
{
if($i->{'wert'}>0)
{ $mx[$i->{'x'}][$i->{'y'}]=$i->{'wert'}; }
else
{ $mx[$i->{'x'}][$i->{'y'}]=0; }
}
return @mx;
}

sub show($)
{
my ($in)=@_;
my @mx=get_matrix($in);
my $d=1;
print "\nSUDOKU:\n";
print "+-------+-------+-------+\n";
for(my $i=0; $i<@mx; $i++)
{
if(int($i/3)==$d)
{
print "+-------+-------+-------+\n";
$d++;
}
print "| ";
my $c=1;
for(my $ii=0; $ii<@{$mx[$i]}; $ii++)
{
if(int($ii/3)==$c)
{
print "| ";
$c++;
}
print $mx[$i][$ii]." ";
}
print "|\n"
}
print "+-------+-------+-------+\n";
}


Ich hoffe man kann es verstehen. Ich habe so gut wie keine Dokumentation da drinnen, da es sich nur um eine Spielerei handelte...
esskar
 2006-10-16 11:52
#38897 #38897
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
es geht kürzer :)
http://www.ecclestoad.co.uk/blog....ed.html\n\n

<!--EDIT|esskar|1160985197-->
lichtkind
 2006-10-16 12:09
#38898 #38898
User since
2004-03-22
5697 Artikel
ModeratorIn + EditorIn
[Homepage]
user image
genau deswegen hab ich das hier gepostet. hab die gui jetzt so weit das man rätseln kann nur der generator und checker, und solver fehlen und die kann ich ja jetzt hier rasukopieren. könnte also schnell fertig werden durch teamwork.

was halt auch nicht so einfach ist, ist sudokus zu generieren die tatsächlich lösbar sind. mein aktuelles heft enthält 20% unlösbare son kack. aber ich glaube es gibt eh bestimmte stufen der lösbarkeit wel ich bei manchen 3 stufen um ecke denke wie bei schach und ich nicht glaube das der 3 lines solver ähnliche denktiefe hinlegt aber erst mal überprüfen. danke soweit an poster ergebnis werde ich natürlich hier veröffentlichen bis jetzt hab ich:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use strict;
use warnings;

package SuKoDo;
our $VERSION = 0.05;
our $NAME = "SoKuDo";

our $icon = 'wxwin.ico';
our $frame;
our %temp;

use Wx qw( wxTOP wxLEFT wxALIGN_CENTRE wxALIGN_CENTER_VERTICAL wxGROW
wxVERTICAL wxHORIZONTAL wxLI_VERTICAL wxLI_HORIZONTAL wxST_NO_AUTORESIZE
wxNO_FULL_REPAINT_ON_RESIZE wxSYSTEM_MENU wxCAPTION wxMINIMIZE_BOX wxCLOSE_BOX
wxBITMAP_TYPE_ICO );
use base qw(Wx::App);
use Wx::Event qw( EVT_MENU EVT_LEFT_DOWN EVT_RIGHT_DOWN );

sub OnInit {
$frame = Wx::Frame->new
( undef, -1, " $NAME ", [-1,-1],[-1,-1], wxNO_FULL_REPAINT_ON_RESIZE |
wxSYSTEM_MENU | wxCAPTION | wxMINIMIZE_BOX | wxCLOSE_BOX );
# set icon
Wx::InitAllImageHandlers();
$frame->SetIcon( Wx::Icon->new($icon, wxBITMAP_TYPE_ICO) ) if -e $icon;

# menubar
my $bar = Wx::MenuBar->new(1);
my $menu_game = Wx::Menu->new();
$menu_game->Append(1000,'New',' random new game');
$menu_game->Append(1001,'Open');
$menu_game->Append(1003,'Save');
$menu_game->Append(1004,'Exit');

my $menu_rules = Wx::Menu->new();
$menu_rules->AppendCheckItem(2000,'Hints allowed');

my $menu_help = Wx::Menu->new();
$menu_help->Append(3000,'Hint');
$menu_help->Append(3001,'How To ...');
$menu_help->Append(3002,'Info ...');

$bar->Append($menu_game, 'Game');
$bar->Append($menu_rules,'Rules');
$bar->Append($menu_help, 'Help');
$frame->SetMenuBar($bar);

# context menu
my $num_selector = Wx::Menu->new();
my $num_menu_id = 10000;
for (0..9){
$num_selector->Append($num_menu_id+$_,$_);
eval 'EVT_MENU($frame, '.($num_menu_id+$_).", sub{set_current_value($_)})";
}
$num_selector->Append(10010,'?');
EVT_MENU($frame, 10010, sub{ set_current_value('?') } );

# statusbar
my $sb = $frame->CreateStatusBar(1);
$sb->SetFieldsCount(1);
$sb->SetStatusWidths( -1 );
$frame->SetStatusBarPane(0);
#$sb->SetStatusText(' welcome',0);

my $panel = Wx::Panel->new( $frame, -1);
my (@cf, $cf, $sl, @h_sizer, $hs); #char field, current field
my $v_sizer = Wx::BoxSizer->new(wxVERTICAL);
$v_sizer->Add(Wx::StaticLine->new($panel, -1,[-1,-1], [-1,3]), 0, wxTOP|wxGROW, 0);
for my $y (1..9){
$hs = $h_sizer[$y] = Wx::BoxSizer->new(wxHORIZONTAL);
$hs->Add(Wx::StaticLine->new($panel, -1,[-1,-1], [3,-1]), 0, wxLEFT|wxGROW, 0);
for my $x (1..9){
$cf = $cf[$x][$y] = Wx::StaticText->new

($panel, -1, '?', [-1,-1], [16,16], wxALIGN_CENTRE|wxST_NO_AUTORESIZE);
EVT_LEFT_DOWN ( $cf[$x][$y], sub{

my ($widget, $event) = @_;

set_current_field($x, $y);

$widget->PopupMenu($num_selector, $event->GetX, $event->GetY);
} );
EVT_RIGHT_DOWN( $cf, sub { status_msg($x.$y) } );
$hs->Add($cf, 0, wxLEFT, 0);
if ($x % 3) {$sl = Wx::StaticLine->new($panel, -1,[-1,-1],[1,-1]) }
else {$sl = Wx::StaticLine->new($panel, -1,[-1,-1],[3,-1]) }
$hs->Add($sl, 0, wxLEFT|wxGROW, 0);
}
$v_sizer->Add($hs, 0, wxTOP, 0);

if ($y % 3) {$sl = Wx::StaticLine->new($panel, -1, [-1,-1], [-1,1]) }
else {$sl = Wx::StaticLine->new($panel, -1, [-1,-1], [-1,3]) }
$v_sizer->Add($sl, 0, wxTOP|wxGROW, 0);
}
$frame->{'num_field'} = \@cf;

$panel->SetSizer($v_sizer);
my $m_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
$m_sizer->Add($panel, 0, wxTOP|wxGROW, 0);
$frame->SetSizer($m_sizer);
$frame->SetAutoLayout(1);
$frame->Fit();
status_msg('welcome to version '.$VERSION);
$frame->Show(1);
}

sub status_msg {
my $msg = shift;
$frame->SetStatusText( " $msg", 0);
}

sub set_current_field{
my $x = shift;
my $y = shift;
$temp{'current_field'}{'x'} = $x;
$temp{'current_field'}{'y'} = $y;
$temp{'current_field'}{'ref'} = $frame->{'num_field'}[$x][$y];
}

sub set_current_value{
my $new = shift;
my $c = $temp{'current_field'};
my $old = $c->{'ref'}->GetLabel;
$c->{'ref'}->SetLabel($new);
status_msg("field [$c->{y},$c->{x}] set from $old to $new");
}

package main;
SuKoDo->new->MainLoop;
Wiki:Tutorien in der Wiki, mein zeug:
kephra, baumhaus, garten, gezwitscher

Es beginnt immer mit einer Entscheidung.
topeg
 2006-10-16 12:42
#38899 #38899
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
@ esskar
Der code im Link von dir arbeitet alle möglichkeiten rekursiv durch (so scheint es mir beim überfliegen) und gibt das Ergebnis zurück (es werden allso alle möglichkeiten durchgespielt).
In meinem Code versuche ich mir so wenig Rekursionen wie möglich aus zu kommen. Dadurch wird das script etwas schneller...
lichtkind
 2006-10-16 14:32
#38900 #38900
User since
2004-03-22
5697 Artikel
ModeratorIn + EditorIn
[Homepage]
user image
da das ganze thema interessant ist werd ich versuchen die API so zu halten das jeder einfach eigne loeser und generatoren zufuegen kann und so die gui nutzen kann.

hat es gemand getestet was haltet ihr von der art der bedienung? werde noch einen benutzermode fuer tataur zufuegen aber das wird etwas komplizierter da es mehr staticlines werden und auch eine komplexere indizierung brauchen.
Wiki:Tutorien in der Wiki, mein zeug:
kephra, baumhaus, garten, gezwitscher

Es beginnt immer mit einer Entscheidung.
renee
 2006-10-16 22:46
#38901 #38901
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Es gibt auch Module zu Sudoku auf CPAN. Und die Frühlingsausgabe von "The Perl Review" war auch ganz interessant dazu...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
lichtkind
 2006-10-16 23:33
#38902 #38902
User since
2004-03-22
5697 Artikel
ModeratorIn + EditorIn
[Homepage]
user image
schon aber ich wollte es selber machen das ist mein mannbarkeitsritus :) die apis ähneln aber in vielem dem woraus ich bereits nach einem tag gekommen bin.

ich präsentiere version 0.1 voll spielbar allerdings nur 1 gespeichertes quest. merkt sich aber den stand und stellt ihn wieder her.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#!/usr/bin/perl -w
use strict;
use warnings;

package SuKoDo;
our $VERSION = 0.1;
our $NAME = "SoKuDo";

our $icon = 'wxwin.ico';
our $default_file = 'autosave.txt';
our $frame;
our %data;

use Wx qw( wxTOP wxLEFT wxALIGN_CENTRE wxALIGN_CENTER_VERTICAL wxGROW
wxVERTICAL wxHORIZONTAL wxLI_VERTICAL wxLI_HORIZONTAL wxST_NO_AUTORESIZE
wxNO_FULL_REPAINT_ON_RESIZE wxSYSTEM_MENU wxCAPTION wxMINIMIZE_BOX wxCLOSE_BOX
wxBITMAP_TYPE_ICO
);
use Wx::Event qw( EVT_MENU EVT_LEFT_DOWN EVT_RIGHT_DOWN );
use base qw(Wx::App);

sub OnInit {
$frame = Wx::Frame->new
( undef, -1, " $NAME ", [-1,-1],[-1,-1], wxNO_FULL_REPAINT_ON_RESIZE |
wxSYSTEM_MENU | wxCAPTION | wxMINIMIZE_BOX | wxCLOSE_BOX );
# set icon
Wx::InitAllImageHandlers();
$frame->SetIcon( Wx::Icon->new($icon, wxBITMAP_TYPE_ICO) ) if -e $icon;

# menubar
my $menu_game = Wx::Menu->new();
$menu_game->Append(1000,'New',' create a random new game');
$menu_game->Append(1001,'Input',' type numbers into the field');
$menu_game->AppendSeparator;
$menu_game->Append(1002,'Copy',' copy into clipboard');
$menu_game->Append(1003,'Paste',' copy from clipboard');
$menu_game->AppendSeparator;
$menu_game->Append(1004,'Open',' load a quest from a file');
$menu_game->Append(1005,'Save', ' store a quest in a file');
$menu_game->AppendSeparator;
$menu_game->Append(1006,'Exit', ' close the game');
EVT_MENU($frame, 1000, sub { load_game('quests/1.txt') } );
EVT_MENU($frame, 1001, sub { \&not_implemented } );
EVT_MENU($frame, 1002, sub { \&not_implemented } );
EVT_MENU($frame, 1003, sub { \&not_implemented } );
EVT_MENU($frame, 1004, sub { load_game($default_file) } );
EVT_MENU($frame, 1005, sub { save_game($default_file) } );
EVT_MENU($frame, 1006, sub { $frame->Close(1) } );
my $menu_changes = Wx::Menu->new();
$menu_changes->Append(2000,'Undo');
$menu_changes->Append(2001,'Redo');
$menu_changes->AppendSeparator;
#$menu_changes->Append(2002,'Fill');
#$menu_changes->AppendSeparator;
$menu_changes->Append(2003,'Solve');
EVT_MENU($frame, 2000, \&not_implemented );
EVT_MENU($frame, 2001, \&not_implemented );
EVT_MENU($frame, 2002, \&not_implemented );
EVT_MENU($frame, 2003, \&not_implemented );
#my $menu_rules = Wx::Menu->new();
#$menu_rules->AppendCheckItem(3000,'Autocheck');
#$menu_rules->AppendCheckItem(3001,'Hints allowed');
#EVT_MENU($frame, 3000, \&not_implemented );
#EVT_MENU($frame, 3001, \&not_implemented );
my $menu_help = Wx::Menu->new();
$menu_help->Append(4000,'Hint', '');
$menu_help->Append(4001,'How To ...', 'how to play sudoku');
#$menu_help->Append(4002,'How To ...', 'how to play sudoku');
$menu_help->Append(4003,'Info ...', 'infos about the program');
EVT_MENU($frame, 4000, \&not_implemented );
EVT_MENU($frame, 4001, \&not_implemented );
EVT_MENU($frame, 4003, \&not_implemented );
my $bar = Wx::MenuBar->new();
$bar->Append($menu_game, 'Game');
$bar->Append($menu_changes, 'Changes');
#$bar->Append($menu_rules,'Rules');
$bar->Append($menu_help, 'Help');
$frame->SetMenuBar($bar);

# context menu
my $num_selector = Wx::Menu->new();
my $num_menu_id = 10000;
for (0..9){
$num_selector->Append($num_menu_id+$_,$_);
eval 'EVT_MENU($frame, '.($num_menu_id+$_).", sub{set_current_value($_)})";
}
$num_selector->Append(10010,'-');
EVT_MENU($frame, 10010, sub{ set_current_value('-') } );

# statusbar
my $sb = $frame->CreateStatusBar(1);
$sb->SetFieldsCount(1);
$sb->SetStatusWidths( -1 );
$frame->SetStatusBarPane(0);
status_msg('welcome to version '.$VERSION);

# number array panel
my $panel = Wx::Panel->new( $frame, -1);
my (@cf, $cf, $sl, @h_sizer, $hs); #char field, current field
my $v_sizer = Wx::BoxSizer->new(wxVERTICAL);
$v_sizer->Add(Wx::StaticLine->new($panel, -1,[-1,-1], [-1,3]), 0, wxTOP|wxGROW, 0);
for my $y (1..9){
$hs = $h_sizer[$y] = Wx::BoxSizer->new(wxHORIZONTAL);
$hs->Add(Wx::StaticLine->new($panel, -1,[-1,-1], [3,-1]), 0, wxLEFT|wxGROW, 0);
for my $x (1..9){
$cf = $cf[$y][$x] = Wx::StaticText->new

($panel,-1,'',[-1,-1],[16,16],wxALIGN_CENTRE|wxST_NO_AUTORESIZE);
EVT_LEFT_DOWN ( $cf[$y][$x], sub{

my ($widget, $event) = @_;

set_current_sqare($x, $y);

$widget->PopupMenu($num_selector, $event->GetX, $event->GetY);
} );
EVT_RIGHT_DOWN( $cf, sub {

#status_msg($x.$y)
} );
$hs->Add($cf, 0, wxLEFT, 0);
if ($x % 3) {$sl = Wx::StaticLine->new($panel, -1,[-1,-1],[1,-1]) }
else {$sl = Wx::StaticLine->new($panel, -1,[-1,-1],[3,-1]) }
$hs->Add($sl, 0, wxLEFT|wxGROW, 0);
}
$v_sizer->Add($hs, 0, wxTOP, 0);

if ($y % 3) {$sl = Wx::StaticLine->new($panel, -1, [-1,-1], [-1,1]) }
else {$sl = Wx::StaticLine->new($panel, -1, [-1,-1], [-1,3]) }
$v_sizer->Add($sl, 0, wxTOP|wxGROW, 0);
}
$frame->{'sqare_field'} = \@cf;

$panel->SetSizer($v_sizer);
my $m_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
$m_sizer->Add($panel, 0, wxTOP|wxGROW, 0);
$frame->SetSizer($m_sizer);
$frame->SetAutoLayout(1);
$frame->Fit;
$frame->Show(1);

load_game($default_file);

1;
}
#
sub OnExit{ save_game($default_file) }
#
sub status_msg {
my $msg = shift;
$frame->SetStatusText( " $msg", 0);
}
#
sub set_num_array{
my $num = shift;
my ($x,$y);
return unless ref $num eq 'ARRAY' and @$num == 9;
for my $row (@$num){
return unless ref $row eq 'ARRAY' and @$row == 9;
$y++;
$x = 1;
$frame->{'sqare_field'}[$y][$x++]->SetLabel($_) for @$row;
}
$data{'num_array'} = $num;
}
sub get_num_array{ $data{'num_array'} }
sub get_num_row{}
sub get_num_col{}
sub get_num_sqare{}

sub clear_num_array{
set_num_array([
[qw(- - - - - - - - -)],
[qw(- - - - - - - - -)],
[qw(- - - - - - - - -)],
[qw(- - - - - - - - -)],
[qw(- - - - - - - - -)],
[qw(- - - - - - - - -)],
[qw(- - - - - - - - -)],
[qw(- - - - - - - - -)],
[qw(- - - - - - - - -)],
] )
}
sub get_array_from_file{
my $name = shift;
return unless -e $name;
my @table;
open my $fh, "<$name";
while (<$fh>){
my @row = ();
chomp;
tr / \t//d;
next unless $_;
unshift @row, chop while $_;
push @table, \@row;
}
return \@table;
}

sub put_array_into_file{
my $array = shift;
my $file = shift;
my ($txt, $row, $l);;
my $temp = $";
$"=" ";
return unless ref $array eq 'ARRAY' and @$array == 9;
for my $row (@$array){
return unless ref $row eq 'ARRAY' and @$row == 9;
$l++;
$row = "@$row\n";
substr $row, 5, 1 , ' ';
substr $row, 12, 1 , ' ';
$txt .= $row;
$txt .= "\n" if $l == 3 or $l == 6;
}
$" = $temp;
open my $fh, ">$file";
print $fh $txt;
}

sub load_game{
my $file = shift;
set_num_array( get_array_from_file($file) );
}

sub save_game{
my $file = shift;
put_array_into_file( get_num_array(), $file);
}
#
sub set_current_sqare{
my $x = shift;
my $y = shift;
$data{'current_sqare'}{'x'} = $x;
$data{'current_sqare'}{'y'} = $y;
$data{'current_sqare'}{'ref'} = $frame->{'sqare_field'}[$y][$x];
$data{'current_sqare'}{'cell'} = \$data{'num_array'}[$y-1][$x-1];
}
#
sub set_current_value{
my $new = shift;
my $c = $data{'current_sqare'};
my $old = $c->{'ref'}->GetLabel;
$c->{'ref'}->SetLabel($new);
#$data{'num_array'}[$c->{'y'}-1][$c->{x}-1] = $new;
${$c->{'cell'}} = $new;
status_msg("cell [$c->{x},$c->{y}] set from $old to $new");
}
#
sub not_implemented{ status_msg(' not yet implemented') }
#
package main;
SuKoDo->new->MainLoop;
Wiki:Tutorien in der Wiki, mein zeug:
kephra, baumhaus, garten, gezwitscher

Es beginnt immer mit einer Entscheidung.
<< |< 1 2 3 >| >> 22 Einträge, 3 Seiten



View all threads created 2006-10-16 00:45.