Use array to decide who is active player (turn based guessing game) - java

I am using a method (as shown below) that allows me to input the amount of players along with a name for each player. Is there a way for me to use this array to decide who is the active player? (turn based guessing game). If you could just point me in the right direction.
public class Program {
String[] playerList;
int playersAmount = 0;
public void inputPlayers() {
playersAmount = Input.readInt();
playerList= new String[playersAmount];
for (int g = 0; g < playersAmount; g++) {
String namePlayer = "player " + (g+1);
playerList [g] = namePlayer;
}
}
}

You should look over the question I had about changing the player number. I think this exactly what you are looking for (or something similar): Java: Changing Player Number
Essentially I used a boolean array to keep track of who is still playing where the array index corresponds to the player number a[0] = Player 0, a[1] = Player 1, etc. If a player gets eliminated mark the corresponding index with false: a[i] = false; You can then use the following method (taken from my question) to switch the player number to the next player still playing:
public static int switchPlayer(int currentPlayer, boolean[] playerList) {
// if the current player + 1 = length (size) of array,
// start back at the beginning and find the first player still playing
if(currentPlayer + 1 == playerList.length) {
for(int i = 0; i < playerList.length; i++) {
if(playerList[i] == true) { // if player is still in the game
currentPlayer = i; // currentPlayer = current index of array
break;
}
}
}
// otherwise the current player number + 1 is not at the end of the array
// i.e. it is less than the length (size) of the array, so find the next player
// still playing
else {
for(int i = (currentPlayer+1); i < playerList.length; i++) {
if(playerList[i] == true) {
currentPlayer = i;
break;
}
}
}
return currentPlayer;
}
Let me know if you have any questions about my code, etc.

You have two different options in my opinion.
create a Player object with instance variables as his name and a boolean that states whether or not he is active.
You can create a boolean array that is sync with the player array that states wether or not the player is active.
ex for 2
boolean[] activeStatus= new boolean[1];
String[] players = new String[1];
activeStatus[0]=true;
players[0]="Joe Smith";

Well, to represent the current player you can use a int
int curplayer = 0;
Every time their round is done you can add one to get the index of the next player.
curplayer++;
As for it returning to the first player after the last player, I suggest you look into the % (modulo) operator.

Keep track of the turn number using an instance variable:
private int turn;
Increment it every turn:
turn++;
The index of the player whose turn it is can be calculated by using the remainder of dividing the turn by the number of players:
int playerIndex = turn % playersAmount;
I leave it to you to work these parts into your code.

My java is a bit rusty, but something like the following should work.
i = 0
while (playing == True)
{
player = playerList[i]
i = (i + 1) % playerList.length
[Do something]
}

Related

How do I defend against user error if the player entered "A11" as a coordinate in the game battleship?

I'm coding a battleship game in Java. The game has a 10x10 grid as the map. (The letters and numbers don't count)
The player then inputs a series of strings to tell the game where he wants to place the ships in the from-to format like "A5 A10" or "A1 C1 ". I'm at the point where I ask the player to input a coordinate to take a shot. Since the user inputs a string.
For example, A1. I use the method private int[] toDigitCoordinates(String coordinates) to process the input into integer coordinates I can then use to check if he hit a ship on the map. Note that the first part of the if statement is used in the earlier stage of the game where the player places ships.
private int[] toDigitCoordinates(String coordinates) {
int[] result;
if(coordinates.length() > 2) {
result = new int[4];
result[0] = coordinates.split(" ")[0].charAt(0) - 65; //since ASCII representation of A is 65
result[1] = Integer.parseInt(coordinates.split(" ")[0].substring(1)) - 1;
result[2] = coordinates.split(" ")[1].charAt(0) - 65;
result[3] = Integer.parseInt(coordinates.split(" ")[1].substring(1)) - 1;
}
else{
result = new int[2];
result[0] = coordinates.split(" ")[0].charAt(0) - 65;
result[1] = Integer.parseInt(coordinates.split(" ")[0].substring(1)) - 1;
}
return result;
}
and I use the method below to make sure the coordinates are on the map
private boolean validateCoordinates(int[] coordinates) throws IllegalAccessException {
boolean isValid = true;
if(coordinates[0] < 0 || coordinates[0] > 9 || coordinates[1] < 0 || coordinates[1] > 9 )
throw new IllegalAccessException("Error! You entered the wrong coordinates! Try again:");
return isValid;
}
Now if the player inputs "A11" my program fails because the first method simply would not work to convert the A11 to [0,10]
I tried using a for-each loop to adapt the first method to the length of input but I failed and I am out of ideas right now. Is there a better way to convert the input into coordinates?

