09. april 2006 - 17:08Der er
23 kommentarer og 1 løsning
Kode og forklaring
Hej alle - hvad gør følgende kode helt præcist?
procedure board; var i, j, k: integer; begin for i := 1 to 3 do begin for j := 1 to 3 do begin k:= (i - 1) * 3 + j - 1; x_position[y, j] := 0; y_position[i][j] := 0; end; end;
I og j antager jo bare nogle værdier mellem 1 og 3, og k er jo et tal mellem 0 og 8, men hvad med den sidste del? x_position og y_position er arrays som i [1..3,1..3]
I dette særtema om aspekter af AI ser vi på skiftet fra sprogmodeller til AI-agenter, og hvordan virksomheder kan navigere i spændet mellem teknologisk hastighed og behovet for menneskelig kontrol.
Hvad med denne kode? Jeg kan fortælle, at den checker, om der er vundet når man spiller kryds og bolle, men jeg kan ikke helt se, hvorledes det virker:
function vundetellerej(iPos: 3x3): integer; //3x3 er en matrix var iScore : Integer; i : Integer; j : Integer; begin Result := -1;
//in rows? iScore := 0; for i := 1 to 3 do begin iScore := 0; Inc(Result); for j := 1 To 3 do Inc(iScore, iPos[i,j]); if iScore = 3 Then Exit end;//for i
//top-left bottom-right diagonal? iScore := 0; Inc(Result); for i := 1 to 3 do Inc(iScore, iPos[i,i]); if iScore = 3 then Exit;
//top-right bottom-left diagonal? iScore := 0; Inc(Result); for i := 1 to 3 do Inc(iScore, iPos[i,4-i]); if iScore = 3 then Exit;
//columns? for i := 1 to 3 do begin iScore := 0; Inc(Result); for j := 1 to 3 do Inc(iScore, iPos[j,i]); if iScore = 3 then Exit; end;//for i
Result := -1; end;
Jeg forstår ikke, hvorledes den kan afgøre det, ved blot at forøge de forskellige tal?
Jeg gætter på at den holder styr på X-og-O brættet ved at have et -1 eller et +1 i hver celle alt efter om der er et 'X', eller et 'O'. Og så i øvrigt 0 i de celler hvor der ikke er noget.
Hvis dette er rigtigt, kan den viste kode finde ud af om der er en række med 3 O'er:
Den tæller simpelthen summen (værdien i iScore) af hver af de 3 rækker, derefter summen af den ene diagonal og summen af den anden, og så til sidst summen af hver af de tre søjler. Hvis summen i blot en af disse er '3', svarende til 3 1-taller, så er der en række (og proceduren exit'er).
Koden kan altså beregne om der er en række med 3 O'er. Der må være noget tilsvarende kode som vurdere på 3 X-er, eller også er der noget kode et eller andet stede, som vender fortegnet på alle værdierne i matricen før at funktionen vundetellerej() kaldes.
Ok, jeg kan faktisk godt se det nu. Jeg har dog et problem - jeg kan sagtens se, at den checker de forskellige steder i matrixen, men der står jo ikke rigtig, hvad den checker for?
Men den tjekker som sagt for om det er 3 1-tallere der står i macticens rækker, diagonaler eller søjler. Så du må kunne gætte svaret ved at finde ud af om det er X eller O som repræsenteres med værdien 1.
for j := 1 To 3 do Inc(iScore, iPos[i,j]); if iScore = 3 Then Exit
Functionen Inc tæller iScore op med værdien fra iPos[i,j]. For-løkken sikre at dette sker 3 gange. I linje nr. 2 testes der om iScore er lig 3. Tilsammen giver de kun mening hvis det er 3 1-taller som giver "det rigtige svar".
Jeg indrømmer at en talrækkefølge som f.eks. 4, 5, -6 også ville giove summen 3, men det gover ikke helt mening i sammenhængen (et X-og-O spil) at der skulle stå det.
Jeg har noget mere uforståelig (i mine øjne) kode, men alligevel har jeg nogle forslag til, hvordan det skal kunne forstås:
function TfrMain.GamePlay(xo_Move : Integer):integer; var x, y : 1..3; iWin : integer; begin Result := -1;
Inc(iMove); x := (xo_Move Div 3) + 1; y := (xo_Move Mod 3) + 1;
if sPlaySign = 'O' then begin iOPos[x,y] := 1; // hvorfor skal den sættes lig 1? iWin := CheckWin(iOPos); // her tjekker den jo bare om der er gevinst end else begin iXPos[x,y] := 1; // .. gør det samme for spiller-X iWin := CheckWin(iXPos); end;
Ahh, programmet bruger *2* forskellige matricer, iOPos og iXPos, som viser hvor hhv O'erne og X'erne er placeret på brættet. Hvis der står et 1-tal på en plads så er det hhv. et O eller et X - og hvis der står 0 er der *ikke* et O eller et X (men der kan være en "modstander-brik").
Bemærk: Dette er ikke noget vildt gennemtænkt design: f.eks. kan der nu - i princippet - være både et O og et X på en og samme plads!
Koden:
x := (xo_Move Div 3) + 1; y := (xo_Move Mod 3) + 1;
omregner fra en værdi 0-8 til en x- og y-position på brættet; Det er faktisk kode som svare til arne_v's bemærkning ang. k i 09/04-2006 17:41:02.
Variablen sPlaySign indeholder enten et 'O' eller noget andet (sandsynligvis et 'X' men det er ikke helt sikkert). Koden:
if sPlaySign = 'O' then begin iOPos[x,y] := 1; // hvorfor skal den sættes lig 1? iWin := CheckWin(iOPos); // her tjekker den jo bare om der er gevinst end else begin iXPos[x,y] := 1; // .. gør det samme for spiller-X iWin := CheckWin(iXPos); end;
indsætter et 1-tal på x,y positionen i den rigtige rigtige matrix: i iOPos hvis det er et 'O' og i iXPos ellers (hvis det er et 'X').
Derefter kaldes CheckWin() med den relevante matrix for at se om den ene eller den anden spiller har vundet. Hvis der er en vinder sættes bGameOver til True.
function vundetellerej(iPos: 3x3): integer; //3x3 er en matrix var iScore : Integer; i : Integer; j : Integer; begin Result := -1;
//in rows? iScore := 0; for i := 1 to 3 do begin iScore := 0; Inc(Result); for j := 1 To 3 do Inc(iScore, iPos[i,j]); if iScore = 3 Then Exit end;//for i
//top-left bottom-right diagonal? iScore := 0; Inc(Result); for i := 1 to 3 do Inc(iScore, iPos[i,i]); if iScore = 3 then Exit;
//top-right bottom-left diagonal? iScore := 0; Inc(Result); for i := 1 to 3 do Inc(iScore, iPos[i,4-i]); if iScore = 3 then Exit;
//columns? for i := 1 to 3 do begin iScore := 0; Inc(Result); for j := 1 to 3 do Inc(iScore, iPos[j,i]); if iScore = 3 then Exit; end;//for i
Result := -1; end;
Den er blevet gennemgået, men jeg har flere spørgsmål. Vil det sige, at hvis der ikke er tre ens i nogle af tabellerne, så bliver iScore lig 11? Og hvilken værdi antager result alt efter, hvilken række/linie der er tre ens i?
iScore bliver med jævne mellemrum sat lig med 0, så nej den vil aldrig komme op på 11. Faktisk exit'er proceduren jo oven i købet hvis den bliver lig 3.
Forklaring på resten af koden:
function vundetellerej(iPos: 3x3): integer; //3x3 er en matrix var iScore : Integer; i : Integer; j : Integer; begin Result := -1; // Result starter med at være -1
// Denne kodeblok undersøger om der er 3 0'er i en af rækkerne
//in rows? iScore := 0; // iScore sættes til 0. Dette er overføldigt, for det gør den også inde i løkken. for i := 1 to 3 do // Gennemløb hver af de 3 rækker. begin iScore := 0; // iScore sættes til 0. Inc(Result); // Result tælles 1 op: værdi=0 ved 1. række, 1 ved 2. og 2 ved 3. række. for j := 1 To 3 do Inc(iScore, iPos[i,j]); // Der lægges 1 til iScore for hvert O i den aktuelle række. if iScore = 3 Then Exit // Hvis der var 3 O'er i rækken exit'es. end;//for i
// Denne kodeblok undersøger diagonalen fra øverste venstre hjørne til nederste højre. // NB: På dette sted i koden er Result lig med 2.
//top-left bottom-right diagonal? iScore := 0; // iScore sættes igen til 0. Inc(Result); // Result tælles 1 op; den er nu lig 3. for i := 1 to 3 do Inc(iScore, iPos[i,i]); // Der lægges 1 til iScore for hvert O i diagonalen. if iScore = 3 then Exit; // Hvis der var 3 O'er i diagonalen exit'es.
// Denne kodeblok undersøger diagonalen fra nederste venstre hjørne til øverste højre. // NB: På dette sted i koden er Result lig med 3.
//top-right bottom-left diagonal? iScore := 0; // iScore nulstilles igen. Inc(Result); // Result tælles 1 op; ny værdi 4. for i := 1 to 3 do Inc(iScore, iPos[i,4-i]); // Der lægges 1 til iScore for hver O i diagonalen. if iScore = 3 then Exit; // Hvis der var 3 O'er i diagonalen exit'es.
// Den sidste kodeblok undersøger om der er 3 O'er i en af søjlerne. // NB: På dette sted i koden er Result lig med 4.
//columns? // Denne gang glemmer programøren at nulstille iScore - men det er jo heller ikke nødvendigt. for i := 1 to 3 do // Gennemløb hver af de 3 søjler. begin iScore := 0; // iScore nulstilles for hver søjle. Inc(Result); // Result tælles 1 op for hver søjle. Værdierne 5, 6 og 7. for j := 1 to 3 do Inc(iScore, iPos[j,i]); //Der lægges 1 til for hver O i den aktuelle søjle. if iScore = 3 then Exit; // Hvis der var 3 O'er i søjlen exit'es. end;//for i
// Hvis der ikke er exit'et på dette tidspunkt, så må det betyde at der hverken // var en række, en diagonal, eller en række O'er et eller andet sted.
Result := -1; end;
Hvis funktionen vundetellerej() returnere et .1 var der altså ikke nogen række. Hvsi det govere en af værdierne 0..7 kan man ud af denne se hvor det var at de 3 ens var henne (hvis man gider det):
0 : 1. række, 1 : 2. række, 2 : 3. række, 3 : Diagonalen fra øverste venstre hjørne til nederste højre, 4 : Diagonalen fra nederste venstre hjørne til øverste højre, 5 : 1. søjle, 6 : 2. søjle, og 7 : 3. søjle
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.