I am writing a method to switch the player number after each player's turn. I am using a boolean array that keeps track of the players still playing (that have not been eliminated). So the array at the beginning of the game is initialized to true and is the size of the number of players in the game. As players get eliminated, the corresponding value of the index gets set to false (For example if Player 2 gets eliminated, the third index of the array gets set to false). (Note: Player 0 does exist, so if two players are playing they are Players 0 and Player 1.) If the player number is equal to the last player, then it needs to start back at the beginning and find the first player that is still in the game. Otherwise, the player number increments to the first player that is still playing. Here is what I have:
public static int switchPlayer(int currentPlayer, boolean[] playerList) {
if(currentPlayer == playerList.length) {
for(int i = 0; i < playerList.length; i++) {
if(playerList[i] == true) {
currentPlayer = i;
break;
}
}
}
else {
for(int i = (currentPlayer+1); i < playerList.length; i++) {
if(playerList[i] == true) {
currentPlayer = i;
break;
}
}
}
return currentPlayer;
}
Any changes or suggestions? It is not quite working and cannot see where it is going wrong.
I have tried to implement one of the answers, but I cannot figure out how to get it implemented. Does anyone have a solution?
If you have Players 0,1,2,3. Then length is 4.
But the argument currentPlayer can only have 0-3 value, since thats the player numbers, so try changing this:
if(currentPlayer == playerList.length) {
for(int i = 0; i < playerList.length; i++) {
if(playerList[i] == true) {
currentPlayer = i;
break;
}
}
}
to:
if(currentPlayer + 1 == playerList.length) {
for(int i = 0; i < playerList.length; i++) {
if(playerList[i] == true) {
currentPlayer = i;
break;
}
}
}
What if you use an ArrayList data structure where you store all players that are currently not eliminated. So when a player is eliminated you remove that object from the ArrayList. This way you wouldn't need to use boolean to keep track of player status.
public static int switchPlayer(int currentPlayer, ArrayList playerList) {
// move to the next player
currentPlayer++;
// reset back to the first player if we reached the end player
if(currentPlayer >= playerList)
currentPlayer = 0;
return currentPlayer;
}
Now originally, in some part of your code I think you are setting the value "false" to indicate that the user has been eliminated. However, my idea is to remove the eliminated player. For example, if you want the second player to be eliminated, then you can do something like this in an array list:
list.remove(2);
Related
I'm making a tic tac toe game in Java with a customizable dimension feature (user can choose to play 3x3, 4x4, 5x5, etc.) and was working on the logic regarding finding a winner. Currently I'm trying to figure out checking for wins horizontally.
I've had the idea to make a nested for-loop to check the 2d array that hosts the board, but am not sure how to execute this. The problem with this code:
for (int i = 0; i < dimension; i++) {
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != '-') {
// you won!
}
}
...Is that its logic is fixed for a 3x3 game, not for any other dimensions. I only know how to add values into 2d arrays, so how can I check if these values are equal? Thank you in advance.
I'm not sure about the rules for winning tic tac toe in higher dimensions, so let's say you have to fill the whole row/column to win.
Divide the if in two parts: The check for the first chararacter and the comparisons. Then use a second for-loop for the comparisons, like this:
for (int i = 0; i < dimension; i++) { // iterate rows
// check for first character
if (board[i][0] == '-') { // if wrong character...
continue; // ... check next row
}
boolean won = true;
for (int j = 0; j < dimension - 1; j++) { // iterate columns
if (board[i][j] != board[i][j+1]) { // if other character...
won = false; // ...not winnable with this column and...
break; // ...stop iteration of columns
}
}
if (won) {
// you won!
}
}
If you win with less crosses 'X' in all dimensions, you would have to add a third loop to go through the possible start points or you could count the amount of crosses in the column and reset the number if there is an 'O'.
Hello I am creating a basic tic tac toe game for my own pleasure that has 4x4 fields I have the program pretty much completed but I am stuck on one part in my game i have to decide a winner if any x's or o's are grouped by 2x2 i already have the horizontal and vertical and diagonal algorithms to decide a winner completed
so for example if we have
x|x|o|o
x|x|o|x
| | |
| | |
X will be the winner since he has a 2x2 group
thank you for any help!
example code for my vertical winner code
public boolean checkForWin()
{
char symbol = SYMBOL[turn];
//check vertical win
Check1:
for(int i=0; i<BOARD_SIZE; i++)
{
for(int j=0; j<BOARD_SIZE; j++)
if(board[i][j] != symbol)
continue Check1;
//if reached, winning line found
return true;
}
//check horizontal win
Check2:
for(int j=0; j<BOARD_SIZE; j++)
{
for(int i=0; i<BOARD_SIZE; i++)
if(board[i][j] != symbol)
continue Check2;
//if reached, winning line found
return true;
}
//check back slash diagonal win q
for(int i=0; i<BOARD_SIZE; i++)
if(board[i][i] != symbol)
break;
else if(i == BOARD_SIZE-1)
return true; // winning line found
//check forward slash diagonal win
for(int i=0; i<BOARD_SIZE; i++)
if(board[i][BOARD_SIZE - i - 1] != symbol)
break;
else if(i == BOARD_SIZE-1)
return true; // winning line found
//if reach here then no win found
return false;
}
where would i input that code ?
Create a list of winning configurations each having 4 locations. There are 4 winning rows, 4 winning columns, 2 diagonals, and 9 blocks. Then just check each configuration.
Code would be roughly
// Set this up once at the start
WinningConfiguration[] allWinningConfigurations = {
WinningConfiguration.row(0),
...
WinningConfiguration.row(3);
WinningConfiguration.column(0);
...
WinningConfiguration.column(3);
WinningConfiguration.block(0,0);
...
WinningConfiguration.block(3,3);
WinningConfiguration.diagonal();
WinningConfiguration.reversedDiagonal();
}
..
// Now all your checks, (row, column, diagonal and blocks) become
for(WinningConfiguration config : allWinningConfigurations) {
boolean configWins = true;
for(int i=0; i<4; ++i) {
if(board[config.pts[i].x][config.pts[i].y]!=symbol) {
configWins = false;
break;
}
}
if(configWins)
return true;
}
return false;
And if you then want to add other winning combinations (say all four corners) you only need to add one row to your winning Configurations array and you're done.
There's further refactoring that could be done to make this neater too, like moving the check into the WinningConfiguration class so that the loop becomes
for(WinningConfiguration config : allWinningConfigurations) {
if(config.wins(symbol)
return true;
}
return false;
Think of it this way: EVERY winning 2x2 square will have a topleft corner. So if you see a mark, you can check to see if the square to the right, bottom, and bottomright are all the same type, and if so, marker that player a winner. Since you're starting your check on the topleft corner, you never need to put a starter check on the rightmost or bottommost lines (because you won't have a square extend outside your board!)
So for int i extending from 0 to BOARD_SIZE-1, and for int j extending from 0 to BOARD_SIZE-1, if board[i][j] == board[i+1][j] == board[i][j+1] == board[i+1][j+1] == symbol then you have yourself a winner.
There are a few things you could do beyond that to make it a bit more efficient, but since it's tic-tac-toe I don't think you're too concerned with scalability =)
In my Tic-tac-toe program, there are three rows and three columns. The game will be played by two people.
The program will get user input via Scanner class(System.in) by typing in cell coordinate. I would like to prevent user from entering into an coordinate which has already been filled. I thought that it might be a good idea to implement this by using two(nested) 'for loops' which would check both rows and columns about whether they'd been already filled or not.
So in its first check, one slot will be occupied and if the user enters the same coordinate as the previous one, I can print a message to the user that the slot is not empty.
But the problem is that when these two nested for-loops run again(since I put them into a while loop where codes that switch between players is located), it will start to check again every cell in the Array table. And then the program will tell me that the slot has already been filled even though the second user does not enter the same coordinate as the second one.
I want the code to behave in a way that, it checks only a particular cell in the table right after a user has entered an coordinate for that cell.
My failed method, isOccupied(), looks like this --
public boolean isOccupied() {
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++) {
if (board.get(r).get(c) != null) {
return false;
}
}
}
return true;
}
And below is my while-loop;
while (scanner.hasNext() && !board.hasWon()){
int x = scanner.nextInt();
int y = scanner.nextInt();
if (player){
System.out.println("Player 2. Please enter your coordinate:");
board.setPiece(x, y, "x");
if (board.hasWon()){
System.out.println(board);
System.out.println("Player 1 has won!");
break;
}
else{
player = false;
}
}else {
board.setPiece(x, y, "o");
if (board.hasWon()){
System.out.println(board);
System.out.println("Player 2 has won!");
break;
}else{
player = true;
}
System.out.println("Player 1. Please enter your coordinate:");
}
System.out.println(board);
}
}
Is there any better way to implement this logic?
public boolean isOccupied(int x, int y){
return (board.get(x).get(y) != null);
return true;
}
return false;
}
This question already has answers here:
Connect 4 check for a win algorithm
(6 answers)
Closed 6 years ago.
I have programming assignment where a 2D board game needs to made. The game I am trying to make is a connect 4 game. The problem I have is that I can't seem to get the win conditions to work. Does anybody have any recommendations. I am still relatively new in programming so I am sorry if it is a simple fix. Here is my Code:
import java.io.*;
import java.net.*;
class C4GameSession implements C4Constants {
private Socket player1;
private Socket player2;
// Create and initialize cells
private char[][] cell = new char[6][7];
private DataInputStream fromPlayer1;
private DataOutputStream toPlayer1;
private DataInputStream fromPlayer2;
private DataOutputStream toPlayer2;
// Continue to play
private boolean continueToPlay = true;
/** Construct a thread */
public C4GameSession(Socket player1, Socket player2) {
this.player1 = player1;
this.player2 = player2;
// Initialize cells with a blank character
for (int i = 0; i < 42; i++)
for (int j = 0; j < 42; j++)
cell[i][j] = ' ';
}
public void runGame() {
try {
// Create data input and output streams
DataInputStream fromPlayer1 = new DataInputStream(player1.getInputStream());
DataOutputStream toPlayer1 = new DataOutputStream(player1.getOutputStream());
DataInputStream fromPlayer2 = new DataInputStream(player2.getInputStream());
DataOutputStream toPlayer2 = new DataOutputStream(player2.getOutputStream());
// Write anything to notify player 1 to start
// This is just to let player 1 know to start
// in other words, don't let the client start until the server is ready
toPlayer1.writeInt(CONTINUE);
// Continuously serve the players and determine and report
// the game status to the players
while (true) {
// Receive a move from player 1
int row = fromPlayer1.readInt();
int column = fromPlayer1.readInt();
cell[row][column] = 'X';
// Check if Player 1 wins
if (isWon('X')) {
toPlayer1.writeInt(PLAYER1_WON);
toPlayer2.writeInt(PLAYER1_WON);
sendMove(toPlayer2, row, column);
break; // Break the loop
}
else if (isFull()) { // Check if all cells are filled
toPlayer1.writeInt(DRAW);
toPlayer2.writeInt(DRAW);
sendMove(toPlayer2, row, column);
break;
}
else {
// Notify player 2 to take the turn - as this message is not '1' then
// this will swicth to the relevant player at the client side
toPlayer2.writeInt(CONTINUE);
// Send player 1's selected row and column to player 2
sendMove(toPlayer2, row, column);
}
// Receive a move from Player 2
row = fromPlayer2.readInt();
column = fromPlayer2.readInt();
cell[row][column] = 'O';
// Check if Player 2 wins
if (isWon('O')) {
toPlayer1.writeInt(PLAYER2_WON);
toPlayer2.writeInt(PLAYER2_WON);
sendMove(toPlayer1, row, column);
break;
}
else {
// Notify player 1 to take the turn
toPlayer1.writeInt(CONTINUE);
// Send player 2's selected row and column to player 1
sendMove(toPlayer1, row, column);
}
}
}
catch(IOException ex) {
System.err.println(ex);
}
}
/** Send the move to other player */
private void sendMove(DataOutputStream out, int row, int column) throws IOException {
out.writeInt(row); // Send row index
out.writeInt(column); // Send column index
}
/** Determine if the cells are all occupied */
private boolean isFull() {
for (int i = 0; i < 43; i++)
for (int j = 0; j < 43; j++)
if (cell[i][j] == ' ')
return false; // At least one cell is not filled
// All cells are filled
return true;
}
/** Determine if the player with the specified token wins */
private boolean isWon(char token) {
/*
int count = 0;
for (int i = 0; i < 6; ++i)
for (int j = 0; j < 7; ++j)
if (cell[i][j] == token)
++count;
if (count == 4)
return true; // found
/* else
count = 0; // reset and count again if not consecutive
*/
int count_piece = 0;
//Checking Horizontal Win
for (int i = 0; i < 6; i++) {
count_piece = 0;
for (int j = 0; j < 7; j++) {
if (cell[i][j] == 'X') {
count_piece++;
if (count_piece == 4) {
System.out.println("you win");
return true;
}
} else {
count_piece = 0;
}
}
}
return false; // no 4-in-a-line found
}
}
(I'll write in pseudocode)
Start with a simple approach: you need to check for vertical, horizontal and diagonal win, then do three separate check code blocks (you do not need to solve all the problem at once).
One for the horizontal direction:
for(every row)
count = 0;
for(each column)
if(cell value = token)
then count++;
else // reset the counting, the eventual sequence has been interrupted
count = 0;
if(count >= 4) then win = 1; // you can break out here, when improving you can break out directly in the inner for loop if count is => 4
If no win detected, go for the vertical direction:
// similar comments for the previous block apply here
for(every column)
count = 0;
for(each row)
if(cell value = token)
then count++;
else
count = 0;
if(count >= 4) then win = 1 and break;
If no win detected, go for the diagonal direction:
// a bit harder, you have to move diagonally from each cell
for(every column from the left)
for(each row from the top)
count = 0
for(delta starting from 0 to 5)
// add more checks to avoid checking outside the cell matrix bounds
// when improving the code, you can compute a better end for the delta
if(cell[row+delta][column+delta] = token)
then count++;
else
count = 0;
When you have written and tested all there three pieces, if you want you can gradually improve the algorithm, i.e. starting from the bottom instead of the top row (as most superior cells will be empty for the most part of the game); next, as 4 consecutive cells with the same element must be found, if you, e.g. haven't found enough consecutive tokens when checking a row you may stop earlier instead of going through all the 7 cells in that row.
While I'm not giving you the complete solution with working code, I hope my answer will put you on the right track.
I want to place obstacles on a game board using a random number generator. 5% of the board will have a pit which is defined as "*", but the asterisk will not show unless the players lands in that spot; 10% of the board will be blocked spots indicated as "X"; the remaining 85% will be open spaces shown as "." The game board is a 10x10 array with the letter "P" at the upper left hand corner as the starting point for the player, and a "T" at the bottom right hand corner for the ending (treasure). So far I've got this, and I been watching video tutorials as well as reading to try and put this all together, but still stuck:
import java.util.Scanner;
import java.util.Random;
public class Adventure {
public static void main(String[] args) {
char grid[][]= new char[10][10];
Scanner move = new Scanner(System.in);
System.out.println("Here is the current game board:");
System.out.println("-------------------------------");
for(int i=0; i<grid.length; i++) {
for(int j=0; j<grid.length; j++) {
grid[i][j]='.';
grid[0][0]='P';
grid[9][9]='T';
System.out.print(grid[i][j]);
}
Random obstacle = new Random();
int obstacleNum;
for(int k=1; k<=100; k++) {
obstacleNum = 1+obstacle.nextInt(100);
}
System.out.println("");
}
System.out.printf("Enter your move (U/D/L/R)>");
}
}
Not sure where to go after "obstacleNum = 1+obstacle.nextInt(100);"
If your game board has 100 spots, then it will have 5 pits, 10 blocks, and 85 open spaces.
Choose 15 random numbers from 1 to 100; the first 5 identify the pits, and the next 10 identify the blocks.
Create a list to keep track of the 15 numbers. Each time you choose a random number, check to see if the number is already present to the list. If it is, discard it and choose a different random number. Otherwise add it to the list and continue until you've chosen all 15 numbers.
As for the actual interactivity, here is an outline:
x = 0; //coordinates of player, location of P
y = 0;
To hide the pits, before printing, stick in and if statement:
if(grid[i][j]=='*') {
System.out.println("."); //looks like ordinary land
} else {
System.out.println(grid[i][j]);
}
Now have this run when it receives input (pseudo)
//following if for moving left
if(grid[y][x+1] isn't out of bounds and right key is pressed and grid[y][x+1]!='X') {
grid[y][x] = '.'; //removes current position
x++; //change location
}
//following if for moving right
if(grid[y][x-1] isn't out of bounds and left key is pressed and grid[y][x-1]!='X') {
grid[y][x] = '.'; //removes current position
x--; //change location
}
//following if for moving down
if(grid[y+1][x] isn't out of bounds and down key is pressed and grid[y+1][x]!='X') {
grid[y][x] = '.'; //removes current position
y++; //change location
}
//following if for moving up
if(grid[y-1][x] isn't out of bounds and up key is pressed and grid[y-1][x]!='X') {
grid[y][x] = '.'; //removes current position
y--; //change location
}
if(grid[y][x] == '*') { //when trapped in a pit
System.out.println("You fell in a pit. Game over.");
} else {
grid[y][x] = 'P'; //update grid
}
Do you need a fixed amount of obstacles? You are better off putting the code in your loop that defines your the board:
for(int i=0; i<grid.length; i++) {
for(int j=0; j<grid.length; j++) {
int random = Math.random();
if (random <.05){
grid[i][j]='*';
}else if (random < .15) {
grid[i][j]='X'
}else {
grid[i][j]='.';
}
System.out.print(grid[i][j]);
}
}
grid[0][0]='P';
grid[9][9]='T';
Also you should put the cod just above define P and T outside the loop afterwards as it seems it only needs to be done once.
EDIT: this method will give you a representation of the game board, to cover the *, you can either change the print method to print them as . Or maintain a display grid, as well as the actual grid (eg make 2 grids)