Last active
December 16, 2015 11:59
-
-
Save kevinbarbour/5431147 to your computer and use it in GitHub Desktop.
Connect 4 game using decision trees in java. WIP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Kevin Barbour | |
// CMSC 401 | |
// Program #5: Connect 4 | |
// Program name: C4.java | |
import java.lang.Math; | |
import java.util.Scanner; | |
class Node { | |
final int MAXSCORE = 9999; | |
final int MINSCORE = -9999; | |
char[][] board; | |
Node[] children; | |
int[] childScores; | |
int score, move, moveRow, level; | |
char turn, ch; | |
boolean compTurn; | |
public Node(int level) { | |
board = new char[6][7]; | |
this.level = level; | |
compTurn = false; | |
ch = 'B'; | |
reset(); | |
} | |
public Node(Node parent, int move, int level) { | |
board = new char[6][7]; | |
for(int i = 0; i < 6; i++) { | |
for(int j = 0; j < 7; j++) { | |
board[i][j] = parent.getBoard()[i][j]; | |
} | |
} | |
//board = (char[][])parent.getBoard().clone(); | |
this.level = level; | |
this.move = move; | |
children = new Node[7]; | |
this.compTurn = !parent.isCompTurn(); | |
if(compTurn) ch = 'R'; | |
else ch = 'B'; | |
makeMove(); | |
calcScore(); | |
} | |
public void genNode() { | |
for(int i = 0; i < 7; i++) { | |
children[i] = new Node(this, i, level - 1); | |
} | |
} | |
void calcScore() { | |
int col = move; | |
int tempScore = -1; | |
if(this.won()) { | |
if(!compTurn) score = MAXSCORE; | |
else score = MINSCORE; | |
return; | |
} | |
int wCount = 0; | |
int bCount = 0; | |
if(!compTurn) { | |
if(9000 > tempScore && ( | |
(board[(moveRow + 1) % 6][move] == 'R' && | |
board[(moveRow + 2) % 6][move] == 'R' && | |
board[(moveRow + 3) % 6][move] == 'R') || | |
(board[Math.abs((moveRow - 1) % 6)][move] == 'R' && | |
board[Math.abs((moveRow - 2) % 6)][move] == 'R' && | |
board[Math.abs((moveRow - 3) % 6)][move] == 'R') || | |
(board[moveRow][(move + 1) % 7] == 'R' && | |
board[moveRow][(move + 2) % 7] == 'R' && | |
board[moveRow][(move + 3) % 7] == 'R') || | |
(board[moveRow][Math.abs((move - 1) % 7)] == 'R' && | |
board[moveRow][Math.abs((move - 2) % 7)] == 'R' && | |
board[moveRow][Math.abs((move - 3) % 7)] == 'R'))) { | |
tempScore = 9000; | |
} | |
if((8000 > tempScore) && ( | |
(board[(moveRow + 1) % 6][move] == 'B' && | |
board[(moveRow + 2) % 6][move] == 'B' && | |
(board[(moveRow + 3) % 6][move] == ' ' || | |
board[Math.abs((moveRow - 1) % 6)][move] == ' ')) || | |
(board[Math.abs((moveRow - 1) % 6)][move] == 'B' && | |
board[Math.abs((moveRow - 2) % 6)][move] == 'B' && | |
(board[Math.abs((moveRow - 3) % 6)][move] == ' ' || | |
board[(moveRow + 1) % 6][move] == ' ')) || | |
(board[moveRow][(move + 1) % 7] == 'B' && | |
board[moveRow][(move + 2) % 7] == 'B' && | |
(board[moveRow][(move + 3) % 7] == ' ' || | |
board[moveRow][Math.abs((move - 1) % 7)] == ' ')) || | |
(board[moveRow][Math.abs(move - 1) % 7] == 'B' && | |
board[moveRow][Math.abs(move - 2) % 7] == 'B' && | |
(board[moveRow][Math.abs(move - 3) % 7] == ' ' || | |
board[moveRow][(move + 1) % 7] == ' ')))) { | |
tempScore = 8000; | |
} | |
if((7000 > tempScore) && ( | |
(board[(moveRow + 1) % 6][move] == 'W' && | |
board[(moveRow + 2) % 6][move] == 'W' && | |
(board[(moveRow + 3) % 6][move] == ' ' || | |
board[Math.abs((moveRow - 1) % 6)][move] == ' ')) || | |
(board[Math.abs((moveRow - 1) % 6)][move] == 'W' && | |
board[Math.abs((moveRow - 2) % 6)][move] == 'W' && | |
(board[Math.abs((moveRow - 3) % 6)][move] == ' ' || | |
board[(moveRow + 1) % 6][move] == ' ')) || | |
(board[moveRow][(move + 1) % 7] == 'W' && | |
board[moveRow][(move + 2) % 7] == 'W' && | |
(board[moveRow][(move + 3) % 7] == ' ' || | |
board[moveRow][Math.abs((move - 1) % 7)] == ' ')) || | |
(board[moveRow][Math.abs(move - 1) % 7] == 'W' && | |
board[moveRow][Math.abs(move - 2) % 7] == 'W' && | |
(board[moveRow][Math.abs(move - 3) % 7] == ' ' || | |
board[moveRow][(move + 1) % 7] == ' ')))) { | |
tempScore = 7000; | |
} | |
if(tempScore < 100) tempScore = 100; | |
score = tempScore; | |
int childScore = 0; | |
if(level > 0) { | |
genNode(); | |
for(int i = 0; i < 7; i++) { | |
childScore += children[i].getScore(); | |
} | |
childScore = childScore/20; | |
score += childScore; | |
} | |
} | |
}//calcScore | |
public boolean won() { | |
int col = move; | |
int row = -1; | |
int count; | |
for(int i = 0; row == -1 && i < 20; i++) { | |
if(board[i % 6][col] == ch) row = i; | |
} | |
if(row < 0) return false; | |
count = 0; | |
for(int i = 0; i < 10; i++) { | |
if(board[row][i % 7] == ch) count++; | |
else count = 0; | |
if(count == 4) return true; | |
} | |
count = 0; | |
for(int i = 0; i < 10; i++) { | |
if(board[i % 6][col] == ch) count++; | |
else count = 0; | |
if(count == 4) return true; | |
} | |
for(int i = 0; i < 3; i++) { | |
for(int j = 0; j < 4; j++) { | |
if((board[i][j] == ch && | |
board[i + 1][j + 1] == ch && | |
board[i + 2][j + 2] == ch && | |
board[i + 3][j + 3] == ch) || | |
(board[i + 3][j] == ch && | |
board[i + 2][j + 1] == ch && | |
board[i + 1][j + 2] == ch && | |
board[i][j + 3] == ch )) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
void reset() { | |
for(int i = 0; i < 6; i++) | |
for(int j = 0; j < 7; j++) | |
board[i][j] = ' '; | |
} | |
void makeMove() { | |
if(board[0][move] != ' ') { | |
score = -9999999; | |
return; | |
} | |
for(int i = 5; i > -1; i--) { | |
if(board[i][move] == ' ') { | |
board[i][move] = ch; | |
moveRow = i; | |
return; | |
} | |
} | |
}//play | |
public void printBoard() { | |
for(int i = 0; i < 6; i++) { | |
for(int j = 0; j < 7; j++) { | |
System.out.printf(" %c ", board[i][j]); | |
} | |
System.out.println(); | |
} | |
System.out.println(" 0 1 2 3 4 5 6"); | |
}//printBoard | |
public char[][] getBoard() { return board; } | |
public int getScore() { return score; } | |
public boolean isCompTurn() { return compTurn; } | |
public Node[] getChildren() { return children; } | |
} | |
class CompPlayer { | |
static public int play(Node curNode) { | |
curNode.genNode(); | |
int score = curNode.getChildren()[0].getScore(); | |
int node = 0; | |
for(int i = 0; i < 7; i++) { | |
if(curNode.getChildren()[i].getScore() > score || | |
(curNode.getChildren()[i].getScore() == score && | |
Math.random() > 0.5)) { | |
score = curNode.getChildren()[i].getScore(); | |
node = i; | |
} | |
} | |
return node; | |
} | |
} | |
class C4 { | |
static Scanner input = new Scanner(System.in); | |
public static void main(String[] args) { | |
boolean gameOver = false; | |
boolean playerTurn = true; | |
int searchLevel; | |
System.out.println("What level should the decision tree search to?"); | |
searchLevel = input.nextInt(); | |
Node gameBoard = new Node(searchLevel); | |
while(!gameOver) { | |
if(playerTurn) { | |
gameBoard.printBoard(); | |
System.out.printf("What column would you like to play in? [0-6] "); | |
int col = input.nextInt(); | |
gameBoard = new Node(gameBoard, col, searchLevel); | |
} else gameBoard = new Node(gameBoard, CompPlayer.play(gameBoard), searchLevel); | |
if(gameBoard.won()) { | |
gameOver = true; | |
gameBoard.printBoard(); | |
if(!playerTurn) { | |
System.out.println("Computer won!"); | |
} else System.out.println("You won!"); | |
} | |
playerTurn = !playerTurn; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment