First time actually using the site so if I do anything wrong I apologize in advance and will work to correct it given guidance. I am currently working on my senior project. It is a game very similar to tic-tac-toe but the height and width of the board are of variable sizes and the amount in a row needed to win is also variable (all chosen by the user through jcomboboxes).
the problem is that the miniMax method will often select a tile that's already been chosen. I'm not entirely sure how to figure out the source of the problem, after having done quite a few hours of research. I just need to be pointed in the right direction on the means of finding the source but will gladly take any help I can get
attached below is the code. I provided all of the code for the program so that it can be compiled and tested, hopefully, with ease. If this is the wrong thing to do I apologize, let me know and I will correct.
I found various examples of the minimax algorithm being implemented and ended up using the one in the following link: simplest MiniMax algorithm for TicTacToe AI in Java
I also tried implementing the following: https://medium.com/#pelensky/unbeatable-tic-tac-toe-minimax-in-java-e1ad687ed821
but that led to numerous stackoverflow errors that I couldn't see how to reasonably mitigate without redoing the entire algorithm.
I am currently working with the former and it works to an extent but the AI doesn't appear to make intelligent decisions and will often try to choose a tile that's already been selected.
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;
public class Konnexion extends JPanel
{
ArrayList<JButton> buttons = new ArrayList<JButton>();
private static int totalButtons;
private JLabel winStat;
private JLabel lossStat;
protected JLabel drawStat;
JPanel gameBoard;
JButton exitButton;
int wins = 0;
int losses = 0;
int draws = 0;
Game game;
public Konnexion(int height, int width, int connects, String ai)
{
JPanel gameStats = new JPanel();
gameStats.setLayout(new GridLayout(1,3));
winStat = new JLabel("Wins: " + wins);
lossStat = new JLabel("Losses: " + losses + " ");
drawStat = new JLabel("Draws: " + draws);
gameStats.add(winStat);
gameStats.add(lossStat);
gameStats.add(drawStat);
add(gameStats);
totalButtons = (height * width) - 1;
gameBoard = new JPanel();
gameBoard.setLayout(new GridLayout(height,width));
initializebuttons();
add(gameBoard);
JPanel menuButtons = new JPanel();
menuButtons.setLayout(new GridLayout(1,1));
exitButton = new JButton();
exitButton.setText("Exit Game");
exitButton.addActionListener(new buttonListener());
menuButtons.add(exitButton);
add(menuButtons);
game = new Game(totalButtons, height, width, connects, ai);
}
public void initializebuttons()
{
for(int i = 0; i <= totalButtons; i++)
{
buttons.add(i, new JButton());
buttons.get(i).setText("");
buttons.get(i).setPreferredSize(new Dimension(75,75));
buttons.get(i).addActionListener(new buttonListener());
gameBoard.add(buttons.get(i));
}
}
public void resetButtons()
{
for(int i = 0; i <= totalButtons; i++)
{
buttons.get(i).setText("");
}
game.resetGameState();
}
private class buttonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
JButton buttonClicked = (JButton)e.getSource(); //get the particular button that was clicked
if (buttonClicked.getText().equals(""))
{
buttonClicked.setText(Game.getSymbol(game.getCurrentPlayer()));
game.setMarker(buttons.indexOf(buttonClicked), game.getSymbol(game.getCurrentPlayer()));
if (Game.getSymbol(game.getCurrentPlayer()).equals("X"))
{
game.changeCurrentPlayer();
if (game.hasWon("X", Game.cells)) {
wins++;
winStat.setText("Wins: " + wins);
JOptionPane.showConfirmDialog(null, "Player X Wins!!!");
resetButtons();
game.resetGameState();
}
}
else
{
game.changeCurrentPlayer();
if (game.hasWon("O", Game.cells)) {
losses++;
lossStat.setText("Losses: " + losses + " ");
JOptionPane.showConfirmDialog(null, "Player O Wins!!!");
resetButtons();
game.resetGameState();
}
}
if (game.getCurrentPlayer() == 2) {
game.printArrays();
game.copyGameState();
//System.out.println(game.miniMax(game.getCurrentPlayer()));
buttons.get(game.miniMax(game.getCurrentPlayer())).doClick();
}
}
else if (buttonClicked.equals(exitButton))
{
Window window = SwingUtilities.getWindowAncestor(exitButton);
window.dispose();
try {
new MainMenu();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
else
{
JOptionPane.showMessageDialog(buttonClicked, "That tile has already been selected!");
}
if (game.checkDraw())
{
draws++;
drawStat.setText("Draws: " + draws);
JOptionPane.showConfirmDialog(null, "It was a Draw!!!");
resetButtons();
}
}
}
}
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class Game {
public static int ROWS;
public static int COLS;
public static int WIN_SIZE;
public static int currentPlayer;
public static String[][] cells; //Game state array
String[][] node; //copy of the game state used for minimax method
public Game(int totalButtons, int height, int width, int connects, String difficulty) {
ROWS = height;
COLS = width;
WIN_SIZE = connects;
currentPlayer = 1;
cells = new String[ROWS][COLS];
node = new String[ROWS][COLS];
resetGameState(cells);
resetGameState(node);
}
public void setMarker(int space, String marker) {
int col = space % COLS;
int rows = space / COLS;
cells[rows][col] = marker;
}
public void changeCurrentPlayer() {
if (currentPlayer == 1)
{
currentPlayer = 2;
}
else if (currentPlayer == 2)
{
currentPlayer = 1;
}
}
public int getCurrentPlayer() {
return currentPlayer;
}
public static String getSymbol(int playerNum) {
if (playerNum == 1)
return "X";
else
return "O";
}
public void resetGameState() {
currentPlayer = 1;
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
cells[i][j] = "-";
}
}
}
public static void resetGameState(String[][] gameState) {
for (int i = 0; i < gameState.length; i++) {
for (int j = 0; j < gameState[i].length; j++) {
gameState[i][j] = "-";
}
}
}
/**
*
* #param theSeed Value expected in each cell
* #param row Row index to check
* #param col Col index to check
* #param count Number of consecutive elements found in the line.
* #param rowIncrement Increment to the row index for the next evaluation
* #param colIncrement Increment to the col index for the next evaluation
* #return true if there is a winner combination in the line, otherwise false.
*/
private boolean checkLine(String theSeed, int row, int col, int count, int rowIncrement, int colIncrement, String[][] gameCheck) {
if (!areValidIndexes(row, col)) {
return false;
}
if (theSeed.equals(gameCheck[row][col])) {
count++;
if (count >= WIN_SIZE) {
return true;
} else {
return checkLine(theSeed, row + rowIncrement, col + colIncrement, count, rowIncrement, colIncrement, gameCheck);
}
} else {
return false;
}
}
private boolean areValidIndexes(int row, int col) {
if (row >= 0 && row < ROWS &&
col >= 0 && col < COLS) {
return true;
}
return false;
}
private boolean checkRow(String theSeed, int row, int col, String[][] gameCheck) {
return checkLine(theSeed, row, col, 0, 1, 0, gameCheck);
}
private boolean checkColumn(String theSeed, int row, int col, String[][] gameCheck) {
return checkLine(theSeed, row, col, 0, 0, 1, gameCheck);
}
private boolean checkForwardDiagonal(String theSeed, int row, int col, String[][] gameCheck) {
return checkLine(theSeed, row, col, 0, 1, 1, gameCheck);
}
private boolean checkBackwardDiagonal(String theSeed, int row, int col, String[][] gameCheck) {
return checkLine(theSeed, row, col, 0, -1, 1, gameCheck);
}
public boolean hasWon(String theSeed, String[][] gameCheck) {
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
if (checkRow(theSeed, row, col, gameCheck) ||
checkColumn(theSeed, row, col, gameCheck) ||
checkForwardDiagonal(theSeed, row, col, gameCheck) ||
checkBackwardDiagonal(theSeed, row, col, gameCheck)) {
return true;
}
}
}
return false;
}
public boolean checkDraw()
{
String s = "";
for (String[] r : cells) {
for (String t : r) {
s += t;
}
}
if (!s.contains("-"))
{
return true;
}
return false;
}
public static boolean checkDraw(String[][] node)
{
String s = "";
for (String[] r : node) {
for (String t : r) {
s += t;
}
}
if (!s.contains("-"))
{
return true;
}
return false;
}
public int checkWin(String[][] gameState) {
if (hasWon("X", gameState))
{
return 1;
}
else if (hasWon("O", gameState))
{
return 2;
}
else
{
return 0;
}
}
public void copyGameState() {
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
node[i][j] = cells[i][j];
}
}
}
public static int[] getAvailableSpaces() {
String s = "";
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
if (cells[i][j].equals("-"))
s += ((j * COLS) + i) + ", ";
}
}
String[] split = s.split(", ");
int[] availableSpaces = new int[split.length];
for (int i = 0; i < split.length; i++)
availableSpaces[i] = Integer.parseInt(split[i]);
return availableSpaces;
}
public void resetSpace(int space) {
int col = space % COLS;
int rows = space / COLS;
cells[rows][col] = "-";
}
public int miniMax(int playerNum)
{
//printArrays();
int victor = checkWin(cells); // returns 0 if game is ongoing, 1 for p1, 2 for p2, 3 for tie.
if(victor != 0) //game over
{
return Score(victor);
}
if(playerNum == 2) //AI
{
int bestVal = Integer.MAX_VALUE;
int bestSpot = 0;
for(int i = 0; i < cells.length; i++)
for (int j = 0; j < cells[i].length; j++)
{
if(!cells[i][j].equals("-"))
continue;
cells[i][j] = getSymbol(playerNum);
int value = miniMax(1);
if(value < bestVal)
{
bestVal = value;
bestSpot = (j * COLS) + i;
System.out.println("Best Value: " + bestVal);
System.out.println("Best Spot: " + bestSpot);
}
cells[i][j] = "-";
}
return bestSpot;
}
else
{
int bestVal = Integer.MIN_VALUE;
int bestSpot = 0;
for(int i = 0; i < cells.length; i++)
for(int j = 0; j < cells[i].length; j++)
{
if(!cells[i][j].equals("-"))
continue;
cells[i][j] = getSymbol(playerNum);
int value = miniMax(2);
if(value > bestVal)
{
bestVal = value;
bestSpot = (j * COLS) + i;
}
cells[i][j] = "-";
}
return bestSpot;
}
}
private int Score(int gameState)
{
if(gameState ==2) //O wins.
return 10;
else if(gameState==1) //X wins
return -10;
return 0;
}
public void printArrays() {
String s = "cells: ";
String l = "node: ";
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j <cells[i].length; j++) {
s += cells[i][j];
l += node[i][j];
}
}
System.out.println(s);
System.out.println(l);
}
}
This project involves three classes. Star creates the stars, Starfield creates a matrix of stars, and StarfieldSimualation is the runner
When I omit row 0, it omits the bottom row, instead of the top one. But, it works for rows 1-4. Thanks in advance for the help.
Starfield Code
public class Starfield
{
private Star[][] Sky;
public Starfield(int rows, int cols)
{
if(rows < 0 || cols < 0)
{
rows = cols = 1;
}
Sky = new Star[rows][cols];
}
public String toString()
{
String S = "";
for (Star[] row: Sky)
{
for(Star X: row)
{
if(X != null)
{
S+= X.getImage() + "\t";
}
else
{
S += "- \t";
}
}
S += "\n";
}
return S;
}
public void addStar(String Image, String Constellation, int row, int col)
{
if(row < 0 || row >= Sky.length || col < 0 || col >= Sky[0].length)
{
return;
}
Sky[row][col] = new Star(Image, Constellation, row, col);
}
public Star[][] omitRow(int r)
{
int i, j, k;
k = 0;
Star[][] rowless = new Star[Sky.length - 1][Sky[0].length];
for(i = 0; i < Sky.length-1; i++)
{
for(j = 0; j < Sky[0].length; j++)
{
k++;
}
}
Star[] ans = new Star[k];
k = 0;
for(i = 0; i < Sky.length; i++)
{
for(j = 0; j < Sky[0].length; j++)
{
if(i != r)
{
ans[k] = Sky[i][j];
k++;
}
}
}
k = 0;
for(i = 0; i < rowless.length; i++)
{
for(j = 0; j < rowless[0].length; j++)
{
if(i != r)
{
rowless[i][j] = ans[k];
k++;
}
}
}
return rowless;
}
Star Code
public class Star
{
private Star[][] Sky;
private String Image, Constellation;
private int row, col;
public Star(String I, String C, int r, int c)
{
Image = I;
Constellation = C;
row = r;
col = c;
}
public String getImage()
{
return Image;
}
public String getConstellation()
{
return Constellation;
}
public int getRow()
{
return row;
}
public int getCol()
{
return col;
}
}
Starfield Simluation Code
public class StarFieldSimulation
{
public static void main(String[] args)
{
Starfield theSky = new Starfield(5,4);
theSky.addStar("*", "Orion", 2, 3);
theSky.addStar("*", "Orion", 2, 2);
theSky.addStar("*", "Orion", 2, 1);
theSky.addStar("*", "Orion", 2, 0);
theSky.addStar("*", "Orion", 1, 3);
System.out.println("IT'S THE SKY EVERYONE");
System.out.println(theSky.toString());
Star[][] minusrow = new Star[4][4];
minusrow = theSky.omitRow(4);
System.out.println("A row has been removed");
System.out.println();
for(Star[] row: minusrow)
{
for(Star X: row)
{
if(X != null)
{
System.out.print(X.getImage() + "\t");
}
else
{
System.out.print("-\t");
}
}
System.out.println();
}
System.out.println();
System.out.println("It's the sky again");
System.out.println(theSky.toString());
}
I have to find the minimum distance between two vertices and no. of edges traversed in finding that minimum distance in a adirected weighted graph. I did write a code on using Dijkstras algo. But my test cases are failing. What am i missing here.?
Ideal input: given any two vertices A,B
Output: min distance between two nodes, no. of edges traversed
If the node is unreachable then output should be -1, -1.
//This is a java program to find the shortest path between source vertex and destination vertex
import java.util.HashSet;
import java.util.InputMismatchException;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
public class Dijkstras_Shortest_Path
{
private int distances[];
private int Numnodes[];
private int numnodes;
private Set<Integer> settled;
private Set<Integer> unsettled;
private int number_of_nodes;
private int adjacencyMatrix[][];
public Dijkstras_Shortest_Path(int number_of_nodes)
{
this.number_of_nodes = number_of_nodes;
distances = new int[number_of_nodes + 1];
Numnodes=new int[number_of_nodes+1];
settled = new HashSet<Integer>();
unsettled = new HashSet<Integer>();
adjacencyMatrix = new int[number_of_nodes + 1][number_of_nodes + 1];
}
public void dijkstra_algorithm(int adjacency_matrix[][], int source)
{
int evaluationNode;
for (int i = 1; i <= number_of_nodes; i++)
for (int j = 1; j <= number_of_nodes; j++)
adjacencyMatrix[i][j] = adjacency_matrix[i][j];
for (int i = 1; i <= number_of_nodes; i++)
{
distances[i] = Integer.MAX_VALUE;
}
unsettled.add(source);
distances[source] = 0;
while (!unsettled.isEmpty())
{
evaluationNode = getNodeWithMinimumDistanceFromUnsettled();
unsettled.remove(evaluationNode);
settled.add(evaluationNode);
evaluateNeighbours(evaluationNode);
}
}
private int getNodeWithMinimumDistanceFromUnsettled()
{
int min;
int node = 0;
Iterator<Integer> iterator = unsettled.iterator();
node = iterator.next();
min = distances[node];
for (int i = 1; i <= distances.length; i++)
{
if (unsettled.contains(i))
{
if (distances[i] <= min)
{
min = distances[i];
node = i;
}
}
}
return node;
}
private void evaluateNeighbours(int evaluationNode)
{
int edgeDistance = -1;
int newDistance = -1;
int newNodes=1;
for (int destinationNode = 1; destinationNode <= number_of_nodes;
destinationNode++)
{
if (!settled.contains(destinationNode))
{
if (adjacencyMatrix[evaluationNode][destinationNode] !=
Integer.MAX_VALUE)
{
edgeDistance = adjacencyMatrix[evaluationNode]
[destinationNode];
newDistance = distances[evaluationNode] + edgeDistance;
newNodes=Numnodes[evaluationNode]+1;
if (newDistance < distances[destinationNode])
{
distances[destinationNode] = newDistance;
Numnodes[destinationNode]=newNodes;
}
unsettled.add(destinationNode);
}
}
}
}
public static void main(String... arg)
{
int adjacency_matrix[][];
int number_of_vertices;
int number_of_edges;
int source = 0, destination = 0;
Scanner scan = new Scanner(System.in);
try
{
number_of_vertices = scan.nextInt();
number_of_edges=scan.nextInt();
if (number_of_vertices<1||number_of_vertices>10000)
{
System.out.println("Number of vertices out of boundary");
}
if (number_of_edges<1||number_of_edges>10000)
{
System.out.println("Number of edges out of boundary");
}
adjacency_matrix = new int[number_of_vertices + 1]
[number_of_vertices + 1];
for (int i = 1; i <= number_of_vertices; i++)
{
for (int j = 1; j <= number_of_vertices; j++)
{
adjacency_matrix[i][j] = 0;
}
}
for(int i=1;i<=number_of_edges;i++)
{
int node1=scan.nextInt();
int node2=scan.nextInt();
adjacency_matrix[node1][node2]=scan.nextInt();
}
for (int i = 1; i <= number_of_vertices; i++)
{
for (int j = 1; j <= number_of_vertices; j++)
{
if (adjacency_matrix[i][j] == 0)
{
adjacency_matrix[i][j] = Integer.MAX_VALUE;
}
}
}
source = scan.nextInt();
destination = scan.nextInt();
Dijkstras_Shortest_Path dijkstrasAlgorithm = new
Dijkstras_Shortest_Path(
number_of_vertices);
dijkstrasAlgorithm.dijkstra_algorithm(adjacency_matrix, source);
for (int i = 1; i <= dijkstrasAlgorithm.distances.length - 1; i++)
{
if (i == destination)
System.out.println(dijkstrasAlgorithm.distances[i] +" "+
dijkstrasAlgorithm.Numnodes[i]);
}
} catch (InputMismatchException inputMismatch)
{
System.out.println("Wrong Input Format");
}
scan.close();
}
}
I have been stuck on this for weeks, I have no idea how to do this. I just want the longest streak of heads. I have tried countless times and I just don't know what I'm doing wrong.
public class LongestStreak extends ConsoleProgram
{
public static final int FLIPS = 100;
int currentRun;
int runStart;
int maxRun;
public void run()
{
double heads = 0;
double tails = 0;
for(int i = 0; i < FLIPS; i++)
{
if(Randomizer.nextBoolean())
{
System.out.println("Heads");
heads++;
currentRun++; // use ++ in preference to +=1, and this should be before maxRun test
if (maxRun < currentRun) {
maxRun = currentRun;
runStart = currentRun - i; // this will produce a 1-based position
} else {
currentRun = 0;
}
}
else
{
System.out.println("Tails");
tails++;
}
}
System.out.println(FLIPS);
}
}
i am not sure if i understand your problem right, but here i have a solution, which will print you the longest streak within the 100 FLIPS
public static void run() {
Random r = new Random();
double heads = 0;
double tails = 0;
for (int i = 0; i < FLIPS; i++) {
if (r.nextBoolean()) {
System.out.println("Heads");
heads++;
currentRun++;
if (maxRun < currentRun) {
maxRun = currentRun;
runStart = currentRun - i;
}
} else {
System.out.println("Tails");
tails++;
currentRun = 0;
}
}
System.out.println(FLIPS);
System.out.println(maxRun);
}
public class LongestStreak extends ConsoleProgram
{
public static final int FLIPS = 100;
public void run()
{
int consecutiveHeads = 0;
int maxRun = 0;
for(int i = 0; i < FLIPS; i++)
{
if(Randomizer.nextBoolean())
{
System.out.println("Heads");
consecutiveHeads++;
if(maxRun < consecutiveHeads)
{
maxRun = consecutiveHeads;
}
}
else
{
System.out.println("Tails");
consecutiveHeads = 0;
}
}
System.out.println("Longest streak of heads: " + maxRun);
}
}
I am interested in implementing the Rabin-Karp algorithm to search for sub strings. Here is the algorithm i used: algorithm.
The code I made for the same is as below.
But output is blank. It says build successfully but gives no output...
package rabinkarp;
public class RabinKarp {
final static int q = 101;
final static int d = 256;
public static void RabinKarpMatcher(String T,String p,int q,int d)
{
int n = T.length();
int M = p.length();
int H = 1,i,j;
for (i = 0; i < M-1; i++)
H = (H*d)%q;
int P = 0;
int t = 0;
for(i = 0;i < M; i++)
{
P = (d*P+p.charAt(i))%q;
t = (d*t+T.charAt(i))%q;
}
for(i = 0; i < n-M; i++)
{
if(P==t)
{
for(j = 0; j < M; j++)
{
if(T.charAt(i+j)!=p.charAt(j))
{
break;
}
}
if(j==M)
{
System.out.println("Pattern found at " + i+1);
}
}
if(i < n-M)
{
t = (d*(t-T.charAt(i)*H)+T.charAt(i+M))%q;
if(i <0)
{
t = t+q;
}
}
}
}
public static void main(String[] args) {
String text = new String("ababaaabhahhhha");
String pat = new String("ha");
RabinKarpMatcher(text,pat,q,d);
}
}