What does array do in this code? - java

I am studying on udemy. I was writing the code of XOX game. I think all of us know XOX game. My code is working but i didn't understand what does this code do ?
for (int [] winningPosition : winningPositions){
if (gameState[winningPosition[0]] == gameState[winningPosition[1]] && gameState[winningPosition[1]] == gameState[winningPosition[2]] &&
gameState[winningPosition[0]] != 2)}
The code which is the i dont get is above. Please help me with understand that.
{ package com.example.anild.xox;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.GridLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
// 0 = yellow, 1 = red
int activePlayer = 0;
boolean gameIsActive = true;
//2 means unplayed
int [] gameState = {2,2,2,2,2,2,2,2,2};
int [][] winningPositions = {{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};
public void dropIn(View view) {
ImageView counter = (ImageView) view;
int tappedCounter = Integer.parseInt(counter.getTag().toString());
if(gameState[tappedCounter] == 2 && gameIsActive) {
//burada tappedCounterdaki sayıyı çekiyor yani tag'i daha sonra gamstate[] dizisine atıyor. Ve zaten hepsi 2 if koşulu sağlanıyor
//Bir asağısında bu kural değişiyor. Bu alınan tag gametate'te artık 0 olarak saklanıyor :)
gameState[tappedCounter] = activePlayer;
counter.setTranslationY(-1000f);
if (activePlayer == 0) {
counter.setImageResource(R.drawable.yellow);
activePlayer = 1;
} else {
counter.setImageResource(R.drawable.red);
activePlayer = 0;
}
counter.animate().translationYBy(1000f).rotation(360).setDuration(300);
for (int [] winningPosition : winningPositions){
if (gameState[winningPosition[0]] == gameState[winningPosition[1]] && gameState[winningPosition[1]] == gameState[winningPosition[2]] &&
gameState[winningPosition[0]] != 2){
//someone has won
gameIsActive = false;
String winner = "Red";
if(gameState[winningPosition[0]] == 0){
winner = "Yellow";
}
TextView winnerMessage = (TextView) findViewById(R.id.winnerMessage);
winnerMessage.setText(winner + "has won !");
LinearLayout layout = (LinearLayout)findViewById(R.id.playAgainLayout);
layout.setVisibility(View.VISIBLE);
}
else {
boolean gameIsOver = true;
for(int counterState : gameState) {
if (counterState == 2) {
gameIsOver = false;
}
if (gameIsOver) {
TextView winnerMessage = (TextView) findViewById(R.id.winnerMessage);
winnerMessage.setText("it's a draw");
LinearLayout layout = (LinearLayout)findViewById(R.id.playAgainLayout);
layout.setVisibility(View.VISIBLE);
}
}
}
}
}
}
public void playAgain(View view) {
gameIsActive = true;
LinearLayout layout = (LinearLayout)findViewById(R.id.playAgainLayout);
layout.setVisibility(View.INVISIBLE);
// 0 = yellow, 1 = red
activePlayer = 0;
for(int i = 0; i < gameState.length; i++) {
gameState[i] = 2;
}
GridLayout gridLayout = (GridLayout) findViewById(R.id.gridLayout);
for(int i = 0; i < gridLayout.getChildCount(); i++) {
((ImageView) gridLayout.getChildAt(i)).setImageResource(0);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
}

Answering based on the question posed below my comment:
At it's most fundamental, the format for that for loop is
for('one object' : 'group of objects')
Now then, under ordinary circumstances you'd use something along the lines of:
for(String oneString : arrayOfStrings)
Based on your question, it appears as if you are unaware that you can statically specify an array of values by putting them inside braces. For example:
String[] arrayOfStrings = {"zero", "one", "two"};
That produces exactly the same result as:
String[] arrayOfStrings = new String[3];
arrayOfStrings[0] = "zero";
arrayOfStrings[1] = "one";
arrayOfStrings[2] = "two";
You could loop over that with for(String string : arrayOfStrings)...
Going back to your original code - they have embedded braces inside braces, which is how you declare a multi-dimensional array. So the following:
int [][] winningPositions = {{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};
Produces the same array as:
int[][] winningPositions = new int[8][3];
winningPositions[0][0] = 0;
winningPositions[0][1] = 1;
winningPositions[0][2] = 2;
...
winningPositions[7][0] = 2;
winningPositions[7][1] = 4;
winningPositions[7][2] = 6;
With me so far?
The full "winningPositions" variable is an object of type array, whose content is itself a sequence of arrays. Okay, so now when you do your loop that you don't understand, this:
for (int [] winningPosition : winningPositions)
Each item in the array "winningPosition" is itself an array - as I just said - so the "one object" resolves to the inner array, which has 3 elements, while the outer has 8.
Does that help?
On a side note: Code like that is either aimed at new programmers, or else is written by someone that doesn't understand OO programming. It's worthwhile to understand how it works, it is not necessarily meant to be emulated. Or at least by the time you know I'm wrong about that, you'll know why I'm wrong.

for (int [] winningPosition : winningPositions)
Iterates through the array called winningPositions. Each iteration has the variable called winningPosition which is an int array of length 3.
if (gameState[winningPosition[0]] == gameState[winningPosition[1]] &&
gameState[winningPosition[1]] == gameState[winningPosition[2]] &&
gameState[winningPosition[0]] != 2)
checks that all the positions are owned by the same player and the last part gameState[winningPosition[0]] != 2 checks that the line isn't empty.
EDIT:
#ChrisParker explains this line very well in the comments. for (int [] winningPosition : winningPositions)

The for loop is iterating through the array and checking each of the conditions inside the if statement, IF all of them are true then the code will go inside the IF loop otherwise it will skip over and continue.
Cheers

Related

Stack Overflow with recursion in Java

I'm trying to write an AI that never loses at Tic Tac Toe, and I want to use the minimax algorithm to do so. However, when I try to run the program, a stack overflow appears and I can't seem to find what is the error. Could you take a look and tell me what I'm doing wrong? It doesn't go as deep in the recursion I believe, since it should only go through all the possible game outcomes, which go up to 8 moves (since the player is first to play, not the AI). It is probably me doing something wrong, but I can't find anything.
EDIT: Here's the full code, the mechanics function is the main part:
EDIT2: Fixed the constructor
package Packet;
import java.util.*;
import java.util.Scanner;
public class Logic {
public static class TicTacToe{
private int[] currentBoard = new int[9];
private int[] availableSpots = new int [9];
private int emptySpace = 0;
private int playerAI = 1;
private int playerHuman = 2;
void TicTacToe(){
for (int i = 0; i < 9; i++){
this.currentBoard[i] = this.emptySpace;
}
for (int i = 0; i < 9; i++){
this.availableSpots[i] = i;
}
}
private int movesNumber(){
int counter = 0;
for (int i = 0; i < 9; i++){
if (this.currentBoard[i] == this.emptySpace){
counter++;
}
}
return counter;
}
private boolean win(int[] board,int player){
if (
(board[0] == player && board[1] == player && board[2] == player) ||
(board[3] == player && board[4] == player && board[5] == player) ||
(board[6] == player && board[7] == player && board[8] == player) ||
(board[0] == player && board[3] == player && board[6] == player) ||
(board[1] == player && board[4] == player && board[7] == player) ||
(board[2] == player && board[5] == player && board[8] == player) ||
(board[0] == player && board[4] == player && board[8] == player) ||
(board[2] == player && board[4] == player && board[6] == player) ){
return true;
}
else{
return false;
}
}
private int mechanics(int[] newBoard, int player){
if (win(newBoard,this.playerHuman)){
return -10;
}
else if (win(newBoard, this.playerAI)){
return +10;
}
else if (this.movesNumber() == 0){
return 0;
}
ArrayList<Integer> moves = new ArrayList<Integer>();
ArrayList<Integer> scores = new ArrayList<Integer>();
for (int i = 0; i < this.movesNumber(); i++){
int[] possibleBoard = new int[9];
possibleBoard = newBoard;
int availableSpotNumber = i;
int j = i;
while (this.availableSpots[j] == 9){
availableSpotNumber++;
j++;
}
possibleBoard[availableSpotNumber] = player;
if (player == this.playerAI){
scores.add(this.mechanics(possibleBoard, this.playerHuman));
}
else{
scores.add(this.mechanics(possibleBoard, this.playerAI));
}
moves.add(availableSpotNumber);
possibleBoard[availableSpotNumber] = this.emptySpace;
}
int bestMove = 0;
if (player == this.playerAI){
int bestScore = -10000;
for (int i = 0; i < moves.size(); i++){
if (scores.get(i) > bestScore){
bestScore = scores.get(i);
bestMove = i;
}
}
}
else {
int bestScore = 10000;
for (int i = 0; i < moves.size(); i++){
if (scores.get(i) < bestScore){
bestScore = scores.get(i);
bestMove = i;
}
}
}
return moves.get(bestMove);
}
public void printTable(){
System.out.println(this.currentBoard[0] + " | " + this.currentBoard[1] + " | " + this.currentBoard[2]);
System.out.println("- - -");
System.out.println(this.currentBoard[3] + " | " + this.currentBoard[4] + " | " + this.currentBoard[5]);
System.out.println("- - -");
System.out.println(this.currentBoard[6] + " | " + this.currentBoard[7] + " | " + this.currentBoard[8]);
System.out.println();
}
private void fillTable(int position,int player){
this.currentBoard[position] = player;
this.availableSpots[position] = 9;
}
public void startGame(){
while(true){
this.printTable();
Scanner ulaz = new Scanner(System.in);
fillTable(ulaz.nextInt(), this.playerHuman);
this.printTable();
fillTable(this.mechanics(this.currentBoard, this.playerAI), this.playerAI);
ulaz.close();
}
}
public void resetGame(){
for (int i = 0; i < 9; i++){
this.currentBoard[i] = this.emptySpace;
}
for (int i = 0; i < 9; i++){
this.availableSpots[i] = i;
}
}
}
public static void main(String[] args){
TicTacToe game = new TicTacToe();
game.startGame();
}
}
Also, here's the exact errors I get:
Exception in thread "main" java.lang.StackOverflowError
at Packet.Logic$TicTacToe.mechanics(Logic.java:54)
at Packet.Logic$TicTacToe.mechanics(Logic.java:84)
at Packet.Logic$TicTacToe.mechanics(Logic.java:87)
at Packet.Logic$TicTacToe.mechanics(Logic.java:84)
at Packet.Logic$TicTacToe.mechanics(Logic.java:87)
at Packet.Logic$TicTacToe.mechanics(Logic.java:84)
at Packet.Logic$TicTacToe.mechanics(Logic.java:87)
After this part, these parts appear a bunch of times (at least 50)
at Packet.Logic$TicTacToe.mechanics(Logic.java:84)
at Packet.Logic$TicTacToe.mechanics(Logic.java:87)
Line 54:
if (win(newBoard,this.playerHuman)){
Line 84:
scores.add(this.mechanics(possibleBoard, this.playerHuman));
Line 87:
scores.add(this.mechanics(possibleBoard, this.playerAI));
This might or might not be a code issue, as Java is not a fully functional language with it comes to recursion, you might want to see this answer: Does Java 8 have tail call optimization?
Basically, a language that allows for unlimited-depth recursion has to have tail recursion optimization. With tail call optimization, if the return value is the result of exactly the same function with different parameters, the stack will get replaced instead of the new call being added to the stack.
If a language does not have tail call optimization, then you're limited by stack size in how deep your recursion goes, even if the recursive calls have correct termination conditions (note: I haven't analyzed the code in depth, so obviously there might be a problem in the recursive logic itself). If you want to tweak the stack size, use the -Xss Java runtime parameter. Generally, increasing the stack size is a good heuristic (although not a fool-proof method) of checking whether the fault is with the language or with your algorithm.
There's a couple of problems, but here's how you can debug this:
add a StringBuilder debug = new StringBuilder(); field to your class, then change the main loop like this:
int debugLen = debug.length();
debug.append("\nSetting ").append(availableSpotNumber).append(" to ").append(player);
possibleBoard[availableSpotNumber] = player;
try {
if (player == this.playerAI) {
scores.add(this.mechanics(possibleBoard, this.playerHuman));
} else {
scores.add(this.mechanics(possibleBoard, this.playerAI));
}
moves.add(availableSpotNumber);
} catch (StackOverflowError error) {
throw new StackOverflowError(debug.toString());
}
debug.setLength(debugLen);
possibleBoard[availableSpotNumber] = this.emptySpace;
Then you will see what is happening, which will give you a clue what to fix next. For example, the current version is doing this, for initial human move 1:
Setting 0 to 1
Setting 0 to 2
Setting 0 to 1
Setting 0 to 2
etc..
But, if you're too lazy, you can find a fixed version here.

Possible bug in android?

I guess that for some reason, the program below is passing by through conditions verifications and executing next condition's lines...
This program of mine should add the values 4 and 0 to the listIntercedeOut, but it removes right after adding them to the list...
If we put an empty for() right after the listIntercedeOut.add() methods, it doesn't remove
after...
Also, if we disable both listIntercedeOut.remove() lines commented on the code, the code works either...
I've made a little interface with TextView and Button to check list's values, I've made a lot of modifications from my main program... Those "almost-empty" conditions are needed there...
Also, that intercede(boolean) method will always return true in the example.
AddDisciplina.java:
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.SparseArray;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class AddDisciplina extends AppCompatActivity {
Button buttonCheck;
TextView text;
private List<Integer> listIntercedeIn = new ArrayList<>();
private List<Integer> listIntercedeOut = new ArrayList<>();
private SparseArray<String> sparseSeg=new SparseArray<>();
String time = "00:00";
String time2 = "01:30";
int var = 3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_add_disciplina);
if(getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
getSupportActionBar().setHomeButtonEnabled(true);
buttonCheck = (Button)findViewById(R.id.buttonCheck);
text = (TextView)findViewById(R.id.text);
buttonCheck.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String items="";
for(int i = 0; i < listIntercedeOut.size(); i++){
items = items + "-" + String.valueOf(listIntercedeOut.get(i));
}
text.setText(items);
}
});
sparseSeg.put(0, "01:00/02:00");
sparseSeg.put(4, "00:00/01:30");
abrirTimePicker(false);
}
private void abrirTimePicker(final boolean inicio){
if(inicio) {
if (time.equals("")) {
}
} else {
if((1<0)||(1==0 && 30<=0)){
}
switch (var){
case 3:
for (int i = 0; i < sparseSeg.size(); i++) {
String[] hs = sparseSeg.valueAt(i).split("/");
int idDoLL = sparseSeg.keyAt(i);
if ((inicio && !hs[1].equals("vazio") && intercede(hs[0], hs[1], time, time2)) ||
(!inicio && !hs[1].equals("vazio") && intercede(time, time2, hs[0], hs[1]))) {
if (inicio) { // DO SOMETHING
} else {
// SHOULD ALWAYS END HERE //
listIntercedeOut.add(4);
listIntercedeOut.add(idDoLL);
// IF WE RELEASE THIS FOR, EVERYTHING WORKS FINE
/*for(i = 1; i < listIntercedeOut.size(); i++) {
}*/
}
} else if (inicio && listIntercedeIn.contains(4) && listIntercedeIn.contains(0)) {
listIntercedeIn.remove(Integer.valueOf(4));
listIntercedeIn.remove(Integer.valueOf(idDoLL));
} else if (!inicio && listIntercedeOut.contains(4) && listIntercedeOut.contains(0)) {
// IF WE DISABLE THE FOLLOWING 2 LINES, EVERYTHING WORKS FINE
listIntercedeOut.remove(Integer.valueOf(4));
listIntercedeOut.remove(Integer.valueOf(0));
}
}
break;
}
}
}
private boolean intercede (String horario1, String horario2, String horario3, String horario4){
String[] hm1 = horario1.split(":");
int horas1 = Integer.parseInt(hm1[0]);
int minutos1 = Integer.parseInt(hm1[1]);
int ms1 = (horas1 * 3600000) + (minutos1 * 60000);
String[] hm2 = horario2.split(":");
int horas2 = Integer.parseInt(hm2[0]);
int minutos2 = Integer.parseInt(hm2[1]);
int ms2 = (horas2 * 3600000) + (minutos2 * 60000);
String[] hm3 = horario3.split(":");
int horas3 = Integer.parseInt(hm3[0]);
int minutos3 = Integer.parseInt(hm3[1]);
int ms3 = (horas3 * 3600000) + (minutos3 * 60000);
String[] hm4 = horario4.split(":");
int horas4 = Integer.parseInt(hm4[0]);
int minutos4 = Integer.parseInt(hm4[1]);
int ms4 = (horas4 * 3600000) + (minutos4 * 60000);
return (ms1<ms3 && ms3<ms2) || (ms1<ms4 && ms4<ms2);
}
}
add_disciplina_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/text"/>
<Button
android:id="#+id/buttonCheck"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="CHECK LIST"/>
</LinearLayout>
Could anyone please explain me what is going on here? Thanks in advance
There are maybe some value of your sparseSeg list who match your third condition loop . Put some log to see what's happen:
for (int i = 0; i < sparseSeg.size(); i++) {
String[] hs = sparseSeg.valueAt(i).split("/");
int idDoLL = sparseSeg.keyAt(i);
if ((inicio && !hs[1].equals("vazio") && intercede(hs[0], hs[1], time, time2)) ||
(!inicio && !hs[1].equals("vazio") && intercede(time, time2, hs[0], hs[1]))) {
if (inicio) { // DO SOMETHING
} else {
// SHOULD ALWAYS END HERE //
listIntercedeOut.add(4);
listIntercedeOut.add(idDoLL);
Log.i("1 CONDITION", i + "");
// IF WE RELEASE THIS FOR, EVERYTHING WORKS FINE
/*for(i = 1; i < listIntercedeOut.size(); i++) {
}*/
}
} else if (inicio && listIntercedeIn.contains(4) && listIntercedeIn.contains(0)) {
listIntercedeIn.remove(Integer.valueOf(4));
listIntercedeIn.remove(Integer.valueOf(idDoLL));
Log.i("2 CONDITION", i + "");
} else if (!inicio && listIntercedeOut.contains(4) && listIntercedeOut.contains(0)) {
// IF WE DISABLE THE FOLLOWING 2 LINES, EVERYTHING WORKS FINE
listIntercedeOut.remove(Integer.valueOf(4));
listIntercedeOut.remove(Integer.valueOf(0));
Log.i("3 CONDITION", i + "");
}
}
I think at least one value match to the last condition so, your values or remove from your list.
You should maybe rework your loop system condition.
Hope this helps.
Sorry for my poor english.
(I did a little correction)

