• No results found

Visual Basic Tic-Tac-Toe

In document Game Design Foundations (Page 155-167)

Our user interface (above) lets the player start a new game, choosing whether he would like to go first or second as either X or O, and lists the moves (spaces marked). The larger “big” board is where the current game is played and the player marks his desired space. The smaller board dis-plays the computer thinking as calculated by the Min-Max with Alpha-Beta pruning search algorithm.

FORM1

Private Sub Form_Load() Dim i As Integer Form1.BorderStyle = 0

Text1.Text = " " + "Moves" + " "

Frame1.Visible = False

InitVariables playerMark = -1 End Sub

Private Sub Option1_Click(index As Integer)

Picture1.Enabled = True

Picture1.PaintPicture BigBoard, 0, 0 Picture2.PaintPicture SmBoard, 0, 0

InitVariables showBigBoard showSmallBoard

playerMark = (2 * (index Mod 2)) - 1 '-1 is "O", 1 is "X"

playerDONE = 1 ' Computer goes first

Option1(index).value = False ' reset Selected value Frame1.Visible = False

Option2.Enabled = True Option2.value = False

Option2.Visible = False

If index < 2 Then ' Player’s turn Text5.Text = "Your turn, please mark a space"

Picture1.Enabled = True ' Player goes first playerDONE = 0

If playerDONE = 1 Then Exit Sub flag = -1

'check the area the player has selected to mark For i = 0 To 8

If PmouseX >= (15 * BigBoxXY(i, 0)) And PmouseX <= (15 * (BigBoxXY(i, 0) + 120))

Then

If PmouseY >= (15 * BigBoxXY(i, 1)) And PmouseY <= (15 * (BigBoxXY(i, 1) + 95))

Then

If ttt(0, i) = 0 Then ttt(0, i) = playerMark

Text1.Text = Text1.Text + "You marked space " + Str(i + 1) + " "

Text4.Text = "Marked " + Str(i + 1)

showSmallBoard ' display current path scenario of board playerDONE = 1

Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)

PmouseX = X

Private Sub Picture2_Paint() showSmallBoard

End Sub

Public Sub showBigBoard() Dim i As Integer

For i = 0 To 8

If ttt(0, i) = 1 Then

Picture1.PaintPicture markX, 15 * BigBoxXY(i, 0), 15 * BigBoxXY(i, 1)

End If

If ttt(0, i) = -1 Then

Picture1.PaintPicture markO, 15 * BigBoxXY(i, 0), 15 * BigBoxXY(i, 1)

End If Next i

Clevel = 0 showSmallBoard End Sub

Public Sub showSmallBoard() Dim i As Integer

For i = 0 To 8

If ttt(Clevel, i) = 1 Then

Picture2.PaintPicture smarkX, 15 * SmBoxXY(i, 0), 15 * SmBoxXY(i, 1) End If

If ttt(Clevel, i) = -1 Then

Picture2.PaintPicture smarkO, 15 * SmBoxXY(i, 0), 15 * SmBoxXY(i, 1) End If

Next i End Sub

MODULE1

'since C++ start arrays at index Zero we will too 'Set the Global variables

Public ttt(0 To 9, 0 To 8) As Integer

Public wp(0 To 7, 0 To 2) As Integer Public BigBoxXY(0 To 8, 0 To 2) As Integer Public SmBoxXY(0 To 8, 0 To 2) As Integer Public playerMark As Integer Public Level1Data(0 To 9) As Integer Sub InitVariables()

Dim i As Integer Dim j As Integer

' Change the path according to your Directory

Path = "C://Wordware//VBTicTacToe//"

Set BigBoard = LoadPicture(Path + "TicTacToeBigBoard.bmp") Set SmBoard = LoadPicture(Path + "TicTacToeSmBoard.bmp") Set markX = LoadPicture(Path + "BigX.bmp")

Set markO = LoadPicture(Path + "BigO.bmp") Set smarkX = LoadPicture(Path + "SmallX.bmp") Set smarkO = LoadPicture(Path + "SmallO.bmp") Clevel = 0

Form1.Picture1.Enabled = False

'Initialize the Tic-Tac-Toe boards (all levels) to Zeor For i = 0 To 9

