#!/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 { \¬_implemented } );
EVT_MENU($frame, 1002, sub { \¬_implemented } );
EVT_MENU($frame, 1003, sub { \¬_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, \¬_implemented );
EVT_MENU($frame, 2001, \¬_implemented );
EVT_MENU($frame, 2002, \¬_implemented );
EVT_MENU($frame, 2003, \¬_implemented );
#my $menu_rules = Wx::Menu->new();
#$menu_rules->AppendCheckItem(3000,'Autocheck');
#$menu_rules->AppendCheckItem(3001,'Hints allowed');
#EVT_MENU($frame, 3000, \¬_implemented );
#EVT_MENU($frame, 3001, \¬_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, \¬_implemented );
EVT_MENU($frame, 4001, \¬_implemented );
EVT_MENU($frame, 4003, \¬_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;