I try to create a vocabulary loop in android

I am trying to make an app that alike vocabulary card.
I have an Answer array(array size = 4).
I am creating random an english word then I am adding true value of english word in answer array and I am removing true value of english word in turkish array in order to not use again in random.I am doing same things to other answer array include wrong value.
Problem is that array size is going to 0.for example my total array 20 .when I remove true value,array size is going to 19-18-17... per click then program close.
Here is my code:
package de.murattekinlive.pwords;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class WordsActivity extends AppCompatActivity {
TextView textView;
TextView deneme;
DataBase dataBase;
Button btn_r1,btn_r2,btn_r3,btn_r4;
String [] TR_WORDS;
String [] EN_WORDS;
String [] Answer;
int control_id = 0;
int random ;
Random control;
Random rnd;
int tr,en;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_words);
textView = (TextView) findViewById(R.id.textView);
deneme = (TextView) findViewById(R.id.textView3);
dataBase = new DataBase(getApplicationContext());
rnd= new Random();
btn_r1 = (Button)findViewById(R.id.button_random1);
btn_r1.setOnClickListener(new myClickListener());
btn_r2 = (Button)findViewById(R.id.button_random2);
btn_r2.setOnClickListener(new myClickListener());
btn_r3 = (Button)findViewById(R.id.button_random3);
btn_r3.setOnClickListener(new myClickListener());
btn_r4 = (Button)findViewById(R.id.button_random4);
btn_r4.setOnClickListener(new myClickListener());
ArrayList<Words> enWordlist = (ArrayList<Words>) dataBase.allEnWords();
ArrayList<Words> trWordlist =(ArrayList<Words>) dataBase.allTrWords();
TR_WORDS = new String[trWordlist.size()];
EN_WORDS = new String[enWordlist.size()];
for(int i=0;i<enWordlist.size();i++){
EN_WORDS[i] =enWordlist.get(i).getWORD().toString();
TR_WORDS[i] =trWordlist.get(i).getTR1().toString();
}
tr = new Random().nextInt(TR_WORDS.length);
/*btn_r1.setText(TR_WORDS[en]);
btn_r2.setText(TR_WORDS[new Random().nextInt(TR_WORDS.length)]);
btn_r3.setText(TR_WORDS[new Random().nextInt(TR_WORDS.length)]);
btn_r4.setText(TR_WORDS[new Random().nextInt(TR_WORDS.length)]);*/
ReStart();
}
private class myClickListener implements View.OnClickListener{
public void onClick(View v){
switch ( v.getId() ) {
case R.id.button_random1:
break;
case R.id.button_random2:
break;
case R.id.button_random3:
break;
case R.id.button_random4:
break;
default:
break;
}
WordsActivity.this.ReStart();
}
}
public void ReStart(){
Answer = new String[4];
control = new Random();
control_id = control.nextInt(4);
en = new Random().nextInt(EN_WORDS.length);
final List<String> newTRList = new ArrayList<>();
textView.setText(EN_WORDS[en]);
final int sayi1,sayi2;
sayi1 = TR_WORDS.length;
Collections.addAll(newTRList,TR_WORDS);
// I added true turkish word in answer array
for(int i=0;i<TR_WORDS.length;i++){
if(en == i){
Answer[control_id]=TR_WORDS[i].toString();
newTRList.remove(TR_WORDS[i].toString()); //remove true value from array in order to not use again.
}
}
TR_WORDS = newTRList.toArray(new String[newTRList.size()]);
//I added another values in answer array and I want to remove values that is used because
//I dont want to see same value in answer array.
for(int i=0;i<=3;i++){
if(i == control_id){
}
else if(i == 0){
random=rnd.nextInt(TR_WORDS.length);
Answer[i]=TR_WORDS[random];
}
else if(i == 1){
random=rnd.nextInt(TR_WORDS.length);
Answer[i]=TR_WORDS[random];
}
else if(i == 2){
random=rnd.nextInt(TR_WORDS.length);
Answer[i]=TR_WORDS[random];
}
else if(i == 3){
random=rnd.nextInt(TR_WORDS.length);
Answer[i]=TR_WORDS[random];
}
}
sayi2 =TR_WORDS.length;
deneme.setText(sayi1+"/"+sayi2);
for(int i=0;i<=3;i++){
if(i == control_id){
}
else if(i == 0){
random =rnd.nextInt(TR_WORDS.length);
Answer[i]=TR_WORDS[random];
}
else if(i == 1){
random =rnd.nextInt(TR_WORDS.length);
Answer[i]=TR_WORDS[random];
}
else if(i == 2){
random =rnd.nextInt(TR_WORDS.length);
Answer[i]=TR_WORDS[random];
}
else if(i == 3){
random =rnd.nextInt(TR_WORDS.length);
Answer[i]=TR_WORDS[random];
}
}
for(int j=0;j<=3;j++){
if(j==0){
btn_r1.setText(Answer[j].toString());
}
else if(j==1){
btn_r2.setText(Answer[j].toString());
}
else if(j==2){
btn_r3.setText(Answer[j].toString());
}
else if(j==3){
btn_r4.setText(Answer[j].toString());
}
}
}
}
Change your for loop to:
for(int i=TR_WORDS.length; i >=0 ;i--){
if(en == i){
Answer[control_id]=TR_WORDS[i].toString();
newTRList.remove(TR_WORDS[i].toString()); //remove true value from array in order to not use again.
}
}
And all the other ones that include a remove in a similar a fashion.