For j = 0 To 8 ttt(i, j) = 0 Next j

Next i

'We start the arrays at Zero to match our C-code

' Rows

' Define our two Tic-Tac-Toe boards

BigBoxXY(0, 0) = 0: BigBoxXY(0, 1) = 0 BigBoxXY(1, 0) = 125: BigBoxXY(1, 1) = 0 BigBoxXY(2, 0) = 243: BigBoxXY(2, 1) = 0 BigBoxXY(3, 0) = 0: BigBoxXY(3, 1) = 101 BigBoxXY(4, 0) = 125: BigBoxXY(4, 1) = 101 BigBoxXY(5, 0) = 243: BigBoxXY(5, 1) = 101 BigBoxXY(6, 0) = 0: BigBoxXY(6, 1) = 196 BigBoxXY(7, 0) = 125: BigBoxXY(7, 1) = 196 BigBoxXY(8, 0) = 243: BigBoxXY(8, 1) = 196

SmBoxXY(0, 0) = 0: SmBoxXY(0, 1) = 0 SmBoxXY(1, 0) = 22: SmBoxXY(1, 1) = 0 SmBoxXY(2, 0) = 44: SmBoxXY(2, 1) = 0 SmBoxXY(3, 0) = 0: SmBoxXY(3, 1) = 22 SmBoxXY(4, 0) = 22: SmBoxXY(4, 1) = 22 SmBoxXY(5, 0) = 44: SmBoxXY(5, 1) = 22 SmBoxXY(6, 0) = 0: SmBoxXY(6, 1) = 44 SmBoxXY(7, 0) = 22: SmBoxXY(7, 1) = 44 SmBoxXY(8, 0) = 44: SmBoxXY(8, 1) = 44

Randomize (Timer) ' initialize the Random number function End Sub

'Copy a new Tic-Tac-Toe board starting with the previous board Sub Copy_ttt(level As Integer)

Dim index As Integer

If level < 1 Then Exit Sub If level > 8 Then Exit Sub

Clevel = level ' for small tic-tac-toe board

For index = 0 To 8

ttt(level, index) = ttt(level - 1, index) Next index

Form1.showSmallBoard End Sub

' Let's verify if there's an empty space to fill Function SpaceEmpty(level As Integer) As Integer Dim index As Integer

For index = 0 To 8

If ttt(level, index) = 0 Then SpaceEmpty = index + 1 Exit Function

End If Next index

SpaceEmpty = 0 'no empty space was found End Function

' A function to check if the current board position is a winning ' one for either player

Function IsThereaWin(level As Integer, MySide As Integer) As Integer

Dim ttWin As Integer ttWin = ttWin + ttt(level, wp(wpindex, i))

Next i

If ttWin = MyWin Then ' I have 3 connecting marks IsThereaWin = 100 'I win plus space to move to Exit Function

End If

If ttWin = OppWin Then ' Opponent can get 3 connecting marks IsThereaWin = -100 'Forced plus space to block

Exit Function End If

Next wpindex

IsThereaWin = 0 End Function

' Let's check to see if there's a forced move to make

' A forced move is a winning space or a blocking space to stop a loss Function Forced_Move(level As Integer, MySide As Integer) As Integer

Dim index As Integer

If level > 0 Then Copy_ttt (level)

If ttt(level, index) = 0 Then ' empty space

Chapter 11

If trys = 0 Then ' Can we win on this turn ttt(level, index) = MySide

Else ' Can our opponent win if we don't block on this turn ttt(level, index) = -MySide 'opponent

End If

FMove = IsThereaWin(level, MySide) If FMove 0 Then

sgn1 = 1

If FMove < 0 Then sgn1 = -1

Forced_Move = sgn1 * (Abs(FMove) + index + 1) If level > 0 Then Copy_ttt (level)

Exit Function End If

End If Next index Next trys

If level > 0 Then Copy_ttt (level) Forced_Move = 0 'No forced move End Function

Sub Tic_Tac_Toe()

Dim X As Integer Dim MySide As Integer Dim spaceon As Integer Dim FMove As Integer Dim i As Integer Dim value As Integer