Matching Card Game in Java

Hi,
I'm making a matching card game and I don't understand how to actually do it. I was hoping someone could help explain what I can do to figure this out.
The following are the specifications:
In a card game of Pairs the goal is to turn over pairs of matching cards.
https://en.wikipedia.org/wiki/Concentration_(game)
Here are the rules for the variation of Pairs we consider.
At the start of the game, there are n cards face-down, where n is a multiple of 4. There are 4 cards
of each type, and the cards are labeled with letters a, b, . . . . For example, if n==24, there are 6
types of cards: a, b, c, d, e, and f. Say 1*4<=n and n<=4*26.
At each turn, the player flips 2 cards, one at a time, that are face-down. If the 2 flips are of the
same type, the matched cards are left face-up. If the 2 flips mismatch, the mismatched cards are
returned to the face-down position. The game ends when all cards are matched, and the score is
the total number of flips made. (Flipping a pair of cards counts as 2 flips, so the best possible score
is n flips.)
Write a pubic class titled MatchCardGame with the following members that implement this game
of Pairs. The starter code in PlayCard.java should give you an idea of how MatchCardGame is
used.
MatchCardGame should have no other public fields, methods, and constructors aside from the ones
specified. However, it may and should have additional private fields, methods, or constructors.
The field
public final int n;
is the size of the game set by the constructor.
The constructor
public MatchCardGame(int n);
initializes a card game with a total of n cards. Assume n is a multiple of 4 and that 4<=n && n<=4*26.
Without shuffling (explained in Problem 2) cards 0,1,2, and 3 should be a, cards 4,5,6, and 7 should
be b, and so on.
The method
public String boardToString();
converts the state of the board to an appropriate String representation. You have freedom to
choose your own representation, but it must reasonably represent the state of the game.
The method
public boolean flip(int i);
plays card number i. If card i cannot be played because it’s face-up, or if i is an invalid card
number, then return false. If i is a card number that can be played, play card i and return
true.
The method
public boolean wasMatch();
returns true if the previous pair was a match and returns false otherwise. This method should be
called only after flip has been successfully called an even number of times and before flipMismatch
is called. (A successful call of flip is a call that results in a flip and returns true.)
The method
public char previousFlipIdentity();
returns the face of the previously flipped card as a char. This method should only be called after
a card has been flipped.
The method
public void flipMismatch();
reverts the mismatched pair to face-down position. This method should only be called after a 2
calls of flip results in a mismatch.
The method
public boolean gameOver();
returns true if all cards have been matched and the game is over and returns false otherwise.
The method
public int getFlips();
returns the total number of card flips that have been performed so far.
Remark. MatchCardGame represents the physical state of the game, not the player. MatchCardGame
has nothing to do with game strategies a human or AI player might employ.
Remark. The problem specifies how these methods should be used. For example, the input n of
MatchCardGame’s constructor needs to be a multiple of 4. You do not have to do any sort of error
handling when these requirements are violated, although using asserts will help debugging.
So far, I have the following:
public class MatchCardGame {
//Private classes
private boolean facingup;
private char[] board;
private int flips = 0;
private int matches = 0;
private int currentflip;
//Public classes
public final int n;
public MatchCardGame(int n) {
for (int i = 0; i < n; i++) {
if (i % 4 == 0) {
this.board[i] = 'a';
}
else if (i % 4 == 1) {
this.board[i] = 'b';
}
else if (i % 4 == 2) {
this.board[i] = 'c';
}
else {
this.board[i] = 'd';
}
}
}
public String boardToString() {
String stringboard = "";
for (int i; i < n; i++) {
if (facingup){
stringboard += stringboard + "[" + this.board[i] + "] ";
}
else {
stringboard += "[-] ";
}
}
return stringboard;
}
public boolean flip(int i) {
flips++;
if (i < 0 || i >= n || currentflip == ((int) this.board[i]) % 32) {
return false;
}
else {
if (flips % 2 != 0) {
currentflip = ((int) board[i]) % 32;
facingup = true;
return true;
}
else if (board[i] == this.board[i]) {
currentflip = -1;
this.facingup = true;
board [i] = '0';
this.board[i] = '0';
matches += 2;
return true;
}
}
}
public boolean wasMatch() {
if (currentflip == -1) {
return true;
}
else {
return false;
}
}
public char previousFlipIdentity() {
return board [i];
}
public void flipMismatch() {
facingup = false;
this.facingup = false;
}
public boolean gameOver() {
if (matches == n) {
return true;
}
else {
return false;
}
}
public int getFlips() {
return flips;
}}
Any assistance would be appreciated.
Try to walk through it in your mind.
You have been given a set of cards
One card, x is flipped
Other card is flipped next; if it's the same as the previous x, remove both cards
If it's not the same as the previous, ignore both flips.
Continue these steps till all cards are matched and no cards are remaining
So to convert it into code, what are the things you need to keep track of?
All cards and their types (a, b and so on)
State of card: Flipped or not flipped
General state of all cards: Matched or still present (remember, if it's matched, we remove it)
Number of flips
How can we keep track of this?
We can keep track of the type of card in the array char[] board
Maintain a private int flips to keep track of number of flips, and private int matches to keep track of matches, initially 0
Maintain a private int currentlyFlippedCard to store the 1st flipped card's index.
If it's the first flip, store it in currentlyFlippedCard.
Increment int flips every time a card is flipped(flips++).
If it's the second flip, check if the type of card matches the type of card in currentlyFlippedCard.
How do you know if the flip is first or second? Because we increment flips every time.
For the first flip, flip == 1; second, flip == 2; if it's flipped again, it becomes flip == 3, which we should take as the first flip.
From this, we can say that when flip is odd, it's the first flip, and when flip is even, it's the second.
If both flips do not match: don't make any changes.
If both flips match: change both index of both flips to '0' in char[] board to mark it as inactive; increment int matches by 2
So next time flip(i) is called, check if board[i] != '0', which will make sure it's still active in the game
How do you know if the game is over? If all cards are matched, game is over. So if matches == n, all cards are matched.
You need to know if the previous flip was a match(for wasMatch()). For this, you can maintain a boolean to keep track of it; or another way is, you can use the variable currentlyFlippedCard itself. For the second way:
When second flip is not a match, do nothing(currentlyFlippedCard will have the index of previous flip, meaning currentlyFlippedCard >= 0)
When second flip is a match, along with incrementing matches, set currentlyFlippedCard = -1.
When you need to call wasMatch(), return true if flips is even and currentlyFlippedCard == -1.
For boardToString(), just put all chars from board[] in a String one by one using a loop.
Here, 0 will mean it's matched; you can just add an if check to see if it's == 0 and change it to another character while inserting into the String.
Same goes for currently flipped card; you can just check when that index comes, and add a * or something to indicate it's flipped.
This is a brief overview, you just have to convert it into code. I have so far refrained from adding actual code, since it'll help you if you try it out yourself.
All the best, keep learning! :)
Edit 1(after comments):
I'm guessing wasMatch() is called after every 2nd flip? I assumed it won't be, and accidentally put the incrementing indexes in flip().
So since wasMatch() is a separate method, you can maintain 2 variables for the flipped cards(say currentlyFlippedCard1 and currentlyFlippedCard2), and increment during wasMatch().
As for flipMismatch(): Specs say it should 'revert it to facedown position'. You can either make no changes, or change currentlyFlippedCard1 and currentlyFlippedCard2 to some default value like -2.
Edit 2(after comments):
For previousFlipIdentity():
Check int flips to see if the previous flip was first or second flip(by checking if int flips is odd or even)
If first flip, return board[currentlyFlippedCard1]
If second flip, return board[currentlyFlippedCard2]
My suggestion is: implement core methods you know first. Once you get some methods running, you will have a better idea, and you can add in more functionality.