Nothing returned from 2D arrays for a simple tic-tac-toe board

public String tictactoe(String game)
{
game = game.toUpperCase();
char[][] board = new char[3][3];
int loc = 0;
for( char r = 0; r < board.length; r++ )
{
for( char c = 0; c < board[r].length; c++)
{ board[r][c] = game.charAt(loc);
loc++;
}
}
if ((board[0][0] =='X' && board[0][1] =='X' && board[0][2] =='X') ||
(board[1][0] =='X' && board[1][1] =='X' && board[1][2] =='X') ||
(board[2][0] =='X' && board[2][1] =='X' && board[2][2] =='X'))
return("Player 1 wins horizontally!");
else if ((board[0][0] =='O' && board[0][1] =='O' && board[0][2] =='O') ||
(board[1][0] =='O' && board[1][1] =='O' && board[1][2] =='O') ||
(board[2][0] =='O' && board[2][1] =='O' && board[2][2] =='O'))
return("Player 2 wins horizontally!");
else if ((board[0][0] =='X' && board[1][0] =='X' && board[2][0] =='X') ||
(board[0][1] =='X' && board[1][1] =='X' && board[2][1] =='X') ||
(board[0][2] =='X' && board[1][2] =='X' && board[2][2] =='X'))
return("PLayer 2 wins vertically!");
else if ((board[0][0] =='O' && board[1][0] =='O' && board[2][0] =='O') ||
(board[0][1] =='O' && board[1][1] =='O' && board[2][1] =='O') ||
(board[0][2] =='O' && board[1][2] =='O' && board[2][2] =='O'))
return("Player 2 wins vertically!");
return "Tie!";
}
Above is my code for this method. It reads in a 9 letter string for a tic-tac-toe game and then puts it one by one into a 2D array. I unfortunately have to use this method because this is unfortunately what we're learning, and I've continuously had to bother my teacher about this...
The if statements check each row and column for a winner (I realize it does not check the horizontals). My issue here is nothing is being returned, even though it is supposed to return a string. As I have said I have to use 2D-arrays here. The goal is to check a tic-tac-toe game and return whom as won.
Consider replacing each instance of this
if(board[0][0] =='X' && board[0][1] =='X' && board[0][2] =='X') ||
...
With this function:
public boolean isRowFilledWith(int row_index, char x_or_o) {
return (board[row_idx][0] == x_or_o &&
board[row_idx][1] == x_or_o &&
board[row_idx][2] == x_or_o);
}
Now, to see if the top-most row contains all x-s, call it with
if(isRowFilledWith(0, 'X') ||
...
This will make your code a lot more concise, easier to read and easier to debug.
Try doing:
System.out.println(fooObject.tictactoe("XXXXXXOOO");
inside your main argument (public static void main(String[] args)
I suspect you've confused return and System.out.println. The console will not print anything if returned. Instead, returning is what is thrown at the computer after the function is called. Try printing the result of calling the function...THAT is what is returned to the computer and is only going to be visible if you print it. There may not be any error in your code.
First off, to directly answer your question:
Your function works fine, I locally tested it. I tried both horizontal, and vertical, with both x and o. It must be something you are doing with the caller.
The biggest problem with this code is clarity. You can do quite a bit about clarity by separating the logic into groups.
Clarity can be achieved by making application specific objects.
If you have an object to represent a move, a game, and the marker... you can drastically simplify you code and most of all make it easy to read and debug.
I went ahead and implemented tic tac toe just to kinda explain what I mean by clarity.
Any time you start having massive if else chains and block return statements you may need to take the extra time to break up the problem.
This is fully compililable and I think if you debug through it a few times you will find it is much easier to spot mistakes.
It is also easy to ajust the game... Right now, we have 2 players and a 3 by 3 game.
However, we have extra constructors to adjust the size of the game and to give the gamers some options on what they want thier tic tac toe game to look like.
The major reason to do this is for clarity and debugging.
It is always easier to find issues if you have problem specific methods and problem specific objects.
Below is a fully compilable console application for tic tac toe. In its current form, it plays 100 random 3 by 3 games and prints the results of all 100 games.
The application is also capable of taking your string input as console input and processing the moves.
Notice that we are still using two dimensional arrays, but we hidden away the complexity of using them by encapsulating the array in the Board object.
We also gave a move object so we can store moves to play later. This was useful in creating the loop to play many games, as all the facts about the move are contained in a single object.
Since we created three separate methods for validating the move input. We have a much clearer explanation of what we are validating and why we are doing it.
Most debuggers will also show the objects toString method, so by embedding the game display within the toString() we are allowed to see what the board looks like when we are debugging.
The trick to making clean code that doesn't require alot of comments is to attempt to split out any complexity to its own unit.
You probably will cover more about units of work later, but just keep it in mind, the more simple a method, the more reusable it is. The more single purpose a class is, the better and clearer it is.
My Example:
Mark.java
-This enum is the representation of the mark used by a player to signify their move.
public enum Mark{
X, Y;
}
TicTacToe.java
-This class is your main class
it handles gathering user input, cleaning it, processing it, and displaying the output to the user
Notice that I am not doing game display anywhere else but the main method. this keeps all display issues localized to one spot. The advantage to breaking up your code into specific objects is knowing where to fix something when it breaks.
package com.clinkworks.example;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.clinkworks.example.Move;
import com.clinkworks.example.Board;
import com.clinkworks.example.Mark;
public class TicTacToe {
//this variable is simply used for output. Since we cant save CAT in the mark enum, we
// use it to hold cats games.
private static final String catsGameIdentity = "CAT";
//this map contains the counts of wins for each symbol
//it also keeps track of ties and stores it in the map as "CAT"
//soo.. gamesToWinsMap.get("CAT") will produce the amount of ties.
private static final Map<String, Integer> gamesToWinsMap = new HashMap<String, Integer>();
public static void main(String[] args){
String game = args[0].toUpperCase(); //better ways to do this and no validation here.. but it will work
Board board = new Board();
//holds our current place in the string passed in from teh console
int currentStringLocation = 0;
for(int row = 0; row < 3; row++){ //loop through the rows
for(int column = 0; column < 3; column++){ //for each row loop through the columns
if(gameOver(board)){ // we don't care about the rest of the input if the game was won
break;
}
//convert the symbol to a string for use in teh ValueOf function in the enum class
String symbol = "" + game.charAt(currentStringLocation); //better than String.valueOf imho
//allow spaces to represent un marked places
if(" ".equals(symbol)){
currentStringLocation++; //this accounts for spaces in our input
break;
}
//convert the string to a Mark enum... over use of strings is a very very bad practice
Mark nextMarkToPlace = Mark.valueOf(symbol);
Move move = new Move(row, column, nextMarkToPlace); //we create a move object that encapsulates the complexity of placing the mark on the game board
board.play(move); //the game already knows how to play itself, just let it
currentStringLocation++; //increment the posision.
}
}
//since you may not have won the game, or gave a complete string for a cats game,
// lets at least display the board for debugging reasons.
if(board.movesLeft() > 0){
System.out.println("Board isn't finished, but here is what it looks like basd on your input: ");
System.out.println(board);
}
}
//call me main if you want to see what I do
public static void main2(String[] args) {
//lets play 100 games and see the wins and ties
playGames(100);
System.out.println("Number wins by X: " + gamesToWinsMap.get(Mark.X.name()));
System.out.println("Number wins by O: " + gamesToWinsMap.get(Mark.O.name()));
System.out.println("Number of ties: " + gamesToWinsMap.get(catsGameIdentity));
}
public static void playGames(int count) {
//play a new game each iteration, in our example, count = 100;
for (int i = 0; i < count; i++) {
playGame();
}
}
public static void playGame() {
//create a new game board. this initalizes our 2d array and lets the complexity of handling that
// array be deligated to the board object.
Board board = new Board();
//we are going to generate a random list of moves. Heres where we are goign to store it
List<Move> moves = new ArrayList<Move>();
//we are creating moves for each space on the board.
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
moves.add(new Move(row, col));
}
}
//randomize the move list
Collections.shuffle(moves);
//do each move
for (Move move : moves) {
board.play(move);
if(gameOver(board)){
break;
}
}
}
public static boolean gameOver(Board board){
if (board.whoWon() != null) {
System.out.println("Player with the mark: " + board.whoWon() + " won the game!");
System.out.println(board);
Integer winCount = gamesToWinsMap.get(board.whoWon().name());
winCount = winCount == null ? 1 : winCount + 1;
gamesToWinsMap.put(board.whoWon().name(), winCount);
return true;
} else if (board.movesLeft() == 0) {
System.out.println("It was a cats game!!");
System.out.println(board);
Integer catCount = gamesToWinsMap.get(catsGameIdentity);
catCount = catCount == null ? 1 : catCount + 1;
gamesToWinsMap.put(catsGameIdentity, catCount);
return true;
}
return false;
}
Move.java
-This class is responsible for ensuring that only integers are passed to the game board
and for telling the game board who is doing the move (optional)
package com.clinkworks.example;
import com.clinkworks.example.Mark;
public class Move {
private int row;
private int column;
private Mark forcedMark;
public Move(int row, int column) {
this.row = row;
this.column = column;
}
//the board already knows who should be next. only use this constructor to override
// what symbol to put on the game board
public Move(int row, int column, Mark markToPlace){
this.row = row;
this.column = column;
forcedMark = markToPlace;
}
public int getRow() {
return row;
}
public int getColumn() {
return column;
}
public Mark getMark(){
return forcedMark;
}
}
Board.java
-This is where all the state of the board is managed, who is the next player, who won, and
is there any moves left to play. It also ensures that only valid moves are played.
package com.clinkworks.example;
import com.clinkworks.example.Mark;
import com.clinkworks.example.Move;
public class Board {
private final int rowSize;
private final int columnSize;
private final Mark[][] gameBoard;
private Mark currentMark;
private Mark winningMark;
/**
* This constructor defaults the starting player to X with a 3 by 3
* game.
*/
public Board() {
gameBoard = new Mark[3][3];
currentMark = Mark.X; // X always goes first ;P
winningMark = null;
this.rowSize = 3;
this.columnSize = 3;
}
/**
* This constructor defaults the starting player to X, and lets the
* board size be adjusted
*/
public Board(int rowSize, int columnSize) {
gameBoard = new Mark[rowSize][columnSize];
currentMark = Mark.X; // X always goes first ;P
winningMark = null;
this.rowSize = getRowSize();
this.columnSize = columnSize;
}
/**
* this constructor allows the players to choose who goes first on a 3
* by 3 board.
*
* #param firstPlayer
*/
public Board(Mark firstPlayer) {
gameBoard = new Mark[3][3];
currentMark = firstPlayer; // Let the player choose
winningMark = null;
rowSize = 3;
columnSize = 3;
}
/**
* this constructor allows the players to choose who goes first and to
* choose the size of the board.
*
* #param firstPlayer
*/
public Board(Mark firstPlayer, int rowSize, int columnSize) {
gameBoard = new Mark[getRowSize()][columnSize];
currentMark = firstPlayer; // Let the player choose
winningMark = null;
this.rowSize = rowSize;
this.columnSize = columnSize;
}
/**
*
* #return the amount of empty spaces remaining on the game board, or if theres a winning player, zero.
*/
public int movesLeft() {
if(whoWon() != null){
return 0;
}
int moveCount = 0;
for (int x = 0; x < getRowSize(); x++) {
for (int y = 0; y < getColumnSize(); y++) {
moveCount += getMarkAt(x, y) == null ? 1 : 0;
}
}
return moveCount;
}
/**
* If someone won, this will return the winning player.
*
* #return the winning player
*/
public Mark whoWon() {
return winningMark;
}
/**
* This move allows the next player to choose where to place their mark.
* if a move is played without a player given, it will use the current player variable
*
* as a side affect, the next player in rotation is chosen.
*
* #param Move
* #return if the game is over, play will return true, otherwise false.
*/
public boolean play(Move move) {
if (!validMove(move)) {
// always fail early
throw new IllegalStateException("Cannot play " + currentMark + " at " + move.getRow() + ", " + move.getColumn() + "\n" + toString());
}
doMove(move);
boolean playerWon = isWinningMove(move);
if (playerWon) {
winningMark = currentMark;
return true;
}
togglePlayer();
boolean outOfMoves = movesLeft() <= 0;
return outOfMoves;
}
public Mark lastMarkPlayed() {
return currentMark;
}
public int getRowSize() {
return rowSize;
}
public int getColumnSize() {
return columnSize;
}
public Mark getCurrentPlayer() {
return currentMark;
}
public Mark getMarkAt(int row, int column) {
return gameBoard[row][column];
}
private void doMove(Move move) {
if(move.getMark() != null){
currentMark = move.getMark();
}
gameBoard[move.getRow()][move.getColumn()] = getCurrentPlayer();
}
private void togglePlayer() {
if (currentMark == Mark.X) {
currentMark = Mark.O;
} else {
currentMark = Mark.X;
}
}
/**
* A valid move is a move where the row and the column are within boundries
* and no move has been made that the location specified by the move.
*/
private boolean validMove(Move move) {
boolean noMarkAtIndex = false;
boolean indexesAreOk = move.getRow() >= 0 || move.getRow() < getRowSize();
indexesAreOk = indexesAreOk && move.getColumn() >= 0 || move.getColumn() < getColumnSize();
if (indexesAreOk) {
noMarkAtIndex = getMarkAt(move.getRow(), move.getColumn()) == null;
}
return indexesAreOk && noMarkAtIndex;
}
private boolean isWinningMove(Move move) {
// since we check to see if the player won on each move
// we are safe to simply check the last move
return winsDown(move) || winsAcross(move) || winsDiagnally(move);
}
private boolean winsDown(Move move) {
boolean matchesColumn = true;
for (int i = 0; i < getColumnSize(); i++) {
Mark markOnCol = getMarkAt(move.getRow(), i);
if (markOnCol != getCurrentPlayer()) {
matchesColumn = false;
break;
}
}
return matchesColumn;
}
private boolean winsAcross(Move move) {
boolean matchesRow = true;
for (int i = 0; i < getRowSize(); i++) {
Mark markOnRow = getMarkAt(i, move.getColumn());
if (markOnRow != getCurrentPlayer()) {
matchesRow = false;
break;
}
}
return matchesRow;
}
private boolean winsDiagnally(Move move) {
// diagnals we only care about x and y being teh same...
// only perfect squares can have diagnals
// so we check (0,0)(1,1)(2,2) .. etc
boolean matchesDiagnal = false;
if (isOnDiagnal(move.getRow(), move.getColumn())) {
matchesDiagnal = true;
for (int i = 0; i < getRowSize(); i++) {
Mark markOnDiagnal = getMarkAt(i, i);
if (markOnDiagnal != getCurrentPlayer()) {
matchesDiagnal = false;
break;
}
}
}
return matchesDiagnal;
}
private boolean isOnDiagnal(int x, int y) {
if (boardIsAMagicSquare()) {
return x == y;
} else {
return false;
}
}
private boolean boardIsAMagicSquare() {
return getRowSize() == getColumnSize();
}
//prints out the board in a nice to view display
public String toString() {
StringBuffer stringBuffer = new StringBuffer();
for(int y = 0; y < getColumnSize(); y++) {
for(int x = 0; x < getRowSize(); x++) {
Mark mark = getMarkAt(x, y);
String markToPrint = "";
if (mark == null) {
markToPrint = " ";
} else {
markToPrint = mark.name();
}
stringBuffer.append("|").append(markToPrint);
}
stringBuffer.append("|\n");
}
return stringBuffer.toString();
}
}
}

Cell life Game java

Hello i am designing a basic java "game" where you put in a starting true point the length and size of array
then the program will check which value is true and it has to follow the next set of rules
if the cell is currently occupied, it remains occupied only if exactly one neighbour is occupied;
it the cell is currently empty, it remains empty only if both neighbours are empty
the code that i have so far kinda works but it puts a true too soon in the beginning which causes rule 1 to not work
import java.util.*;
class Cell
{
public static void main (String[] args)
{int l;
int g; //number of the generation
String s, a;//stands for automata
int p; //position of the true cells
int currentG; //current generation
Scanner scanner;
scanner= new Scanner(System.in);
a=scanner.next();
l=scanner.nextInt();
g=scanner.nextInt();
s=scanner.next();
boolean[][] cellsCurrent = new boolean[g][l+2];
currentG=0;
while(scanner.hasNextInt()){ //put the position values in an array
p=scanner.nextInt();
if(p<=l){
cellsCurrent[currentG][p] = true;
}
}
s=scanner.next();//ik weet niet echt wat ik anders met die *init_end* moet
if(a.equals("A")){
for(currentG=0; currentG<g-1; currentG++){ //for all generations
for(int i=1; i<l+1; i++){ //for all cells
if(cellsCurrent[currentG][i] == true && ((cellsCurrent[currentG][i+1] == true && cellsCurrent[currentG][i-1] == false)||(cellsCurrent[currentG][i+1] == false && cellsCurrent[currentG][i-1] == true ))){ //dit werkt dus nog niet
cellsCurrent[currentG+1][i] = true;
}
else {if (cellsCurrent[currentG][i] == true){
cellsCurrent[currentG+1][i] = false;
}}
if(cellsCurrent[currentG][i] == false && cellsCurrent[currentG][i+1] == false && cellsCurrent[currentG][i-1] == false){
cellsCurrent[currentG+1][i] = false;
}
else{
cellsCurrent[currentG+1][i] = true;
}
}
}
}
for (int i = 0; i < cellsCurrent.length; i++) {
System.out.println(Arrays.toString(cellsCurrent[i]).replace("true", "*")
.replace("false", " "));
}
}
}
You can increase your chances of success with cleaner code. Use an extra method like this:
static int getLivingNeighbors (boolean[] arr, int index) {
int result = 0;
if (index > 0 && arr[index-1])
result++;
if (index < arr.length-1 && arr[index+1])
result++;
return result;
}
Using this will help you to get a clearer view on what you really want to do.
You can call it roughly like this: getLivingNeighbors(cellsCurrent[currentG],i)

Categories