John.Wiley.and.Sons.Rapid.Mobile.Enterprise.Development.for.Symbian.OS.An.Introduction.to.OPL.Application.Design.and.Programming.May.2005.eBook-LinG (779881), страница 19
Текст из файла (страница 19)
What we need to give the computer is a way to determinewhich choice is the best choice.As with any programming task, you need to break down the task, andthink about how you decide on your move. Because the aim of the gameis to have as many pieces as possible at the end of the game, one validstrategy is to capture the most number of pieces on every move, and it isthis ‘rule’ that we will use to make the computer’s move.5.5.2 A Simple RuleSo how do we do this? Well, how do you do it when you’re playing? Youlook at every square you can make a move to and then count the numberof pieces that you would capture. Then you make the move that capturesthe most. This is what we will program into the computer.The Main LoopPROC MakeComputerMove%:LOCAL RecordMove%, WhichSquare%, BestMove%, BestMoveSquare%rem Go through all the squares...WhichSquare%=0DOWhichSquare%=WhichSquare%+1RecordMove%=CheckComputerMove%:(WhichSquare%)IF RecordMove%>BestMove%BestMove%=RecordMove%BestMoveSquare%=WhichSquare%ENDIFTHE COMPUTER’S MOVE – DOING A.I.95UNTIL WhichSquare%=KGridWidth%*KGridHeight%rem if there is no move, then pass.IF BestMove%<>0PlayComputerMove:(BestMoveSquare%)RETURN 1ELSEdINIT "Pass"dTEXT "","I have no move"dBUTTONS "OK",KdBUTTONEnter%LOCK ONDIALOGLOCK OFFRETURN 0ENDIFENDPChecking Each Square’s ValueSo here we go through the 64 squares on the board, and each time throughwe call another procedure CheckComputerMove%:, which returns thenumber of pieces that would be captured if the move was made.
This issimilar to the MakePlayerMove: procedure:PROC CheckComputerMove:(Target%)LOCAL DeltaX%,DeltaY%,FooX%,FooY%,X%,Y%,Captured%Y%=INT((Target%-1)/KGridWidth%)X%=(Target%-1)-(Y%*KGridWidth%)IF BoardOut:(X%,Y%)<>0RETURN 0ENDIFDeltaX%=-2DODeltaX%=DeltaX%+1DeltaY%=-2DODeltaY%=DeltaY%+1IF DeltaX%<>0 AND DeltaY%<>0rem Check Surrounding piece for opponentIF TBoardOut:(X%+DeltaX%,Y%+DeltaY%)=1DOrem Found an player’s piece, let’s carry on up thelineFooX%=X%+(2*DeltaX%) : FooY%=Y%+(2*DeltaY%)IF BoardOut:(FooX%,FooY%)=1FooX%=FooX%+DeltaX% : FooY%=FooY%+DeltaY%ELSEIF BoardOut:(FooX%,FooY%)=2rem reverse direction - no need to turnpieces overDOCaptured%=Captured%+1FooX%=FooX%-DeltaX% :FooY%=FooY%-DeltaY%UNTIL (FooX%=X% AND FooY%=Y%)ELSEIF BoardOut:(FooX%,FooY%)=096USING GRAPHICS IN AN OTHELLO GAMEFooX%=-2 : rem Quick way to fulfill the UNTILconditionsENDIFUNTIL (FooX%=X% AND FooY%=Y%) OR FooX%=-1 ORFooX%=KGridWidth% OR FooY%=-1 ORFooY%=KGridHeight%ENDIFENDIFUNTIL DeltaY%=1UNTIL DeltaX%=1RETURN Captured%ENDPThere are only a few changes in this, compared to the one in theMakePlayerMove:.
It’s worth pointing out that while we still continueto use the main Board%() array, we don’t actually change anything inthe array (this is only done in our code through BoardIn:, which isn’tcalled anywhere in the above code).The first two lines calculate the (X%,Y%) coordinates of the square fromthe position in the array, and we then do a check to see if the squareis occupied. If it is, there’s no need to go through the long process ofchecking around the square as it’s going to be impossible to play a piecethere, hence the RETURN 0 as soon as possible.We then have an eerily similar procedure for PlayComputerMove:,but can dispense with the two DO...UNTIL loops as we know whichsquare we’ll be playing in (BestMoveSquare%).And that’s how the computer moves.5.5.3Mini-Max: Advanced A.I.While we’re not going to go into depth on actually programming theMini-Max method of doing A.I., we’ll talk about the principles here andleave the actual coding of the system as a project for you.Mini-Max is named after the principle of minimizing your opponent’schances, while maximizing your own.
We’ve actually already done halfof this operation in our simple rule, where the computer always plays thebest move available, maximizing its opportunity. What the computer failsto do here is to take into account what the board will look like for theplayer after their move. If you are playing Othello, you would visualizethe board and make sure that your opponent doesn’t have a ‘killer’ moveavailable.
You would make sure this isn’t available – you’re minimizinghis opportunities.So, ideally, once the computer has found a ‘max’ move, it needsto complete this move in a separate temporary array, and then checkevery resulting move available to the player after that. The best movePUTTING IT TOGETHER – THE MAIN GAME LOOP97available to the player should be stored.
We would do this for everycomputer move.At the end of this, we’ll have a list of moves and be able to see whichone gives the best results for the computer. In Othello’s case, we wouldsee which computer move (coupled with the best player move) gives thecomputer the greatest advantage in the score.Even looking two moves ahead (the computer and the player) you cansee that the memory requirements to store all the information are muchgreater than for just looking at the best computer move.
There is alsoa trade-off in speed, as we have many, many more states of the boardto consider.5.6 Putting it Together – the Main Game Loop5.6.1 Initializing EverythingWe’ve got a lot of bits of code now, all ready to be glued together. Beforewe do that, we need to set up a few things in our PROC InitApp:.The main one here is to clear the board of pieces, and to reset thescores.
While these will be at zero the first time the game is run, theyneed to be reset when a new game is started from within the application:PROC InitApp:Foo%=0DOFoo%=Foo%+1Board%(Foo%)=0UNTIL Foo%=KGridWidth%*KGridHeight%PlayerScore%=0ComputerScore%=0CursorX%=0 : CursorY%=0OldX%=KGridWidth%+1, OldY%=KGridHeight%+1ENDPThe initial cursor values are inside the visible window, but we don’t callthe procedure that displays the cursor until after a cursor key has beenpressed.
This is so that if the pen tap method is used by the player, thecursor is never displayed – but when any cursor key is pressed, up popsthe cursor as expected. The old position is set outside the grid so it willnot interfere with the drawing process.5.6.2 Showing the CursorThis is similar to ShowPiece:, but overlays the cursor on the squarepassed to this routine. Note the change in the graphics mode here, it98USING GRAPHICS IN AN OTHELLO GAMEoverwrites, not replaces, thus any playing piece under the cursor will stillbe seen:PROC ShowCursor:(X%,Y%)gUSE KBoardWindow%gAT X%*KGridSize%,Y%*KGridSize%gCOPY Id%(KCursorPiece%,0,0,KGridSize%,KGridSize%,2)ENDP5.6.3 The Game LoopPreviously in Event Core, we simply looped around the call to read eventsin the main procedure.
Here it is in plain English:PROC Main:GLOBAL rem We’ll fill these in as we plan the programLOCAL rem We’ll fill these in as we plan the programInit:InitApp:DOrem Get a key press (an event)rem Act on this key pressUNTIL rem we need to exit the programExit:ENDPFor Othello, we need to loop around the player move, and then thecomputer move, until all the squares are full:PROC Main:GLOBAL rem We’ll fill these in as we plan the programLOCAL rem We’ll fill these in as we plan the programInit:InitApp:DOrem Player MoveDOrem Get a key press (an event)rem Act on this key pressUNTIL a move is maderem Computer Moverem Apply the A.I. rulesrem make the moveUNTIL all 64 squares are filledShow who the winner isSUMMARY99Exit:ENDPThis now needs to be translated into full OPL code, and all the elementswe’ve discussed in this chapter need to be added in as well.
You shouldnow be able to do this with little assistance, although the full source codeas always is on the supporting website www.symbian.com/books/rmed/rmed-info.html5.7 SummaryThis chapter showed you how to use graphics in an OPL program, namely:• creating the graphics on your PC• using bmconv.exe to create Symbian mbm graphics files from windows bitmaps• loading mbms into memory to use them in a program• copying mbms in memory to a visible window.We then started again with Event Core, and this time created a graphicallyrich game of Othello. We looked at reading pen taps on the screen, orreading in key presses to move a cursor. This way the program could beused on any platform.We looked at representing a board and the pieces on the board in anarray, how to read and act on this array, and how to display it.
UsingMini-Max, you learned how to make a basic computer A.I. player andhow to apply this to other games.Finally, we showed you how to put this all together to make yourOthello game.6Databases and a Notepad ProgramFor our final OPL project in this book, we will bring together elementsfrom our previous three projects by building a Notepad program. Althougha similar application may already be present in your phone, programmingyour own will allow you to use all your new OPL skills, from workingthrough an interface, moving a cursor around information where there ismore than one screen, accessing variables, presenting information, andmaking your own program look and feel like a built-in one.It will also allow us to look in depth at using databases under OPL.Databases are powerful little creatures that can be used to store hugeamounts of information that never change (like an encyclopedia), orrapidly changing information (like your diary/calendar).
Learning tomanipulate databases in OPL is an important step in creating genuinelyuseful programs.6.1 What is a Database?A database, like everything else on a computer, is a collection of 1s and0s; don’t forget that. The power in a database is how OPL can read andmanipulate the information that is stored inside it.One way of visualizing a database is to think of a pile of index cardsrepresenting the database, just as we did in Chapter 3 with the EventCore’s INI file. Each index card has on it the same information in themargin. These are the headings. If you were creating a database of namesand telephone numbers, then the two headings may be NAME and TEL.Note that the headings must be the same on every index card in thepile. On each card is written the name of one person, and one telephonenumber.
In a database, this is called an entry, or a record.How big is a database? As big as it needs to be is the short answer.In our analogy above, we can use as many index cards as we like, aslong as the first one is always regarded as number one, and the rest arenumbered in sequential order.While we don’t have the physical card holder in the file on our computer, we still have the database that holds all the records of information,102DATABASES AND A NOTEPAD PROGRAMtied to their headings. Databases on a computer work in a very similarway to their real-life counterparts.