AFFECTIVESILICON

Japanese Kanji Tester Application

Revision 1.0 2022-08-21

This Kanji tester desktop application was quickly put together in Perl and Tk. It's useful for a short quiz. The user types in what they think is the English meaning and clicks "Check Kanji" to move on to the next.

Screenshot of Kanji tester

Source Code


#!/usr/bin/perl
# Kanji tester app 

use v5.16;
use Tk;
use utf8;
use List::Util qw(shuffle);

require Tk::LabEntry;

#### create a Tk main window
my $MW = MainWindow->new;
$MW->title("Kanji Tester");
$MW->geometry("580x370+20+20");

#### read in the kanjis
my @kanjis;
while ( my $line = <DATA> ) {
	chomp($line);
	my ($kanji, $eigo) = split(/,/, $line);
	push @kanjis, [$kanji, $eigo];
}

say "There are " . scalar(@kanjis) . " kanji in the database.";

# randomize the kanjis
my @kanji_rand = shuffle @kanjis;

#### variables

# for kanji
my $kanji_text = q{};
my $kanji_eigo = q{};

# for scoring
my $score = 0;
my $total = 30;
my $count = 1;
my $score_text;

# for entry box
my $entry_text = q{};

#### create TK user interface

# Kanji display label
my $label = $MW->Label(
	-textvariable	=>		\$kanji_text,
	-relief			=>		'flat',
	-padx				=>		20,
	-pady				=>		20,
	-font				=>		[ -size => 72 ],
)->pack;

my $score_label = $MW->Label(
	-textvariable	=>	\$score_text,
	-font		=>	[ -size => 24 ],
)->pack;

my $labentry_box = $MW->LabEntry(
	-label			=>		"Enter guess: ",
	-labelPack		=>		[ -side => 'left', -anchor => 'w' ],
	-labelFont		=>		[ -size => 18 ],
	-textvariable	=>		\$entry_text,
	-font				=>		[ -size => 18 ],
)->pack( -expand => 1, -fill => 'x' );

# 'next' button
my $next = $MW->Button(
	-text    	=> 	'Check Kanji',
	-font			=>		[ -size => 18 ],
	-command 	=> 	\&check_kanji,
)->pack(	-expand => 1, -fill => 'both' );

# 'restart' button
my $restart = $MW->Button(
	-text    	=> 	'Restart Quiz',
	-font			=>		[ -size => 18 ],
	-command 	=> 	sub {  	$score = 0;
										$total = 10;
										$count = 1;
										$entry_text = q{};
										next_kanji();
										get_score();
									},
)->pack(	-expand => 1, -fill => 'both' );

# 'exit' button
my $exit = $MW->Button(
	-text    	=> 	'Exit',
	-font			=>		[ -size => 18 ],
	-command 	=> 	sub { say "Exiting..."; exit; },
)->pack(	-expand => 1, -fill => 'both' );

#### Initialise and main loop

next_kanji();
get_score();

MainLoop;	# the TK gui main loop

exit;

END {
	say "Your final score is $score out of $total";
}

sub next_kanji {

		my $ar_ref = pop @kanji_rand;							# get the next Kanji
		$kanji_text = $count . ": " . $ar_ref->[0];		# display with the current question number
		$kanji_eigo = $ar_ref->[1];							# also store the English meaning
}

sub check_kanji {

	if ( 	length($entry_text) && 			# only check the user's guess if text is entered 
			($count <= $total) && 			# while still asking questions
			scalar(@kanji_rand) 				# make sure there's Kanji left in the list
			) {

		# increase score if correct and ask next Kanji
		$score++ if $kanji_eigo =~ /$entry_text/i;	# sometimes a Kanji has several meanings, 
		say $entry_text, "\t-\t", $kanji_eigo;			# so be nice to the user

		$count++;

		next_kanji() if $count <= $total;

		$entry_text = q{};

		get_score();
	}
}

sub get_score {

	$score_text = ($count > $total ? "Final" : "Current");
	$score_text .= " score: $score out of $total";
}

# Kanji database - add Kanjis here
__DATA__
一,one
一人,one person
一日目,the first day
二,two
三,three
三月,march
四,four
五,five
六,six
七,seven
八,eight
九,nine
十,ten
千,thousand
人,person
人口,population
入,enter
入口,entrance
力,power
力土,sumo wrestler
上,top
上手,skillful
下,low
下手,unskillful/awkward
大,big
小,small
小犬,puppy
口,mouth
山,mountain
子,child
女,woman
女子,woman/women's
夕,evening
夕力,evening
川,river
川上,upstream
土,earth
円,round/yen
王,king
火,fire
火山,volcano
月,month/moon
犬,dog
手,hand
水,water
中,centre/China
日,sun/day/Japan
日本,Japan
天,heaven
天下,the whole world
文,writing
木,tree/wood
右,right
右手,right hand
左,left
左右,left and right
玉,jewel/jade/ball
玉子,egg
出,emerge/go out/send
出口,exit
正,right/correct
正月,new year's
生,life/birth/grow/student
石,stone
田,rice field/paddy
本,book/true/real
目,eye
目玉,eyeball
目上,one's superior