#!/usr/local/bin/ruby =begin gcbr - Gtk CodeBraker in Ruby Copyright(C) 1999-2002 HIRATA Naoto Author: HIRATA Naoto This program is free software; You can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. =end require 'gtk' begin require 'intl' rescue LoadError class Intl def initialize( d ) end def _( s ) return s; end end end LOCALEDIR = '/usr/local/share/locale'; MIN_FIGURE = 3; MAX_FIGURE = 5; MIN_MAXNUMBER = 7; MAX_MAXNUMBER = 9; MAX_TIME = 8; class Gcbr def initialize( f, m ) @times = 0 @number = GcbrNumber.new( f, m ); @wnd = GcbrWindow.new( @number ) end def run() Gtk::main(); end end class GcbrNumber def initialize( f, m ) init_number( f, m ); end def init_number( f = MIN_FIGURE, m = MIN_MAXNUMBER ) @figure = f; @maxnumber = m; @comp = Array.new( MAX_MAXNUMBER ); @comp.each_index{ |i| @comp[i] = i+1; } randomize(); end def randomize() srand(); @comp.each{ |i| index_a = rand( @maxnumber ); index_b = rand( @maxnumber ); tmp = @comp[index_a]; @comp[index_a] = @comp[index_b]; @comp[index_b] = tmp; } end def compare( u ) @hit = 0; @blow = 0; u.each_index{ |i| u.each_index{ |j| if @comp[j] == u[i] if j == i @hit += 1; else @blow += 1; end end } } end attr( "figure" ); attr( "maxnumber"); attr( "hit" ); attr( "blow" ); end class GcbrWindow < Gtk::Window def initialize( n ) @number = n; @times = 0 @box = Array.new( MAX_TIME ); @spn_input = Array.new( MAX_TIME ); @btn_go = Array.new( MAX_TIME ); @lbl_result = Array.new( MAX_TIME ); @spn_input.each_index{ |i| @spn_input[i] = Array.new( MAX_FIGURE ); } super( Gtk::WINDOW_TOPLEVEL ); set_title( $intl._( "Code Breaker!" ) ); set_policy( false, false, false ); @accel_group = Gtk::AccelGroup.new(); add_accel_group( @accel_group ); signal_connect( "delete_event" ){ # Gtk::main_quit(); false; } signal_connect( "destroy" ){ Gtk::main_quit(); } @vbox = Gtk::VBox.new( false, 0 ); add( @vbox ); init_menu(); @box.each_index{ |i| @box[i] = Gtk::HBox.new( false, 0 ); @spn_input[i].each_index{ |j| @adj = Gtk::Adjustment.new( 1, 1, @number.maxnumber(), 1, 5, 0 ); @spn_input[i][j] = Gtk::SpinButton.new( @adj, 0, 0 ); @spn_input[i][j].set_wrap( true ); # @spn_input[i][j].set_shadow_type( Gtk::SHADOW_OUT ); @box[i].pack_start( @spn_input[i][j], true, true, 1 ); } @btn_go[i] = Gtk::Button.new( $intl._( "Go!" ) ); @btn_go[i].signal_connect( "clicked" ){ go(); } @box[i].pack_start( @btn_go[i], true, true, 3 ); @lbl_result[i] = Gtk::Label.new( "!!H, !!B" ); @box[i].pack_start( @lbl_result[i], true, true, 3 ); @vbox.pack_start( @box[i], false, true, 3 ); hsep = Gtk::HSeparator.new(); @vbox.pack_start( hsep, false, true, 0 ); } hsep = Gtk::HSeparator.new(); @vbox.pack_start( hsep, false, true, 0 ); @lbl_result_all = Gtk::Label.new( "" ); @vbox.pack_start( @lbl_result_all, true, true, 7 ); new_game(); show_all(); set_usize( -1, -1 ); end def new_game() @number.randomize(); @times = 0; @lbl_result_all.set( "" ); @number.figure().times{ |i| @adj = Gtk::Adjustment.new( 1, 1, @number.maxnumber(), 1, 5, 0 ); @spn_input[0][i].set_sensitive( true ); @spn_input[0][i].set_value( 1 ); @spn_input[0][i].set_adjustment( @adj ); } (@number.figure() ... MAX_FIGURE).each{ |i| @spn_input[0][i].set_sensitive( false ); @spn_input[0][i].set_value( 1 ); } @btn_go[0].set_sensitive( true ); @lbl_result[0].set( "? H,? B" ); (1 ... MAX_TIME).each { |i| @spn_input[i].each_index{ |j| @adj = Gtk::Adjustment.new( 1, 1, @number.maxnumber(), 1, 5, 0 ); @spn_input[i][j].set_sensitive( false ); @spn_input[i][j].set_value( 1 ); @spn_input[i][j].set_adjustment( @adj ); } @btn_go[i].set_sensitive( false ); @lbl_result[i].set( "? H, ? B" ); } end def go() user = Array.new( @number.figure() ); str = nil; @number.figure().times{ |i| user[i] = @spn_input[@times][i].get_value_as_int(); } @number.figure().times{ |i| ((i+1) ... @number.figure()).each{ |j| if user[i] == user[j] str = sprintf( $intl._( "duplicated!!" ) ); @lbl_result[@times].set( str ); return; end } } @number.compare( user ); update(); end def init_menu() # game menu @p_menu_g = Gtk::Menu.new(); @menu_game = Gtk::MenuItem.new( $intl._( "Game" ) ); @menu_game_new = Gtk::MenuItem.new( $intl._( "New" ) ); @p_menu_g.append( @menu_game_new ); @menu_game_new.signal_connect( "activate" ){ new_game(); } @menu_game_new.add_accelerator( "activate", @accel_group, Gdk::GDK_n, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE ); @menu_game_setting = Gtk::MenuItem.new( $intl._( "Setting" ) ); @p_menu_g.append( @menu_game_setting ); @menu_game_setting.signal_connect( 'activate' ){ setting = GcbrSetting.new( self, @number.figure(), @number.maxnumber() ); if setting.exit_status @number.init_number( setting.figure, setting.maxnumber ); new_game(); end } @menu_game_setting.add_accelerator( "activate", @accel_group, Gdk::GDK_s, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE ); @menu_game_sep = Gtk::MenuItem.new(); @p_menu_g.append( @menu_game_sep ); @menu_game_quit = Gtk::MenuItem.new( $intl._( "Quit" ) ); @p_menu_g.append( @menu_game_quit ); @menu_game_quit.signal_connect( "activate" ){ exit(); } @menu_game_quit.add_accelerator( "activate", @accel_group, Gdk::GDK_x, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE ); @menu_game.set_submenu( @p_menu_g ); # help menu @p_menu_h = Gtk::Menu.new(); @menu_help = Gtk::MenuItem.new( $intl._( "Help" ) ); @menu_help_about = Gtk::MenuItem.new( $intl._( "About" ) ); @p_menu_h.append( @menu_help_about ); @menu_help_about.signal_connect( "activate" ) { about = GcbrAbout.new( self ); } @menu_help_about.add_accelerator( "activate", @accel_group, Gdk::GDK_a, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE ); @menu_help.set_submenu( @p_menu_h ); # menubar @handlebox = Gtk::HandleBox.new(); @menu_bar = Gtk::MenuBar.new(); @handlebox.add( @menu_bar ); @vbox.pack_start( @handlebox, false, false, 2 ); @menu_bar.append( @menu_game ); @menu_bar.append( @menu_help ); end def update() str = sprintf( "%d H, %d B", @number.hit(), @number.blow() ); @lbl_result[@times].set( str ); @number.figure().times{ |i| @spn_input[@times][i].set_sensitive( false ); } @btn_go[@times].set_sensitive( false ); @times += 1; if @number.hit() == @number.figure() str = sprintf( $intl._( "Clear in %d times!" ), @times ); @lbl_result_all.set( str ); return; end if @times == MAX_TIME str = sprintf( $intl._( "Game Over!!!" ) ); @lbl_result_all.set( str ); return; end @number.figure().times{ |i| @spn_input[@times][i].set_sensitive( true ); } @btn_go[@times].set_sensitive( true ); end end class GcbrAbout < Gtk::Dialog def initialize( parent ) super(); set_modal( true ); set_transient_for( parent ); set_title( $intl._( "About" ) ); set_policy( false, false, true ); signal_connect( "delete_event" ){ Gtk::main_quit(); false; } @label = Gtk::Label.new( "Copyright (C) 1999-20002 HIRATA Naoto\nhttp://www.page.sannet.ne.jp/hirata-naoto/" ); vbox().pack_start( @label, true, true, 5 ); @button = Gtk::Button.new( "Ok" ); @button.grab_focus(); action_area().pack_start( @button, true, false, 5 ); @button.set_flags( Gtk::Widget::CAN_DEFAULT ); @button.grab_default(); @button.signal_connect( "clicked" ){ |obj, *event_infos| Gtk::main_quit(); destroy(); } show_all(); Gtk::main(); end end class GcbrSetting < Gtk::Dialog def initialize( p, f, m ) @exit_status = false; @rbtn_figure = Array.new( MAX_FIGURE - MIN_FIGURE + 1 ); @rbtn_maxnumber = Array.new( MAX_MAXNUMBER - MIN_MAXNUMBER + 1 ); # dialog super(); set_title( $intl._( "Setting" ) ); set_modal( true ); set_transient_for( p); set_policy( false, false, true ); signal_connect( "delete_event" ){ Gtk::main_quit(); false; } # figure @box = Gtk::HBox.new( false, 0 ); @frame = Gtk::Frame.new( $intl._( "Figure" ) ); @rbtn_figure[0] = Gtk::RadioButton.new( MIN_FIGURE.to_s() ); @box.pack_start( @rbtn_figure[0], true, true, 3 ); ((MIN_FIGURE+1) .. MAX_FIGURE ).each{ |i| j = i-MIN_FIGURE; @rbtn_figure[j] = Gtk::RadioButton.new( @rbtn_figure[0], i.to_s() ); @box.pack_start( @rbtn_figure[j], true, true, 3 ); } @frame.add( @box ); vbox().pack_start( @frame, true, true, 0); @rbtn_figure[f-MIN_FIGURE].set_active( true ); # max number @box = Gtk::HBox.new( false, 0 ); @frame = Gtk::Frame.new( $intl._( "Max Number" ) ); @rbtn_maxnumber[0] = Gtk::RadioButton.new( MIN_MAXNUMBER.to_s() ); @box.pack_start( @rbtn_maxnumber[0], true, true, 3 ); ((MIN_MAXNUMBER+1) .. MAX_MAXNUMBER).each{ |i| j = i-MIN_MAXNUMBER; @rbtn_maxnumber[j] = Gtk::RadioButton.new( @rbtn_maxnumber[0], i.to_s() ); @box.pack_start( @rbtn_maxnumber[j], true, true, 3 ); } @frame.add( @box ); vbox().pack_start( @frame, true, true, 0); @rbtn_maxnumber[m-MIN_MAXNUMBER].set_active( true ); # button @box = Gtk::HBox.new( true, 0 ); @btn_ok = Gtk::Button.new( "Ok" ); @btn_ok.set_flags( Gtk::Widget::CAN_DEFAULT ); @btn_ok.signal_connect( "clicked" ){ @rbtn_figure.each_index{ |i| if @rbtn_figure[i].active() @figure = i+MIN_FIGURE; end } @rbtn_maxnumber.each_index{ |i| if @rbtn_maxnumber[i].active() @maxnumber = i+MIN_MAXNUMBER; end } @exit_status = true; Gtk::main_quit(); destroy(); } @box.pack_start( @btn_ok, true, true, 5 ); @btn_cancel = Gtk::Button.new( $intl._( "Cancel" ) ); @btn_cancel.signal_connect( "clicked" ){ @exit_status = false; Gtk::main_quit(); destroy(); } @box.pack_start( @btn_cancel, true, true, 5 ); action_area().pack_start( @box, true, true, 0 ); @btn_ok.grab_default(); show_all(); Gtk::main(); end attr( "exit_status" ); attr( "figure" ); attr( "maxnumber" ); end if __FILE__ == $0 $intl = Intl.new( 'gcb' ); $intl.bindtextdomain( 'gcb', LOCALEDIR ); app = Gcbr.new( MIN_FIGURE, MIN_MAXNUMBER ); app.run(); end