Presentation is loading. Please wait.

Presentation is loading. Please wait.

Implementing the 8-puzzle Design (no corresponding text chapter)

Similar presentations


Presentation on theme: "Implementing the 8-puzzle Design (no corresponding text chapter)"— Presentation transcript:

1 Implementing the 8-puzzle Design (no corresponding text chapter)

2 Possible Implementation of StateInfo Class Suppose your StateInfo class for the 8-puzzle looks like: class StateInfo { private:... public:... State blankUp(); State blankDown(); State blankLeft(); State blankRight();... }

3 solve() Pseudocode Revisited void solve() current = get start state from problem final = get final state from problem alist = get action list from problem count = 0 while current is not final do display current action = get action from user if action is valid then new = apply action to current current = new increment count else issue message display current and count congratulate Recall the pseudocode for SolverInfo::solve() :

4 Possible Implementation of solve() Suppose the pseudocode in bold were implemented as follows:... String actionName = promptActionName(); if (strcmp(actionName,"up") == 0) newState = currentState->blankUp(); else if (strcmp(actionName,"down") == 0) newState = currentState->blankDown(); else if (strcmp(actionName,"left") == 0) newState = currentState->blankLeft(); else if (strcmp(actionName,"right") == 0) newState = currentState->blankRight(); else cout << "action " << actionName << " is not recognized." << endl;...

5 Problems With The Implementation  Recall a design goal for this program:  Only the ProblemInfo and StateInfo classes should know any details about the problem domain  The SolverInfo class should be applicable to domains other than the 8-puzzle  Does the solve() method, as implemented, meet this goal? No.  We therefore introduce the classes Action and ActionList to act as a layer of abstraction between the solver and the domain.

6 A Better Approach  Wrap each of the methods StateInfo::blankUp(), StateInfo::blankDown(), etc., in a new Action object.  Put each of these Action s onto an ActionList object to which the solver has access.  Provide a method in the ActionList class that will search for and return the Action corresponding to the string entered by the user.  Provide a method in the Action class that will execute its tile-moving operation on a given State.

7 A Better Implementation of solve()... String actionName = promptActionName(); Action action = actionList->findAction(actionName); if (action == NULL) { cout << "action " << actionName << " is not recognized." << endl; } else { State newState = action->execute(currentState);... }... Now there are no references to any details that indicate the domain is the 8-puzzle.

8 Recall the ActionInfo Class  Data:  Name (up, down, left, right)  Operation to perform the action--What, an operation as data??  Operations:  Create a new action  Execute the action operation ...

9 Operations As Data in C++ Suppose we want a program calc to behave like this: 64% calc add 25 2 The result is 27 65% calc sub 25 2 The result is 23 66% calc mult 25 2 The result is 50 67% calc div 25 2 The result is 12 68%

10 Strategy  Develop a class called CalcInfo that has:  Two integer values as data fields  A constructor with two integer arguments  A method calculate with a string argument, either ``add'', ``sub'', ``mult'', or ``div''. This method does the right calculation on its operands based on its argument.  Get the operation and operands from the command line.  Create a CalcInfo object with the operands.  Invoke the calculate method on the object with the operation as argument.

11 Main Program for calc int main(Integer argc, StringArray operands) { String oper = operands[1]; Integer x = atoi(operands[2]); Integer y = atoi(operands[3]); Calc c = new CalcInfo(x, y); Integer result = c->calculate(oper); cout << "The result is " << result << endl << endl; }

12 One Implementation of CalcInfo class CalcInfo { private: Integer operand1; Integer operand2; public: CalcInfo(Integer x, Integer y); Integer calculate(String operation); }; CalcInfo::CalcInfo(Integer x, Integer y) { operand1 = x; operand2 = y; }...

