The purpose of the program is to generate a two-dimensional grid array made of periods ( . ). The user designates a starting point for the 'walker' which is marked by 'A', and then the walker will generate numbers from 0-3 to represent the four cardinal directions. It will move in these random directions while incrementing the alphabet with each mark it leaves until it either runs in to the wall and is "arrested" or reaches 'Z' at which it "made it home". If it runs in to a space it has already been to, it has to jump ahead in the same direction until it reaches an empty space or hits the wall.
My problem now is that I have it on a counter to make sure it doesn't run past 'Z', and will "make it home" if it reaches that point. But even the movements that it is taking to avoid overwriting where it has already been are registering on the counter (which they shouldn't be), so its returning true even though it hasn't hit Z yet, and its also still calling my random number generator so its not keeping to the same direction when it tries to correct itself. It also seems to be occasionally even jumping over empty spaces.
The problem is in processing()
package walktester;
import java.lang.Math;
import java.util.Random;
import java.util.Scanner;
class DrunkWalker {
private char[][] walkgrid = new char[10][10];
private static int randNSEW;
private int randomnum;
private int startrow;
private int startcol;
private char alpha = 'A';
private int nextrow;
private int nextcol;
public DrunkWalker(int r, int c) {
startrow = r;
startcol = c;
nextrow = startrow;
nextcol = startcol;
for (int i = 0; i < 10; i ++) {
for (int j = 0; j < 10; j++)
walkgrid[i][j] = '.';
}
walkgrid[r][c] = alpha++;
}
public static void getRand(){
int x100 = 0;
double randomNum = 0.0;
randomNum = Math.random();
x100 = (int) (randomNum * 100);
randNSEW = x100 % 4;
}
public int getNextRow(){
return nextrow;
}
public int getNextCol(){
return nextcol;
}
public boolean processing(){
for(int i = 1; i < 26; i ++){
getRand();
if(randNSEW == 0){
nextcol--;
}
if(randNSEW == 1){
nextrow++;
}
if(randNSEW == 2){
nextcol++;
}
if(randNSEW == 3){
nextrow--;
}
if(nextrow < 0 || nextrow >= 10 || nextcol < 0 || nextcol >= 10) {
return false;
}
if(randNSEW == 0 && walkgrid[nextrow][nextcol] != '.'){
nextcol--;
continue;
}
if(randNSEW == 1 && walkgrid[nextrow][nextcol] != '.'){
nextrow++;
continue;
}
if(randNSEW == 2 && walkgrid[nextrow][nextcol] != '.'){
nextcol++;
continue;
}
if(randNSEW == 3 && walkgrid[nextrow][nextcol] != '.'){
nextrow--;
continue;
}
walkgrid[nextrow][nextcol] = alpha++;
}
return true;
}
public char[][] DisplayGrid() {
for(int y = 0; y < 10; y++) {
for(int x = 0; x < 10; x++) {
System.out.print(walkgrid[x][y] + " ");
}
System.out.println();
}
return walkgrid;
}
}
public class WalkTester {
public static void main(String[] args) {
Scanner inpr = new Scanner(System.in);
Scanner inpc = new Scanner(System.in);
Scanner inpchoice = new Scanner(System.in);
int r = 0;
int c = 0;
char choice = 'y';
while(choice == 'y' || choice == 'Y') {
System.out.println("Please enter x coordinate between 1 and 10.");
r = inpr.nextInt();
r = r - 1;
System.out.println("Please enter y coordinate between 1 and 10");
c = inpr.nextInt();
c = c - 1;
if(r < 0 || r > 9 || c < 0 || c > 9){
System.out.println("Invalid Entry. Restart? y/n");
choice = inpchoice.next().charAt(0);
if(choice == 'y' || choice == 'Y'){
continue;
}
else if(choice == 'n' || choice == 'N'){
return;
}
else{
System.out.println("Invalid Entry. Restart? y/n");
choice = inpchoice.next().charAt(0);
}
}
DrunkWalker drunkwalker = new DrunkWalker(r, c);
boolean walkerSucceeded = drunkwalker.processing();
drunkwalker.DisplayGrid();
if(walkerSucceeded) {
System.out.println("You made it home");
} else {
System.out.println("You were arrested");
}
System.out.println("Restart? y/n");
choice = inpchoice.next().charAt(0);
if(choice == 'y' || choice == 'Y'){
continue;
}
else if(choice == 'n' || choice == 'N'){
return;
}
else{
System.out.println("Invalid Entry. Restart? y/n");
choice = inpchoice.next().charAt(0);
}
}
}
}
The following code fixes your problems. You basically did not have 'state' distinguishing a valid move, vs. moving to 'jump' over past visit points. I tried to keep the code as close as possible to your existing code.
class DrunkWalker {
private char[][] walkgrid = new char[10][10];
private static int randNSEW;
private int randomnum;
private int startrow;
private int startcol;
private char alpha = 'A';
private int nextrow;
private int nextcol;
public DrunkWalker(int r, int c) {
startrow = r;
startcol = c;
nextrow = startrow;
nextcol = startcol;
for (int i = 0; i < 10; i ++) {
for (int j = 0; j < 10; j++)
walkgrid[i][j] = '.';
}
walkgrid[r][c] = alpha++;
}
public static void getRand(){
int x100 = 0;
double randomNum = 0.0;
randomNum = Math.random();
x100 = (int) (randomNum * 100);
randNSEW = x100 % 4;
}
public int getNextRow(){
return nextrow;
}
public int getNextCol(){
return nextcol;
}
enum Mode {WALKING, CORRECTING};
Mode mode = Mode.WALKING;
public boolean processing(){
for(int i = 1; i < 26; i ++){
if (mode == Mode.WALKING) {
getRand();
if(randNSEW == 0){
nextcol--;
}
if(randNSEW == 1){
nextrow++;
}
if(randNSEW == 2){
nextcol++;
}
if(randNSEW == 3){
nextrow--;
}
}
if(nextrow < 0 || nextrow >= 10 || nextcol < 0 || nextcol >= 10) {
return false;
}
if(randNSEW == 0 && walkgrid[nextrow][nextcol] != '.'){
i--;
nextcol--;
mode = Mode.CORRECTING;
continue;
}
if(randNSEW == 1 && walkgrid[nextrow][nextcol] != '.'){
i--;
nextrow++;
mode = Mode.CORRECTING;
continue;
}
if(randNSEW == 2 && walkgrid[nextrow][nextcol] != '.'){
i--;
nextcol++;
mode = Mode.CORRECTING;
continue;
}
if(randNSEW == 3 && walkgrid[nextrow][nextcol] != '.'){
i--;
nextrow--;
mode = Mode.CORRECTING;
continue;
}
mode = Mode.WALKING;
walkgrid[nextrow][nextcol] = alpha++;
}
return true;
}
Related
As of right now, I added an if statement to calculate whether there already is a character in a specific place in the TicTacToe gameboard, which mostly works, but it still has some issues because it only works once. That means that if I enter the row and column and there already is a character at that specific row and column, it will prevent me from placing it, which is what I intended, although if I place it incorrectly twice, it no longer works and lets me overwrite the character in that specific place.
I already tried doing this using a while loop, and it didn't succeed as it kept saying every input I entered is invalid.
What I want to prevent is the overwriting of characters in the gameboard, for example if there already is an X at row 0, column 1, if I enter row 0 and column 1 the program should prevent me from placing the X there an infinite number of times.
Main
import java.util.Random;
import java.util.Scanner;
import java.util.InputMismatchException;
class Main {
public static void main(String[] args) {
Board b = new Board();
Scanner sc = new Scanner(System.in);
int count = 0;
char p = 'X';
int r = -1;
int c = -1;
//introduction to game
System.out.println("-----------------------------------------------------------------");
System.out.println(" Welcome ");
System.out.println("-----------------------------------------------------------------");
System.out.println(" to ");
System.out.println("-----------------------------------------------------------------");
System.out.println(" my ");
System.out.println("-----------------------------------------------------------------");
System.out.println(" TicTacToe ");
System.out.println("-----------------------------------------------------------------");
System.out.println(" program!!! ");
System.out.println("-----------------------------------------------------------------");
boolean error = false;
boolean playing = true;
while(playing){
b.print();
if(count % 2 == 0)
{
do {
error = false;
try {
System.out.println("Your turn:");
p = 'X';
System.out.print("Enter row:");
r = sc.nextInt();
while(r < 0 || r > 2)
{
System.out.println("Sorry, please enter a number that is ONLY in-between 0 and 2.");//sc.nextLine();
System.out.print("Enter row:");
r = sc.nextInt();
if(r >= 0 && r <= 2)
{
break;
}
}
} catch(InputMismatchException e) {
error = true;
System.out.println("Sorry, please enter a number in-between 0 and 2.");
sc.nextLine();
}
}while(error);
do{
error = false;
try {
System.out.print("Enter column:");
c = sc.nextInt();
while(c < 0 || c > 2)
{
System.out.println("Sorry, please enter a number that is ONLY in-between 0 and 2.");//sc.nextLine();
System.out.print("Enter column:");
c = sc.nextInt();
if(c >= 0 && c <= 2)
{
break;
}
}
} catch(InputMismatchException e) {
error = true;
System.out.println("Sorry, please enter a number in-between 0 and 2.");
sc.nextLine();
}
}while(error);
if(b.fullSpace(p)) {
System.out.println("Invalid input, try again.");
System.out.print("Enter row:");
r = sc.nextInt();
System.out.print("Enter column:");
c = sc.nextInt();
}else if(b.emptySpace()) {
System.out.println("You've made it here!");
//break;
}
} else if(count % 2 == 1) {
System.out.println("Computer's turn:");
p = 'O';
Random rand = new Random();
r = rand.nextInt(2 - 0 + 1) + 0;
c = rand.nextInt(2 - 0 + 1) + 0;
//int computer = rand.nextInt();
}
/*if(getWinner()) {
System.out.println("You won!");
playing = false;
}
*/
//if statement for only X's turn
//ai that picks a random number from 0 to 2
b.move(p,r,c);
if(b.isWinner('X') || b.isWinner('O') || b.isTied())
playing = false;
count++;
}
b.print();
if(b.isWinner('X')) {
System.out.println("You win! Congratulations!");
}
if(b.isWinner('O')) {
System.out.println("Computer wins! Boohoo!");
}
if(b.isTied()) {
System.out.println("Nobody wins! It's a tie!");
}
}
}
Board
import java.util.Random;
public class Board {
private char[][] board = new char[3][3];
public Board(){
for(int r = 0; r < 3; r++){
for(int c = 0; c < 3; c++){
board[r][c] = ' ';
}
}
}
public void move(char p, int r, int c){
board[r][c] = p;
while(board[r][c] == 'X' || board[r][c] == 'O')
{
Random randTwo = new Random();
r = randTwo.nextInt(2 - 0 + 1) + 0;
c = randTwo.nextInt(2 - 0 + 1) + 0;
if(board[r][c] != 'X' || board[r][c] != 'O') {
break;
}
}
}
public char get(int r, int c){
return board[r][c];
}
public void print(){
for(int r = 0; r < 3;r++){
for(int c = 0; c < 3;c++){
System.out.print("[" + board[r][c] + "]");
}
System.out.println();
}
}
public boolean isWinner(char p){
for(int r = 0; r < 3; r++) {
if(board[r][0] == p && board[r][1] == p && board[r][2] == p) {
return true;
}
}
for(int c = 0; c < 3; c++) {
if(board[0][c] == p && board[1][c] == p && board[2][c] == p) {
return true;
}
}
if(board[0][0] == p && board[1][1] == p && board[2][2] == p) {
return true;
} else if(board[0][2] == p && board[1][1] == p && board[2][0] == p) {
return true;
}
return false;
}
public boolean isTied(){
for(int r = 0; r < 3; r++) {
for(int c = 0; c < 3; c++) {
if(board[r][c] == ' ') {
return false;
}
}
}
return true;
}
public boolean fullSpace(char p) {
for(int r = 0; r < 3; r++) {
for(int c = 0; c < 3; c++) {
if(board[r][c] == p) {
return true;
}
}
}
return false;
}
public boolean emptySpace() {
for(int r = 0; r < 3; r++) {
for(int c = 0; c < 3; c++) {
if(board[r][c] == ' ') {
return true;
}
}
}
return false;
}
}
How do I prevent the same tic tac toe coordinate from being inputted by the user?
The user input is taken at the main method in the Game Class.
The tic tac toe cells with [x, y] coordinates ranging from (0-2) can be either:
0(_), 1 (X) or 2 (O)
Grid Class with alpha beta search tree pruning algorithm
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
class Grid {
List<Cell> availableCells;
int[][] board = new int[3][3];
Scanner scan = new Scanner(System.in);
// Set limit to search tree depth
int treeDepth = 9;
List<CellsAndScores> rootsChildrenScore = new ArrayList<>();
public int score() {
int score = 0;
// Check all columns
for (int j = 0; j < 3; ++j) {
int X = 0;
int O = 0;
for (int i = 0; i < 3; ++i) {
if (board[i][j] == 0) {
} else if (board[i][j] == 1) {
X++;
} else {
O++;
}
}
score += changeInScore(X, O);
}
// Check all rows
for (int i = 0; i < 3; ++i) {
int X = 0;
int O = 0;
for (int j = 0; j < 3; ++j) {
if (board[i][j] == 0) {
} else if (board[i][j] == 1) {
X++;
} else {
O++;
}
}
score += changeInScore(X, O);
}
int X = 0;
int O = 0;
// Check diagonal (first)
for (int i = 0, j = 0; i < 3; ++i, ++j) {
if (board[i][j] == 1) {
X++;
} else if (board[i][j] == 2) {
O++;
} else {
}
}
score += changeInScore(X, O);
X = 0;
O = 0;
// Check Diagonal (Second)
for (int i = 2, j = 0; i > -1; --i, ++j) {
if (board[i][j] == 1) {
X++;
} else if (board[i][j] == 2) {
O++;
} else {
}
}
score += changeInScore(X, O);
return score;
}
private int changeInScore(int X, int O) {
int change;
if (X == 3) {
change = 100;
} else if (X == 2 && O == 0) {
change = 10;
} else if (X == 1 && O == 0) {
change = 1;
} else if (O == 3) {
change = -100;
} else if (O == 2 && X == 0) {
change = -10;
} else if (O == 1 && X == 0) {
change = -1;
} else {
change = 0;
}
return change;
}
public int alphaBetaMinimax(int alpha, int beta, int depth, int turn) {
if (beta <= alpha) {
System.out.println("Pruning at tree depth = " + depth + " alpha: " + alpha + " beta: " + beta);
if (turn == 1)
return Integer.MAX_VALUE;
else
return Integer.MIN_VALUE;
}
if (depth == treeDepth || gameOver()) {
return score();
}
List<Cell> cellsAvailable = getAvailableStates();
if (cellsAvailable.isEmpty()) {
return 0;
}
if (depth == 0) {
rootsChildrenScore.clear();
}
int maxValue = Integer.MIN_VALUE, minValue = Integer.MAX_VALUE;
for (int i = 0; i < cellsAvailable.size(); ++i) {
Cell cell = cellsAvailable.get(i);
int currentScore = 0;
if (turn == 1) {
placeAMove(cell, 1);
currentScore = alphaBetaMinimax(alpha, beta, depth + 1, 2);
maxValue = Math.max(maxValue, currentScore);
// Set alpha
alpha = Math.max(currentScore, alpha);
if (depth == 0) {
rootsChildrenScore.add(new CellsAndScores(currentScore, cell));
}
} else if (turn == 2) {
placeAMove(cell, 2);
currentScore = alphaBetaMinimax(alpha, beta, depth + 1, 1);
minValue = Math.min(minValue, currentScore);
// Set beta
beta = Math.min(currentScore, beta);
}
// reset board
board[cell.x][cell.y] = 0;
// Do not evaluate the rest of the branches after search tree is pruned
if (currentScore == Integer.MAX_VALUE || currentScore == Integer.MIN_VALUE)
break;
}
return turn == 1 ? maxValue : minValue;
}
public boolean gameOver() {
// Game is over is someone has won, or board is full (draw)
return (hasXWon() || hasOWon() || getAvailableStates().isEmpty());
}
public boolean hasXWon() {
if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == 1)
|| (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] == 1)) {
// System.out.println("X Diagonal Win");
return true;
}
for (int i = 0; i < 3; ++i) {
if (((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 1)
|| (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 1))) {
// System.out.println("X Row or Column win");
return true;
}
}
return false;
}
public boolean hasOWon() {
if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == 2)
|| (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] == 2)) {
// System.out.println("O Diagonal Win");
return true;
}
for (int i = 0; i < 3; ++i) {
if ((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 2)
|| (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 2)) {
// System.out.println("O Row or Column win");
return true;
}
}
return false;
}
public List<Cell> getAvailableStates() {
availableCells = new ArrayList<>();
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (board[i][j] == 0) {
availableCells.add(new Cell(i, j));
}
}
}
return availableCells;
}
public void placeAMove(Cell Cell, int player) {
board[Cell.x][Cell.y] = player; // player = 1 for X, 2 for O
}
public Cell returnBestMove() {
int MAX = -100000;
int best = -1;
for (int i = 0; i < rootsChildrenScore.size(); ++i) {
if (MAX < rootsChildrenScore.get(i).score) {
MAX = rootsChildrenScore.get(i).score;
best = i;
}
}
return rootsChildrenScore.get(best).cell;
}
public void displayBoard() {
System.out.println();
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (board[i][j] == 0)
System.out.print("_" + " ");
if (board[i][j] == 1)
System.out.print("X" + " ");
if (board[i][j] == 2)
System.out.print("O" + " ");
}
System.out.println("");
}
System.out.println();
}
public void resetGrid() {
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
board[i][j] = 0;
}
}
}
}
Cell class
class Cell {
int x, y;
public Cell(int x, int y) {
this.x = x;
this.y = y;
}
public String toString() {
return "[" + x + ", " + y + "]";
}
}
class CellsAndScores {
int score;
Cell cell;
CellsAndScores(int score, Cell cell) {
this.score = score;
this.cell = cell;
}
}
Game Class with main method - takes user input
import java.util.Random;
public class Game {
public static void main(String[] args) {
Grid grid = new Grid();
Random random = new Random();
grid.displayBoard();
System.out.print("Who moves first? [1]Computer(X) [2]User(O): ");
int turn = grid.scan.nextInt();
if (turn == 1) {
Cell p = new Cell(random.nextInt(3), random.nextInt(3));
grid.placeAMove(p, 1);
grid.displayBoard();
}
while (!grid.gameOver()) {
int x = 0, y = 0;
System.out.print("Please enter an x coordinate [0-2]: ");
x = grid.scan.nextInt();
System.out.print("Please enter an y coordinate [0-2]: ");
y = grid.scan.nextInt();
Cell userMove = new Cell(y, x);
grid.placeAMove(userMove, 2); // 2 for O and O is the user
grid.displayBoard();
if (grid.gameOver())
break;
grid.alphaBetaMinimax(Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 1);
for (CellsAndScores pas : grid.rootsChildrenScore)
System.out.println("Cell: " + pas.cell + " Score: " + pas.score);
grid.placeAMove(grid.returnBestMove(), 1);
grid.displayBoard();
}
if (grid.hasXWon()) {
System.out.println("Unfortunately, you lost!");
grid.resetGrid();
} else if (grid.hasOWon()) {
System.out.println("You win!");
grid.resetGrid();
} else {
System.out.println("It's a draw!");
grid.resetGrid();
}
}
}
My answer would be to add a boolean check method into your Grid.java class and then in your main method - call this boolean check method before the placeAMove() method.
For example, in your Grid.java class, adding the following method:
/*
* Return true if space is ok to use.
*/
public boolean isMoveOK(Cell cell) {
return board[cell.x][cell.y] == 0;
}
This way, using your pre-existing 0/1/2 values that keep track of empty/X/O space values, you may provide a check to see if the space value is zero or not.
This would be one way to use it in your main method, to answer your question of, 'How do I prevent the same tic tac toe coordinate from being inputted by the user?'
Cell userMove = new Cell(y, x);
if (grid.isMoveOK(userMove)) {
grid.placeAMove(userMove, 2); // 2 for O and O is the user
} else {
System.out.println("Please try a different space/cell");
continue;
}
grid.displayBoard();
if (grid.gameOver())
break;
In this way, I am skipping the remaining loop code in your main method loop, until there's a valid open space. (When there is, then the program should proceed to check for winning values or whether to proceed playing)
Hope this answers your question! :)
Cheers
My checkTie method in my TicTacToe program doesn't work and results in an out of bounds array and I can't see why.
Running this code will print the board and allow the game to run until either someone wins, or there are 3 _'s left and then it will end the game.
I'm not sure why that happens though, I believe it has something to do with my checkTie for loop. Also, if a tie was to occur either nothing happens or an Array out of bounds happens.
import java.util.Scanner;
public class TicTac {
public static int row, col;
public static Scanner scan = new Scanner(System.in);
public static char[][] board = new char[3][3];
public static char turn = 'X';
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = '_';
}
}
Play();
}
public static boolean Play() {
boolean playing = true;
PrintBoard();
while (playing) {
System.out.println();
System.out.print("Please enter row: ");
row = scan.nextInt() - 1;
System.out.print("Please enter column: ");
col = scan.nextInt() - 1;
board[row][col] = turn;
if (GameOver(row, col)) {
playing = false;
System.out.println("Game Over! Player " + turn + " wins!");
**I feel like this code below is where the problem is**
if (checkTie(board)) {
System.out.println("Tie Game!");
return true;
}
}
PrintBoard();
if (turn == 'X')
turn = '0';
else
turn = 'X';
}
return false;
}
public static void PrintBoard() {
for (int i = 0; i < 3; i++) {
System.out.println();
for (int j = 0; j < 3; j++) {
if (j == 0)
System.out.print("| ");
System.out.print(board[i][j] + " | ");
}
}
System.out.println();
}
public static boolean GameOver(int rMove, int cMove) {
// Check if perpendicular victory
if (board[0][cMove] == board[1][cMove] && board[0][cMove] == board[2][cMove])
return true;
if (board[rMove][0] == board[rMove][1] && board[rMove][0] == board[rMove][2])
return true;
// Check Diagonal Victory
if (board[0][2] == board[1][1] && board[0][0] == board[2][2] && board[1][1] != '_')
return true;
if (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[1][1] != '_')
return true;
return false;
}
This is where the method to see if the game result is a tie.
public static boolean checkTie(char[][] board) {
int spacesLeft = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j] == '_') {
spacesLeft++;
}
}
}
if (spacesLeft == 0) {
return true;
} else {
return false;
}
}
}
I think you meant to do checkTie when gameOver returns false'. As things stand,checkTieis only ever called aftergameOver' has returned `true'.
EDIT: I don't know why somebody links me a TicTacToe as duplicate for my question, there isn't even a MinMax-Algorithm in it.
Currently i'm working on a Connect4 game against the computer which should use the MinMax-Algorithm.
Before that, we wrote a TicTacToe which also uses the MinMax, but i'm not sure how to change my old algorithm to match the Connect4-Game :/.
In TicTacToe i evaluated each possible move with the win-conditions i wrote, it worked fine, but now it won't work with my new conditions.
My makeAMove etc. works fine!
These are my old conditions and the MinMax for TicTacToe:
//Player 1 wins
static boolean has1Won(int[][] array) {
gameBoard = array;
//Diagonal
if ((gameBoard[0][0] == gameBoard[1][1] && gameBoard[0][0] == gameBoard[2][2] && gameBoard[0][0] == 1)
|| (gameBoard[0][2] == gameBoard[1][1] && gameBoard[0][2] == gameBoard[2][0] && gameBoard[0][2] == 1)) {
return true;
}
//Spalten/Zeilen
for (int i = 0; i < 3; ++i) {
if (((gameBoard[i][0] == gameBoard[i][1] && gameBoard[i][0] == gameBoard[i][2] && gameBoard[i][0] == 1)
|| (gameBoard[0][i] == gameBoard[1][i] && gameBoard[0][i] == gameBoard[2][i] && gameBoard[0][i] == 1))) {
return true;
}
}
return false;
}
// Player 2 wins
static boolean has2Won(int[][] array) {
gameBoard = array;
//Diagonal
if ((gameBoard[0][0] == gameBoard[1][1] && gameBoard[0][0] == gameBoard[2][2] && gameBoard[0][0] == 2)
|| (gameBoard[0][2] == gameBoard[1][1] && gameBoard[0][2] == gameBoard[2][0] && gameBoard[0][2] == 2)) {
return true;
}
//Spalten/Zeilen
for (int i = 0; i < 3; ++i) {
if (((gameBoard[i][0] == gameBoard[i][1] && gameBoard[i][0] == gameBoard[i][2] && gameBoard[i][0] == 2)
|| (gameBoard[0][i] == gameBoard[1][i] && gameBoard[0][i] == gameBoard[2][i] && gameBoard[0][i] == 2))) {
return true;
}
}
return false;
}
As I said, i used these conditions for my MinMax like this:
public static int minimax(int depth, int turn) {
if (Board.has1Won(Board.gameBoard)){
return +1; // Der Computer gewinnt
}
if (Board.has2Won(Board.gameBoard)){
return -1; // Der Spieler gewinnt
}
List<GameMove> gameMovesAvailable = GameMove.getAvailableGameMoves();
if (gameMovesAvailable.isEmpty()){
return 0; // Das Spiel endet unentschieden
}
...
I'm not sure how i can get this to work with my new conditions:
I think i have to write an evaluating function which checks this for example (this is my wincondition for Rows):
boolean getWinnerInRow (Playboard brd){
int count = 0;
for (int i = 0; i < 6; i++){
for (int j = 0; j < 7; j++){
if (brd.gameBoard[i][j] != 0 && brd.gameBoard[i][j] == brd.gameBoard[i][j+1]){
count++;
} else {
count = 1;
}
if (count >= 4){
return true;
}
}
}
return false;
I know it's a lot of text, but maybe somebody can give me some useful tips :)
Thanks!
Max
I'm not sure that your test to find the winner is correct. Try this (you'll need to change it a little bit, but at least I'm sure that it's correct):
public static boolean testWinner(int[][] game, int lastColumn, Integ e) {
int lastRow = 0;
while (lastRow < 6 && game[lastRow][lastColumn] == 0) {
lastRow++;
}
lastRow = lastRow;
int i = 0;
int j = 0;
int currentPlayer = game[lastRow][lastColumn];
e.setI(currentPlayer);
int sequence = 0;
i = lastRow;
boolean b = i < 3
&& game[i][lastColumn] == currentPlayer
&& game[i+1][lastColumn] == currentPlayer
&& game[i+2][lastColumn] == currentPlayer
&& game[i+3][lastColumn] == currentPlayer;
if(b) {
return true;
}
sequence = 0;
j = lastColumn;
do {
j--;
} while(0 < j && game[lastRow][j] == currentPlayer);
if(j < 0 || game[lastRow][j] != currentPlayer) {
j++;
}
while(j <= 6 && game[lastRow][j] == currentPlayer) {
j++;
sequence++;
}
if (sequence >= 4) {
return true;
}
sequence = 0;
i = lastRow;
j = lastColumn;
do {
i--;
j--;
} while(0 < i && 0 < j && game[i][j] == currentPlayer);
if(i < 0 || j < 0 || game[i][j] != currentPlayer) {
i++;
j++;
}
while(i <= 5 && j <= 6 && game[i][j] == currentPlayer) {
i++;
j++;
sequence++;
}
if (sequence >= 4) {
return true;
}
sequence = 0;
i = lastRow;
j = lastColumn;
do {
i++;
j--;
} while(i < 5 && 0 < j && game[i][j] == currentPlayer);
if (5 < i || j < 0 || game[i][j] != currentPlayer) {
i--;
j++;
}
while(0 <= i && j <= 6 && game[i][j] == currentPlayer) {
i--;
j++;
sequence++;
}
if (sequence >= 4) {
return true;
}
return false;
}
Integ is just a class with an integer. I've created it because the wrapper is not really an object (can't pass by reference).
private static class Integ {
private int i;
public Integ() {
this.i = 0;
}
public void increment() {
this.i = this.i + 1;
}
public int getI() {
return this.i;
}
public void setI(int i) {
this.i = i;
}
}
The purpose of this program is to build a 10x10 array grid made out of periods (.), allow the user to designate a starting point, and then the program will randomly choose numbers which are assigned to directions for the 'walker' to go. Each time it moves it marks its spot with the next letter in the alphabet (the starting point is marked by A). If the walker crosses out of the bounds of the array (AKA > 10 or < 0) it will say "you were arrested" and if the variable alpha == 'Z' it way say "You made it home".
The only thing I have left to do is make it so that if the walker tries to go back to a spot it has already been to, it will skip to the next space until it reaches a space it hasn't been.
package walktester;
import java.lang.Math;
import java.util.Random;
import java.util.Scanner;
class DrunkWalker {
private char[][] walkgrid = new char[10][10];
private static int randNSEW;
private int randomnum;
private int startrow;
private int startcol;
private char alpha = 'A';
private int nextrow;
private int nextcol;
public DrunkWalker(int r, int c) {
startrow = r;
startcol = c;
nextrow = startrow;
nextcol = startcol;
for (int i = 0; i < 10; i ++) {
for (int j = 0; j < 10; j++)
walkgrid[i][j] = '.';
}
walkgrid[r][c] = alpha++;
}
public static void getRand(){
int x100 = 0;
double randomNum = 0.0;
randomNum = Math.random();
x100 = (int) (randomNum * 100);
randNSEW = x100 % 4;
}
public int getNextRow(){
return nextrow;
}
public int getNextCol(){
return nextcol;
}
public boolean processing(){
for(int i = 0; i < 25; i ++){
getRand();
if(randNSEW == 0){
nextcol--;
}
if(randNSEW == 1){
nextrow++;
}
if(randNSEW == 2){
nextcol++;
}
if(randNSEW == 3){
nextrow--;
}
if(nextrow < 0 || nextrow >= 10 || nextcol < 0 || nextcol >= 10) {
return false;
}
walkgrid[nextrow][nextcol] = alpha++;
}
return true;
}
public char[][] DisplayGrid() {
for(int y = 0; y < 10; y++) {
for(int x = 0; x < 10; x++) {
System.out.print(walkgrid[x][y] + " ");
}
System.out.println();
}
return walkgrid;
}
}
public class WalkTester {
public static void main(String[] args) {
Scanner inpr = new Scanner(System.in);
Scanner inpc = new Scanner(System.in);
Scanner inpchoice = new Scanner(System.in);
int r = 0;
int c = 0;
char choice = 'y';
while(choice == 'y' || choice == 'Y') {
System.out.println("Please enter x coordinate between 1 and 10.");
r = inpr.nextInt();
r = r - 1;
System.out.println("Please enter y coordinate between 1 and 10");
c = inpr.nextInt();
c = c - 1;
if(r < 0 || r > 9 || c < 0 || c > 9){
System.out.println("Invalid Entry. Restart? y/n");
choice = inpchoice.next().charAt(0);
if(choice == 'y' || choice == 'Y'){
continue;
}
else if(choice == 'n' || choice == 'N'){
return;
}
else{
System.out.println("Invalid Entry. Restart? y/n");
choice = inpchoice.next().charAt(0);
}
}
DrunkWalker drunkwalker = new DrunkWalker(r, c);
boolean walkerSucceeded = drunkwalker.processing();
drunkwalker.DisplayGrid();
if(walkerSucceeded) {
System.out.println("You made it home");
} else {
System.out.println("You were arrested");
}
System.out.println("Restart? y/n");
choice = inpchoice.next().charAt(0);
if(choice == 'y' || choice == 'Y'){
continue;
}
else if(choice == 'n' || choice == 'N'){
return;
}
else{
System.out.println("Invalid Entry. Restart? y/n");
choice = inpchoice.next().charAt(0);
}
}
}
}
By "skip to the next space until it reaches a space" I assume you mean they continue on in the same direction.
So, just before you do:
walkgrid[nextrow][nextcol] = alpha++;
you need to check:
if (walkgrid[nextrow][nextcol] == '.')
so something along these lines:
...
do {
if (randNSEW == 0) nextcol--;
if (randNSEW == 1) nextrow++;
if (randNSEW == 2) nextcol++;
if (randNSEW == 3) nextrow--;
if ((nextrow < 0) || (nextrow >= 10) || (nextcol < 0) || (nextcol >= 10)) {
return false;
}
if (walkgrid[nextrow][nextcol] == '.') continue; /* try next */
walkgrid[nextrow][nextcol] = alpha++;
} while (false);
Or we could rewrite those last three lines as:
} while (walkgrid[nextrow][nextcol] == '.');
walkgrid[nextrow][nextcol] = alpha++;