X = 0: MySide = -playerMark

If SpaceEmpty(0) Then 'Game still on

' A forced move to win or to block a win is the best mark move X = Forced_Move(1, MySide)

spaceon = Abs(X) Mod 100

If X 0 Then ' A forced move has been calculated ttt(0, spaceon - 1) = MySide ' either a '1' or a '-1' Form1.Text1.Text = Form1.Text1.Text + " I marked space " +

Str(spaceon) + " "

End If

'find a space that's not forced If X = 0 Then

' Initialize the level 1 available mark spaces to an extremely low value

For i = 0 To 9 Level1Data(i) = -999 Next i

' Call the Min-Max Function where Alpha is very low and Beta is very high

X = MinMaxValue(1, MySide, -999, 999) ' find the best move

' find the best space to mark from the level 1 list of valid spaces to mark

spaceon = SpaceEmpty(0) - 1 X = -999

For i = 1 To 9

if Level1Data(i) > X Then spaceon = i

X= Level1Data(i) End If

Next i

ttt(0, spaceon - 1) = MySide ' Mark the best space

Form1.Text1.Text = Form1.Text1.Text + " I marked space " + Str(spaceon) + " "

End If

Form1.Text4.Text = "Marked " + Str(spaceon)

Form1.showSmallBoard ' display current path scenario of board End If

Form1.showBigBoard playerDONE = 0

FMove = IsThereaWin(0, playerMark)

If FMove <= -100 Then ' Be prepared to see this message often Form1.Text1.Text = Form1.Text1.Text + " " + "HURRAY! I WON!"

+ " "

Form1.Text1.Text = Form1.Text1.Text + " Play me again?"

Form1.Text5.Text = "Would you like to play me again?"

playerDONE = 100

Form1.Option2.Visible = True Exit Sub

End If

Chapter 11

If FMove >= 100 Then ' You may never see this message

Form1.Text1.Text = Form1.Text1.Text + " " + "WOW! YOU'VE WON!"

+ " "

Form1.Text1.Text = Form1.Text1.Text + " Play me again?"

Form1.Text5.Text = "Would you like to play me again?"

playerDONE = 100

Form1.Option2.Visible = True Exit Sub

End If

If FMove = 0 Then ' No win found and all spaces marked

playerDONE = 0

Form1.Text5.Text = "Your turn, please mark a space"

If SpaceEmpty(0) = 0 Then ' no more empty spaces to mark Form1.Text1.Text = Form1.Text1.Text + " " + "DRAW!" + " "

Form1.Text1.Text = Form1.Text1.Text + " Play me again?"

Form1.Text5.Text = "Would you like to play me again?"

Form1.Option2.Visible = True Exit Sub

End If End If End Sub

' Just like a chess opening database, here are standard ' Tic-Tac-Toe opening marks

Sub opening()

Dim i As Integer Dim j As Integer Dim k As Integer

Form1.Text5.Text = "" ' clear message

' Check to see if we go first and second j = 0

Tic_Tac_Toe ' find a space to mark Exit Sub

Form1.Text4.Text = "Marked " + Str(i + 1)

Form1.Text1.Text = Form1.Text1.Text + " I marked space " +

Str(i + 1) + " "

playerDONE = 0 Form1.showBigBoard

Form1.Text5.Text = "Your turn, please mark a space"

Form1.Picture1.Enabled = True ' Player goes Exit Sub

End If

If j = 1 Then ' we go second

' valid moves are center and the opposite corner if the opponent ' marked a corner space

i = -1 ' a flag

If k = 4 And i = -1 Then ' center space marked

AAA: i = Int(Rnd * 4) ' valid first marks are spaces 1,3,7 and 9 If i = 4 Then GoTo AAA ' can't mark the center space

i = i * 2 ' we have a random number 0 through 4 so we double it End If

If i = -1 Then ' center space was not marked

i = 4 ' mark center space (space 5)

End If

ttt(0, i) = -playerMark

Form1.Text4.Text = "Marked " + Str(i + 1)

Form1.Text1.Text = Form1.Text1.Text + " I marked space " + ' Str(i + 1) + " "

playerDONE = 0 Form1.showBigBoard

