1 problem, 50 points (extra credit is also possible)
In this problem, you will be extending the Connect Four code from last week's
assignment so that it actually plays the game (rather than simply hosting a game
between two human players). In doing so, you will build a new class, named
Player, which will have several methods for selecting Connect Four
moves.
You will need to start with your code for Hw10Pr1 (the CS5App and Board classes. Similar code is provided in Hw11Pr1.zip, but you should feel free to replace any of that code with your own! Note that the winsFor, allowsMove, and isFull methods will need to be copied from your Hw10 to your Hw11 code! In addition, you will be creating two or three more methods in the Board class this week.
main method of
your CS5App class will be similar to last week's, but with
some crucial differences to take advantage of the Player class. This
description will highlight the differences. Your main method inside
the CS5App class should do the following:
playerForX
of class Player should have. The choices should be
(-1) A human player
(0) The computer with 0-ply lookahead
(1) The computer with 1-ply lookahead
(2) The computer with 2-ply lookahead
(3) The computer with 3-ply lookahead
(4) The computer with 4-ply lookahead
(N) The computer with N-ply lookahead [Optional]
(0) Tie-breaking to the left of the board
(1) Tie-breaking to the right of the board
(2) Tie-breaking randomly
Player named playerForX using
the constructor from the Player class.
The Player constructor will take as input three things (1)
the checker that the Player will represent ('X' or
'O'), (2) the type of Player (-1 (human) through
4 (4-ply lookahead)), and (3) the tie-breaking type (0 (left-side)
through 2 (tie-breaking randomly)). See the Player
class (below) for a list of the other methods needed in Player.
Player player = playerForX; // X starts the game
double[] s = player.findScores(b); // s is an array of length 7
Additional methods required in the CS5App class
None are required, though I created one called getPly that queries the
human user for a lookahead type and returns it along with one called getTie
that does the same thing for the tiebreaking strategy.
Additional methods to be placed in the Board class
Your Board class needs three additional methods beyond those
required in Assignment 10:
Required data members to have in the Player class
Player class should have three data members: private char checker;
private int lookahead; private int tiebreakType; private because only the Player class should
directly access them. Player
class public Player(char ch, int la, int tbk) Player object that takes three input arguments.
It should then assign those inputs to the data members of this Player:
this.checker = ch;
this.lookahead = la;
this.tiebreakType = tbk;
public double[] findScores(Board b) public double[] ply0(Board b) public double[] ply1(Board b) public double[] ply2(Board b) public double[] ply3(Board b) public double[] ply4(Board b) public double[] plyHuman(Board b) public int breaktie(double[] s) public double evaluate(Board b) public char getChecker() public char me() public char opp() public static void printScores(double[] scores)
Scores:
0 1 2 3 4 5 6
100.0 50.0 50.0 50.0 50.0 50.0 0.0
Notice that this method is static. This means it is owned by the
class Player, not any particular object of type Player.
As a result, you can call it with the class name or an
object name (whereas the nonstatic methods above must have an
object name):
Player.printScores(s);
or
player.printScores(s);
Samples
We will test your code by running a human vs. a human
and then asking (with the -1, -2, and -3 options) for the scores that
your code assigns to each possible move. We will also run your
computer players against each other to check for tie-breaking and lookahead.
Here are some of the test cases we will try -- check to be sure your code works!
TEST CASE 1
With the following board, obtained through the moves 4-3-4-3-4-5
| | | | | | | | (X's move)
| | | | | | | |
| | | | | | | |
| | | | |X| | |
| | | |O|X| | |
| | | |O|X|O| |
---------------
0 1 2 3 4 5 6
It is X's move, and asking for 1-ply scores should produce these scores:
X's move (-N for an N-ply hint): -1
Scores:
0 1 2 3 4 5 6
50.0 50.0 50.0 50.0 100.0 50.0 50.0
Of course the best move is column 4, which wins for X.
-----------------------------------------------------------------
TEST CASE 2
With the following board, obtained through the moves 0-6-1-0-2
| | | | | | | | (O's move)
| | | | | | | |
| | | | | | | |
| | | | | | | |
|O| | | | | | |
|X|X|X| | | |O|
---------------
0 1 2 3 4 5 6
It is O's move, and asking for 1-ply scores should produce
no distinction among the columns:
O's move (-N for an N-ply hint): -1
Scores:
0 1 2 3 4 5 6
50.0 50.0 50.0 50.0 50.0 50.0 50.0
2-ply (or 3-ply) lookahead should show that column 3 is the best:
O's move (-N for an N-ply hint): -2
Scores:
0 1 2 3 4 5 6
0.0 0.0 0.0 50.0 0.0 0.0 0.0
-----------------------------------------------------------------
TEST CASE 3
With the following board, obtained through the moves 1-2-1-1-2-4-4-4-4-0
| | | | | | | | (X's move)
| | | | | | | |
| | | | |X| | |
| |O| | |O| | |
| |X|X| |X| | |
|O|X|O| |O| | |
---------------
0 1 2 3 4 5 6
It is X's move, and asking for 3-ply scores should produce
a perfect score in column 3:
X's move (-N for an N-ply hint): -3
Scores:
0 1 2 3 4 5 6
50.0 50.0 50.0 100.0 50.0 50.0 50.0
Then, if you move 'X' to column 3, you can new ask 'O' what it thinks:
| | | | | | | | (O's move)
| | | | | | | |
| | | | |X| | |
| |O| | |O| | |
| |X|X| |X| | |
|O|X|O|X|O| | |
---------------
0 1 2 3 4 5 6
O's move (-N for an N-ply hint): -3
Scores:
0 1 2 3 4 5 6
0.0 0.0 0.0 0.0 0.0 0.0 0.0
O's move (-N for an N-ply hint): -2
Scores:
0 1 2 3 4 5 6
0.0 0.0 0.0 0.0 0.0 0.0 0.0
O's move (-N for an N-ply hint): -1
Scores:
0 1 2 3 4 5 6
50.0 50.0 50.0 50.0 50.0 50.0 50.0
Which, perhaps, sends the message that things might look
better if you don't look too far ahead... .
-----------------------------------------------------------------
TEST CASE 4
With an almost identical board, obtained through the moves 1-2-1-1-2-4-4-4-4
| | | | | | | | (O's move)
| | | | | | | |
| | | | |X| | |
| |O| | |O| | |
| |X|X| |X| | |
| |X|O| |O| | |
---------------
0 1 2 3 4 5 6
Ask O what it thinks of its situation at 4-ply and below:
O's move (-N for an N-ply hint): -4
Scores:
0 1 2 3 4 5 6
0.0 0.0 0.0 0.0 0.0 0.0 0.0
O's move (-N for an N-ply hint): -3 (or -2)
Scores:
0 1 2 3 4 5 6
50.0 50.0 50.0 0.0 50.0 50.0 50.0
because, in this case, it only sees the immediate threat.
Submission Be sure to submit your
CS5App.java file under homework 11, problem 1.
To judge your tournamentEvaluate method, we will run a
tournament of the Players that people submit for this extra credit.
You will receive some credit (3 points), as long as your tournamentEvaluate
method does _at least_ as well as the simple evaluate method
described in the Player class. Additional credit (up to 15-20
points) will be awarded according to how your Player does in the
round-robin tournament.
Submission For this extra credit, submit your
Hw11Pr1 code including tournamentEvaluate .
Be sure to leave your code so that the basic,
default behavior is to use the normal evaluate.
We will set up a separate file with all of the tournament entries.