Why does algorithm in Tic Tac Toe game doesn't block my moves?

I have a working TicTacToe game, where I am trying to implement an Ai to act as player "O". The issue I'm having is that it won't block my moves. I have read through the code many times using breakpoints, but I still can't find the issue. Do any of you know what the issue could be?
This is the main minimax function:
public int miniMax(String player, int currentDepth, String[] board) {
if(checkWin("O",board)){ //Checks if O wins. Returns 10-currentDepth to give value to terminal state (Ai wins)
return 10-currentDepth;
}
if(checkWin("X",board)){ //checks if X wins. Returns -10-currentDepth to give value to terminal state (Ai loses)
return -10-currentDepth;
}
if(checkTie(board)){ //Checks for tie. Returns 0-currentDepth
return 0-currentDepth;
}
currentDepth++;//Increases depth
if(player.equals("O")){ //If the player turn is O, I.E. the AI's turn/Max function of minimax
bestVal=Integer.MIN_VALUE;
bestSpot=0;
for(int i=0;i<board.length;i++){ //For loop that iterates through each possible move for O.
if(board[i].equals(" ")){ //Checks if the spot is empty before modifying it
board[i] = "O"; //When spot is empty, sets equal to O
int value = miniMax("X",currentDepth,board); //Recursive part of function. Recalls function changing the current player. Once it hits an end spot, gives it terminal value
if((value)>bestVal){ //Checks if value is better then the best, to determine best possible move.
bestVal = value; //If value is better, then sets new best to it.
bestSpot = i;// The location of the next best move
}
board[i]=" ";//sets the original location to empty to prevent board from being permanently changed
}
else{}//When the spot isn't empty, just skips that check.
}
return bestSpot;//Returns the best spot to allow program to make a move. This is what gets sent to gamelogic
}
else{ //If the player turn is X, I.E. the players turn/Mini function of minimax
minVal=Integer.MAX_VALUE;
bestSpot=0;
for(int i =0;i<board.length;i++){ //For loop that iterates through each possible move for X.
if(board[i].equals(" ")){ //Checks if the spot is empty before modifying it
board[i] = "X"; //When spot is empty, sets equal to X
int value = miniMax("O",currentDepth,board); //Recursive part of function. Recalls function changing the current player. Once it hits an end spot, gives it terminal value
if((value)<minVal){ //Checks if value is worse then the worst, to determine best possible move.
minVal = value; //If value is better, then sets new best to it.
bestSpot = i; //The location of the next best move
}
board[i] = " "; //Sets the original location to empty to prevent board from being permanently changed
}
else{} //When the spot isn't empty, just skips that check.
}
return bestSpot; //Returns the best move for X.
}
}
This is my checkwin and check tie function:
private boolean checkWin(String player, String[] board){
if(
(board[0].equals(player) && board[1].equals(player) && board[2].equals(player)) ||//first col
(board[3].equals(player) && board[4].equals(player) && board[5].equals(player)) ||//sec col
(board[6].equals(player) && board[7].equals(player) && board[8].equals(player)) ||//third col
(board[0].equals(player) && board[3].equals(player) && board[6].equals(player)) ||//first row
(board[1].equals(player) && board[4].equals(player) && board[7].equals(player)) ||//second row
(board[2].equals(player) && board[5].equals(player) && board[8].equals(player)) ||//third row
(board[0].equals(player) && board[4].equals(player) && board[8].equals(player)) ||//diag \
(board[2].equals(player) && board[4].equals(player) && board[6].equals(player)) //diag /
){
return true;
}
else{
return false;
}
}
private boolean checkTie(String[] board){
int inter=0;
for (String s : board) {
if(!s.trim().isEmpty()){
inter++;
}
}
return inter == 9;
}
Let me know if you need any more code from the program.
Have you tried using a more sophisticated reward function given a game state? I see that you only check for terminal states and there is no extra reward for "blocking" the opponent. The AI needs an incentive to perform certain moves, i.e. you need to reward it for certain actions such as blocking.

