Trò chơi 15
Có
15 quân cờ được đánh mã số từ 1 đến 15 được đặt trong một bàn cờ hình vuông 4 ´ 4 ô theo hình
trạng ban đầu như rong hình . Mỗi bước đi, ta được phép di chuyển một quân nằm
cạnh ô trống vào trong ô trống.
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
10
|
11
|
12
|
13
|
14
|
15
|
|
Trò chơi 15
|
Viết chương
trình thực hiện hai chức năng sau đây:
a) Đảo ngẫu nhiên các quân cờ để chuyển từ hình trạng
ban đầu về một hình trạng H nào đó.
b) Nhận phím điều khiển của người chơi rồi di chuyển
quân cờ theo phím đó. Khi nào người chơi đạt được hình trạng ban đầu thì kết
thúc một ván.
Trò chơi này có tên là Trò chơi
15, từng nổi tiếng ở thế kỉ XIX như trò chơi Rubic ở thời đại chúng ta vậy.
Tag: gia sư tin học, gia sư tin học tại hà nội, dạy kèm tin học tại nhà
Gợi ý
Trò chơi này khá dễ lập trình. Bạn cần lưu ý sự
khác biệt giữa vị trí của phần tử a[i, j] trong ma trận a với vị trí hiển
thị của nó trên màn hình, vì thủ tục gotoxy(i,
j) đưa con trỏ màn hình đến cột i,
dòng j trong khi a[i, j] lại truy cập tới
dòng (i) và cột (j). Sự khác biệt này được tính đến trong thủ tục Den (đến - chuyển con trỏ đến vị trí thích hợp để hiển thị phần tử a[i,
j]).
Mảng b
chứa hình trạng ban đầu của bàn cờ và dùng để kiểm tra xem mảng a có trùng với hình trạng này không (xem
hàm lôgic Dung).
Hai thủ tục DaoNgauNhien và Game15 đều cùng gọi đến thủ tục Chuyen(k) - dịch chuyển một trong bốn quân sát với ô trống vào ô trống. Ta quy
ước chọn các giá trị của k là:
0: Lên - chuyển quân nằm sát dưới ô trống vào ô trống.
1: Xuống - chuyển quân nằm sát trên ô trống vào ô trống.
2: Phải - chuyển quân nằm sát trái ô trống vào ô trống.
3: Trái - chuyển quân nằm sát phải ô trống vào ô trống.
Đương nhiên, nếu ô trống nằm sát đường biên thì có thể có trường hợp
không chuyển được.
Ta phân biệt phần tử (i, j)
của mảng a với vị trí hiển thị giá trị a[i, j] của phần tử đó trên màn hình như
sau. Gọi (x, y) là vị trí góc trên
trái của vùng hiển thị, dx và dy là chiều dài hai cạnh của ô sẽ hiển
thị giá trị a[i, j], khi đó thủ tục Den(i,j) dưới đây chuyển con trỏ
màn hình đến vị trí hiển thị được mô tả như sau:
procedure Den(i,j: byte);
begin
Gotoxy(y+(j-1)*dy,x+(i-1)*dx);
end;
Khi đó thủ tục Viet(i,j:
byte)viết giá trị a[i, j] vào ô tương ứng
trên màn hình sẽ thực hiện các thao tác sau. Trước hết cần chuyển con trỏ màn
hình đến vị trí cần viết bằng thủ tục Den(i,j). Sau
đó xét ô a[i, j]. Nếu đó là ô trống (a[i, j] = 0) thì xoá ô đó, ngược lại ta
ghi giá trị của a[i, j] vào ô cần hiển thị.
procedure Viet(i,j: byte);
begin
Den(i,j);
if a [i,j] = 0 then
begin
TextBackGround(YELLOW);
write(BL:2);
TextBackGround(BLUE);
end
else write(a [i,j]:2);
end;
Khi khởi động chương trình sẽ hiển thị trò chơi và
tiến hành đảo ngẫu nhiên các quân cờ cho đến khi người chơi nhấn một phím tùy
ý. Từ thời điểm đó, người chơi sẽ tìm cách di chuyển các quân cờ để đạt tới
hình trạng ban đầu.
(* Pascal *)
(*----------------------
Game 15
-----------------------*)
uses crt;
const
BL = #32;
DD = 4;
x = 2; y = 3; {Goc Tay-Bac cua ban
co}
dx = 2; dy = 3; {Khoang cach giua
cac o}
{cac ma dich chuyen con tro}
LEN = 200;
XUONG = 208;
PHAI = 205;
TRAI = 203;
var
a, b: array [1..DD,1..DD] of byte;
{ban co}
xx, yy: byte; {Toa do cua con tro}
{------------------------
Nhan tham 1 ki tu
-------------------------}
Function GetKey: integer;
var c: char;
begin
c:= ReadKey;
if c <> #0 then GetKey:=
Ord(c)
else begin
c:= ReadKey;
GetKey:= Ord(c) + 128;
end;
end;
{-------------------------
Chuyen con tro man hinh
den vi tri hien thi
quan co (i,j)
--------------------------}
procedure Den(i,j: byte);
begin
Gotoxy(y+(j-1)*dy,x+(i-1)*dx);
end;
{-----------------------------
Viet gia tri cua quan co
a[i,j] vao o tuong ung
------------------------------}
procedure Viet(i,j: byte);
begin
Den(i,j);
if a[i,j] = 0 then
begin
TextBackGround(YELLOW);
write(BL:2);
TextBackGround(BLUE);
end
else write(a[i,j]:2);
end;
{-------------------------------
Khoi
tri:
1.
Dat mau chu, mau nen
2. Ve ban co
-------------------------------}
procedure Init;
var i, j, k: byte;
begin k := 0;
{nen ngoai mau vang}
TextBackGround(YELLOW);
Gotoxy(1,1);
{ Ve cac o trong }
for i:= 1 to dx*DD+1 do
begin
for j := 1 to dy*DD+3 do write(BL);
writeln;
end;
TextBackGround(BLUE); {nen ban co mau xanh}
TextColor(WHITE); {chu trang}
{Khoi tri va hien thi cac quan co}
for i:= 1 to DD do
for j:= 1 to DD do
begin
inc(k); a[i,j]:= k;
b[i,j]:= k; Viet(i,j);
end;
a[DD,DD]:= 0; b[DD,DD]:= 0;
Viet(DD,DD); Den(DD,DD);
xx:= DD; yy:= DD;
end;
{------------------------------
Di chuyen quan co a[xx,yy]
vao o trong ke no
-------------------------------}
procedure Chuyen(k: integer);
begin
case k of
0: {LEN}
if xx < DD then
begin
a[xx,yy]:= a[xx+1,yy];
Viet(xx,yy);
inc(xx); a[xx,yy]:= 0;
Viet(xx,yy);
end;
1: {XUONG}
if xx > 1 then
begin
a[xx,yy]:= a[xx-1,yy];
Viet(xx,yy);
dec(xx); a[xx,yy]:= 0;
Viet(xx,yy);
end;
2: {PHAI}
if yy > 1 then
begin
a[xx,yy]:= a[xx,yy-1];
Viet(xx,yy);
dec(yy); a[xx,yy]:= 0;
Viet(xx,yy);
end;
3: {TRAI}
if yy < DD then
begin
a[xx,yy]:= a[xx,yy+1];
Viet(xx,yy);
inc(yy); a[xx,yy]:= 0;
Viet(xx,yy);
end;
end;
end;
{-----------------------------
Dao ngau nhien cac quan co
------------------------------}
procedure DaoNgauNhien;
var c: integer;
begin
repeat
Chuyen(random(4));
Delay(50); {Dat do tre de kip quan sat}
until KeyPressed;
c:= GetKey;
end;
{--------------------------
Kiem tra ban co a co
trung voi cau hinh chuan ?
----------------------------}
function Dung: Boolean;
var i, j: byte;
begin
Dung:= FALSE;
for i:= 1 to DD do
for j:= 1 to DD do
if (a[i,j] <> b[i,j]) then exit;
Dung:= TRUE;
end;
procedure Game15;
var k: integer;
d, v: longint;
sx, sy, ex, ey: byte;
begin
Randomize;
ClrScr; d:= 0; v:= 1;
TextBackGround(BLUE);
TextBackGround(BLUE);
TextColor(WHITE);
Init;
gotoxy(5,25); clreol;
write(' Van: ');
sx:= Wherex; sy:= Wherey;
write(v); write(' Tong so buoc: ');
ex:= Wherex; ey:= Wherey;
DaoNgauNhien;
repeat
gotoxy(sx,sy); write(BL:10);
gotoxy(sx,sy); write(v);
gotoxy(ex,ey); clreol; {xoa cho den het dong}
gotoxy(ex,ey); write(d);
Den(xx,yy);
k:= GetKey;
case k of
LEN: k:= 0;
XUONG: k:= 1;
PHAI: k:= 2;
TRAI: k:= 3;
end;
Chuyen(k); inc(d);
if Dung then
begin
DaoNgauNhien;
inc(v); d:= 0;
gotoxy(sx,sy); write(BL:10);
gotoxy(sx,sy); write(v);
end;
until UpCase(chr(k)) in [#27, 'Q'];
Textattr := 7; clrscr;
end;
BEGIN
Game15;
END.
Không có nhận xét nào:
Đăng nhận xét