#!/usr/bin/perl -w
# 從命令列上讀入棋盤的列數與行數, 讓騎士從第 0 列, 第 0 行開始走起,
# 看看是否可以一步一格, 把整個棋盤走完, 既不重複也不遺漏.
# http://www.cyut.edu.tw/~ckhung/b/pl/

use strict;
require "sitio";

my (%bdinfo, $board, $delta, $success);	#, 重要的全域變數
# Perl 內沒有真正的二維陣列, 我們用陣列的陣列來模擬二維陣列.
# $board->[0][3] 記載的是: 第 0 列第 3 行那一格是第幾步走到的?
# 請見詳談變數單元

$bdinfo{height} = $#ARGV >= 0 ? $ARGV[0] : 5;
$bdinfo{width} = $#ARGV >= 1 ? $ARGV[1] : 5;

# 請注意: 陣列的陣列在設定初始值時, 內層的括弧是方括弧!
$delta = [
	[2, 1],		[1, 2],		[-1, 2],	[-2, 1],
	[-2, -1],	[-1, -2],	[1, -2],	[2, -1],
];

$| = 1;
clearscr();

$board->[0][0] = 1;
drawcell(0, 0);
$success = march(2, 0, 0);

gotorc(23, 1);
printf($success ? "走完全程了!\n" : "這是不可能的任務!\n");

sub march {
    my ($step, $row, $col) = @_;
    my ($i, $r_next, $c_next);

    return 1 if ($step > $bdinfo{width} * $bdinfo{height});
    for ($i=0; $i<8; ++$i) {
	$r_next = $row + $delta->[$i][0];
	$c_next = $col + $delta->[$i][1];
	next if ($r_next < 0 or $r_next >= $bdinfo{height} or
	    $c_next < 0 or $c_next >= $bdinfo{width} or
	    defined $board->[$r_next][$c_next]);
	$board->[$r_next][$c_next] = $step;
	drawcell($r_next, $c_next);
	return 1 if (march($step+1, $r_next, $c_next));
	undef $board->[$r_next][$c_next];
	drawcell($r_next, $c_next);
    }
    return 0;
}

sub drawcell {
    my ($row, $col) = @_;
    my ($r0, $c0) = ((24 - $bdinfo{height}*2) / 2, (80 - $bdinfo{width}*4) / 2);

    gotorc($row*2+$r0, $col*4+$c0);
    printf "%2s", (defined $board->[$row][$col]) ? $board->[$row][$col] : "";
}