Java. Efficient check for winning condition in 5 in raw

I've started writing a bot to play Gomoku. Briefly each player tries to score unbroken line of five tolkens. The game is played on 15*15 board.
Finding a win in one move by exhaust search is the first task.
Should I use 1D or 2D array to represent the board? 2D seems more natural, but 1D array might be faster.
What is the resource efficient way to check the winning condition?
I considered making an array.
win[i][j]=[p1,p2,p3,p4,p5], where win[i] is (the set of winning combos ) && (with one tolken in i-th position).
What would be an efficient way to do this check?
Also, how can I account for all winning combos by forking moves? The total number of winning combos will be quite large? Should I move to on the fly evaluation.
Thank you in advance,
Stepan
Should I use 1D or 2D array?
I think that you could either 1 or 2 dimension array, and with each (i, j) you could access to your cell. in 1D you must code to find correct index of the array and in 2D, simply you could access to your cells.
so in this sample code I use a 2D array.
What is the resource efficient way to check the winning condition?
you have to check the cell values with fix values (eg. booleans or numbers) frequently and the lowest assembly structure of equal statement is checking zero flag. so I think that the most efficient isEqual is for Boolean.
so in this sample code I use Boolean.
since Gomoku has 2 players, each cell could have 3 values (black, wight, empty), but we could use 2 arrays of Boolean for each player and each cell has 2 values (stone, empty) for that player.
public class Main {
final static int row = 15;
final static int column = 15;
final static int win_count = 5;
public static void main(String[] args) {
boolean[][] board1 = new boolean[row][column];
boolean[][] board2 = new boolean[row][column];
/*
* for each change by player1 in (i,j) in the board. (index start from 0
* to 14)
*/
int i = 2;
int j = 3;
Boolean win = checkWin(board1, i, j);
System.out.println("player1 win=" + win);
}
private static Boolean checkWin(boolean[][] board1, int i, int j) {
/**
* 1) check horizontal
*/
int leftBound = 0;
if (j - win_count >= 0)
leftBound = j - win_count;
else
leftBound = 0;
int rightBound = 0;
if (j + win_count < column)
rightBound = j + win_count;
else
rightBound = column - 1;
int hitCount = 0;
int jk = j;
// go left
while (jk >= leftBound && hitCount < win_count) {
if (board1[i][jk]) {
hitCount++;
jk--;
} else {
jk = j;
break;
}
}
// go right
while (jk <= rightBound && hitCount < win_count) {
if (board1[i][jk]) {
hitCount++;
jk++;
} else {
break;
}
}
if (hitCount >= win_count)
return true;
/**
* 2) check vertical
*/
/**
* 3) check principal diagonal
*/
/**
* 4) check minor diagonal
*/
// otherwise:
return false;
}
}
I write the structure of this code and you should complete other parts that is marked with comments.
I hope this sample code could help you.
Please check this article for ideas:
"Go-Moku Solved by New Search Techniques" (1993)
Briefly,
(1) A brute force 2 ply deep search is a cheap and dirty approach, but there is a better way
(2) Whenever forcing moves are involved you can run 10-20 ply deep search in a second
(3) Human professionals rely on this; your bot should utilize it as well
Hope this helps.

