|
Second Summer 2002
|
Lecture Notes Fourteen:
Computer Games. (In which Tigger has guests from another tale).
Have you ever played Nim?
|
No. But do you play croquet?
|
I'd love to but I don't have the time.
|
Well, how do you play Nim?
|
Allow me to describe it.
|
Very well, but please be very clear, my dear.
|
|
Yes, try to be very clear.
|
Nim is a well-known game with a number of variants.
We will consider the following variant, which has an interesting
winning strategy.
|
Two players alternately take marbles from a pile.
In each move, a player chooses how many marbles to take, then
removes the marbles.
|
The player must take
- at least one but
- at most half
of the marbles.
|
Then the other player takes a turn.
|
You already said that.
|
I thought you were sleeping.
|
This is very provoking...
|
Sorry, dear. Ahem.
The player who takes the last marble loses.
|
You will write a program in which a computer plays
agains a human opponent.
|
Generate a random number between 10 and 100 to denote the
initial size of the pile.
|
Generate a random integer between 0 and 1 to decide whether the
computer or the human takes the first turn. Then start the game.
|
This variant of the game has an interesting winning strategy.
Careful thinking will reveal that whoever moves first can win.
|
How?
|
Take off enough marbles to make the pile a power of two minus one,
that is 1, 3, 7, 15, 31, or 63.
|
I see.
|
One could program the computer to always play in
what could be called smart mode.
|
That would not be too much fun for the user.
|
One could also program the computer to always perform a random legal move.
|
That's what we'll do, as it seems a bit more fair.
|
OK, let's get started.
|
First of all, what do we need?
|
No pile of marbles, no Nim.
|
Let's bring one in.
|
How does it look?
|
What do you think of this?
|
Looks like a good start.
|
class PileOfMarbles {
int height;
PileOfMarbles (int height) {
this.height = height;
}
int report() {
return this.height;
}
}
A pile of marbles is like a bank account.
|
Whoever withdraws the last cent loses.
|
It has a balance (height ).
|
An a get balance (report ) method.
|
We also need a withdraw, don't we?
|
Yes, let's call it move .
|
What do you think of this?
|
You have to be careful when withdrawing.
|
void move(int number) {
System.out.println("***Removing " + number + " marbles from the pile.");
this.height -= number;
System.out.println("Pile of marbles is now: " + this.report());
}
So how do you check that?
|
How about this condition?
|
if (number <= 0 || ((number > height / 2) && (number != 1))) {
// then it's a bad move
} else {
// it is a good move
}
Can I look at this again?
|
You mean the check for a bad move?
|
Yes.
|
Here it is (a bad move).
|
if (number <= 0 || ((number > height / 2) && (number != 1))) {
System.out.println("***Bad move: you lose.");
System.exit(0);
} else {
|
Or, just the condition, again:
|
(number <= 0 || ((number > height / 2) && (number != 1)))
Either zero marbles or less, ...
|
... or more than half, and not the last.
|
I think this last part is rather tricky.
|
Using de Morgan's law we can reformulate this to represent
a good move. Perhaps that would help.
|
Yes, let's write down its negation.
|
Here it is (a good move):
|
(number > 0 && ((number <= height / 2) || (number == 1)))
To me this looks better, easier to understand.
|
It does seem that way to me too.
|
Even if this is no easier to read than the first version you now have a choice, an option.
|
I quite agree with that.
|
So we can finish report now.
|
Yes. Let's make the pile of marble responsible
for announcing the end of the game too.
|
Then it needs to know who moved.
|
I think I can accommodate that.
|
void move(int number, String user) {
System.out.println("***Removing " + number +
" marbles from the pile for: " + user);
if (number <= 0 || ((number > height / 2) && (number != 1))) {
System.out.println("***Bad move for " + user + ". " +
user + " loses.");
System.exit(0);
} else {
this.height -= number;
if (this.height == 0) {
System.out.println("***End of game. " + user + " loses.");
System.exit(0);
}
}
System.out.println("Pile of marbles is now: " + this.report());
}
That's pretty much it, isn't it?
|
Yes. Now we need to set up the game.
|
We need a while loop.
|
We need a loop, like we did in Echo , yes.
|
Here's my suggestion.
|
Looks like you finished it altogether now.
|
int height = (int)(Math.random() * 90 + 10);
PileOfMarbles pile = new PileOfMarbles(height);
System.out.println("Game starts with a pile of height: "
+ pile.report());
int number, currentHeight;
while (true) {
System.out.println("*** Computer moves.");
System.out.println("Pile of marbles of height: " + pile.report());
currentHeight = pile.report();
if (currentHeight == 1) {
number = 1;
} else {
number = (int)(Math.random() * (currentHeight / 2)) + 1;
}
System.out.println("Computer chooses to remove: " +
number + " marbles.");
pile.move(number, "Computer");
System.out.println("--------------------------");
System.out.println("*** Now " + user + " has to move.");
System.out.println("Pile of marbles of height: " + pile.report());
System.out.print(user +
", please enter number of marbles you want to take: ");
number = console.readInt();
pile.move(number, user);
System.out.println("--------------------------");
}
Yes, here's the whole thing:
| |
class Nim {
public static void main(String[] args) {
ConsoleReader console = new ConsoleReader(System.in);
System.out.println("Hello, and welcome to the game of Nim!");
System.out.print("What is your name: ");
String user = console.readLine();
int height = (int)(Math.random() * 90 + 10);
PileOfMarbles pile = new PileOfMarbles(height);
System.out.println("Game starts with a pile of height: "
+ pile.report());
int number, currentHeight;
while (true) {
System.out.println("*** Computer moves.");
System.out.println("Pile of marbles of height: " +
pile.report());
currentHeight = pile.report();
if (currentHeight == 1) {
number = 1;
} else {
number = (int)(Math.random() * (currentHeight / 2)) + 1;
}
System.out.println("Computer chooses to remove: " +
number + " marbles.");
pile.move(number, "Computer");
System.out.println("--------------------------");
System.out.println("*** Now " + user + " has to move.");
System.out.println("Pile of marbles of height: " +
pile.report());
System.out.print(user +
", please enter number of marbles you want to take: ");
number = console.readInt();
pile.move(number, user);
System.out.println("--------------------------");
}
}
}
class PileOfMarbles {
int height;
PileOfMarbles (int height) {
this.height = height;
}
int report() {
return this.height;
}
void move(int number, String user) {
System.out.println("***Removing " + number +
" marbles from the pile for: " + user);
if (number <= 0 || ((number > height / 2) && (number != 1))) {
System.out.println("***Bad move for " + user + ". " +
user + " loses.");
System.exit(0);
} else {
this.height -= number;
if (this.height == 0) {
System.out.println("***End of game. " +
user + " loses.");
System.exit(0);
}
}
System.out.println("Pile of marbles is now: " + this.report());
}
}
Don't forget your ConsoleReader !
|
I'm ready!
|
Let's play!
|
(This is Problem Six-Seventeen).
|
frilled.cs.indiana.edu%javac Nim.java
frilled.cs.indiana.edu%java Nim
Hello, and welcome to the game of Nim!
What is your name: Mary-Ann
Game starts with a pile of height: 86
*** Computer moves.
Pile of marbles of height: 86
Computer chooses to remove: 23 marbles.
***Removing 23 marbles from the pile for: Computer
Pile of marbles is now: 63
--------------------------
*** Now Mary-Ann has to move.
Pile of marbles of height: 63
Mary-Ann, please enter number of marbles you want to take: 30
***Removing 30 marbles from the pile for: Mary-Ann
Pile of marbles is now: 33
--------------------------
*** Computer moves.
Pile of marbles of height: 33
Computer chooses to remove: 1 marbles.
***Removing 1 marbles from the pile for: Computer
Pile of marbles is now: 32
--------------------------
*** Now Mary-Ann has to move.
Pile of marbles of height: 32
Mary-Ann, please enter number of marbles you want to take: 16
***Removing 16 marbles from the pile for: Mary-Ann
Pile of marbles is now: 16
--------------------------
*** Computer moves.
Pile of marbles of height: 16
Computer chooses to remove: 7 marbles.
***Removing 7 marbles from the pile for: Computer
Pile of marbles is now: 9
--------------------------
*** Now Mary-Ann has to move.
Pile of marbles of height: 9
Mary-Ann, please enter number of marbles you want to take: 2
***Removing 2 marbles from the pile for: Mary-Ann
Pile of marbles is now: 7
--------------------------
*** Computer moves.
Pile of marbles of height: 7
Computer chooses to remove: 1 marbles.
***Removing 1 marbles from the pile for: Computer
Pile of marbles is now: 6
--------------------------
*** Now Mary-Ann has to move.
Pile of marbles of height: 6
Mary-Ann, please enter number of marbles you want to take: 3
***Removing 3 marbles from the pile for: Mary-Ann
Pile of marbles is now: 3
--------------------------
*** Computer moves.
Pile of marbles of height: 3
Computer chooses to remove: 1 marbles.
***Removing 1 marbles from the pile for: Computer
Pile of marbles is now: 2
--------------------------
*** Now Mary-Ann has to move.
Pile of marbles of height: 2
Mary-Ann, please enter number of marbles you want to take: 1
***Removing 1 marbles from the pile for: Mary-Ann
Pile of marbles is now: 1
--------------------------
*** Computer moves.
Pile of marbles of height: 1
Computer chooses to remove: 1 marbles.
***Removing 1 marbles from the pile for: Computer
***End of game. Computer loses.
frilled.cs.indiana.edu%java Nim
Hello, and welcome to the game of Nim!
What is your name: Queen
Game starts with a pile of height: 77
*** Computer moves.
Pile of marbles of height: 77
Computer chooses to remove: 8 marbles.
***Removing 8 marbles from the pile for: Computer
Pile of marbles is now: 69
--------------------------
*** Now Queen has to move.
Pile of marbles of height: 69
Queen, please enter number of marbles you want to take: 33
***Removing 33 marbles from the pile for: Queen
Pile of marbles is now: 36
--------------------------
*** Computer moves.
Pile of marbles of height: 36
Computer chooses to remove: 11 marbles.
***Removing 11 marbles from the pile for: Computer
Pile of marbles is now: 25
--------------------------
*** Now Queen has to move.
Pile of marbles of height: 25
Queen, please enter number of marbles you want to take: 12
***Removing 12 marbles from the pile for: Queen
Pile of marbles is now: 13
--------------------------
*** Computer moves.
Pile of marbles of height: 13
Computer chooses to remove: 5 marbles.
***Removing 5 marbles from the pile for: Computer
Pile of marbles is now: 8
--------------------------
*** Now Queen has to move.
Pile of marbles of height: 8
Queen, please enter number of marbles you want to take: 1
***Removing 1 marbles from the pile for: Queen
Pile of marbles is now: 7
--------------------------
*** Computer moves.
Pile of marbles of height: 7
Computer chooses to remove: 2 marbles.
***Removing 2 marbles from the pile for: Computer
Pile of marbles is now: 5
--------------------------
*** Now Queen has to move.
Pile of marbles of height: 5
Queen, please enter number of marbles you want to take: 2
***Removing 2 marbles from the pile for: Queen
Pile of marbles is now: 3
--------------------------
*** Computer moves.
Pile of marbles of height: 3
Computer chooses to remove: 1 marbles.
***Removing 1 marbles from the pile for: Computer
Pile of marbles is now: 2
--------------------------
*** Now Queen has to move.
Pile of marbles of height: 2
Queen, please enter number of marbles you want to take: 1
***Removing 1 marbles from the pile for: Queen
Pile of marbles is now: 1
--------------------------
*** Computer moves.
Pile of marbles of height: 1
Computer chooses to remove: 1 marbles.
***Removing 1 marbles from the pile for: Computer
***End of game. Computer loses.
|
Oh, Nim is so easy. I like Nim.
|
frilled.cs.indiana.edu%java Nim
Hello, and welcome to the game of Nim!
What is your name: Mary-Ann
Game starts with a pile of height: 11
*** Computer moves.
Pile of marbles of height: 11
Computer chooses to remove: 4 marbles.
***Removing 4 marbles from the pile for: Computer
Pile of marbles is now: 7
--------------------------
*** Now Mary-Ann has to move.
Pile of marbles of height: 7
Mary-Ann, please enter number of marbles you want to take: 6
***Removing 6 marbles from the pile for: Mary-Ann
***Bad move for Mary-Ann. Mary-Ann loses.
frilled.cs.indiana.edu%
"Why, Mary Ann, what are you doing out here?
Run home this moment, and fetch me a pair of gloves and a fan! Quick, now!"
|
Last updated: Jun 16, 2002 by Adrian German for A201