Matching Card Game in Java - 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.

Related

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.

Weather/Bike riding method assistance needed

I am currently starting a Java course and am a relative beginner, I have been given an exercise one part of which asks me to write a method that prints out whether or not it is good enough weather to go on a bike ride.
It must be greater than 40 degrees and less than 100 degrees unless it is raining in which case it must be greater than 70 degrees and less than 110 degrees.
The problem is that I am way more of a beginner (to programming in general) than most others on the course, and this exercise seems like a step up from the rest of the same assignment.
E.g the previous task, to create a dice rolling method -
public static int diceAverage (int pNumberofRolls) {
int total=0;
Random rand = new Random();
for (int loopy=1; loopy<=pNumberofRolls; loopy++){
total = total + rand.nextInt(6) + 1;
}
}
Sorry if formatting is off, I am on my mobile.
Kyle's answer is good. For academic purpose, the same code with ternary operator:
public static boolean bikeOrNot (int temp, boolean rain) {
return rain
? temp > 70 && temp < 110
: temp > 40 && temp < 100;
}
Few explanations:
I'm using boolean instead of Boolean because the answer should not be null. Same thing for the argument boolean rain instead of Boolean rain. For that point, you can check the primtive data type concept
ternary operator is a shortcut for if ... then ... else... written in one line: (condition) ? (return this if condition is true) : (return this if condition is false)
I think you are looking for this:
public static Boolean bikeOrNot (int temp, Boolean rain) {
// check for rain
if (rain){
if (temp > 70 && temp < 110){
return true;
}
} else {
if (temp > 40 && temp < 100){
return true;
}
}
return false;
}
Call this like:
Boolean shouldIBike = bikeOrNot(60, false);
It checks if its raining, then checks the temperate and does the same if its not raining. If it doesn't fall into any if, it will reach the last line and return false, in that case, you should not go cycling.

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.

Sudoku backtracking algorithm (Java)

I've created a Sudoku solver that will solve a Sudoku as a human might- by checking possibilities + definite values in squares corresponding to the square being checked.
(Source: http://pastebin.com/KVrXUDBF)
However, I would like to create a random Sudoku generator (from a blank grid), and so have decided to use a backtracking algorithm. I understand the concept of backtracking, but am confused about one thing:
How do I know which previous node to return to (and change) once I know a certain solution is not allowed?
Should I simply return to the previous node and cycle through all possibilities? (And then if this yields no correct answers, return to the value before, etc.). This seems like a viable method, but also quite inefficient. Is this the correct way of implementing a backtracking method or is there a better way to go about it?
Thanks in advance.
More can be found about backtracking here: http://en.wikipedia.org/wiki/Backtracking
Sudoku Puzzle can be reduced to graph coloring problem which can be solved using simple backtracking like assigning colors to node (1-9) till the there is no violation that all directly connected nodes have no same color.
Constructing Graph from Sudoku : -
There is an direct edge between two grid points if they are in same
row or column or square.
Backtracking :-
Assign one color (1-9) to node
Check if there is no other directly connected node with same color
If valid color move to next node.
else change the color and recheck.
If all color exhausted backtrack to previous node.
Do recursion till all nodes are color.
Once You are done with it you can start removing numbers from the grid at random till you think the problem is unsolvable if any more numbers are removed.
A simple way to generate random Sudoku is that
1) generate a random completing Sudoku, that is, generate random Sudoku no square is blank.
2) Remove numbers from squares of 1).
3) Solve Sudoku of 2). If there are many solutions, then add a number removed at 2).
If there are still many solutions, then repeat 3).
1) sample source code:
public int[][] generateRandomCompleteSudoku() {
int[][] sudoku = new int[10];
for(int i = 1; i <= 9; i++) {
sudoku[i] = new int[10];
Arrays.fill(sudoku[i], 0);
}
generateRandomCompleteSudoku(sudoku, 1, 1);
return sudoku;
}
private boolean generateRandomCompleteSudoku(int[][] sudoku, int x, int y) {
if(x > 9) {
x = 1;
y++;
}
//sudoku of the argument is completing sudoku.
//so return true
if(y > 9) {
return true;
}
// enumerate the possible numbers of the pos(x,y).
List<Integer> possibleNumbers = new ArrayList<Integer>();
for(int i = 1; i <= 9; i++) {
boolean possible = true;
//check i is a possible number.
//check there isn't i in the raw of y .
for(int j = 1; j <= x - 1; j++) {
if(sudoku[j][y] == i) {
possible = false;
break;
}
}
//check there isn't i in the column of x(omitted).
//check there isn't i in the group of x,y(omitted).
if(possible) {
possibleNumbers.add(i);
}
}
//sudoku is wrong so return false.(There is no solution of sudoku)
if(possibleNumbers.size() <= 0) {
return false;
}
Collections.shuffle(possibleNumbers);// This gives sudoku randomness.
for(Integer possibleNumber : possibleNumbers) {
sudoku[x][y] = possibleNumber;
// a sudoku is generated, so return true
if(generateRandomCompleteSudoku(sudoku, x + 1, y)) {
return true;
}
}
// No sudoku is generated, so return false
return false;
}
For a backtracking solution, the first step is to define the state. So for this problem, I think the most straightforward way is (x,y, blank , num) with x , y is the position of the current state, blank is the number of blank position left, and num is the value you want to fill in that position (from 0 to 9 and 0 means blank).
And the return type should be boolean, which determine whether the move is valid or not (which means is there any valid solution for this move).
So, the state transition is column by column, row by row: x, y to x , (y + 1) or x , y to (x + 1), 0.
Similarly, the blank will be from a -> a - 1-> ... 0.
We have a draft solution here:
public boolean move(int x, int y, int blank, int num, int[][]sudoku){
sudoku[x][y] = num;
//checking condition and return if x,y is the last position, code omitted
if(y == sudoku[x].length){
x++;
y = 0;
}else{
y++;
}
for(int i = 1; i < 10; i++){
if(move(x,y,blank,i,sudoku){//Backtrack here
return true;
}
}
if(blank > 0){
if(move(x,y,blank - 1, 0, sudoku){//Backtrack here
return true;
}
}
return false;
}
So when ever there is a false return from the current state, it will backtrack to the last state , and the last state will continue to check for the next num until it find a correct solution (or return false).

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

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]
}

Categories

Resources