Basic Requirements
The experience playing the game (as with all pages) should be as smooth as possible. If we consider this, there’s pretty much only two ways we could build the interface for a game in Ampscript:
- hyperlinks everywhere
- forms with submit buttons everywhere
Both options are fairly easy, but I chose do it with forms, as it’s more elegant – links would force us to pass the game state as URL parameters visible in the address bar and when we hover over a link in our browsers.
Using forms allows us to use method="POST"
which conveniently hides from the player all parameters passed between page submits.
Sections
The interface should have the following parts basic parts:
- The game board where players can select their next move
- A section showing the game state
- if somebody won
- if the game ended in a draw
- which player moves now
- A button starting a new round
Reading the Current Game State
set @playerTurn = RequestParameter('playerTurn')
set @firstPlayer = RequestParameter('firstPlayer')
set @fields = RequestParameter('fields')
IF Empty(@playerTurn) THEN set @playerTurn = "X" ENDIF
IF Empty(@firstPlayer) THEN set @firstPlayer = IIF(Random(1,2) == 1, "X", "O") ENDIF
IF Empty(@fields) THEN set @fields = "123456789" ENDIF
Each time when you enter the page we are using the RequestParameter()
function to check for the following variables and assign default values if needed:
@playerTurn
– which players turn is it, if the value is empty, we give this turn to playerX
@firstPlayer
– which player started the current round, the default value is selected randomly@fields
– the representation of the board as a string, if it’s empty we assign an empty board:123456789
where no players has made a move.
Then we build the @verification
string as described in the previous section to determine if the game has ended.
Building the board
/* Field Display: START*/
FOR @i = 1 TO 9 DO
IF
Substring(@fields, @i, 1) == "X"
THEN
]%%
<div>
<input type="submit" class="f x" value="X" disabled>
</div>
%%[
ELSEIF
Substring(@fields, @i, 1) == "O"
THEN
]%%
<div>
<input type="submit" class="f o" value="O" disabled>
</div>
%%[
ELSEIF
Substring(@fields, @i, 1) != "X"
AND
Substring(@fields, @i, 1) != "O"
AND
IndexOf(@state, "Win") > 0
THEN
]%%
<div>
<input type="submit" class="f" value=" " disabled>
</div>
%%[
ELSE
]%%
<div>
<form method="POST" action="%%=RedirectTo(@url)=%%">
<input type="hidden" name="fields" value="%%=v(Replace(@fields, @i, @playerTurn))=%%">
<input type="hidden" name="playerTurn" value="%%=v(@nextPlayer)=%%">
<input type="hidden" name="firstPlayer" value="%%=v(@firstPlayer)=%%">
<input type="submit" class="f" value="%%=v(@playerTurn)=%%">
</form>
</div>
%%[
ENDIF
IF MOD(@i, 3) == 0
THEN ]%% <br> %%[
ENDIF
NEXT @i
Yes, this section is large, but it’s fairly simple:
- We start a loop that will go from 1 to 9
- In each iteration we extract a substring from the
@fields
string to see what a given character at that position contains:- if it’s an
X
orO
, we put this character inside of a disabled input button, so that the players can’t select this move again - if it’s not one of the above and we concluded that the game has ended (
IndexOf(@state, "Win") > 0
) then we output a disabled empty field - if none of the above conditions is true, we output a small form for each available and playable field:
- if it’s an
<div>
<form method="POST" action="%%=RedirectTo(@url)=%%">
<input type="hidden" name="fields" value="%%=v(Replace(@fields, @i, @playerTurn))=%%">
<input type="hidden" name="playerTurn" value="%%=v(@nextPlayer)=%%">
<input type="hidden" name="firstPlayer" value="%%=v(@firstPlayer)=%%">
<input type="submit" class="f" value="%%=v(@playerTurn)=%%">
</form>
What does this mean?
It means that we can have up to 9 forms if it’s our turn to make the first move. The four hidden fields are the core of our game – with them we can allow the game to make moves by selecting one of the fields.
Let’s consider an example of what is contained in the fields
inputs when we are about to make the first move on the board:
X23456789 | 1X3456789 | 12X456789 |
123X56789 | 1234X6789 | 12345X789 |
123456X89 | 1234567X9 | 12345678X |
By clicking the button, we submit the 3 values with a HTTP Post request to our page and we can again read the game state as we did already in a step before this.
Showing the Game State
<div class="results %%=v(@stateClass)=%%">
<div>%%=v(@state)=%%</div>
</div>
This <div>
uses two variables you have seen already a couple of times before:
@state
– this is the text displayed to the player telling- if somebody won
- if the game ended in a draw
- which player moves now or what game mode this is
@stateClass
is just the name of the CSS class that will change thebackground-color
to the one corresponding to the winning player
Resetting the Board
<!-- Reset the board -->
<form method="POST" action="%%=RedirectTo(@url)=%%">
<input type="submit" class="newGame" value="New Round">
<input type="hidden" name="fields" value="123456789">
<input type="hidden" name="playerTurn" value="%%=v(@nextPlayer)=%%">
<input type="hidden" name="firstPlayer" value="%%=v(@firstPlayer)=%%">
</form>
When we hit the New Round
button the following happens:
- we reset the board to the default state with no field taken by any player
- we assign who will start the game – it will be the other player from the one hitting the button
@firstPlayer
is used to change the order