Thứ Năm, 2 tháng 1, 2014

Trò chơi 15



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 DaoNgauNhienGame15 đề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ị, dxdy 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