mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-22 23:26:40 -08:00
MAINT: Apply pre-commit
Remove byte-order-marker pre-commit check as there would be many adjustments necessary
This commit is contained in:
@@ -9,100 +9,100 @@ import java.util.Scanner;
|
||||
* <p>
|
||||
* Note: The idea was to create a version of the 1970's BASIC game in Java, without introducing
|
||||
* new features - no additional text, error checking, etc has been added.
|
||||
*
|
||||
*
|
||||
* Converted from BASIC to Java by Darren Cardenas.
|
||||
*/
|
||||
|
||||
|
||||
public class Tower {
|
||||
|
||||
|
||||
private final static int MAX_DISK_SIZE = 15;
|
||||
|
||||
|
||||
private final static int MAX_NUM_COLUMNS = 3;
|
||||
|
||||
|
||||
private final static int MAX_NUM_MOVES = 128;
|
||||
|
||||
private final static int MAX_NUM_ROWS = 7;
|
||||
|
||||
|
||||
private final static int MAX_NUM_ROWS = 7;
|
||||
|
||||
private final Scanner scan; // For user input
|
||||
|
||||
|
||||
// Represent all possible disk positions
|
||||
private int[][] positions;
|
||||
|
||||
|
||||
private enum Step {
|
||||
INITIALIZE, SELECT_TOTAL_DISKS, SELECT_DISK_MOVE, SELECT_NEEDLE, CHECK_SOLUTION
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Tower() {
|
||||
|
||||
scan = new Scanner(System.in);
|
||||
|
||||
|
||||
scan = new Scanner(System.in);
|
||||
|
||||
// Row 0 and column 0 are not used
|
||||
positions = new int[MAX_NUM_ROWS + 1][MAX_NUM_COLUMNS + 1];
|
||||
|
||||
} // End of constructor Tower
|
||||
|
||||
|
||||
positions = new int[MAX_NUM_ROWS + 1][MAX_NUM_COLUMNS + 1];
|
||||
|
||||
} // End of constructor Tower
|
||||
|
||||
|
||||
public class Position {
|
||||
|
||||
|
||||
public int row;
|
||||
public int column;
|
||||
|
||||
|
||||
public Position(int row, int column) {
|
||||
this.row = row;
|
||||
this.column = column;
|
||||
|
||||
|
||||
} // End of constructor Position
|
||||
|
||||
|
||||
} // End of inner class Position
|
||||
|
||||
|
||||
|
||||
|
||||
public void play() {
|
||||
|
||||
showIntro();
|
||||
startGame();
|
||||
|
||||
} // End of method play
|
||||
|
||||
|
||||
private void showIntro() {
|
||||
|
||||
} // End of method play
|
||||
|
||||
|
||||
private void showIntro() {
|
||||
|
||||
System.out.println(" ".repeat(32) + "TOWERS");
|
||||
System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
|
||||
System.out.println("\n\n");
|
||||
|
||||
} // End of method showIntro
|
||||
|
||||
} // End of method showIntro
|
||||
|
||||
|
||||
private void startGame() {
|
||||
private void startGame() {
|
||||
|
||||
boolean diskMoved = false;
|
||||
|
||||
|
||||
int column = 0;
|
||||
int disk = 0;
|
||||
int needle = 0;
|
||||
int disk = 0;
|
||||
int needle = 0;
|
||||
int numDisks = 0;
|
||||
int numErrors = 0;
|
||||
int numMoves = 0;
|
||||
int row = 0;
|
||||
|
||||
Step nextStep = Step.INITIALIZE;
|
||||
|
||||
int row = 0;
|
||||
|
||||
Step nextStep = Step.INITIALIZE;
|
||||
|
||||
String userResponse = "";
|
||||
|
||||
|
||||
Position diskPosition = new Position(0, 0);
|
||||
|
||||
// Begin outer while loop
|
||||
|
||||
// Begin outer while loop
|
||||
while (true) {
|
||||
|
||||
|
||||
switch (nextStep) {
|
||||
|
||||
|
||||
|
||||
|
||||
case INITIALIZE:
|
||||
|
||||
|
||||
// Initialize error count
|
||||
numErrors = 0;
|
||||
|
||||
|
||||
// Initialize positions
|
||||
for (row = 1; row <= MAX_NUM_ROWS; row++) {
|
||||
for (column = 1; column <= MAX_NUM_COLUMNS; column++) {
|
||||
@@ -116,46 +116,46 @@ public class Tower {
|
||||
System.out.println("YOU MUST TRANSFER THE DISKS FROM THE LEFT TO THE RIGHT");
|
||||
System.out.println("TOWER, ONE AT A TIME, NEVER PUTTING A LARGER DISK ON A");
|
||||
System.out.println("SMALLER DISK.\n");
|
||||
|
||||
|
||||
nextStep = Step.SELECT_TOTAL_DISKS;
|
||||
break;
|
||||
|
||||
|
||||
case SELECT_TOTAL_DISKS:
|
||||
|
||||
|
||||
case SELECT_TOTAL_DISKS:
|
||||
|
||||
while (numErrors <= 2) {
|
||||
|
||||
|
||||
// Get user input
|
||||
System.out.print("HOW MANY DISKS DO YOU WANT TO MOVE (" + MAX_NUM_ROWS + " IS MAX)? ");
|
||||
numDisks = scan.nextInt();
|
||||
System.out.println("");
|
||||
|
||||
|
||||
numMoves = 0;
|
||||
|
||||
|
||||
// Ensure the number of disks is valid
|
||||
if ((numDisks < 1) || (numDisks > MAX_NUM_ROWS)) {
|
||||
|
||||
|
||||
numErrors++;
|
||||
|
||||
|
||||
// Handle user input errors
|
||||
if (numErrors < 3) {
|
||||
System.out.println("SORRY, BUT I CAN'T DO THAT JOB FOR YOU.");
|
||||
}
|
||||
|
||||
System.out.println("SORRY, BUT I CAN'T DO THAT JOB FOR YOU.");
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
break; // Leave the while loop
|
||||
}
|
||||
}
|
||||
|
||||
// Too many user input errors
|
||||
if (numErrors > 2) {
|
||||
System.out.println("ALL RIGHT, WISE GUY, IF YOU CAN'T PLAY THE GAME RIGHT, I'LL");
|
||||
System.out.println("JUST TAKE MY PUZZLE AND GO HOME. SO LONG.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Display detailed instructions
|
||||
// Too many user input errors
|
||||
if (numErrors > 2) {
|
||||
System.out.println("ALL RIGHT, WISE GUY, IF YOU CAN'T PLAY THE GAME RIGHT, I'LL");
|
||||
System.out.println("JUST TAKE MY PUZZLE AND GO HOME. SO LONG.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Display detailed instructions
|
||||
System.out.println("IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE.");
|
||||
System.out.println("3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE,");
|
||||
System.out.println("7 THE NEXT, AND SO ON, UP TO 15. IF YOU DO THE PUZZLE WITH");
|
||||
@@ -164,28 +164,28 @@ public class Tower {
|
||||
System.out.println("ARE NUMBERED FROM LEFT TO RIGHT, 1 TO 3. WE WILL");
|
||||
System.out.println("START WITH THE DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM");
|
||||
System.out.println("TO NEEDLE 3.\n");
|
||||
System.out.println("GOOD LUCK!\n");
|
||||
|
||||
System.out.println("GOOD LUCK!\n");
|
||||
|
||||
disk = MAX_DISK_SIZE;
|
||||
|
||||
|
||||
// Set disk starting positions
|
||||
for (row = MAX_NUM_ROWS; row > (MAX_NUM_ROWS - numDisks); row--) {
|
||||
positions[row][1] = disk;
|
||||
disk = disk - 2;
|
||||
}
|
||||
|
||||
for (row = MAX_NUM_ROWS; row > (MAX_NUM_ROWS - numDisks); row--) {
|
||||
positions[row][1] = disk;
|
||||
disk = disk - 2;
|
||||
}
|
||||
|
||||
printPositions();
|
||||
|
||||
|
||||
nextStep = Step.SELECT_DISK_MOVE;
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case SELECT_DISK_MOVE:
|
||||
|
||||
|
||||
System.out.print("WHICH DISK WOULD YOU LIKE TO MOVE? ");
|
||||
|
||||
|
||||
numErrors = 0;
|
||||
|
||||
|
||||
while (numErrors < 2) {
|
||||
disk = scan.nextInt();
|
||||
|
||||
@@ -194,154 +194,154 @@ public class Tower {
|
||||
|
||||
// Check if disk exists
|
||||
diskPosition = getDiskPosition(disk);
|
||||
|
||||
|
||||
// Disk found
|
||||
if ((diskPosition.row > 0) && (diskPosition.column > 0))
|
||||
{
|
||||
// Disk can be moved
|
||||
if (isDiskMovable(disk, diskPosition.row, diskPosition.column) == true) {
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
// Disk cannot be moved
|
||||
else {
|
||||
|
||||
System.out.println("THAT DISK IS BELOW ANOTHER ONE. MAKE ANOTHER CHOICE.");
|
||||
System.out.print("WHICH DISK WOULD YOU LIKE TO MOVE? ");
|
||||
|
||||
}
|
||||
|
||||
System.out.println("THAT DISK IS BELOW ANOTHER ONE. MAKE ANOTHER CHOICE.");
|
||||
System.out.print("WHICH DISK WOULD YOU LIKE TO MOVE? ");
|
||||
|
||||
}
|
||||
}
|
||||
// Mimic legacy handling of valid disk number but disk not found
|
||||
else {
|
||||
|
||||
|
||||
System.out.println("THAT DISK IS BELOW ANOTHER ONE. MAKE ANOTHER CHOICE.");
|
||||
System.out.print("WHICH DISK WOULD YOU LIKE TO MOVE? ");
|
||||
numErrors = 0;
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// Invalid disk number
|
||||
else {
|
||||
|
||||
System.out.println("ILLEGAL ENTRY... YOU MAY ONLY TYPE 3,5,7,9,11,13, OR 15.");
|
||||
|
||||
System.out.println("ILLEGAL ENTRY... YOU MAY ONLY TYPE 3,5,7,9,11,13, OR 15.");
|
||||
numErrors++;
|
||||
|
||||
if (numErrors > 1) {
|
||||
|
||||
if (numErrors > 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
System.out.print("? ");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (numErrors > 1) {
|
||||
|
||||
if (numErrors > 1) {
|
||||
|
||||
System.out.println("STOP WASTING MY TIME. GO BOTHER SOMEONE ELSE.");
|
||||
return;
|
||||
}
|
||||
|
||||
nextStep = Step.SELECT_NEEDLE;
|
||||
|
||||
nextStep = Step.SELECT_NEEDLE;
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case SELECT_NEEDLE:
|
||||
|
||||
|
||||
numErrors = 0;
|
||||
|
||||
while (true) {
|
||||
|
||||
|
||||
System.out.print("PLACE DISK ON WHICH NEEDLE? ");
|
||||
needle = scan.nextInt();
|
||||
|
||||
|
||||
// Handle valid needle numbers
|
||||
if ((needle - 1) * (needle - 2) * (needle - 3) == 0) {
|
||||
|
||||
// Ensure needle is safe for disk move
|
||||
if ((needle - 1) * (needle - 2) * (needle - 3) == 0) {
|
||||
|
||||
// Ensure needle is safe for disk move
|
||||
if (isNeedleSafe(needle, disk, row) == false) {
|
||||
|
||||
|
||||
System.out.println("YOU CAN'T PLACE A LARGER DISK ON TOP OF A SMALLER ONE,");
|
||||
System.out.println("IT MIGHT CRUSH IT!");
|
||||
System.out.print("NOW THEN, ");
|
||||
System.out.print("NOW THEN, ");
|
||||
|
||||
nextStep = Step.SELECT_DISK_MOVE;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
diskPosition = getDiskPosition(disk);
|
||||
|
||||
|
||||
// Attempt to move the disk on a non-empty needle
|
||||
diskMoved = false;
|
||||
diskMoved = false;
|
||||
for (row = 1; row <= MAX_NUM_ROWS; row++) {
|
||||
if (positions[row][needle] != 0) {
|
||||
row--;
|
||||
|
||||
|
||||
positions[row][needle] = positions[diskPosition.row][diskPosition.column];
|
||||
positions[diskPosition.row][diskPosition.column] = 0;
|
||||
|
||||
|
||||
diskMoved = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Needle was empty, so move disk to the bottom
|
||||
if (diskMoved == false) {
|
||||
positions[MAX_NUM_ROWS][needle] = positions[diskPosition.row][diskPosition.column];
|
||||
positions[diskPosition.row][diskPosition.column] = 0;
|
||||
}
|
||||
|
||||
positions[diskPosition.row][diskPosition.column] = 0;
|
||||
}
|
||||
|
||||
nextStep = Step.CHECK_SOLUTION;
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
// Handle invalid needle numbers
|
||||
else {
|
||||
|
||||
|
||||
numErrors++;
|
||||
|
||||
if (numErrors > 1) {
|
||||
|
||||
if (numErrors > 1) {
|
||||
System.out.println("I TRIED TO WARN YOU, BUT YOU WOULDN'T LISTEN.");
|
||||
System.out.println("BYE BYE, BIG SHOT.");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
else {
|
||||
System.out.println("I'LL ASSUME YOU HIT THE WRONG KEY THIS TIME. BUT WATCH IT,");
|
||||
System.out.println("I ONLY ALLOW ONE MISTAKE.");
|
||||
}
|
||||
System.out.println("I ONLY ALLOW ONE MISTAKE.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case CHECK_SOLUTION:
|
||||
|
||||
printPositions();
|
||||
|
||||
|
||||
printPositions();
|
||||
|
||||
numMoves++;
|
||||
|
||||
|
||||
// Puzzle is solved
|
||||
if (isPuzzleSolved() == true) {
|
||||
|
||||
|
||||
// Check for optimal solution
|
||||
if (numMoves == (Math.pow(2, numDisks) - 1)) {
|
||||
System.out.println("");
|
||||
System.out.println("CONGRATULATIONS!!\n");
|
||||
System.out.println("CONGRATULATIONS!!\n");
|
||||
}
|
||||
|
||||
|
||||
System.out.println("YOU HAVE PERFORMED THE TASK IN " + numMoves + " MOVES.\n");
|
||||
System.out.print("TRY AGAIN (YES OR NO)? ");
|
||||
System.out.print("TRY AGAIN (YES OR NO)? ");
|
||||
|
||||
// Prompt for retries
|
||||
while (true) {
|
||||
userResponse = scan.next();
|
||||
|
||||
if (userResponse.toUpperCase().equals("YES")) {
|
||||
nextStep = Step.INITIALIZE;
|
||||
|
||||
if (userResponse.toUpperCase().equals("YES")) {
|
||||
nextStep = Step.INITIALIZE;
|
||||
break;
|
||||
}
|
||||
else if (userResponse.toUpperCase().equals("NO")) {
|
||||
@@ -352,86 +352,86 @@ public class Tower {
|
||||
else {
|
||||
System.out.print("'YES' OR 'NO' PLEASE? ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Puzzle is not solved
|
||||
else {
|
||||
|
||||
|
||||
// Exceeded maximum number of moves
|
||||
if (numMoves > MAX_NUM_MOVES) {
|
||||
System.out.println("SORRY, BUT I HAVE ORDERS TO STOP IF YOU MAKE MORE THAN");
|
||||
System.out.println("128 MOVES.");
|
||||
return;
|
||||
}
|
||||
System.out.println("128 MOVES.");
|
||||
return;
|
||||
}
|
||||
|
||||
nextStep = Step.SELECT_DISK_MOVE;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
System.out.println("INVALID STEP");
|
||||
break;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
} // End outer while loop
|
||||
|
||||
}
|
||||
|
||||
} // End outer while loop
|
||||
|
||||
} // End of method startGame
|
||||
|
||||
|
||||
|
||||
private boolean isPuzzleSolved() {
|
||||
|
||||
|
||||
int column = 0;
|
||||
int row = 0;
|
||||
|
||||
// Puzzle is solved if first 2 needles are empty
|
||||
for (row = 1; row <= MAX_NUM_ROWS; row++) {
|
||||
for (column = 1; column <= 2; column++) {
|
||||
// Puzzle is solved if first 2 needles are empty
|
||||
for (row = 1; row <= MAX_NUM_ROWS; row++) {
|
||||
for (column = 1; column <= 2; column++) {
|
||||
if (positions[row][column] != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
} // End of method isPuzzleSolved
|
||||
|
||||
|
||||
|
||||
private Position getDiskPosition(int disk) {
|
||||
|
||||
|
||||
int column = 0;
|
||||
int row = 0;
|
||||
|
||||
|
||||
Position pos = new Position(0, 0);
|
||||
|
||||
// Begin loop through all rows
|
||||
// Begin loop through all rows
|
||||
for (row = 1; row <= MAX_NUM_ROWS; row++) {
|
||||
|
||||
|
||||
// Begin loop through all columns
|
||||
for (column = 1; column <= MAX_NUM_COLUMNS; column++) {
|
||||
|
||||
|
||||
// Found the disk
|
||||
if (positions[row][column] == disk) {
|
||||
|
||||
|
||||
pos.row = row;
|
||||
pos.column = column;
|
||||
return pos;
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // End loop through all columns
|
||||
|
||||
} // End loop through all rows
|
||||
|
||||
return pos;
|
||||
|
||||
} // End of method getDiskPosition
|
||||
} // End loop through all rows
|
||||
|
||||
|
||||
private boolean isDiskMovable(int disk, int row, int column) {
|
||||
return pos;
|
||||
|
||||
} // End of method getDiskPosition
|
||||
|
||||
|
||||
private boolean isDiskMovable(int disk, int row, int column) {
|
||||
|
||||
int ii = 0; // Loop iterator
|
||||
|
||||
@@ -440,88 +440,88 @@ public class Tower {
|
||||
|
||||
// Disk can be moved
|
||||
if (positions[ii][column] == 0) {
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Disk cannot be moved
|
||||
if (positions[ii][column] < disk) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End loop through all rows above disk
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
} // End of method isDiskMovable
|
||||
} // End of method isDiskMovable
|
||||
|
||||
|
||||
private boolean isNeedleSafe(int needle, int disk, int row) {
|
||||
|
||||
|
||||
for (row = 1; row <= MAX_NUM_ROWS; row++) {
|
||||
|
||||
// Needle is not empty
|
||||
if (positions[row][needle] != 0) {
|
||||
|
||||
|
||||
// Disk crush condition
|
||||
if (disk >= positions[row][needle]) {
|
||||
if (disk >= positions[row][needle]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
} // End of method isNeedleSafe
|
||||
|
||||
|
||||
|
||||
|
||||
private void printPositions() {
|
||||
|
||||
|
||||
int column = 1;
|
||||
int ii = 0; // Loop iterator
|
||||
int numSpaces = 0;
|
||||
int row = 1;
|
||||
|
||||
int numSpaces = 0;
|
||||
int row = 1;
|
||||
|
||||
// Begin loop through all rows
|
||||
for (row = 1; row <= MAX_NUM_ROWS; row++) {
|
||||
|
||||
numSpaces = 9;
|
||||
|
||||
|
||||
numSpaces = 9;
|
||||
|
||||
// Begin loop through all columns
|
||||
for (column = 1; column <= MAX_NUM_COLUMNS; column++) {
|
||||
|
||||
// No disk at the current position
|
||||
if (positions[row][column] == 0) {
|
||||
|
||||
|
||||
System.out.print(" ".repeat(numSpaces) + "*");
|
||||
numSpaces = 20;
|
||||
}
|
||||
|
||||
numSpaces = 20;
|
||||
}
|
||||
|
||||
// Draw a disk at the current position
|
||||
else {
|
||||
|
||||
|
||||
System.out.print(" ".repeat(numSpaces - ((int) (positions[row][column] / 2))));
|
||||
|
||||
for (ii = 1; ii <= positions[row][column]; ii++) {
|
||||
System.out.print("*");
|
||||
}
|
||||
|
||||
System.out.print("*");
|
||||
}
|
||||
|
||||
numSpaces = 20 - ((int) (positions[row][column] / 2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // End loop through all columns
|
||||
|
||||
System.out.println("");
|
||||
|
||||
} // End loop through all rows
|
||||
|
||||
} // End of method printPositions
|
||||
|
||||
|
||||
System.out.println("");
|
||||
|
||||
} // End loop through all rows
|
||||
|
||||
} // End of method printPositions
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
||||
Tower tower = new Tower();
|
||||
tower.play();
|
||||
|
||||
|
||||
} // End of method main
|
||||
|
||||
} // End of class Tower
|
||||
} // End of class Tower
|
||||
|
||||
Reference in New Issue
Block a user