13 One Implementation of CalcInfo (cont'd)... Integer CalcInfo::calculate(String operation) { if (strcmp(operation, "add") == 0) return (operand1 + operand2); else if (strcmp(operation, "sub") == 0) return (operand1 - operand2); else if (strcmp(operation, "mult") == 0) return (operand1 * operand2); else if (strcmp(operation, "div") == 0) return (operand1 / operand2); else return 0; }

14 CalcInfo Modification Suppose we want to remove the arithmetic details from CalcInfo, to be handled by another class: Integer CalcInfo::calculate(ArithFun fun) { <Apply fun to the operands and return the result> }  This requires:  Being able to treat functions as arguments  Being able to return functions as function values

15 A New Class: ArithmeticInfo This class will contain the functions (methods) for doing arithmetic that will be passed to the CalcInfo::calculate method: class ArithmeticInfo { public: static Integer add (Integer a, Integer b); static Integer sub (Integer a, Integer b); static Integer mult (Integer a, Integer b); static Integer div (Integer a, Integer b); ArithFun getFun(String oper); };

16 Notes on Class ArithmeticInfo " The arithmetic methods are static because they are associated with the whole class and not class instances:  A nonstatic method is called using the obj->method(...) syntax, but  In this case there is no obj involved, because the method is passed to another object, where it is called as if it were a straight C function.  The ArithmeticInfo::getFun(...) method determines the right static method to pass, given a string parameter. It is not static because we are going to ask an ArithmeticInfo object to invoke it.

17 ArithmeticInfo::getFun Method ArithFun ArithmeticInfo::getFun(String oper) { if (strcmp(oper,"add") == 0) return add; else if (strcmp(oper,"sub") == 0) return sub; else if (strcmp(oper,"mult") == 0) return mult; else // assume must be "div" return div; } Note that we are returning a static method (function) name. So what is the type ArithFun ?

18 Pointer to void ( void * ) In C/C++  add, sub, etc., are function names, and thus address places in memory. " An address in C/C++ is just a pointer.  To indicate a pointer to a function as the return type for ArithmeticInfo::getFun(), we use an all- encompassing type called pointer to void, or void *  void * means pointer to anything, including pointer to integer, pointer to class object, or pointer to function (static method)  To simplify: typedef void * ArithFun;

19 New Main Program for calc int main(Integer argc, StringArray operands) { String oper = operands[1]; Arithmetic a = new ArithmeticInfo(); ArithFun f = a->getFun(oper); Integer x = atoi(operands[2]); Integer y = atoi(operands[3]); Calc c = new CalcInfo(x, y); Integer result = c->calculate(f); cout << "The result is " << result << endl << endl; } Now we just need to change CalcInfo::calculate to accept a function as an argument, and then apply it.

20 Functions Passed as Arguments in C/C++ Integer CalcInfo::calculate(ArithFun fun) { <Apply fun to the operands and return the result> }  The argument fun is of type void * " We must cast it to the proper type before using it: 1. Declare a local variable f of the proper type, 2. Cast fun to f, 3. Apply f to the operands and return the result.

21 Functions Passed as Arguments in C/C++ (cont'd) " Q: So what is the ``proper type''?  A: A function with two Integer arguments that returns an Integer result:  Integer (*) (Integer, Integer)  This is just a type. It can be read as: ``Pointer to a function that takes two integer arguments and returns an integer as a result''.  To declare a variable f of this type:  Integer (*f) (Integer, Integer)

22 Final Version of CalcInfo::calculate Integer CalcInfo::calculate(ArithFun fun) { Integer (*f) (Integer, Integer); f = (Integer (*) (Integer, Integer))fun; return (*f)(operand1, operand2); } Note that f is a pointer to the function, so *f must be used to refer to the function itself. Also, the parentheses (*f) are necessary since the function operator f(..) has higher precedence than the indirection operator *.

23 Recall Possible Implementation of StateInfo Class class StateInfo { private:... public:... State blankUp(); State blankDown(); State blankLeft(); State blankRight();... }

24 New Implementation of StateInfo  The tile-moving methods must be made static, since they will be passed to the ActionInfo constructor, and  They must have an argument of type State, since they are static. class StateInfo { private:... public:... static State blankUp(State s); static State blankDown(State s); static State blankLeft(State s); static State blankRight(State s);... }

25 Recall the ActionInfo Class (yet again)  Data:  Name (up, down, left, right)  Operation to perform the action  Operations:  Create a new action  Execute the action operation ...

26 An ActionInfo Class Declaration " Q: What is the type of the action operation?  A: Look at the signatures of the static tile- moving methods in StateInfo :  State (*) (State, State) class ActionInfo { private: String name; State (*actionFun) (State state); public: ActionInfo(String n, State (*fun) (State state)); State execute(State state); String getName(); };

27 ActionInfo Class Constructor ActionInfo::ActionInfo(String n, State (*fun) (State state)) { name = n; actionFun = fun; } Q: Who calls the ActionInfo constructor?

28 Recall The Problem Class Problem -startState: State -finalState: State -actionList: ActionList +Problem(startTileNums: StringArray) +getStartState(): State +getFinalState(): State +getActionList(): ActionList -createActionList(): void Each action is stored in the ProblemInfo object's ActionList data variable.

29 The ActionListInfo Class  An ActionListInfo object is just a collection of ActionInfo objects.  In this design, it is created by the ProblemInfo class for use by the solver. " The solver gets the action list from the problem and uses it to find the action matching the user's input.

30 Recall the Implementation of solve()... String actionName = promptActionName(); Action action = actionList->findAction(actionName); if (action == NULL) { cout << "action " << actionName << " is not recognized." << endl; } else { State newState = action->execute(currentState);... }...

31 Executing the Action State ActionInfo::execute(State state) { return (*actionFun)(state); } When the Action object is found, it applies its stored, static, tile-moving method to the current state: However, note that the ActionInfo class knows nothing about the details of the state-changing methods it executes. For all it knows, it could be executing actions in domains other than the 8-puzzle.


Download ppt "Implementing the 8-puzzle Design (no corresponding text chapter)"

Similar presentations


Ads by Google