#!/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;