Counting the longest consecutive run in a Coin Toss simulator

I am in a beginning Java programming class and one of our assignment is to write a program that simulates tossing a coin a user-specified number of times. The functional class, CoinToss.java, looks like this:
public class CoinToss {
private char[] results;
private int numHeads;
private int numTails;
private double headsFrac;
private double tailsFrac;
private int currentRun;
private char currentOutcome;
public CoinToss(int numTosses) {
results = new char[numTosses];
for(int i = 0; i < results.length; i++) {
double number = Math.random();
if(number < 0.5) {
results[i] = 't';
}
else {
results[i] = 'h';
}
}
}
public void count() {
for(int i = 0; i < results.length; i++) {
if(results[i] == 't') numTails++;
else numHeads++;
}
headsFrac = (double)numHeads/results.length;
tailsFrac = (double)numTails/results.length;
}
public double getFracHeads() {
return headsFrac;
}
public double getFracTails() {
return tailsFrac;
}
public char[] getTosses() {
return results;
}
public void getLongestRun() {
currentOutcome = 'h';
for(int i = 0; i < results.length; i++) {
if(currentOutcome == results[i]) {
currentRun++;
}
else {
currentOutcome = results[i];
currentRun = 1;
}
}
if(currentOutcome == 'h') {
System.out.println("Longest run was " + currentRun + " heads.");
}
else {
System.out.println("Longest run was " + currentRun + " tails.");
}
}
}
My main area of concern is the getLongestRun() method. The instructions say: Create a method that examines the array of coin tosses to locate the longest
possible run of heads or tails that were tossed. You will need two attributes,
these attributes have the current number of consecutive outcomes (a run) and
the outcome associated with the run (head or tail). In a loop, compare each toss
in the array to the outcome
of the current run. If they match, the current run is
now recognized as one longer. If they don’t match, then the current run has
ended. Compare the number of consecutive outcomes in this run that has just
ended with the largest number of consecutive outcomes that has been
previously seen
(the longest run so far). Whether or not this is a new longest
run, reset the current outcome to the one just examined and reset the length of
the current run to 1. Think about if any special processing needs to happen
when the loop terminates.
My main concern is how to get that method working correctly. It is not counting the longest consecutive number of heads or tails correctly.
You don't store the results of each run; you simply overwrite the previous value when a new run begins. That means that your getLongestRun() method will only ever print the length of the last run, rather than the longest.
To fix this, you will need to record the results of each run in an array (or, preferably, an object structure like ArrayList) then traverse it to find the maximum value. Alternatively, you could simply have a variable which always holds the maximum streak and simply discard the latest one if it's lower than the current maximum.
I won't provide full code for you since this is coursework, but here's a pseudocode (Pythonic) idea of what I mean:
current_streak = 0
longest_streak = 0
current_coin = coin_toss_list[0]
for coin in coin_toss_list:
if current_coin == coin:
current_streak = current_streak + 1
else:
if current_streak > longest_streak:
longest_streak = current_streak
current_streak = 1
current_coin = coin
print "Longest streak was " + longest_streak

Categories

Resources