Trò chơi úp bài
Cho M quân bài mang các số từ 1 đến M ( M<=12 ) , các quân bài
đang lật ngửa .Cho một số nguyên dơng N ( N<=200 ) . Trò chơi nh sau :
Hai ngời lần lợt thay nhau úp quân bài theo qui tắc :
+ Cộng giá trị quân bài vào tổng điểm , nếu tổng điểm bằng N thì ngời đó thắng
+ Khi úp một quân bài (ngửa ) thì đồng thời lật ngửa lại quân bài đang bị úp trớc
đó.
Hãy lập trình theo yêu cầu :
1) Nhậptừ bàn phím số N,M.
2) Bốc thăm ai đi trớc
3) Thể hiện trò chơi trên màn hình trò chơi giữa ngời và máy sao cho khả năng thắng của
máy có thuận lợi hơn
Thuật toán :
Giả sử N=10 , M=3 . Trớc hết lập bảng phơng án sau :
1 2 3 4 5 6 7 8 9 10
1 1 0 0 1 1 0 0 1 1 0
2 0 0 0 1 0 0 0 1 0 0
3 0 0 1 1 0 0 1 0 0 0
Nếu máy đi trớc :
Chọn quân số 1 ( vì A[1,1] = 1 ) , dồn ngời chơi phải chọn quân 2 hoặc 3 , do đó
cột điểm tiếp theo là 1+2 =3 hoặc 1+3=4 . Trong các cột điểm 3 và 4 , đến lợt máy đi lại
có số 1 , nên máy lại đợc chọn quân ở hàng nào đó có số 1 . . . Quá trình cứ nh thế , cho
đến khi sẽ dẫn tới tình trạng : sau khi ngời đi quân số 2 hoặc 3 thì tổng điểm là 9 đến lợt
máy đi , máy úp quân số 1 , đợc tổng điểm là 10 . Máy thắng .
Nếu máy đi sau :
Rất có thể máy bị dồn vào tình trạng : nhận cột điểm không có số 1 . Khi đó máy
phải úp quân nào đó để cột điểm mới có ít số 1 nhất , nghĩa là tạo ra tình thế bất lợi nhất
cho ngời ( Máy hy vọng ngời chơi này này không biết qui luật , úp phải quân bài ở hàng 0
của cột điểm mới này)
Vấn đề còn lại các em sẽ thắc mắc là : Làm thế nào có bảng phơng án nh vậy ?
Lý do đơn giản là chúng ta lần ngợc từ trạng thái kết thúc chắc thắng về trạng thái
đầu . Cụ thể
+ Gán A[1,N-1] = 1
+ Sau đó xây dựng dần các số 1 ở các cột điểm đ = N-2,N-3,.....,1 theo qui tắc :
Chọn số quân lần lợt là Sq = 1 .. M . Gọi số lợng số 1 ở cột đ+Sq là x ( với điều
kiện x<=N ) . Nếu x=0 hoặc ( x=1 và A[Sq,x]=1 ) thì A[Sq,đ]=1 ; còn lại A[Sq,đ]=0
Chơng trình
Uses Crt;
Type pt = 0..1;
Var Diem,sq,m,n,Luu : Byte;
S : String;
A : Array[1..12,0..200] of 0..1;
Ch : Char;
Ok : Boolean;
Procedure Ve(i,j : Byte;Ch : Char);
Var k,h : Byte;
Begin
Textcolor(7);
If j<>0 then
For k:=i to i+4 do
For h := j to j+4 do
Begin
Gotoxy(h,k);
Write(ch);
End;
Textcolor(14);
End;
Procedure Nhap;
Begin
Repeat
Clrscr;
Write('So diem toi da ( N<= 200), N = ');
{$I-} Readln(N); {$I+}
Until (Ioresult=0) and (N in [1..200]);
Repeat
Gotoxy(1,2);
Write('So quan bai ( M<=12 ) , M = ');
{$I-} Readln(M); {$I+}
Until (Ioresult=0) and (M in [1..12]);
End;
Function Sl_dau(diem : Byte) : Byte;
Var d,j : Byte;
Begin
d := 0;
For j:=1 to M do
If A[j,diem]=1 then Inc(d);
SL_dau := d;
End;
Function Thang(i,t : Byte) : pt;
Var j,p : Byte;
Begin
p := SL_dau(i+t);
If p>1 then Thang := 0
Else
If p=0 then Thang := 1
Else
If p=1 then
Begin
If A[t,i+t]=1 then Thang := 1
Else Thang := 0;
End;
End;
Procedure Taobang;
Var i,j : Byte;
Begin
For sq:=1 to M do
Begin
Ve(5,sq*6,char(219));
Gotoxy(sq*6+2,10);
Write(sq);
End;
FillChar(A,Sizeof(A),0);
A[1,N-1] := 1;
For j:=N-2 downto 0 do
For i:=1 to M do
If (i+j<=N) and (Thang(j,i)=1) then A[i,j] := 1;
{A[1,1] := 0;}
Diem := 0;
Luu := 0;
End;
Procedure Boctham;
Begin
Gotoxy(20,16);
Write('Ban chon di truoc hay di sau (T/S) ? ');
Repeat
Ch := Upcase(Readkey);
Until Ch in ['T','S'];
Gotoxy(20,16);
Clreol;
End;
Procedure GhiMaydi(sqm,diem : Byte);
Begin
Gotoxy(50,16); Write('May up quan bai so ',sqm:3);
Gotoxy(20,18); Textcolor(12);
Write('Tong so diem ',diem:6);
Textcolor(14);
End;
Procedure May_choi;
Var k,x : Byte;
Begin
{ Tinh huong tot }
For k:=1 to M do
If (k<>Luu) and (A[k,diem]=1) then
Begin
Ve(5,luu*6,char(219));{Lat bai cua nguoi}
Luu := k;
Ve(5,luu*6,char(176));{May up quan moi }
Inc(diem,k);
Ghimaydi(k,diem);
Exit;
End;
{ Tinh huong xau : chon cot co it hang co dau }
{ de hy vong nguoi kia boc dung hang khong dau }
x := M;
For k:=1 to M do
If k<>Luu then
If (SL_dau(k+diem)<x) then x := k;
Ve(5,luu*6,char(219)); { Lat bai cua nguoi }
Luu := x;
Ve(5,luu*6,char(176));{ May up quan bai moi }
Inc(diem,x);
Ghimaydi(x,diem);
End;
Procedure Nguoidi;
Var Ch : Char;
Begin
Gotoxy(1,24);
Write('Ban chon quan bai bang cach chuyen mui ten ',char(24));
Repeat
Gotoxy(sq*6+2,11);
Writeln(char(24));{Viet mui ten len }
Ch := Upcase(Readkey);
Gotoxy(sq*6+2,11);
Write(chr(32)); {Xoa mui ten len }
Case ch of
'K' : If sq>1 then Dec(sq) Else sq := m;
'M' : If sq<m then Inc(sq) Else sq := 1;
End;
Until (sq<>Luu) and (Ch=#13);
Gotoxy(1,16);Write(' ');
Gotoxy(1,16);
Write('Ban vua up quan = ',sq);
Inc(diem,sq);
If Luu>0 then Ve(5,luu*6,char(219));
Luu := sq;
Ve(5,luu*6,char(176));
Delay(1000);
End;
BEGIN
Textcolor(14);
TextBackGround(1);
Repeat
Nhap;
Taobang;
Boctham;
If ch='T' then nguoidi;
Ok := False;
If diem<=N then
Repeat
May_choi;
If Diem<=N then Nguoidi Else Ok := True;
Until Diem>N;
Clrscr;
Gotoxy(20,20);
If Ok then Writeln('Ban thang ! ') Else Writeln('May thang ! ');
Gotoxy(40,20); Write('ESC to quit ...');
Until Readkey=#27;
END.