In this lab you will explore using Finite State Machines to build a small Tic-Tac-Toe game. The tic-tac-toe game is simplified from the usual 3×3 type of game to a 2×2 type of game (called Tic-Tac).
For example:
The Front Panel of the game will be built with four “O” buttons from the Boolean Controls Palette. Place the four controls close together to make a matrix. The computer begins by placing an X in some location of the matrix. One then uses the buttons to click on them and then select the square to place an O into. If one gets two in a row one wins (diagonal does not count).
The Game will start with the empty matrix, like the following:
The Computer begins by placing an X in a location:
The player then clicks on one location, and in so doing changes the value of the button text from a null string to an O. The button must also be disabled so that a subsequent click cannot change it.
The Computer then selects a place to put another X (initially set so it will always win) and this matrix location receives the X and its button is disabled. (The original X should have been disabled at the beginning.)
The application will pop up a two button dialog box saying “I Have Won”. The two buttons on the dialog box should say “Play Again” and “Quit”, where “Quit” stops the program and “Play Again” clears the board and allows you to play again. You should also add a button on the Front Panel, “Restart” which will clear the board and restart.
In order to simplify the game, we will make two changes:
1. The computer starts first, and always moves in the upper left corner with an X.
2. The computer stops as soon as it wins.
To do this lab you will have to do multiple things:
1. Learn how to dynamically change the names on the OK buttons, and disable.
a. Setup: Do this by creating Property Nodes for each button (right click while in the Front Panel, under “Create”. On the Block Diagram you need to add another element to each property node (right-click, choose “Add Element”). Then set one element to “Disabled”, the other to `BoolText.text' by searching through the “Properties” menu on a right click. Change both elements to write.
b. Changing strings: You should now be able to attach a string to the “Booltext.text” and display it in the button when you run the program. To make a selection, build an array of strings, and select a single element of the array with an index. Set the array of strings to be “X”, “O”, and “ ” (an empty string). Test with a numeric control (make it U8!): when the program runs change the values of the numeric control to select different values of the text to be displayed on the button.
c. Disabling: Add a Boolean switch. In the dialog box, convert the Boolean value to a number using the “Boolean to (0:1)” function. Send the output of this to the Disable element of the button. If one passes a 0 to the Disable element, the button behaves normally. If one passes a 1, it is disabled. (FYI, if a 2 is passed to the button, the button is grayed out and disabled). By running the application you should be able to enable or disable the button at will, as well as change its caption.
2. Design a finite state machine on paper.
a. Work through the states of a FWM which compromise the Tic-Tac game. Start by assuming an unchecked space has a 0, a space with an X has a 1, and a space with an O has a 2. Each state could then have a label abcd, as below.
b. What is the initial state? Draw a circle for this one and label with
So this is state abcd = 0000. (The labels following the pattern of buttons.)
c. What are the first four possible states (primary states)? In a row below the initial state, draw a circle for each primary state and provide a label. For instance, if there is an X in upper left corner, the primary state would be labeled as
This is therefore state abcd = 1000. Draw an arrow from the initial state to each of the four different possible primary states.
d. Now draw a row of secondary states below the row of primary states. We will simplify by following only one of the primary states in this lab, otherwise the number of states grows tremendously. So for only state abcd = 1000 out of the first possible initial states, define the secondary states. For instance if the player chooses to move into bottom left, this would be a state abcd = 1020.
Each secondary state should be unique, but there may be arrows from two different primary states to
a single secondary state.
e. Now define the third level states and fourth level states. Note that the computer can win in every case, so the third level states are essentially predefined for two of the secondary states, but one of the secondary states has two different third state possibilities. There is only one fourth level state, where the computer prints out its victory message and waits.
3. Now that you have the state diagram, you have a certain number of unique states. Assign each of the above states a number. This is an arbitrary assignment and does not have to be in any order. The easiest way to do this is to name them abcd, i.e. state 1020, 2010, 1120, 0010, etc. In this case you have almost no work to do. Note that state 0000 would be interpreted by the Case Structure in LabVIEW as state 0. (One could use strings of the numbers to select as well actual numbers). The final victor state can be any number you have not already used; e.g. 9999.
4. Use a Case Structure imbedded within a While Loop to generate the finite element machine that jumps between the various states. In each state, assess what the input data is (the values of each of the 4 buttons in the matrix as well as the “Restart” switch) and select the next state to jump to. Pass this state back to the case statement using a tunnel in the While Loop. If you choose to number the states as 1020, 2010, etc, then as you add each case to the case statement, and change the case value to these numbers. State 0000 would be interpreted as state 0.
a. You will need to have a sort of numeric scratch pad where you can write some data and store it as well as read it back. The strategy here will be to use a local variable. First create four numeric controls. Each represents the states of each of the 4 matrix check boxes. Give each controll a representation of U8. You can hide the numeric controls from being visible on the Front Panel by right clicking on the numeric control from the front panel, and selecting “Hide Control” (located under submenu “Advanced”). Int the Block Diagram, make sure these numeric controls are outside of the Case Structure which controls the finite state machine sequence, but inside the overall While Loop. Use these variables to select the caption of the individual matrix element buttons (using the Array select, as in the part 1) as well as to disable the matrix element buttons (check to see if the variable is non-zero; if it is, disable the button).
b. Go to your initial state abcd = 0000 in the Block Diagram. Right click on the data object to select Create→Local Variable. Drop a local variable for each of the four numerical controls buttons into the abcd = 0000 state. Assign all of these value 0, except a, which will have value 2. You can use numeric constants to assign these values. Setup the jump to the next state abcd = 1000
c. Go to next state: abcd = 1000. Again, add local variables for bcd into this case. Assign b,c,d from the b, c, and matrix switch values. Setup a new state to jump to based on these switch values. (Hint: form an integer P= a +2b + 4c , then pass this to a new case statement embedded within this particular case statement. Select what the next state will be depending upon P=0, P=1, P=2 & P=4 ).
5. One state will pop up a dialog box. Be sure to wire the cancel output to stop the program.
6. One state, abcd = 1002, will have two possible computer moves to win. Use a random number generator to select which path will occur. The random number generator makes a number between 0.0 and 1.0. So compare the random number with 0.5, if it is less, the jump to one state, if it is more, jump to each other.
7. Be sure to initialize the state of the machine to 0 outside the main while loop. You probably will want to initialize each of the numeric matrix values as well here.
8. Try using the debugging features of LabVIEW as they will help you to discover problems. In particular, it can help you trace through the steps that your finite state machine is progressing through, and help you to diagnose when you are not jumping to the correct state.
For example:
The Front Panel of the game will be built with four “O” buttons from the Boolean Controls Palette. Place the four controls close together to make a matrix. The computer begins by placing an X in some location of the matrix. One then uses the buttons to click on them and then select the square to place an O into. If one gets two in a row one wins (diagonal does not count).
The Game will start with the empty matrix, like the following:
The Computer begins by placing an X in a location:
The player then clicks on one location, and in so doing changes the value of the button text from a null string to an O. The button must also be disabled so that a subsequent click cannot change it.
The Computer then selects a place to put another X (initially set so it will always win) and this matrix location receives the X and its button is disabled. (The original X should have been disabled at the beginning.)
The application will pop up a two button dialog box saying “I Have Won”. The two buttons on the dialog box should say “Play Again” and “Quit”, where “Quit” stops the program and “Play Again” clears the board and allows you to play again. You should also add a button on the Front Panel, “Restart” which will clear the board and restart.
In order to simplify the game, we will make two changes:
1. The computer starts first, and always moves in the upper left corner with an X.
2. The computer stops as soon as it wins.
To do this lab you will have to do multiple things:
1. Learn how to dynamically change the names on the OK buttons, and disable.
a. Setup: Do this by creating Property Nodes for each button (right click while in the Front Panel, under “Create”. On the Block Diagram you need to add another element to each property node (right-click, choose “Add Element”). Then set one element to “Disabled”, the other to `BoolText.text' by searching through the “Properties” menu on a right click. Change both elements to write.
b. Changing strings: You should now be able to attach a string to the “Booltext.text” and display it in the button when you run the program. To make a selection, build an array of strings, and select a single element of the array with an index. Set the array of strings to be “X”, “O”, and “ ” (an empty string). Test with a numeric control (make it U8!): when the program runs change the values of the numeric control to select different values of the text to be displayed on the button.
c. Disabling: Add a Boolean switch. In the dialog box, convert the Boolean value to a number using the “Boolean to (0:1)” function. Send the output of this to the Disable element of the button. If one passes a 0 to the Disable element, the button behaves normally. If one passes a 1, it is disabled. (FYI, if a 2 is passed to the button, the button is grayed out and disabled). By running the application you should be able to enable or disable the button at will, as well as change its caption.
2. Design a finite state machine on paper.
a. Work through the states of a FWM which compromise the Tic-Tac game. Start by assuming an unchecked space has a 0, a space with an X has a 1, and a space with an O has a 2. Each state could then have a label abcd, as below.
b. What is the initial state? Draw a circle for this one and label with
So this is state abcd = 0000. (The labels following the pattern of buttons.)
c. What are the first four possible states (primary states)? In a row below the initial state, draw a circle for each primary state and provide a label. For instance, if there is an X in upper left corner, the primary state would be labeled as
This is therefore state abcd = 1000. Draw an arrow from the initial state to each of the four different possible primary states.
d. Now draw a row of secondary states below the row of primary states. We will simplify by following only one of the primary states in this lab, otherwise the number of states grows tremendously. So for only state abcd = 1000 out of the first possible initial states, define the secondary states. For instance if the player chooses to move into bottom left, this would be a state abcd = 1020.
Each secondary state should be unique, but there may be arrows from two different primary states to
a single secondary state.
e. Now define the third level states and fourth level states. Note that the computer can win in every case, so the third level states are essentially predefined for two of the secondary states, but one of the secondary states has two different third state possibilities. There is only one fourth level state, where the computer prints out its victory message and waits.
3. Now that you have the state diagram, you have a certain number of unique states. Assign each of the above states a number. This is an arbitrary assignment and does not have to be in any order. The easiest way to do this is to name them abcd, i.e. state 1020, 2010, 1120, 0010, etc. In this case you have almost no work to do. Note that state 0000 would be interpreted by the Case Structure in LabVIEW as state 0. (One could use strings of the numbers to select as well actual numbers). The final victor state can be any number you have not already used; e.g. 9999.
4. Use a Case Structure imbedded within a While Loop to generate the finite element machine that jumps between the various states. In each state, assess what the input data is (the values of each of the 4 buttons in the matrix as well as the “Restart” switch) and select the next state to jump to. Pass this state back to the case statement using a tunnel in the While Loop. If you choose to number the states as 1020, 2010, etc, then as you add each case to the case statement, and change the case value to these numbers. State 0000 would be interpreted as state 0.
a. You will need to have a sort of numeric scratch pad where you can write some data and store it as well as read it back. The strategy here will be to use a local variable. First create four numeric controls. Each represents the states of each of the 4 matrix check boxes. Give each controll a representation of U8. You can hide the numeric controls from being visible on the Front Panel by right clicking on the numeric control from the front panel, and selecting “Hide Control” (located under submenu “Advanced”). Int the Block Diagram, make sure these numeric controls are outside of the Case Structure which controls the finite state machine sequence, but inside the overall While Loop. Use these variables to select the caption of the individual matrix element buttons (using the Array select, as in the part 1) as well as to disable the matrix element buttons (check to see if the variable is non-zero; if it is, disable the button).
b. Go to your initial state abcd = 0000 in the Block Diagram. Right click on the data object to select Create→Local Variable. Drop a local variable for each of the four numerical controls buttons into the abcd = 0000 state. Assign all of these value 0, except a, which will have value 2. You can use numeric constants to assign these values. Setup the jump to the next state abcd = 1000
c. Go to next state: abcd = 1000. Again, add local variables for bcd into this case. Assign b,c,d from the b, c, and matrix switch values. Setup a new state to jump to based on these switch values. (Hint: form an integer P= a +2b + 4c , then pass this to a new case statement embedded within this particular case statement. Select what the next state will be depending upon P=0, P=1, P=2 & P=4 ).
5. One state will pop up a dialog box. Be sure to wire the cancel output to stop the program.
6. One state, abcd = 1002, will have two possible computer moves to win. Use a random number generator to select which path will occur. The random number generator makes a number between 0.0 and 1.0. So compare the random number with 0.5, if it is less, the jump to one state, if it is more, jump to each other.
7. Be sure to initialize the state of the machine to 0 outside the main while loop. You probably will want to initialize each of the numeric matrix values as well here.
8. Try using the debugging features of LabVIEW as they will help you to discover problems. In particular, it can help you trace through the steps that your finite state machine is progressing through, and help you to diagnose when you are not jumping to the correct state.
No comments:
Post a Comment