There is a 2D array with dimensions 9x9. The ant starts in cell (5,5) , or the center. It moves randomly north, south, east, or west. The ant stops walking when it falls off the grid. The space where it falls is marked by an X. In the matrix, it should display the amount of times the ant visited each cell and the number of moves the ant took to fall off.
I'm not sure where to start or how to go about it. Like how to make the north, south, west, east methods.
Here's what I have so far.
public static void main(String [] args)
{
int [][] grid = new int[9][9];
for (int r = 0; r< grid.length; r++)
{
for (int c = 0 ; c<grid[0].length; c++)
{
grid[r][c] = 0;
}
}
boolean test = true;
while(test)
{
int random = (int)Math.random()*4+1;
if (random == 1)
{
}
else if (random == 2)
{
}
else if (random == 3)
{
}
else if (random == 4)
{
}
}
}
You've got the right idea, now what you want to do is move in the direction specified by random, and increment the value in your array. Here is how I would do it.
int count = 0;
int x = 4;
int y = 4; // arrays are 0 based
while(true)
{
int random = (int)Math.random()*4+1;
if (random == 1)
{
x--; // move left
}
else if (random == 2)
{
x++; // move right
}
else if (random == 3)
{
y--; // move down
}
else if (random == 4)
{
y++; // move up
}
if(x < 0 || y < 0 || x >= grid.length || y >= grid[x].length) break;
count++;
grid[x][y]++;
}
System.out.println(count); // number of moves before it fell
Here is a random walk of an ant on the grid. See comments in the code. The ant walks STEPS on a predefined size grid.
import java.util.Random;
public class Ants {
/** height and width of the grid */
public static final int HEIGHT = 9 ;
public static final int WIDTH = 9 ;
/** NOVAL means "no value" */
public static final int NOVAL = -1;
/** world directions */
public static final int NORTH = 0 ;
public static final int WEST = 1 ;
public static final int SOUTH = 2 ;
public static final int EAST = 3 ;
/** how many steps for ant to walk */
public static final int STEPS = 10;
/** where does the ant start it's walk */
public static final int START_X = 5;
public static final int START_Y = 5;
/** printing related */
public static final String ANT = "ANT";
private static final Random random = new Random();
/** grid for ant to walk on */
static int[] grid;
/** get height of the grid */
static int getHeight() {
return HEIGHT;
}
/** get width of the grid */
static int getWidth() {
return WIDTH;
}
/** size of the grid */
static int getSize() {
return getWidth()*getHeight();
}
/** coordinates are converted to one dimension */
/** #return index from coordinates. */
static int idx(int x, int y) {
return y*getWidth() + x;
}
/** get x coordinate of idx */
static int x(int idx) {
return idx % getWidth();
}
/** get y coordinate of idx */
static int y(int idx) {
return (idx - x(idx)) / getWidth();
}
/** get cell */
static int getCell(int idx) {
return grid[idx];
}
static int getCell(int x, int y) {
return getCell(
idx(x,y));
}
static void setCell(int idx, int value) {
grid[idx] = value;
}
/** init array with some value */
private static void initArr(int[] arr, int value) {
for (int i = 0; i < arr.length; i++) {
arr[i] = value;
}
}
/**
* #return adjancted cells indexes.
*/
public static int[] adjanctedTo(int idx) {
int[] adj = new int[4];
initArr(adj, NOVAL);
int x = x(idx);
int y = y(idx);
/** Is North available? */
if (y - 1 >= 0) {
adj[NORTH] = idx(x,y-1);
}
/** West? */
if (x - 1 >= 0) {
adj[WEST] = idx(x-1, y);
}
/** South? */
if (y + 1 < getHeight()) {
adj[SOUTH] = idx(x,y+1);
}
/** East? */
if (x + 1 < getWidth()) {
adj[EAST] = idx(x+1, y);
}
return adj;
}
/** picks random value from array */
public static int pick(int[] arr) {
int ret = NOVAL;
int idx = random.nextInt(4);
for (int i = idx;; i++) {
if (NOVAL != arr[i]) {
ret = arr[i];
break;
}
if (3 == i) {
/** cycle if not yet found a NOVAL value in array */
i = 0;
}
}
return ret;
}
public static void main(String[] args) {
/** init grid */
grid = new int[getSize()];
int nextStep = NOVAL;
int current = idx(START_X, START_Y);
setVisited(current);
for (int s = 0; s < STEPS; s++) {
System.out.println("STEP "+s);
System.out.println(
"Standing #" + position(current) + ".");
printGrid(current);
nextStep = pick(
adjanctedTo(current));
System.out.println(
"Moving to " + position(nextStep));
setVisited(current);
printGrid(nextStep);
current = nextStep;
}
}
public static void setVisited(int idx) {
setCell(idx, getCell(idx)+1);
}
public static String position(int idx) {
return idx+"("+x(idx) + ";" + y(idx) +")";
}
public static void printGrid(int antPosition) {
for (int x = 0; x < getWidth(); x++) {
for (int y = 0; y < getHeight(); y++) {
if (idx(x,y) == antPosition) {
System.out.print(ANT);
} else {
System.out.format(
"%2d|",
getCell(x,y));
}
}
System.out.println();
}
}
}
public static void main(String[] args) {
String[][] sim = ant(3,3);
for (int i = 0; i < sim.length; i++) {
for (int j = 0; j < sim[i].length; j++) {
System.out.print(sim[i][j] + " ");
}
System.out.println();
}
}
static String[][] ant(int x, int y) {
if(x<0||x>=9||y<0||y>=9){
return null;
}
int[] rn = {-1, 1}; //next ant random direction , you can include 0 if you wanted
String[][] mat = new String[9][9];
for (int i = 0; i < 9; i++) {
Arrays.fill(mat[i], "0");//fill array with 0 to avoid null default value
}
int a = x, b = y; // a and b are the Cartesian coordinates of the ant
while (true) {
mat[a][b] = String.valueOf(Integer.parseInt(mat[a][b]) + 1);
int newx = a + rn[(int) (Math.random() * rn.length)];
int newy = b + rn[(int) (Math.random() * rn.length)];
//these are the ant new coordinates , we have to check them before going to them
if (newx < 0 || newx >= 9 || newy < 0 || newy >= 9) {
mat[a][b] = "X";
return mat;
}
a = newx;
b = newy;
}
}
Related
I am trying to create a method/ while loop which checks to see which player moves. For now I check to see which play moves in a for loop. I am trying to make my code a bit more clear and concise. Here is the main method:
public static void main(String[] args) {
try (Scanner input = new Scanner(System.in)) {
int height = 6, width = 8, moves = height * width;
ConnectFour board = new ConnectFour(width, height);
System.out.println("Use 0-" + (width - 1) + " to choose a column.");
System.out.println(board);
for (int player = 0; moves-- > 0; player = 1 - player) { // Here is where i check to see who plays
char symbol = players[player];
board.chooseAndDrop(symbol, input);
System.out.println(board);
if (board.isWinningPlay()) {
System.out.println("Player " + symbol + " wins!");
return;
}
}
System.out.println("Game over, no winner.");
}
}
I was thinking more along the lines of:
int playerNb = 0;
while (thegamestarted)
{
if (playerNb == 0)
// Get user input
else
// Get second player input
// Process the input
// Change playerNb to 1 or 0
}
Below is the full code:
import java.util.Arrays;
import java.util.Scanner;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class ConnectFour {
private static final char[] players = new char[] { 'X', 'O' };
private final int width, height;
private final char[][] grid;
private int lastCol = -1, lastTop = -1;
public ConnectFour(int width, int height) {
this.width = width;
this.height = height;
this.grid = new char[height][];
for (int h = 0; h < height; h++) {
Arrays.fill(this.grid[h] = new char[width], '.');
}
}
public String toString() {
return IntStream.range(0, this.width)
.mapToObj(Integer::toString)
.collect(Collectors.joining()) + "\n" +
Arrays.stream(this.grid)
.map(String::new)
.collect(Collectors.joining("\n"));
}
/**
* Prompts the user for a column, repeating until a valid
* choice is made.
*/
public void chooseAndDrop(char symbol, Scanner input) {
do {
System.out.print("\nPlayer " + symbol + " turn: ");
int col = input.nextInt();
if (! (0 <= col && col < this.width)) {
System.out.println("Column must be between 0 and " +
(this.width - 1));
continue;
}
for (int h = this.height - 1; h >= 0; h--) {
if (this.grid[h][col] == '.') {
this.grid[this.lastTop=h][this.lastCol=col] = symbol;
return;
}
}
System.out.println("Column " + col + " is full.");
} while (true);
}
/**
* Detects whether the last chip played was a winning move.
*/
public boolean isWinningPlay() {
if (this.lastCol == -1) {
throw new IllegalStateException("No move has been made yet");
}
char sym = this.grid[this.lastTop][this.lastCol];
String streak = String.format("%c%c%c%c", sym, sym, sym, sym);
return contains(this.horizontal(), streak) ||
contains(this.vertical(), streak) ||
contains(this.slashDiagonal(), streak) ||
contains(this.backslashDiagonal(), streak);
}
/**
* The contents of the row containing the last played chip.
*/
private String horizontal() {
return new String(this.grid[this.lastTop]);
}
/**
* The contents of the column containing the last played chip.
*/
private String vertical() {
StringBuilder sb = new StringBuilder(this.height);
for (int h = 0; h < this.height; h++) {
sb.append(this.grid[h][this.lastCol]);
}
return sb.toString();
}
/**
* The contents of the "/" diagonal containing the last played chip
* (coordinates have a constant sum).
*/
private String slashDiagonal() {
StringBuilder sb = new StringBuilder(this.height);
for (int h = 0; h < this.height; h++) {
int w = this.lastCol + this.lastTop - h;
if (0 <= w && w < this.width) {
sb.append(this.grid[h][w]);
}
}
return sb.toString();
}
/**
* The contents of the "\" diagonal containing the last played chip
* (coordinates have a constant difference).
*/
private String backslashDiagonal() {
StringBuilder sb = new StringBuilder(this.height);
for (int h = 0; h < this.height; h++) {
int w = this.lastCol - this.lastTop + h;
if (0 <= w && w < this.width) {
sb.append(this.grid[h][w]);
}
}
return sb.toString();
}
private static boolean contains(String haystack, String needle) {
return haystack.indexOf(needle) >= 0;
}
public static void main(String[] args) {
try (Scanner input = new Scanner(System.in)) {
int height = 6, width = 8, moves = height * width;
ConnectFour board = new ConnectFour(width, height);
System.out.println("Use 0-" + (width - 1) + " to choose a column.");
System.out.println(board);
for (int player = 0; moves-- > 0; player = 1 - player) {
char symbol = players[player];
board.chooseAndDrop(symbol, input);
System.out.println(board);
if (board.isWinningPlay()) {
System.out.println("Player " + symbol + " wins!");
return;
}
}
System.out.println("Game over, no winner.");
}
}
}
Its a bit difficult to tell what you want from your code, but the absolute simplest way to keep track of what player it is, is to keep track of the turn number, and check if it is even or odd with the modulus function
This is just a brief bit of psuedocode to show you how you can tell what the turn is with simple math. You will have to adapt it to your own needs. You can see that it will only be "Player 2"'s turn on an even turn number where the turn number divided by 2 has no remainder. Just remember to increment the turn after every move.
There's no "good" answer. You're the one writing the code, you can decide whose turn it is, you just have to keep track of it.
int turn = 1;
for ( ) {
if (turn % 2 == 0) {
System.out.println("Player 2");
} else {
System.out.println("Player 1");
}
turn++;
}
I have this class that randomly creates rooms next to each other, and prints brackets (which represent the rooms) to the console. But I wanted to know how to add something like that to a JPanel for a GUI. Here is the room generator class:
public class Rooms {
static final int width = 15, height = 10;
static final int rooms = 19;
static boolean[][] room = new boolean[width][height];
static int neighborCount(int x, int y) {
int n = 0;
if (x > 0 && room[x-1][y]) n++;
if (y > 0 && room[x][y-1]) n++;
if (x < width-1 && room[x+1][y]) n++;
if (y < height-1 && room[x][y+1]) n++;
return n;
}
public void Rooms() {
room[width/2][height/2] = true;
Random r = new Random();
int x, y, nc;
for (int i = 0; i < rooms; i++) {
while (true) {
x = r.nextInt(width);
y = r.nextInt(height);
nc = neighborCount(x, y);
if (!room[x][y] && nc == 1) break;
}
room[x][y] = true;
}
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++)
System.out.print(room[x][y] ? "[]" : " ");
System.out.print();
}
}
}
Thanks for the help!
You probably want to use java.awt.Graphics. It lets you draw primitive shapes like lines, rectangles, circles, etc. This might get you started. Section 2 also covers how to draw on a JPanel.
I have been trying to get my tic tac toe program to work for a while now.
At the moment I'm stuck in the win condition.
The game can now end as a draw but no player (human || computer) can win it.
I need to determine the winning conditions (horizontal, vertical, across) in playerHasWon but have no idea how to implement them.
import java.util.Scanner;
import java.util.Random;
public class NewTicTacToe {
public static final int DRAW = 0;
public static final int COMPUTER = 1;
public static final int PLAYER = 2;
public static final char PLAYER_MARK = 'X';
public static final char COMPUTER_MARK = 'O';
public static int size;
public static String[][] board;
public static int score = 0;
public static Scanner scan = new Scanner(System.in);
/**
* Creates base for the game.
*
* #param args the command line parameters. Not used.
*/
public static void main(String[] args) {
while (true) {
System.out.println("Select board size");
System.out.print("[int]: ");
try {
size = Integer.parseInt(scan.nextLine());
} catch (Exception e) {
System.out.println("You can't do that.");
continue;
}
break;
}
int[] move = {};
board = new String[size][size];
setupBoard();
int i = 1;
loop:
while (true) {
if (i % 2 == 1) {
displayBoard();
move = getMove();
} else {
computerTurn();
}
switch (isGameFinished(move)) {
case PLAYER:
System.err.println("YOU WIN!");
break loop;
case COMPUTER:
System.err.println("Computer WINS!\nYOU LOSE!");
break loop;
case DRAW:
System.err.println("IT'S A DRAW");
break loop;
}
i++;
}
}
private static int isGameFinished(int[] move) {
if (isDraw()) {
return DRAW;
} else if (playerHasWon(board, move, COMPUTER_MARK)) {
return COMPUTER;
} else if (playerHasWon(board, move, PLAYER_MARK)) {
return PLAYER;
}
return -1;
}
/**
* Checks for win.
*
* #param board
* #return if the game is won.
*/
public static boolean playerHasWon(String[][] board, int[] move,
char playerMark) { //playermark x || o
boolean hasWon = false;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
// check if 5 in a line
if (board[i][j].equals(playerMark)) {
score++;
} else {
score = 0;
}
if (score == 5) {
return true;
}
}
}
return hasWon;
}
/**
* Checks for draws.
*
* #return if this game is a draw
*/
public static boolean isDraw() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (board[i][j] == " ") {
return false;
}
}
}
return true;
}
/**
* Displays the board.
*
*
*/
public static void displayBoard() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
System.out.printf("[%s]", board[i][j]);
}
System.out.println();
}
}
/**
* Displays the board.
*
*
*/
public static void setupBoard() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
board[i][j] = " ";
}
}
}
/*
* Takes in userinput and sends it to isValidPlay.
*
*
*/
public static int[] getMove() {
Scanner sc = new Scanner(System.in);
System.out.println("Your turn:");
while (true) {
try {
System.out.printf("ROW: [0-%d]: ", size - 1);
int x = Integer.parseInt(sc.nextLine());
System.out.printf("COL: [0-%d]: ", size - 1);
int y = Integer.parseInt(sc.nextLine());
if (isValidPlay(x, y)) {
board[x][y] = "" + PLAYER_MARK;
return new int[]{x, y};
}
} catch (Exception e) {
System.out.println("You can't do that.");
}
return null;
}
}
/*
* Randomizes computer's turn - where it inputs the mark 'O'.
*
*
*/
public static void computerTurn() {
Random rgen = new Random(); // Random number generator
while (true) {
int x = (int) (Math.random() * size);
int y = (int) (Math.random() * size);
if (isValidPlay(x, y)) {
board[x][y] = "" + COMPUTER_MARK;
break;
}
}
}
/**
* Checks if the move is possible.
*
* #param inX
* #param inY
* #return
*/
public static boolean isValidPlay(int inX, int inY) {
// Play is out of bounds and thus not valid.
if ((inX >= size) || (inY >= size)) {
return false;
}
// Checks if a play have already been made at the location,
// and the location is thus invalid.
return (board[inX][inY] == " ");
}
}
// End of file
You could use a different approach to check for victories. Maybe split in three parts? Horizontal, vertical, and diagonals?
I made some changes to your code to give an example:
public static boolean playerHasWon(String[][] board, int[] move,
String playerMark) { //playermark x || o
//Horizontal check
for (int i = 0; i < size; i++) {
if (board[i][0].equals(playerMark)) {
int j;
for (j = 1; j < size; j++) {
if (!board[i][j].equals(playerMark)) {
break;
}
}
if (j == size) {
return true;
}
}
}
//Vertical check
for (int i = 0; i < size; i++) {
if (board[0][i].equals(playerMark)) {
int j;
for (j = 1; j < size; j++) {
if (!board[j][i].equals(playerMark)) {
break;
}
}
if (j == size) {
return true;
}
}
}
//Diagonals
int i;
for (i = 0; i < size; i++) {
if (!board[i][i].equals(playerMark)) {
break;
}
}
if (i == size) {
return true;
}
for (i = 0; i < size; i++) {
if (!board[i][(size - 1) - i].equals(playerMark)) {
break;
}
}
if (i == size) {
return true;
}
return false;
}
Note that you have to change the playerMarks from char to String.
Also, I suggest displaying the board just before announcing who won. That way, if the computer wins, you can see its last move
I currently have it so it prints of a 2 by 2 grid and renames my position as P and everything else as - and it hides the chest until i step on it and ask's me if i want to open the chest then ends the game but i want it to rename the randomly generated chest to C so i can see on the grid where it is, Could someone please help me with this issue
/**
* Auto Generated Java Class.
*/
import java.util.*;
public class Adventure {
public static final int rows= 2;
public static String tile = "";
public static final int cols= 2;
public static String input = "";
public static boolean run = true;
public static String[][] map = new String[rows][cols];
public static int xpos = 0;
public static int ypos = 0;
public static Random gen = new Random();
public static final int xx = gen.nextInt(rows);
public static final int yy = gen.nextInt(cols);
public static void main(String[] args) {
for(int x = 0; x < rows; x++) {
for(int y = 0; y < cols; y++) {
map[x][y] = "you see nothing, on the fields of justice";
}
}
map[xx][yy] = "You find a chest: Open?";
while(run) {
displayMap();
System.out.println(map[xpos][ypos]);
input = userinput();
input = input.toLowerCase();
if(input.equals("w")) {
if (ypos < cols - 1) {
ypos++;
}else{
System.out.println("You're at the edge of the map");
}
}else if(input.equals("d")) {
if (xpos < rows - 1) {
xpos++;
}else{
System.out.println("You're at the edge of the map");
}
}else if(input.equals("s")) {
if (ypos > 0) {
ypos--;
}else{
System.out.println("You're at the edge of the map");
}
}else if(input.equals("a")) {
if (xpos > 0) {
xpos--;
}else{
System.out.println("You're at the edge of the map");
}
}else if(input.equals("open")) {
if(map[xpos][ypos].equals("You find a chest: Open?")){
System.out.println("You find a sword");
System.out.println("()==[:::::::::::::>");
run = false;
}else{
System.out.println("There's nothing to open");
}
}else {
System.out.println("Wrong direction, W , A, S , D");
}
}
}
public static String userinput(){
System.out.println("Which direction do you want to move: w , a ,s ,d ? ");
Scanner keyboard = new Scanner(System.in);
return keyboard.nextLine();
}
public static void displayMap() {
for (int y = cols - 1; y >= 0; y--) {
for (int x = 0; x < rows; x++) {
if (y == ypos && x == xpos) {
tile = tile + "P";
}
//Heres where i want to rename the chest to 'C' on the grid
else if (xx && yy) {
tile = tile + "C";
}
else{
tile = tile + "-";
}
}
System.out.println(tile);
tile = "";
}
}
}
Replace else if (xx && yy) with else if (y==yy && x==xx). It's an easy error to make.
I'm working on a tictactoe board for practice making classes and i have ran into a problem with my algorithm. it seems to be returning the best move offensive, but it doesn't play defense. i dont know where i have messed up and cant seem to find it. i have looked over a lot of things on here about it and ive compared it to simular projects, but still can't seem to get it. here is my code.
package TicTacToe;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
public class Solution {
private static GameBoard currentBoard;
private static Player botPlayer;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String player;
System.out.println("ENTER bot: ");
player = in.next();
if(player.equalsIgnoreCase("X")) {
botPlayer = Player.X;}
else {botPlayer = Player.O;}
String board[] = new String[3];
for(int i = 0; i < 3; i++) {
System.out.println("ENTER board: ");
board[i] = in.next();
}
currentBoard = new GameBoard(3,3, board);
List<Space> OpenSpaces = getOpenSquares(currentBoard);
MakeMove(OpenSpaces);
System.exit(-1);
}
public static List<Space> getOpenSquares(GameBoard GB) {
List<Space> OpenSpaces = new ArrayList<Space>();
for(int r = 0; r < 3; r++) {
for(int c = 0; c < 3; c++) {
if(GB.squares[r][c] == Player.Open) {
OpenSpaces.add(new Space(r,c));
}
}
}
return OpenSpaces;
}
private static Space bestMove;
private static Space currentMove;
private static Space previousMove;
private static void MakeMove(List<Space> OpenSpaces) {
if(OpenSpaces.size() == currentBoard.Size) {
Random random = new Random();
bestMove = new Space(random.nextInt(2),2);
} else {
for(Space child: OpenSpaces) {
currentMove = GetBestMove(currentBoard,botPlayer);
if (currentMove != null){
}else{
continue;}
if(previousMove != null && previousMove.Rank < currentMove.Rank ||
previousMove == null && currentMove != null) {
bestMove = currentMove;
}
previousMove = currentMove;
}
}
if (bestMove != null) {
currentBoard.squares[bestMove.X][bestMove.Y] = botPlayer;
System.out.println("the best move is: " + currentMove.X + " " + currentMove.Y);
}
}
private static Space GetBestMove(GameBoard gb, Player p) {
Space bestSpace = null;
List<Space> cloneOpenSpaces = getOpenSquares(gb);
GameBoard cloneBoard = null;
cloneBoard = gb.Clone();
for(Space Open: cloneOpenSpaces) {
cloneBoard = gb.Clone();
Space newSpace = Open;
cloneBoard.squares[newSpace.X][newSpace.Y] = p;
if(cloneBoard.Winner == Player.Open && cloneOpenSpaces.size() > 0) {
Player InP;
if(p == Player.X) {
InP = Player.O;
}else {
InP = Player.X;
}
Space tempMove = GetBestMove(cloneBoard, InP);
if(tempMove != null){
newSpace.Rank = tempMove.Rank;
}
} else {
if(cloneBoard.Winner == Player.Open) {
newSpace.Rank = 0;
}else if(cloneBoard.Winner == Player.O) {
newSpace.Rank = -1;
}else if(cloneBoard.Winner == Player.X) {
newSpace.Rank = 1;
}
}
System.out.println(newSpace.Rank);
if(bestSpace == null ||
(p == Player.X && newSpace.Rank < ((Space)bestSpace).Rank)||
(p == Player.O && newSpace.Rank > ((Space)bestSpace).Rank)) {
bestSpace = newSpace;
}
}
return (Space)bestSpace;
}
public static enum Player {
X (1),
O (-1),
Open (0);
private final double value;
Player(double value){
this.value = value;
}
}
public static class Space {
public int X;
public int Y;
public double Rank;
public Space(int x, int y) {
this.X = x;
this.Y = y;
Rank = 0;
}
public Space() {
}
}
public static class GameBoard {
public int Rows;
public int getRows() {
return this.Rows;
}
public void setRows(int rows) {
Rows = rows;
}
public int Columns;
public int getColumns() {
return this.Columns;
}
public void setColumns(int columns) {
Columns = columns;
}
public Player[][] squares;
//public Player[x][y]
public Player getPlayer(int x, int y) {
return this.squares[x][y];
}
public void setPlayer(int x, int y, Player player) {
squares[x][y] = player;
}
public boolean Full;
public boolean isFull() {
for(int r = 0; r < 2; r++) {
for(int c = 0; c < 2; c++) {
if (squares[r][c] != Player.Open) {return false;}
}
}
return true;
}
public int Size;
public int getSize() {
return this.Size;
}
public void setSize(int size) {
Size = size;
}
public List<Space> OpenSquares;
public List<Space> getOpenSquares() {
List<Space> OpenSquares = new ArrayList<Space>();
for(int r = 0; r < Rows; r++) {
for(int c = 0; c < Columns; c++) {
if(squares[r][c] == Player.Open) {
OpenSquares.add(new Space(r,c));
}
}
}
return this.OpenSquares;
}
public Player Winner;
public Player getWinner() {
int count = 0;
//columns
for (int x = 0; x < Rows; x++)
{
count = 0;
for (int y = 0; y < Columns; y++) {
count += squares[x][y].value;
}
if (count == 3) {
return Player.X;
}else if (count == -3) {
return Player.O;
}
}
//rows
for (int x = 0; x < Rows; x++) {
count = 0;
for (int y = 0; y < Columns; y++) {
count += squares[y][x].value;
}
if (count == 3) {
return Player.X;
}else if (count == -3) {
return Player.O;
}
}
// Diagonals right to left
count = 0;
count += squares[0][0].value;
count += squares[1][1].value;
count += squares[2][2].value;
if (count == 3) {
return Player.X;
}else if (count == -3) {
return Player.O;
}
// Diagonals left to right
count = 0;
count += squares[0][2].value;
count += squares[1][1].value;
count += squares[2][0].value;
if (count == 3) {
return Player.X;
}else if (count == -3) {
return Player.O;
}
return Player.Open;
}
public GameBoard Clone() {
GameBoard b = new GameBoard(Rows,Columns);
b.squares = (Player[][])this.squares.clone();
b.Winner = getWinner();
return b;
}
// Class initializer
public GameBoard(int boardRows, int boardColumns, String[] board) {
// Set the dimensions
Rows = boardRows;
Columns = boardColumns;
// Create game spaces
squares = new Player[Rows][Columns];
for(int r = 0; r < Rows; r++) {
for(int c = 0; c < Columns; c++) {
//squares[i][n] = Player.Open;
if(board[r].charAt(c) == 'X') {
squares[r][c] = Player.X;
}
if(board[r].charAt(c) == 'O') {
squares[r][c] = Player.O;
}
if(board[r].charAt(c) == '_') {
squares[r][c] = Player.Open;
}
}
}
this.Winner = getWinner();
this.OpenSquares = getOpenSquares();
//Size of the board
this.Size = Rows * Columns;
}
// clone Class initializer
public GameBoard(int boardRows, int boardColumns) {
// Set the dimensions
Rows = boardRows;
Columns = boardColumns;
// Create game spaces
squares = new Player[Rows][Columns];
for(int r = 0; r < Rows; r++) {
for(int c = 0; c < Columns; c++) {
squares[r][c] = Player.Open;
}
}
this.Winner = getWinner();
this.OpenSquares = getOpenSquares();
//Size of the board
Size = Rows * Columns;
}
}
}
all of the classes are at the bottom. Thanks in advance for any help and corrections. :)
i made it recursive in the following code, although i still cant figure out the scoring.. if the value is either 1, 0, or -1 then if there are multipule moves with the same value it will just take the 1st one which may not be the best move "blocking.
private static Space GetBestMove(GameBoard gb, Player p) {
Space bestSpace = null;
List<Space> cloneOpenSpaces = getOpenSquares(gb);
GameBoard cloneBoard = null;
cloneBoard = gb.Clone();
for(Space Open: cloneOpenSpaces) {
cloneBoard = gb.Clone();
Space newSpace = Open;
cloneBoard.squares[newSpace.X][newSpace.Y] = p;
if(cloneBoard.Winner == Player.Open && cloneOpenSpaces.size() > 0) {
Player InP;
if(p == Player.X) {
InP = Player.O;
}else {
InP = Player.X;
}
***Space tempMove = GetBestMove(cloneBoard, InP);***
if(tempMove != null){
newSpace.Rank = tempMove.Rank;
}
the results of the test are as follows
test 1
ENTER bot:
O
ENTER board:
[ ][O][ ]
ENTER board:
[ ][ ][ ]
ENTER board:
[ ][X][X]
-1.0
-1.0
-1.0
-1.0
-1.0
-1.0
-1.0
-1.0
-1.0
the best move is: 0 2
test 2
ENTER bot:
O
ENTER board:
[ ][X][X]
ENTER board:
[ ][ ][ ]
ENTER board:
[ ][O][ ]
1.0
1.0
1.0
1.0
1.0
-1.0
1.0
-1.0
-1.0
1.0
-1.0
1.0
1.0
-1.0
-1.0
the best move is: 1 1
I haven't ran your code, but I think I may know why you are having issues. The minimax algorithm is recursive in nature. You look at each open space, and determine some sort of score for each one. I see this in your code. However, what I don't see is the recursion that equates to the logic "if I move here, then what options will my opponent have during his next turn". Notice that you can keep calling the same scoring function, but scoring both players' options. This is where the computation can get intensive, and where stuff like pruning comes into play. Say I want to look 3 moves ahead. Say there are initially 5 open spaces. For each of the 5 open spaces, I examine my options and give a score to each one. Then I pretend to move there, and send the new board through the scoring function, and assume my opponent will take the highest scoring move of the remaining 4 possible moves. Then I pretend he moves there, and I again run the board through the scoring function, now with 2 hypothetical moves on it. You continue this for a set "depth", or number of potential moves, and pick the move that results in the highest value, assuming the opponent will do what you calculated they would.
I realize this was long-winded, but I hope there was a little bit of value buried in there somewhere. Take a look at your code, figure out where you are scoring moves (if you see a win, take it; if you can block a win, take it; etc.). Then continue calling this function where you keep adding fake/potential moves (those with the highest value from your scoring function), and once you reach the depth, you can simply pick the move that is likely to give you the most valuable outcome.
Basically, in your code, you should call GetBestMove(...) once from MakeMove(...). However, GetBestMove(...) should repeatedly call itself, with a modified board each time; and each time, it will return the best move given a hypothetical (or real) board. What I don't see in your code is that recursive call to GetBestMove(...), and the necessary upkeep that goes along with it. This explains why you only get aggressive behavior; it only looks to see what the best immediate move is, without any regard to what your opponent might be able to do if you make that move!
If my assumptions are wrong, provide a test case where you expect some behavior, but are getting something different.