implementing the 8-puzzle design (no corresponding text chapter)
TRANSCRIPT
![Page 1: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/1.jpg)
Implementing the 8-puzzle Design
(no corresponding text chapter)
![Page 2: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/2.jpg)
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();...}
![Page 3: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/3.jpg)
solve() Pseudocode Revisited
void solve()current = get start state from problemfinal = get final state from problemalist = get action list from problemcount = 0while current is not final do
display currentaction = get action from userif action is valid then
new = apply action to currentcurrent = newincrement count
elseissue message
display current and countcongratulate
Recall the pseudocode for SolverInfo::solve():
![Page 4: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/4.jpg)
Possible Implementation of solve()
Suppose the pseudocode in bold were implementedas 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; ...
![Page 5: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/5.jpg)
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.
![Page 6: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/6.jpg)
A Better Approach
Wrap each of the methods StateInfo::blankUp(), StateInfo::blankDown(), etc., in a new Action object.
Put each of these Actions 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.
![Page 7: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/7.jpg)
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 indicatethe domain is the 8-puzzle.
![Page 8: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/8.jpg)
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 . . .
![Page 9: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/9.jpg)
Operations As Data in C++
Suppose we want a program calc to behave like this:
64% calc add 25 2The result is 27
65% calc sub 25 2The result is 23
66% calc mult 25 2The result is 50
67% calc div 25 2The result is 12
68%
![Page 10: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/10.jpg)
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.
![Page 11: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/11.jpg)
Main Program for calcint 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;}
![Page 12: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/12.jpg)
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;}...
![Page 13: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/13.jpg)
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;}
![Page 14: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/14.jpg)
CalcInfo Modification
Suppose we want to remove the arithmetic detailsfrom 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
![Page 15: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/15.jpg)
A New Class: ArithmeticInfo
This class will contain the functions (methods) for doingarithmetic 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);};
![Page 16: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/16.jpg)
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.
![Page 17: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/17.jpg)
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?
![Page 18: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/18.jpg)
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;
![Page 19: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/19.jpg)
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.
![Page 20: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/20.jpg)
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.
![Page 21: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/21.jpg)
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)
![Page 22: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/22.jpg)
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 beused to refer to the function itself.
Also, the parentheses (*f) are necessary since the function operator f(..) has higher precedence than the indirection operator *.
![Page 23: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/23.jpg)
Recall Possible Implementation of StateInfo Class
class StateInfo {private:...public:... State blankUp(); State blankDown(); State blankLeft(); State blankRight();...}
![Page 24: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/24.jpg)
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);...}
![Page 25: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/25.jpg)
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 . . .
![Page 26: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/26.jpg)
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();};
![Page 27: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/27.jpg)
ActionInfo Class Constructor
ActionInfo::ActionInfo(String n, State (*fun) (State state)) { name = n; actionFun = fun;}
Q: Who calls the ActionInfo constructor?
![Page 28: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/28.jpg)
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'sActionList data variable.
![Page 29: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/29.jpg)
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.
![Page 30: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/30.jpg)
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); . . .}...
![Page 31: Implementing the 8-puzzle Design (no corresponding text chapter)](https://reader036.vdocuments.site/reader036/viewer/2022081516/56649f1d5503460f94c3430f/html5/thumbnails/31.jpg)
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 nothingabout the details of the state-changing methods it executes. For all it knows, it could be executing actionsin domains other than the 8-puzzle.