Form1.Text5.Text = "Your turn, please mark a space"

Form1.Picture1.Enabled = True ' Player goes Exit Sub

End If End Sub

Function MinMaxValue(level As Integer, MySide As Integer, alpha As Integer, beta As Integer) As Integer

Dim WIN As Integer Dim index As Integer Dim MTlist As Long Dim nextspace As Integer

Dim X As Integer

Chapter 11

Dim succval As Integer ' reset current level board

Copy_ttt (level)

If SpaceEmpty(level) = 0 Then MinMaxValue = 0

Exit Function End If

'find a space that's not forced 'list all open spaces

MTlist = 0 ' List all the open (unmarked) spaces on this level

X = Forced_Move(level, MySide) ' Is there a forced move (a win or a ' block of a win)

If X 0 Then ' a forced move has been flagged MTlist = Abs(X Mod 100) ' space is 1 to 9

Else

For index = 0 To 8

If ttt(level, 8 - index) = 0 Then ' subtract from 8 for ascending order

MTlist = MTlist * 10 + (9 - index) End If

Next index End If

While MTlist > 0

nextspace = MTlist Mod 10 ' next space to mark

MTlist = (MTlist - nextspace) / 10 ' remainder of possible spaces ' to mark

Copy_ttt (level)

ttt(level, nextspace - 1) = MySide

Form1.Text4.Text = "Marked " + Str(nextspace)

Form1.showSmallBoard ' display current path scenario of board WIN = IsThereaWin(level, MySide)

If WIN >= 100 Then succval = WIN Else

succval = -MinMaxValue(level + 1, -MySide, -beta, -alpha) Endif

If level = 1 Then ' Save this space's value Level1Data(nextspace) = succval

If succval = 100 Then ' Winning line found MinMaxValue = succval

Exit Function End If

End If

'The Alpha-Beta pruning code

If succval >= beta Then MinMaxValue = beta Exit Function End If

If succval > alpha Then alpha = succval Wend

MinMaxValue = alpha ' return a draw End Function

//since C++ start arrays at index Zero we will too int ttt[8][8]={ {0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}};

int wp[8][3]={{0,1,2},{3,4,5},{6,7,8}, // Rows {0,3,6},{1,4,7},{2,5,8}, // Columns {0,4,8},{2,4,6}}; // Diagonals

// Copy a new Tic-Tac-Toe board starting with the previous board void Copy_ttt(int level)

{

int index;

if(level<1) return; // invalid parameter for(index=0; index<9; index++)

ttt[level][index]= ttt[level-1][index]

}

// Let's verify if there's an empty space to fill int SpaceEmpty(int level)

{

int index;

for(index=0; index<9; index++)

if(ttt[level][index]==0)return(index+1);

return 0; // no empty space was found }

// Let's check to see if there's a forced move to make

Chapter 11

// A forced move is a winning space or a blocking space to stop // a loss

int Forced_Move(int level, int MySide) {

int index, trys, ttWin;

int OppWin= -3 * MySide;

int MyWin= 3 * MySide;

for(index=0; index<9;index++) for(trys=0; trys<2; trys++){

if(level>0) Copy_ttt(level);

if(ttt[level][index] == 0){ // empty space if(trys ==0)ttt[level][index]= MySide;

else ttt[level][index]=-MySide; // opponent

ttWin= ttt[level][wp[index][0] + ttt[level][wp[index][1] + ttt[level][wp[index][2];

if(ttWin == MyWin)return(100 + index); // I win plus space to move to else

if(ttWin == OppWin)return(-(100 + index)); // Forced plus space to block }

return 0; // No forced move }

void Tic_Tac_Toe() {

int x=0, MySide= 1, spaceon;

while(SpaceEmpty(0) && x < 100){ // Game still on x= Forced_Move(1, MySide);

spaceon= abs(x)%100;

if(x != 0)ttt[0][spaceon]= x/100; // either a '1' or a '-1' else{ // find a space that's not forced

BestMove(1); // find the best move }

x= 0; // reset 'x' }

}

(This code can be found on the book’s companion CD.)

Visual C++ Language: Code

In document Game Design Foundations (Page 155-167)